From 21d8816b5d8cbe13081f0e02d9cccff4fcc6581b Mon Sep 17 00:00:00 2001 From: Cloudmersive <35204726+Cloudmersive@users.noreply.github.com> Date: Sun, 2 Jul 2023 02:30:17 +0000 Subject: [PATCH] 3.0.1 --- README.md | 2 +- build.ps1 | 23 + composer.json | 6 +- composer.lock | 3817 +++++++--- lib/Configuration.php | 4 +- packageconfig.json | 2 +- vendor/autoload.php | 20 +- vendor/bin/php-cs-fixer | 120 +- vendor/bin/php-cs-fixer.bat | 5 + vendor/bin/phpcbf | 120 +- vendor/bin/phpcbf.bat | 5 + vendor/bin/phpcs | 120 +- vendor/bin/phpcs.bat | 5 + vendor/bin/phpunit | 123 +- vendor/bin/phpunit.bat | 5 + vendor/composer/ClassLoader.php | 204 +- vendor/composer/InstalledVersions.php | 359 + vendor/composer/autoload_classmap.php | 62 +- vendor/composer/autoload_files.php | 12 +- vendor/composer/autoload_namespaces.php | 3 +- vendor/composer/autoload_psr4.php | 27 +- vendor/composer/autoload_real.php | 60 +- vendor/composer/autoload_static.php | 206 +- vendor/composer/installed.json | 6426 +++++++++++------ vendor/composer/installed.php | 599 ++ vendor/composer/pcre/LICENSE | 19 + vendor/composer/pcre/README.md | 134 + vendor/composer/pcre/composer.json | 46 + vendor/composer/pcre/src/MatchAllResult.php | 46 + .../pcre/src/MatchAllWithOffsetsResult.php | 48 + vendor/composer/pcre/src/MatchResult.php | 39 + .../pcre/src/MatchWithOffsetsResult.php | 41 + vendor/composer/pcre/src/PcreException.php | 60 + vendor/composer/pcre/src/Preg.php | 303 + vendor/composer/pcre/src/Regex.php | 142 + vendor/composer/pcre/src/ReplaceResult.php | 44 + vendor/composer/platform_check.php | 26 + vendor/composer/semver/CHANGELOG.md | 209 + vendor/composer/semver/LICENSE | 19 + vendor/composer/semver/README.md | 98 + vendor/composer/semver/composer.json | 59 + vendor/composer/semver/src/Comparator.php | 113 + .../composer/semver/src/CompilingMatcher.php | 94 + .../composer/semver/src/Constraint/Bound.php | 122 + .../semver/src/Constraint/Constraint.php | 435 ++ .../src/Constraint/ConstraintInterface.php | 75 + .../src/Constraint/MatchAllConstraint.php | 85 + .../src/Constraint/MatchNoneConstraint.php | 83 + .../semver/src/Constraint/MultiConstraint.php | 325 + vendor/composer/semver/src/Interval.php | 98 + vendor/composer/semver/src/Intervals.php | 478 ++ vendor/composer/semver/src/Semver.php | 129 + vendor/composer/semver/src/VersionParser.php | 586 ++ vendor/composer/xdebug-handler/CHANGELOG.md | 124 + vendor/composer/xdebug-handler/LICENSE | 21 + vendor/composer/xdebug-handler/README.md | 291 + vendor/composer/xdebug-handler/UPGRADE.md | 30 + vendor/composer/xdebug-handler/composer.json | 44 + .../composer/xdebug-handler/src/PhpConfig.php | 92 + .../composer/xdebug-handler/src/Process.php | 122 + vendor/composer/xdebug-handler/src/Status.php | 224 + .../xdebug-handler/src/XdebugHandler.php | 745 ++ vendor/doctrine/annotations/LICENSE | 19 + vendor/doctrine/annotations/README.md | 24 + vendor/doctrine/annotations/composer.json | 72 + .../annotations/docs/en/annotations.rst | 252 + .../doctrine/annotations/docs/en/custom.rst | 443 ++ vendor/doctrine/annotations/docs/en/index.rst | 110 + .../doctrine/annotations/docs/en/sidebar.rst | 6 + .../Common/Annotations/Annotation.php | 57 + .../Annotations/Annotation/Attribute.php | 21 + .../Annotations/Annotation/Attributes.php | 15 + .../Common/Annotations/Annotation/Enum.php | 69 + .../Annotation/IgnoreAnnotation.php | 43 + .../Annotation/NamedArgumentConstructor.php | 13 + .../Annotations/Annotation/Required.php | 13 + .../Common/Annotations/Annotation/Target.php | 101 + .../Annotations/AnnotationException.php | 167 + .../Common/Annotations/AnnotationReader.php | 389 + .../Common/Annotations/AnnotationRegistry.php | 190 + .../Common/Annotations/CachedReader.php | 266 + .../Doctrine/Common/Annotations/DocLexer.php | 143 + .../Doctrine/Common/Annotations/DocParser.php | 1506 ++++ .../Common/Annotations/FileCacheReader.php | 315 + .../ImplicitlyIgnoredAnnotationNames.php | 178 + .../Common/Annotations/IndexedReader.php | 100 + .../NamedArgumentConstructorAnnotation.php | 14 + .../Doctrine/Common/Annotations/PhpParser.php | 92 + .../Common/Annotations/PsrCachedReader.php | 232 + .../Doctrine/Common/Annotations/Reader.php | 80 + .../Annotations/SimpleAnnotationReader.php | 114 + .../Common/Annotations/TokenParser.php | 206 + vendor/doctrine/annotations/psalm.xml | 15 + vendor/doctrine/deprecations/LICENSE | 19 + vendor/doctrine/deprecations/README.md | 157 + vendor/doctrine/deprecations/composer.json | 38 + .../lib/Doctrine/Deprecations/Deprecation.php | 312 + .../PHPUnit/VerifyDeprecations.php | 66 + vendor/doctrine/deprecations/phpcs.xml | 22 + vendor/doctrine/deprecations/phpstan.neon | 9 + vendor/doctrine/deprecations/psalm.xml | 30 + .../instantiator/.doctrine-project.json | 47 + vendor/doctrine/instantiator/CONTRIBUTING.md | 2 +- vendor/doctrine/instantiator/README.md | 6 +- vendor/doctrine/instantiator/composer.json | 21 +- .../doctrine/instantiator/docs/en/index.rst | 68 + .../doctrine/instantiator/docs/en/sidebar.rst | 4 + vendor/doctrine/instantiator/psalm.xml | 16 + .../Exception/ExceptionInterface.php | 23 +- .../Exception/InvalidArgumentException.php | 48 +- .../Exception/UnexpectedValueException.php | 35 +- .../Doctrine/Instantiator/Instantiator.php | 156 +- .../Instantiator/InstantiatorInterface.php | 27 +- vendor/doctrine/lexer/LICENSE | 19 + vendor/doctrine/lexer/README.md | 9 + vendor/doctrine/lexer/UPGRADE.md | 14 + vendor/doctrine/lexer/composer.json | 56 + vendor/doctrine/lexer/src/AbstractLexer.php | 346 + vendor/doctrine/lexer/src/Token.php | 145 + vendor/friendsofphp/php-cs-fixer/.php_cs | 34 - vendor/friendsofphp/php-cs-fixer/CHANGELOG.md | 3177 +++++++- .../friendsofphp/php-cs-fixer/CONTRIBUTING.md | 125 +- .../php-cs-fixer/COOKBOOK-FIXERS.md | 489 -- vendor/friendsofphp/php-cs-fixer/LICENSE | 3 +- vendor/friendsofphp/php-cs-fixer/README.md | 75 + vendor/friendsofphp/php-cs-fixer/README.rst | 753 -- .../CS/AbstractAnnotationRemovalFixer.php | 61 - .../php-cs-fixer/Symfony/CS/AbstractFixer.php | 68 - .../CS/AbstractLinesBeforeNamespaceFixer.php | 51 - .../php-cs-fixer/Symfony/CS/Config.php | 188 - .../php-cs-fixer/Symfony/CS/Config/Config.php | 38 - .../Symfony/CS/Config/MagentoConfig.php | 49 - .../Symfony/CS/Config/Symfony23Config.php | 49 - .../Symfony/CS/ConfigInterface.php | 86 - .../InvalidConfigurationException.php | 34 - .../InvalidFixerConfigurationException.php | 34 - .../Symfony/CS/ConfigurationResolver.php | 239 - .../Symfony/CS/Console/Application.php | 81 - .../Symfony/CS/Console/Command/FixCommand.php | 649 -- .../CS/Console/Command/ReadmeCommand.php | 268 - .../CS/Console/Command/SelfUpdateCommand.php | 236 - .../Symfony/CS/DocBlock/Annotation.php | 212 - .../Symfony/CS/DocBlock/DocBlock.php | 189 - .../php-cs-fixer/Symfony/CS/DocBlock/Tag.php | 80 - .../php-cs-fixer/Symfony/CS/ErrorsManager.php | 67 - .../Symfony/CS/FileCacheManager.php | 159 - .../Symfony/CS/Finder/DefaultFinder.php | 88 - .../Symfony/CS/Finder/MagentoFinder.php | 83 - .../Symfony/CS/Finder/Symfony23Finder.php | 52 - .../php-cs-fixer/Symfony/CS/Fixer.php | 425 -- .../CS/Fixer/Contrib/AlignEqualsFixer.php | 95 - .../Fixer/Contrib/ClassKeywordRemoveFixer.php | 202 - .../Fixer/Contrib/ConcatWithSpacesFixer.php | 85 - .../CS/Fixer/Contrib/EchoToPrintFixer.php | 91 - .../CS/Fixer/Contrib/EmptyReturnFixer.php | 120 - .../CS/Fixer/Contrib/HeaderCommentFixer.php | 156 - .../LogicalNotOperatorsWithSpacesFixer.php | 64 - ...calNotOperatorsWithSuccessorSpaceFixer.php | 62 - .../CS/Fixer/Contrib/LongArraySyntaxFixer.php | 54 - .../CS/Fixer/Contrib/MbStrFunctionsFixer.php | 97 - .../MultilineSpacesBeforeSemicolonFixer.php | 52 - .../Contrib/NewlineAfterOpenTagFixer.php | 61 - .../NoBlankLinesBeforeNamespaceFixer.php | 46 - .../CS/Fixer/Contrib/NoUselessElseFixer.php | 225 - .../CS/Fixer/Contrib/OrderedUseFixer.php | 247 - .../Fixer/Contrib/PhpUnitConstructFixer.php | 180 - .../Contrib/PhpUnitDedicateAssertFixer.php | 264 - .../CS/Fixer/Contrib/PhpUnitStrictFixer.php | 79 - .../CS/Fixer/Contrib/PhpdocVarToTypeFixer.php | 57 - .../Fixer/Contrib/ShortArraySyntaxFixer.php | 60 - .../CS/Fixer/Contrib/ShortEchoTagFixer.php | 71 - .../Contrib/SilencedDeprecationErrorFixer.php | 63 - .../Symfony/CS/Fixer/Contrib/StrictFixer.php | 59 - .../CS/Fixer/Contrib/StrictParamFixer.php | 124 - .../Symfony/CS/Fixer/PSR0/Psr0Fixer.php | 182 - .../Symfony/CS/Fixer/PSR1/EncodingFixer.php | 59 - .../Symfony/CS/Fixer/PSR1/ShortTagFixer.php | 106 - .../Symfony/CS/Fixer/PSR2/BracesFixer.php | 646 -- .../CS/Fixer/PSR2/ClassDefinitionFixer.php | 338 - .../Symfony/CS/Fixer/PSR2/ElseifFixer.php | 70 - .../Symfony/CS/Fixer/PSR2/EofEndingFixer.php | 85 - .../Fixer/PSR2/FunctionDeclarationFixer.php | 117 - .../CS/Fixer/PSR2/IndentationFixer.php | 68 - .../CS/Fixer/PSR2/LineAfterNamespaceFixer.php | 77 - .../Symfony/CS/Fixer/PSR2/LinefeedFixer.php | 66 - .../CS/Fixer/PSR2/LowercaseConstantsFixer.php | 92 - .../CS/Fixer/PSR2/LowercaseKeywordsFixer.php | 50 - .../Fixer/PSR2/MethodArgumentSpaceFixer.php | 86 - .../CS/Fixer/PSR2/MultipleUseFixer.php | 208 - .../NoTrailingWhitespaceInCommentFixer.php | 48 - .../CS/Fixer/PSR2/ParenthesisFixer.php | 93 - .../CS/Fixer/PSR2/PhpClosingTagFixer.php | 65 - .../PSR2/SingleLineAfterImportsFixer.php | 110 - .../PSR2/SwitchCaseSemicolonToColonFixer.php | 68 - .../CS/Fixer/PSR2/SwitchCaseSpaceFixer.php | 69 - .../CS/Fixer/PSR2/TrailingSpacesFixer.php | 77 - .../Symfony/CS/Fixer/PSR2/VisibilityFixer.php | 198 - .../ArrayElementNoSpaceBeforeCommaFixer.php | 99 - .../ArrayElementWhiteSpaceAfterCommaFixer.php | 98 - .../Symfony/BlanklineAfterOpenTagFixer.php | 79 - .../Symfony/ConcatWithoutSpacesFixer.php | 55 - .../Symfony/DeclareEqualNormalizeFixer.php | 52 - .../DoubleArrowMultilineWhitespacesFixer.php | 67 - .../Fixer/Symfony/DuplicateSemicolonFixer.php | 66 - .../CS/Fixer/Symfony/ExtraEmptyLinesFixer.php | 76 - .../Symfony/FunctionTypehintSpaceFixer.php | 80 - .../Fixer/Symfony/HashToSlashCommentFixer.php | 47 - .../CS/Fixer/Symfony/HeredocToNowdocFixer.php | 79 - .../Symfony/CS/Fixer/Symfony/IncludeFixer.php | 120 - .../CS/Fixer/Symfony/JoinFunctionFixer.php | 58 - .../CS/Fixer/Symfony/LowercaseCastFixer.php | 48 - .../MethodArgumentDefaultValueFixer.php | 177 - .../MultilineArrayTrailingCommaFixer.php | 78 - .../NamespaceNoLeadingWhitespaceFixer.php | 82 - .../NoBlankLinesAfterClassOpeningFixer.php | 71 - .../CS/Fixer/Symfony/NoEmptyCommentFixer.php | 128 - .../Symfony/NoEmptyLinesAfterPhpdocsFixer.php | 87 - .../CS/Fixer/Symfony/NoEmptyPhpdocFixer.php | 60 - .../Fixer/Symfony/NoEmptyStatementFixer.php | 161 - .../CS/Fixer/Symfony/ObjectOperatorFixer.php | 54 - .../CS/Fixer/Symfony/OperatorsSpacesFixer.php | 107 - .../Symfony/PhpUnitFqcnAnnotationFixer.php | 58 - .../PhpdocAnnotationWithoutDotFixer.php | 67 - .../CS/Fixer/Symfony/PhpdocIndentFixer.php | 112 - .../CS/Fixer/Symfony/PhpdocInlineTagFixer.php | 76 - .../CS/Fixer/Symfony/PhpdocNoAccessFixer.php | 42 - .../Symfony/PhpdocNoEmptyReturnFixer.php | 79 - .../CS/Fixer/Symfony/PhpdocNoPackageFixer.php | 42 - .../CS/Fixer/Symfony/PhpdocParamsFixer.php | 206 - .../CS/Fixer/Symfony/PhpdocScalarFixer.php | 67 - .../Symfony/PhpdocShortDescriptionFixer.php | 105 - .../PhpdocSingleLineVarSpacingFixer.php | 95 - .../CS/Fixer/Symfony/PhpdocToCommentFixer.php | 201 - .../CS/Fixer/Symfony/PhpdocTrimFixer.php | 117 - .../CS/Fixer/Symfony/PhpdocTypeToVarFixer.php | 70 - .../CS/Fixer/Symfony/PhpdocTypesFixer.php | 85 - .../Symfony/PhpdocVarWithoutNameFixer.php | 73 - .../CS/Fixer/Symfony/PreIncrementFixer.php | 106 - .../CS/Fixer/Symfony/PrintToEchoFixer.php | 51 - .../Symfony/RemoveLeadingSlashUseFixer.php | 71 - .../Symfony/RemoveLinesBetweenUsesFixer.php | 95 - .../Symfony/CS/Fixer/Symfony/ReturnFixer.php | 82 - .../CS/Fixer/Symfony/SelfAccessorFixer.php | 102 - .../CS/Fixer/Symfony/ShortBoolCastFixer.php | 79 - .../CS/Fixer/Symfony/ShortScalarCastFixer.php | 61 - .../SingleBlankLineBeforeNamespaceFixer.php | 46 - .../CS/Fixer/Symfony/SingleQuoteFixer.php | 58 - .../Symfony/SpacesAfterSemicolonFixer.php | 61 - .../Symfony/SpacesBeforeSemicolonFixer.php | 55 - .../CS/Fixer/Symfony/SpacesCastFixer.php | 74 - .../Symfony/StandardizeNotEqualFixer.php | 46 - .../CS/Fixer/Symfony/TernarySpacesFixer.php | 106 - .../Fixer/Symfony/UnalignDoubleArrowFixer.php | 62 - .../CS/Fixer/Symfony/UnalignEqualsFixer.php | 62 - .../Symfony/UnaryOperatorsSpacesFixer.php | 51 - .../UnneededControlParenthesesFixer.php | 138 - .../CS/Fixer/Symfony/UnusedUseFixer.php | 258 - .../CS/Fixer/Symfony/WhitespacyLinesFixer.php | 81 - .../Symfony/CS/FixerFileProcessedEvent.php | 112 - .../php-cs-fixer/Symfony/CS/LintManager.php | 90 - .../Symfony/CS/Resources/phar-stub.php | 38 - .../CS/Test/IntegrationCaseFactory.php | 245 - .../Symfony/CS/Tokenizer/Token.php | 509 -- .../Symfony/CS/Tokenizer/Tokens.php | 1448 ---- .../Tokenizer/Transformer/ArrayTypehint.php | 47 - .../Tokenizer/Transformer/ClassConstant.php | 54 - .../CS/Tokenizer/Transformer/CurlyClose.php | 60 - .../Transformer/DollarCloseCurlyBraces.php | 52 - .../Transformer/DynamicPropBrace.php | 59 - .../Tokenizer/Transformer/DynamicVarBrace.php | 71 - .../Symfony/CS/Tokenizer/Transformers.php | 175 - .../php-cs-fixer/Symfony/CS/ToolInfo.php | 106 - .../Symfony/CS/UniqueFileIterator.php | 41 - .../php-cs-fixer/Symfony/CS/Utils.php | 118 - vendor/friendsofphp/php-cs-fixer/UPGRADE.md | 185 + vendor/friendsofphp/php-cs-fixer/benchmark.sh | 26 - vendor/friendsofphp/php-cs-fixer/box.json | 21 - .../php-cs-fixer/ci-integration.sh | 8 + .../friendsofphp/php-cs-fixer/composer.json | 81 +- .../friendsofphp/php-cs-fixer/doc/config.rst | 73 + .../php-cs-fixer/doc/cookbook_fixers.rst | 563 ++ .../php-cs-fixer/doc/custom_rules.rst | 38 + .../php-cs-fixer/doc/installation.rst | 126 + .../doc/ruleSets/DoctrineAnnotation.rst | 17 + .../doc/ruleSets/PHP54Migration.rst | 12 + .../doc/ruleSets/PHP56Migration.rst | 10 + .../doc/ruleSets/PHP56MigrationRisky.rst | 10 + .../doc/ruleSets/PHP70Migration.rst | 11 + .../doc/ruleSets/PHP70MigrationRisky.rst | 18 + .../doc/ruleSets/PHP71Migration.rst | 16 + .../doc/ruleSets/PHP71MigrationRisky.rst | 11 + .../doc/ruleSets/PHP73Migration.rst | 20 + .../doc/ruleSets/PHP74Migration.rst | 12 + .../doc/ruleSets/PHP74MigrationRisky.rst | 13 + .../doc/ruleSets/PHP80Migration.rst | 12 + .../doc/ruleSets/PHP80MigrationRisky.rst | 16 + .../doc/ruleSets/PHPUnit30MigrationRisky.rst | 12 + .../doc/ruleSets/PHPUnit32MigrationRisky.rst | 13 + .../doc/ruleSets/PHPUnit35MigrationRisky.rst | 13 + .../doc/ruleSets/PHPUnit43MigrationRisky.rst | 13 + .../doc/ruleSets/PHPUnit48MigrationRisky.rst | 13 + .../doc/ruleSets/PHPUnit50MigrationRisky.rst | 11 + .../doc/ruleSets/PHPUnit52MigrationRisky.rst | 13 + .../doc/ruleSets/PHPUnit54MigrationRisky.rst | 13 + .../doc/ruleSets/PHPUnit55MigrationRisky.rst | 13 + .../doc/ruleSets/PHPUnit56MigrationRisky.rst | 16 + .../doc/ruleSets/PHPUnit57MigrationRisky.rst | 13 + .../doc/ruleSets/PHPUnit60MigrationRisky.rst | 13 + .../doc/ruleSets/PHPUnit75MigrationRisky.rst | 13 + .../doc/ruleSets/PHPUnit84MigrationRisky.rst | 14 + .../php-cs-fixer/doc/ruleSets/PSR1.rst | 11 + .../php-cs-fixer/doc/ruleSets/PSR12.rst | 36 + .../php-cs-fixer/doc/ruleSets/PSR12Risky.rst | 11 + .../php-cs-fixer/doc/ruleSets/PSR2.rst | 37 + .../php-cs-fixer/doc/ruleSets/PhpCsFixer.rst | 52 + .../doc/ruleSets/PhpCsFixerRisky.rst | 24 + .../php-cs-fixer/doc/ruleSets/Symfony.rst | 127 + .../doc/ruleSets/SymfonyRisky.rst | 50 + .../php-cs-fixer/doc/ruleSets/index.rst | 38 + .../doc/rules/alias/array_push.rst | 34 + .../rules/alias/backtick_to_shell_exec.rst | 38 + .../doc/rules/alias/ereg_to_preg.rst | 33 + .../doc/rules/alias/mb_str_functions.rst | 45 + .../doc/rules/alias/no_alias_functions.rst | 113 + .../no_alias_language_construct_call.rst | 30 + .../doc/rules/alias/no_mixed_echo_print.rst | 55 + .../doc/rules/alias/pow_to_exponentiation.rst | 49 + .../doc/rules/alias/random_api_migration.rst | 95 + .../doc/rules/alias/set_type_to_cast.rst | 39 + .../doc/rules/array_notation/array_syntax.rst | 96 + ...ltiline_whitespace_around_double_arrow.rst | 32 + .../no_trailing_comma_in_singleline_array.rst | 30 + .../no_whitespace_before_comma_in_array.rst | 75 + .../array_notation/normalize_index_brace.rst | 36 + .../trailing_comma_in_multiline_array.rst | 58 + .../array_notation/trim_array_spaces.rst | 33 + .../whitespace_after_comma_in_array.rst | 30 + .../php-cs-fixer/doc/rules/basic/braces.rst | 198 + .../php-cs-fixer/doc/rules/basic/encoding.rst | 40 + .../rules/basic/non_printable_character.rst | 84 + .../php-cs-fixer/doc/rules/basic/psr0.rst | 59 + .../php-cs-fixer/doc/rules/basic/psr4.rst | 29 + .../doc/rules/basic/psr_autoloading.rst | 66 + .../doc/rules/casing/constant_case.rst | 71 + .../doc/rules/casing/lowercase_constants.rst | 27 + .../doc/rules/casing/lowercase_keywords.rst | 51 + .../casing/lowercase_static_reference.rst | 69 + .../rules/casing/magic_constant_casing.rst | 30 + .../doc/rules/casing/magic_method_casing.rst | 46 + .../rules/casing/native_function_casing.rst | 30 + ...ative_function_type_declaration_casing.rst | 77 + .../doc/rules/cast_notation/cast_spaces.rst | 76 + .../rules/cast_notation/lowercase_cast.rst | 90 + .../cast_notation/modernize_types_casting.rst | 44 + .../cast_notation/no_short_bool_cast.rst | 30 + .../doc/rules/cast_notation/no_unset_cast.rst | 33 + .../rules/cast_notation/short_scalar_cast.rst | 68 + .../class_attributes_separation.rst | 96 + .../rules/class_notation/class_definition.rst | 158 + .../doc/rules/class_notation/final_class.rst | 36 + .../class_notation/final_internal_class.rst | 98 + ...final_public_method_for_abstract_class.rst | 34 + .../class_notation/final_static_access.rst | 29 + .../class_notation/method_separation.rst | 31 + .../no_blank_lines_after_class_opening.rst | 38 + .../no_null_property_initialization.rst | 43 + .../class_notation/no_php4_constructor.rst | 43 + .../no_unneeded_final_method.rst | 86 + .../class_notation/ordered_class_elements.rst | 135 + .../class_notation/ordered_interfaces.rst | 103 + .../rules/class_notation/ordered_traits.rst | 34 + .../class_notation/protected_to_private.rst | 38 + .../rules/class_notation/self_accessor.rst | 46 + .../class_notation/self_static_accessor.rst | 83 + .../single_class_element_per_statement.rst | 79 + .../single_trait_insert_per_statement.rst | 36 + .../class_notation/visibility_required.rst | 100 + .../rules/class_usage/date_time_immutable.rst | 24 + .../doc/rules/comment/comment_to_phpdoc.rst | 62 + .../rules/comment/hash_to_slash_comment.rst | 22 + .../doc/rules/comment/header_comment.rst | 129 + .../multiline_comment_opening_closing.rst | 43 + .../doc/rules/comment/no_empty_comment.rst | 34 + .../no_trailing_whitespace_in_comment.rst | 38 + .../comment/single_line_comment_style.rst | 96 + .../native_constant_invocation.rst | 143 + .../doc/rules/control_structure/elseif.rst | 39 + .../doc/rules/control_structure/include.rst | 37 + .../no_alternative_syntax.rst | 63 + .../control_structure/no_break_comment.rst | 84 + .../no_superfluous_elseif.rst | 32 + .../no_trailing_comma_in_list_call.rst | 30 + .../no_unneeded_control_parentheses.rst | 83 + .../no_unneeded_curly_braces.rst | 75 + .../control_structure/no_useless_else.rst | 32 + .../simplified_if_return.rst | 20 + .../switch_case_semicolon_to_colon.rst | 42 + .../control_structure/switch_case_space.rst | 42 + .../switch_continue_to_break.rst | 58 + .../trailing_comma_in_multiline.rst | 125 + .../rules/control_structure/yoda_style.rst | 121 + .../doctrine_annotation_array_assignment.rst | 71 + .../doctrine_annotation_braces.rst | 69 + .../doctrine_annotation_indentation.rst | 75 + .../doctrine_annotation_spaces.rst | 178 + .../combine_nested_dirname.rst | 47 + .../function_notation/fopen_flag_order.rst | 34 + .../rules/function_notation/fopen_flags.rst | 66 + .../function_declaration.rst | 89 + .../function_typehint_space.rst | 43 + .../rules/function_notation/implode_call.rst | 51 + .../lambda_not_used_import.rst | 30 + .../method_argument_space.rst | 254 + .../native_function_invocation.rst | 205 + .../no_spaces_after_function_name.rst | 43 + .../no_unreachable_default_argument_value.rst | 40 + .../function_notation/no_useless_sprintf.rst | 34 + ...ype_declaration_for_default_null_value.rst | 55 + .../phpdoc_to_param_type.rst | 78 + .../phpdoc_to_property_type.rst | 67 + .../phpdoc_to_return_type.rst | 114 + .../regular_callable_call.rst | 46 + .../return_type_declaration.rst | 79 + .../function_notation/single_line_throw.rst | 30 + .../rules/function_notation/static_lambda.rst | 25 + .../function_notation/use_arrow_functions.rst | 37 + .../rules/function_notation/void_return.rst | 38 + .../import/fully_qualified_strict_types.rst | 59 + .../rules/import/global_namespace_import.rst | 108 + .../doc/rules/import/group_import.rst | 20 + .../rules/import/no_leading_import_slash.rst | 34 + .../doc/rules/import/no_unused_imports.rst | 32 + .../doc/rules/import/ordered_imports.rst | 166 + .../import/single_import_per_statement.rst | 38 + .../import/single_line_after_imports.rst | 61 + .../php-cs-fixer/doc/rules/index.rst | 595 ++ .../class_keyword_remove.rst | 22 + .../combine_consecutive_issets.rst | 27 + .../combine_consecutive_unsets.rst | 27 + .../declare_equal_normalize.rst | 61 + .../rules/language_construct/dir_constant.rst | 34 + .../language_construct/error_suppression.rst | 97 + .../explicit_indirect_variable.rst | 34 + .../function_to_constant.rst | 90 + .../doc/rules/language_construct/is_null.rst | 50 + .../no_unset_on_property.rst | 35 + .../silenced_deprecation_error.rst | 27 + .../single_space_after_construct.rst | 73 + .../doc/rules/list_notation/list_syntax.rst | 72 + .../blank_line_after_namespace.rst | 50 + .../namespace_notation/clean_namespace.rst | 44 + .../no_blank_lines_before_namespace.rst | 21 + .../no_leading_namespace_whitespace.rst | 32 + .../single_blank_line_before_namespace.rst | 46 + .../doc/rules/naming/no_homoglyph_names.rst | 34 + .../rules/operator/binary_operator_spaces.rst | 210 + .../doc/rules/operator/concat_space.rst | 70 + .../doc/rules/operator/increment_style.rst | 61 + .../doc/rules/operator/logical_operators.rst | 37 + .../doc/rules/operator/new_with_braces.rst | 32 + .../operator/not_operator_with_space.rst | 22 + .../not_operator_with_successor_space.rst | 22 + .../object_operator_without_whitespace.rst | 29 + .../doc/rules/operator/operator_linebreak.rst | 74 + .../doc/rules/operator/pre_increment.rst | 25 + .../rules/operator/standardize_increment.rst | 41 + .../rules/operator/standardize_not_equals.rst | 30 + .../operator/ternary_operator_spaces.rst | 32 + .../operator/ternary_to_elvis_operator.rst | 44 + .../operator/ternary_to_null_coalescing.rst | 39 + .../rules/operator/unary_operator_spaces.rst | 38 + .../php_tag/blank_line_after_opening_tag.rst | 36 + .../doc/rules/php_tag/echo_tag_syntax.rst | 128 + .../doc/rules/php_tag/full_opening_tag.rst | 41 + .../php_tag/linebreak_after_opening_tag.rst | 31 + .../doc/rules/php_tag/no_closing_tag.rst | 40 + .../doc/rules/php_tag/no_short_echo_tag.rst | 22 + .../doc/rules/php_unit/php_unit_construct.rst | 80 + .../php_unit/php_unit_dedicate_assert.rst | 147 + ...php_unit_dedicate_assert_internal_type.rst | 83 + .../rules/php_unit/php_unit_expectation.rst | 190 + .../php_unit/php_unit_fqcn_annotation.rst | 44 + .../php_unit/php_unit_internal_class.rst | 60 + .../rules/php_unit/php_unit_method_casing.rst | 63 + .../doc/rules/php_unit/php_unit_mock.rst | 110 + .../php_unit_mock_short_will_return.rst | 51 + .../rules/php_unit/php_unit_namespaced.rst | 133 + .../php_unit_no_expectation_annotation.rst | 163 + .../php_unit/php_unit_ordered_covers.rst | 28 + .../php_unit_set_up_tear_down_visibility.rst | 49 + .../rules/php_unit/php_unit_size_class.rst | 57 + .../doc/rules/php_unit/php_unit_strict.rst | 80 + .../php_unit/php_unit_test_annotation.rst | 84 + ...php_unit_test_case_static_method_calls.rst | 88 + .../php_unit_test_class_requires_covers.rst | 37 + .../rules/phpdoc/align_multiline_comment.rst | 85 + .../general_phpdoc_annotation_remove.rst | 54 + .../phpdoc/general_phpdoc_tag_rename.rst | 127 + .../phpdoc/no_blank_lines_after_phpdoc.rst | 35 + .../doc/rules/phpdoc/no_empty_phpdoc.rst | 29 + .../phpdoc/no_superfluous_phpdoc_tags.rst | 149 + .../phpdoc_add_missing_param_annotation.rst | 83 + .../doc/rules/phpdoc/phpdoc_align.rst | 114 + .../phpdoc/phpdoc_annotation_without_dot.rst | 33 + .../doc/rules/phpdoc/phpdoc_indent.rst | 38 + .../doc/rules/phpdoc/phpdoc_inline_tag.rst | 32 + .../phpdoc/phpdoc_inline_tag_normalizer.rst | 66 + .../doc/rules/phpdoc/phpdoc_line_span.rst | 77 + .../doc/rules/phpdoc/phpdoc_no_access.rst | 36 + .../doc/rules/phpdoc/phpdoc_no_alias_tag.rst | 74 + .../rules/phpdoc/phpdoc_no_empty_return.rst | 42 + .../doc/rules/phpdoc/phpdoc_no_package.rst | 36 + .../phpdoc/phpdoc_no_useless_inheritdoc.rst | 52 + .../doc/rules/phpdoc/phpdoc_order.rst | 37 + .../rules/phpdoc/phpdoc_order_by_value.rst | 64 + .../phpdoc/phpdoc_return_self_reference.rst | 93 + .../doc/rules/phpdoc/phpdoc_scalar.rst | 79 + .../doc/rules/phpdoc/phpdoc_separation.rst | 43 + .../phpdoc/phpdoc_single_line_var_spacing.rst | 30 + .../doc/rules/phpdoc/phpdoc_summary.rst | 34 + .../doc/rules/phpdoc/phpdoc_tag_casing.rst | 51 + .../doc/rules/phpdoc/phpdoc_tag_type.rst | 65 + .../doc/rules/phpdoc/phpdoc_to_comment.rst | 35 + .../doc/rules/phpdoc/phpdoc_trim.rst | 36 + ...trim_consecutive_blank_line_separation.rst | 44 + .../doc/rules/phpdoc/phpdoc_types.rst | 66 + .../doc/rules/phpdoc/phpdoc_types_order.rst | 117 + .../phpdoc_var_annotation_correct_order.rst | 28 + .../rules/phpdoc/phpdoc_var_without_name.rst | 43 + .../blank_line_before_return.rst | 27 + .../return_notation/no_useless_return.rst | 32 + .../return_notation/return_assignment.rst | 31 + .../simplified_null_return.rst | 33 + ...multiline_whitespace_before_semicolons.rst | 65 + .../rules/semicolon/no_empty_statement.rst | 51 + ...multiline_whitespace_before_semicolons.rst | 26 + ...ingleline_whitespace_before_semicolons.rst | 29 + .../semicolon/semicolon_after_instruction.rst | 29 + .../rules/semicolon/space_after_semicolon.rst | 67 + .../doc/rules/strict/declare_strict_types.rst | 40 + .../doc/rules/strict/strict_comparison.rst | 31 + .../doc/rules/strict/strict_param.rst | 45 + .../escape_implicit_backslashes.rst | 145 + .../explicit_string_variable.rst | 47 + .../string_notation/heredoc_to_nowdoc.rst | 28 + .../string_notation/no_binary_string.rst | 41 + .../no_trailing_whitespace_in_string.rst | 40 + .../simple_to_complex_string_variable.rst | 49 + .../rules/string_notation/single_quote.rst | 62 + .../string_notation/string_line_ending.rst | 38 + .../rules/whitespace/array_indentation.rst | 33 + .../blank_line_before_statement.rst | 243 + .../whitespace/compact_nullable_typehint.rst | 39 + .../rules/whitespace/heredoc_indentation.rst | 89 + .../doc/rules/whitespace/indentation_type.rst | 39 + .../doc/rules/whitespace/line_ending.rst | 41 + .../method_chaining_indentation.rst | 29 + .../rules/whitespace/no_extra_blank_lines.rst | 248 + .../no_extra_consecutive_blank_lines.rst | 237 + .../whitespace/no_spaces_around_offset.rst | 70 + .../no_spaces_inside_parenthesis.rst | 53 + .../whitespace/no_trailing_whitespace.rst | 36 + .../no_whitespace_in_blank_line.rst | 34 + .../whitespace/single_blank_line_at_eof.rst | 48 + .../doc/schemas/fix/checkstyle.xsd | 44 + .../php-cs-fixer/doc/schemas/fix/junit-10.xsd | 135 + .../php-cs-fixer/doc/schemas/fix/schema.json | 47 + .../php-cs-fixer/doc/schemas/fix/xml.xsd | 83 + .../doc/schemas/list-sets/schema.json | 31 + .../friendsofphp/php-cs-fixer/doc/usage.rst | 244 + vendor/friendsofphp/php-cs-fixer/logo.md | 3 + vendor/friendsofphp/php-cs-fixer/logo.png | Bin 0 -> 18627 bytes vendor/friendsofphp/php-cs-fixer/php-cs-fixer | 107 +- .../AbstractAlignFixerHelper.php} | 58 +- .../src/AbstractDoctrineAnnotationFixer.php | 228 + .../php-cs-fixer/src/AbstractFixer.php | 217 + .../src/AbstractFopenFlagFixer.php | 127 + .../src/AbstractFunctionReferenceFixer.php | 67 + .../src/AbstractLinesBeforeNamespaceFixer.php | 110 + .../src/AbstractNoUselessElseFixer.php | 218 + .../AbstractPhpdocToTypeDeclarationFixer.php | 240 + .../CS => src}/AbstractPhpdocTypesFixer.php | 51 +- .../php-cs-fixer/src/AbstractProxyFixer.php | 122 + .../php-cs-fixer/src/Cache/Cache.php | 138 + .../php-cs-fixer/src/Cache/CacheInterface.php | 56 + .../src/Cache/CacheManagerInterface.php | 35 + .../php-cs-fixer/src/Cache/Directory.php | 56 + .../Cache/DirectoryInterface.php} | 12 +- .../src/Cache/FileCacheManager.php | 144 + .../php-cs-fixer/src/Cache/FileHandler.php | 110 + .../src/Cache/FileHandlerInterface.php | 33 + .../src/Cache/NullCacheManager.php | 30 + .../php-cs-fixer/src/Cache/Signature.php | 110 + .../src/Cache/SignatureInterface.php | 53 + .../friendsofphp/php-cs-fixer/src/Config.php | 331 + .../php-cs-fixer/src/ConfigInterface.php | 196 + .../InvalidConfigurationException.php | 40 + .../InvalidFixerConfigurationException.php | 54 + ...validForEnvFixerConfigurationException.php | 22 + .../RequiredFixerConfigurationException.php | 22 + .../php-cs-fixer/src/Console/Application.php | 148 + .../src/Console/Command/DescribeCommand.php | 468 ++ .../Command/DescribeNameNotFoundException.php | 59 + .../Console/Command/DocumentationCommand.php | 124 + .../src/Console/Command/FixCommand.php | 279 + .../FixCommandExitStatusCalculator.php | 58 + .../src/Console/Command/HelpCommand.php | 675 ++ .../src/Console/Command/ListFilesCommand.php | 99 + .../src/Console/Command/ListSetsCommand.php | 92 + .../src/Console/Command/SelfUpdateCommand.php | 187 + .../src/Console/ConfigurationResolver.php | 991 +++ .../src/Console/Output/ErrorOutput.php | 154 + .../src/Console/Output/NullOutput.php | 23 + .../src/Console/Output/ProcessOutput.php | 167 + .../Output/ProcessOutputInterface.php} | 8 +- .../Report/FixReport/CheckstyleReporter.php | 74 + .../Report/FixReport/GitlabReporter.php | 60 + .../Console/Report/FixReport/JsonReporter.php | 71 + .../Report/FixReport/JunitReporter.php | 141 + .../Report/FixReport/ReportSummary.php | 122 + .../Report/FixReport/ReporterFactory.php | 95 + .../Report/FixReport/ReporterInterface.php | 33 + .../Console/Report/FixReport/TextReporter.php | 108 + .../Console/Report/FixReport/XmlReporter.php | 140 + .../Report/ListSetsReport/JsonReporter.php | 54 + .../Report/ListSetsReport/ReportSummary.php | 45 + .../Report/ListSetsReport/ReporterFactory.php | 95 + .../ListSetsReport/ReporterInterface.php | 33 + .../Report/ListSetsReport/TextReporter.php | 56 + .../src/Console/SelfUpdate/GithubClient.php | 52 + .../SelfUpdate/GithubClientInterface.php | 24 + .../Console/SelfUpdate/NewVersionChecker.php | 114 + .../SelfUpdate/NewVersionCheckerInterface.php | 46 + .../CS => src}/Console/WarningsDetector.php | 43 +- .../src/Differ/DiffConsoleFormatter.php | 102 + .../src/Differ/DifferInterface.php | 31 + .../php-cs-fixer/src/Differ/FullDiffer.php | 48 + .../php-cs-fixer/src/Differ/NullDiffer.php | 27 + .../src/Differ/SebastianBergmannDiffer.php | 39 + .../Differ/SebastianBergmannShortDiffer.php | 39 + .../php-cs-fixer/src/Differ/UnifiedDiffer.php | 43 + .../php-cs-fixer/src/DocBlock/Annotation.php | 320 + .../php-cs-fixer/src/DocBlock/DocBlock.php | 288 + .../{Symfony/CS => src}/DocBlock/Line.php | 20 +- .../src/DocBlock/ShortDescription.php | 65 + .../php-cs-fixer/src/DocBlock/Tag.php | 113 + .../CS => src}/DocBlock/TagComparator.php | 21 +- .../src/DocBlock/TypeExpression.php | 293 + .../src/Doctrine/Annotation/Token.php | 99 + .../src/Doctrine/Annotation/Tokens.php | 378 + .../Documentation/DocumentationGenerator.php | 556 ++ .../php-cs-fixer/src/Error/Error.php | 118 + .../php-cs-fixer/src/Error/ErrorsManager.php | 79 + .../php-cs-fixer/src/Event/Event.php | 31 + .../php-cs-fixer/src/FileReader.php | 84 + .../{Symfony/CS => src}/FileRemoval.php | 37 +- .../{Symfony/CS => src}/Finder.php | 6 +- .../Fixer/AbstractIncrementOperatorFixer.php | 61 + .../src/Fixer/AbstractPhpUnitFixer.php | 70 + .../src/Fixer/Alias/ArrayPushFixer.php | 227 + .../Fixer/Alias/BacktickToShellExecFixer.php | 145 + .../Fixer/Alias}/EregToPregFixer.php | 127 +- .../src/Fixer/Alias/MbStrFunctionsFixer.php | 130 + .../src/Fixer/Alias/NoAliasFunctionsFixer.php | 258 + .../NoAliasLanguageConstructCallFixer.php | 68 + .../src/Fixer/Alias/NoMixedEchoPrintFixer.php | 162 + .../Fixer/Alias/PowToExponentiationFixer.php | 239 + .../Fixer/Alias/RandomApiMigrationFixer.php | 174 + .../src/Fixer/Alias/SetTypeToCastFixer.php | 250 + .../Fixer/ArrayNotation/ArraySyntaxFixer.php | 156 + ...tilineWhitespaceAroundDoubleArrowFixer.php | 86 + ...NoTrailingCommaInSinglelineArrayFixer.php} | 56 +- .../NoWhitespaceBeforeCommaInArrayFixer.php | 152 + .../NormalizeIndexBraceFixer.php | 59 + .../TrailingCommaInMultilineArrayFixer.php | 104 + .../ArrayNotation}/TrimArraySpacesFixer.php | 67 +- .../WhitespaceAfterCommaInArrayFixer.php | 102 + .../src/Fixer/Basic/BracesFixer.php | 1059 +++ .../src/Fixer/Basic/EncodingFixer.php | 97 + .../Basic/NonPrintableCharacterFixer.php | 180 + .../src/Fixer/Basic/Psr0Fixer.php | 96 + .../src/Fixer/Basic/Psr4Fixer.php | 70 + .../src/Fixer/Basic/PsrAutoloadingFixer.php | 292 + .../src/Fixer/Casing/ConstantCaseFixer.php | 155 + .../Fixer/Casing/LowercaseConstantsFixer.php | 60 + .../Fixer/Casing/LowercaseKeywordsFixer.php | 75 + .../Casing/LowercaseStaticReferenceFixer.php | 105 + .../Fixer/Casing/MagicConstantCasingFixer.php | 98 + .../Fixer/Casing/MagicMethodCasingFixer.php | 228 + .../Casing}/NativeFunctionCasingFixer.php | 64 +- ...tiveFunctionTypeDeclarationCasingFixer.php | 186 + .../Fixer/CastNotation/CastSpacesFixer.php | 129 + .../Fixer/CastNotation/LowercaseCastFixer.php | 95 + .../ModernizeTypesCastingFixer.php | 159 + .../CastNotation/NoShortBoolCastFixer.php | 106 + .../Fixer/CastNotation/NoUnsetCastFixer.php | 100 + .../CastNotation/ShortScalarCastFixer.php | 86 + .../ClassAttributesSeparationFixer.php | 518 ++ .../ClassNotation/ClassDefinitionFixer.php | 446 ++ .../Fixer/ClassNotation/FinalClassFixer.php | 60 + .../ClassNotation/FinalInternalClassFixer.php | 229 + ...FinalPublicMethodForAbstractClassFixer.php | 168 + .../ClassNotation/FinalStaticAccessFixer.php | 75 + .../ClassNotation/MethodSeparationFixer.php | 84 + .../NoBlankLinesAfterClassOpeningFixer.php | 101 + .../NoNullPropertyInitializationFixer.php | 147 + .../ClassNotation/NoPhp4ConstructorFixer.php} | 319 +- .../NoUnneededFinalMethodFixer.php | 176 + .../OrderedClassElementsFixer.php | 527 ++ .../ClassNotation/OrderedInterfacesFixer.php | 231 + .../ClassNotation/OrderedTraitsFixer.php | 194 + .../ProtectedToPrivateFixer.php | 92 +- .../Fixer/ClassNotation/SelfAccessorFixer.php | 191 + .../ClassNotation/SelfStaticAccessorFixer.php | 206 + .../SingleClassElementPerStatementFixer.php | 242 + .../SingleTraitInsertPerStatementFixer.php | 119 + .../ClassNotation/VisibilityRequiredFixer.php | 201 + .../ClassUsage/DateTimeImmutableFixer.php | 167 + .../Fixer/Comment/CommentToPhpdocFixer.php | 240 + .../Fixer/Comment/HashToSlashCommentFixer.php | 58 + .../src/Fixer/Comment/HeaderCommentFixer.php | 493 ++ .../MultilineCommentOpeningClosingFixer.php | 95 + .../src/Fixer/Comment/NoEmptyCommentFixer.php | 173 + .../NoTrailingWhitespaceInCommentFixer.php | 85 + .../Comment/SingleLineCommentStyleFixer.php | 182 + .../src/Fixer/ConfigurableFixerInterface.php | 51 + .../ConfigurationDefinitionFixerInterface.php | 28 + .../NativeConstantInvocationFixer.php | 295 + .../Fixer/ControlStructure/ElseifFixer.php | 102 + .../Fixer/ControlStructure/IncludeFixer.php | 153 + .../NoAlternativeSyntaxFixer.php | 231 + .../ControlStructure/NoBreakCommentFixer.php | 368 + .../NoSuperfluousElseifFixer.php | 115 + .../NoTrailingCommaInListCallFixer.php} | 29 +- .../NoUnneededControlParenthesesFixer.php | 194 + .../NoUnneededCurlyBracesFixer.php | 177 + .../ControlStructure/NoUselessElseFixer.php | 129 + .../SimplifiedIfReturnFixer.php | 139 + .../SwitchCaseSemicolonToColonFixer.php | 132 + .../ControlStructure/SwitchCaseSpaceFixer.php | 92 + .../SwitchContinueToBreakFixer.php | 269 + .../TrailingCommaInMultilineFixer.php | 219 + .../Fixer/ControlStructure/YodaStyleFixer.php | 772 ++ .../src/Fixer/DefinedFixerInterface.php | 29 + .../src/Fixer/DeprecatedFixerInterface.php | 26 + ...DoctrineAnnotationArrayAssignmentFixer.php | 104 + .../DoctrineAnnotationBracesFixer.php | 123 + .../DoctrineAnnotationIndentationFixer.php | 199 + .../DoctrineAnnotationSpacesFixer.php | 349 + .../CS => src/Fixer}/FixerInterface.php | 45 +- .../CombineNestedDirnameFixer.php | 234 + .../FunctionNotation/FopenFlagOrderFixer.php | 130 + .../FunctionNotation/FopenFlagsFixer.php | 114 + .../FunctionDeclarationFixer.php | 231 + .../FunctionTypehintSpaceFixer.php | 83 + .../FunctionNotation/ImplodeCallFixer.php | 150 + .../LambdaNotUsedImportFixer.php | 365 + .../MethodArgumentSpaceFixer.php | 512 ++ .../NativeFunctionInvocationFixer.php | 422 ++ .../NoSpacesAfterFunctionNameFixer.php} | 126 +- ...NoUnreachableDefaultArgumentValueFixer.php | 218 + .../NoUselessSprintfFixer.php | 118 + ...ypeDeclarationForDefaultNullValueFixer.php | 170 + .../PhpdocToParamTypeFixer.php | 207 + .../PhpdocToPropertyTypeFixer.php | 244 + .../PhpdocToReturnTypeFixer.php | 218 + .../RegularCallableCallFixer.php | 238 + .../ReturnTypeDeclarationFixer.php | 133 + .../FunctionNotation/SingleLineThrowFixer.php | 183 + .../FunctionNotation/StaticLambdaFixer.php | 186 + .../UseArrowFunctionsFixer.php | 220 + .../FunctionNotation/VoidReturnFixer.php | 264 + .../Import/FullyQualifiedStrictTypesFixer.php | 178 + .../Import/GlobalNamespaceImportFixer.php | 751 ++ .../src/Fixer/Import/GroupImportFixer.php | 296 + .../Import/NoLeadingImportSlashFixer.php | 99 + .../src/Fixer/Import/NoUnusedImportsFixer.php | 278 + .../src/Fixer/Import/OrderedImportsFixer.php | 534 ++ .../Import/SingleImportPerStatementFixer.php | 237 + .../Import/SingleLineAfterImportsFixer.php | 158 + .../ClassKeywordRemoveFixer.php | 256 + .../CombineConsecutiveIssetsFixer.php | 172 + .../CombineConsecutiveUnsetsFixer.php | 100 +- .../DeclareEqualNormalizeFixer.php | 140 + .../LanguageConstruct/DirConstantFixer.php | 131 + .../ErrorSuppressionFixer.php | 175 + .../ExplicitIndirectVariableFixer.php | 91 + .../FunctionToConstantFixer.php | 318 + .../Fixer/LanguageConstruct/IsNullFixer.php | 203 + .../NoUnsetOnPropertyFixer.php | 232 + .../SilencedDeprecationErrorFixer.php | 55 + .../SingleSpaceAfterConstructFixer.php | 346 + .../Fixer/ListNotation/ListSyntaxFixer.php | 152 + .../BlankLineAfterNamespaceFixer.php | 144 + .../NamespaceNotation/CleanNamespaceFixer.php | 106 + .../NoBlankLinesBeforeNamespaceFixer.php | 73 + .../NoLeadingNamespaceWhitespaceFixer.php | 101 + .../SingleBlankLineBeforeNamespaceFixer.php | 68 + .../Fixer/Naming/NoHomoglyphNamesFixer.php | 244 + .../Operator/AlignDoubleArrowFixerHelper.php} | 94 +- .../Fixer/Operator/AlignEqualsFixerHelper.php | 76 + .../Operator/BinaryOperatorSpacesFixer.php | 870 +++ .../src/Fixer/Operator/ConcatSpaceFixer.php | 164 + .../Fixer/Operator/IncrementStyleFixer.php | 174 + .../Fixer/Operator/LogicalOperatorsFixer.php | 76 + .../Fixer/Operator}/NewWithBracesFixer.php | 115 +- .../Operator/NotOperatorWithSpaceFixer.php | 81 + .../NotOperatorWithSuccessorSpaceFixer.php | 79 + .../ObjectOperatorWithoutWhitespaceFixer.php | 68 + .../Fixer/Operator/OperatorLinebreakFixer.php | 329 + .../src/Fixer/Operator/PreIncrementFixer.php | 56 + .../Operator/StandardizeIncrementFixer.php | 133 + .../Operator/StandardizeNotEqualsFixer.php | 66 + .../Operator/TernaryOperatorSpacesFixer.php | 188 + .../Operator/TernaryToElvisOperatorFixer.php | 270 + .../Operator/TernaryToNullCoalescingFixer.php | 215 + .../Operator/UnaryOperatorSpacesFixer.php | 78 + .../PhpTag/BlankLineAfterOpeningTagFixer.php | 98 + .../src/Fixer/PhpTag/EchoTagSyntaxFixer.php | 275 + .../src/Fixer/PhpTag/FullOpeningTagFixer.php | 131 + .../PhpTag/LinebreakAfterOpeningTagFixer.php | 77 + .../src/Fixer/PhpTag/NoClosingTagFixer.php | 69 + .../src/Fixer/PhpTag/NoShortEchoTagFixer.php | 63 + .../Fixer/PhpUnit/PhpUnitConstructFixer.php | 218 + .../PhpUnit/PhpUnitDedicateAssertFixer.php | 451 ++ ...PhpUnitDedicateAssertInternalTypeFixer.php | 192 + .../Fixer/PhpUnit/PhpUnitExpectationFixer.php | 290 + .../PhpUnit/PhpUnitFqcnAnnotationFixer.php | 93 + .../PhpUnit/PhpUnitInternalClassFixer.php | 173 + .../PhpUnit/PhpUnitMethodCasingFixer.php | 233 + .../src/Fixer/PhpUnit/PhpUnitMockFixer.php | 138 + .../PhpUnitMockShortWillReturnFixer.php | 124 + .../Fixer/PhpUnit/PhpUnitNamespacedFixer.php | 230 + .../PhpUnitNoExpectationAnnotationFixer.php | 274 + .../PhpUnit/PhpUnitOrderedCoversFixer.php | 71 + .../PhpUnitSetUpTearDownVisibilityFixer.php | 119 + .../Fixer/PhpUnit/PhpUnitSizeClassFixer.php | 206 + .../src/Fixer/PhpUnit/PhpUnitStrictFixer.php | 146 + .../Fixer/PhpUnit/PhpUnitTargetVersion.php | 62 + .../PhpUnit/PhpUnitTestAnnotationFixer.php | 477 ++ .../PhpUnitTestCaseStaticMethodCallsFixer.php | 482 ++ .../PhpUnitTestClassRequiresCoversFixer.php | 132 + .../Phpdoc/AlignMultilineCommentFixer.php | 175 + .../GeneralPhpdocAnnotationRemoveFixer.php | 130 + .../Phpdoc/GeneralPhpdocTagRenameFixer.php | 209 + .../Phpdoc/NoBlankLinesAfterPhpdocFixer.php | 114 + .../src/Fixer/Phpdoc/NoEmptyPhpdocFixer.php | 71 + .../Phpdoc/NoSuperfluousPhpdocTagsFixer.php | 510 ++ .../PhpdocAddMissingParamAnnotationFixer.php | 278 + .../src/Fixer/Phpdoc/PhpdocAlignFixer.php | 434 ++ .../PhpdocAnnotationWithoutDotFixer.php | 135 + .../src/Fixer/Phpdoc/PhpdocIndentFixer.php | 139 + .../src/Fixer/Phpdoc/PhpdocInlineTagFixer.php | 93 + .../Phpdoc/PhpdocInlineTagNormalizerFixer.php | 120 + .../src/Fixer/Phpdoc/PhpdocLineSpanFixer.php | 154 + .../src/Fixer/Phpdoc/PhpdocNoAccessFixer.php | 70 + .../Fixer/Phpdoc/PhpdocNoAliasTagFixer.php | 132 + .../Fixer/Phpdoc/PhpdocNoEmptyReturnFixer.php | 123 + .../src/Fixer/Phpdoc/PhpdocNoPackageFixer.php | 70 + .../Phpdoc/PhpdocNoUselessInheritdocFixer.php | 190 + .../Fixer/Phpdoc/PhpdocOrderByValueFixer.php | 218 + .../Fixer/Phpdoc}/PhpdocOrderFixer.php | 88 +- .../Phpdoc/PhpdocReturnSelfReferenceFixer.php | 231 + .../src/Fixer/Phpdoc/PhpdocScalarFixer.php | 125 + .../Fixer/Phpdoc}/PhpdocSeparationFixer.php | 92 +- .../PhpdocSingleLineVarSpacingFixer.php | 102 + .../src/Fixer/Phpdoc/PhpdocSummaryFixer.php | 104 + .../src/Fixer/Phpdoc/PhpdocTagCasingFixer.php | 102 + .../src/Fixer/Phpdoc/PhpdocTagTypeFixer.php | 211 + .../src/Fixer/Phpdoc/PhpdocToCommentFixer.php | 97 + ...rimConsecutiveBlankLineSeparationFixer.php | 217 + .../src/Fixer/Phpdoc/PhpdocTrimFixer.php | 129 + .../src/Fixer/Phpdoc/PhpdocTypesFixer.php | 159 + .../Fixer/Phpdoc/PhpdocTypesOrderFixer.php | 223 + .../PhpdocVarAnnotationCorrectOrderFixer.php | 78 + .../Phpdoc/PhpdocVarWithoutNameFixer.php | 151 + .../BlankLineBeforeReturnFixer.php | 71 + .../ReturnNotation}/NoUselessReturnFixer.php | 71 +- .../ReturnNotation/ReturnAssignmentFixer.php | 357 + .../SimplifiedNullReturnFixer.php | 170 + ...ltilineWhitespaceBeforeSemicolonsFixer.php | 304 + .../Fixer/Semicolon/NoEmptyStatementFixer.php | 194 + ...ltilineWhitespaceBeforeSemicolonsFixer.php | 78 + ...glelineWhitespaceBeforeSemicolonsFixer.php | 75 + .../SemicolonAfterInstructionFixer.php | 73 + .../Semicolon/SpaceAfterSemicolonFixer.php | 145 + .../Fixer/Strict/DeclareStrictTypesFixer.php | 152 + .../Fixer/Strict/StrictComparisonFixer.php | 86 + .../src/Fixer/Strict/StrictParamFixer.php | 174 + .../EscapeImplicitBackslashesFixer.php | 167 + .../ExplicitStringVariableFixer.php | 172 + .../StringNotation/HeredocToNowdocFixer.php | 115 + .../StringNotation/NoBinaryStringFixer.php | 65 + .../NoTrailingWhitespaceInStringFixer.php | 113 + .../SimpleToComplexStringVariableFixer.php | 113 + .../Fixer/StringNotation/SingleQuoteFixer.php | 116 + .../StringNotation/StringLineEndingFixer.php | 85 + .../Whitespace/ArrayIndentationFixer.php | 277 + .../BlankLineBeforeStatementFixer.php | 378 + .../CompactNullableTypehintFixer.php | 79 + .../Whitespace/HeredocIndentationFixer.php | 200 + .../Fixer/Whitespace/IndentationTypeFixer.php | 163 + .../src/Fixer/Whitespace/LineEndingFixer.php | 102 + .../MethodChainingIndentationFixer.php | 202 + .../Whitespace/NoExtraBlankLinesFixer.php | 488 ++ .../NoExtraConsecutiveBlankLinesFixer.php | 73 + .../Whitespace/NoSpacesAroundOffsetFixer.php | 107 + .../NoSpacesInsideParenthesisFixer.php | 110 + .../Whitespace/NoTrailingWhitespaceFixer.php | 114 + .../NoWhitespaceInBlankLineFixer.php | 103 + .../Whitespace/SingleBlankLineAtEofFixer.php | 73 + .../Fixer/WhitespacesAwareFixerInterface.php | 23 + .../FixerConfiguration/AliasedFixerOption.php | 101 + .../AliasedFixerOptionBuilder.php | 92 + .../FixerConfiguration/AllowedValueSubset.php | 56 + .../DeprecatedFixerOption.php | 99 + .../DeprecatedFixerOptionInterface.php | 21 + .../FixerConfigurationResolver.php | 133 + .../FixerConfigurationResolverInterface.php | 28 + .../FixerConfigurationResolverRootless.php | 97 + .../src/FixerConfiguration/FixerOption.php | 172 + .../FixerConfiguration/FixerOptionBuilder.php | 145 + .../FixerOptionInterface.php | 53 + .../InvalidOptionsForEnvException.php | 24 + .../src/FixerDefinition/CodeSample.php | 54 + .../FixerDefinition/CodeSampleInterface.php | 29 + .../FileSpecificCodeSample.php | 67 + .../FileSpecificCodeSampleInterface.php | 26 + .../src/FixerDefinition/FixerDefinition.php | 118 + .../FixerDefinitionInterface.php | 55 + .../VersionSpecificCodeSample.php | 65 + .../VersionSpecificCodeSampleInterface.php | 26 + .../FixerDefinition/VersionSpecification.php | 75 + .../VersionSpecificationInterface.php | 26 + .../php-cs-fixer/src/FixerFactory.php | 246 + .../src/FixerFileProcessedEvent.php | 59 + .../php-cs-fixer/src/FixerNameValidator.php | 36 + .../Indicator/PhpUnitTestCaseIndicator.php | 71 + .../php-cs-fixer/src/Linter/CachingLinter.php | 72 + .../php-cs-fixer/src/Linter/Linter.php | 64 + .../src/Linter/LinterInterface.php | 44 + .../src/Linter/LintingException.php | 20 + .../src/Linter/LintingResultInterface.php | 24 + .../php-cs-fixer/src/Linter/ProcessLinter.php | 171 + .../Linter/ProcessLinterProcessBuilder.php | 50 + .../src/Linter/ProcessLintingResult.php | 98 + .../src/Linter/TokenizerLinter.php | 77 + .../src/Linter/TokenizerLintingResult.php | 50 + .../src/Linter/UnavailableLinterException.php | 22 + .../php-cs-fixer/src/PharChecker.php | 39 + .../php-cs-fixer/src/PharCheckerInterface.php | 26 + vendor/friendsofphp/php-cs-fixer/src/Preg.php | 233 + .../php-cs-fixer/src/PregException.php | 24 + .../friendsofphp/php-cs-fixer/src/RuleSet.php | 27 + .../RuleSet/AbstractRuleSetDescription.php | 35 + .../php-cs-fixer/src/RuleSet/RuleSet.php | 184 + .../RuleSet/RuleSetDescriptionInterface.php | 45 + .../src/RuleSet/RuleSetInterface.php | 60 + .../php-cs-fixer/src/RuleSet/RuleSets.php | 72 + .../RuleSet/Sets/DoctrineAnnotationSet.php | 40 + .../src/RuleSet/Sets/PHP54MigrationSet.php | 33 + .../RuleSet/Sets/PHP56MigrationRiskySet.php | 33 + .../src/RuleSet/Sets/PHP56MigrationSet.php | 33 + .../RuleSet/Sets/PHP70MigrationRiskySet.php | 44 + .../src/RuleSet/Sets/PHP70MigrationSet.php | 34 + .../RuleSet/Sets/PHP71MigrationRiskySet.php | 34 + .../src/RuleSet/Sets/PHP71MigrationSet.php | 41 + .../src/RuleSet/Sets/PHP73MigrationSet.php | 37 + .../RuleSet/Sets/PHP74MigrationRiskySet.php | 36 + .../src/RuleSet/Sets/PHP74MigrationSet.php | 35 + .../RuleSet/Sets/PHP80MigrationRiskySet.php | 41 + .../src/RuleSet/Sets/PHP80MigrationSet.php | 35 + .../Sets/PHPUnit30MigrationRiskySet.php | 36 + .../Sets/PHPUnit32MigrationRiskySet.php | 37 + .../Sets/PHPUnit35MigrationRiskySet.php | 37 + .../Sets/PHPUnit43MigrationRiskySet.php | 37 + .../Sets/PHPUnit48MigrationRiskySet.php | 37 + .../Sets/PHPUnit50MigrationRiskySet.php | 34 + .../Sets/PHPUnit52MigrationRiskySet.php | 37 + .../Sets/PHPUnit54MigrationRiskySet.php | 37 + .../Sets/PHPUnit55MigrationRiskySet.php | 37 + .../Sets/PHPUnit56MigrationRiskySet.php | 40 + .../Sets/PHPUnit57MigrationRiskySet.php | 37 + .../Sets/PHPUnit60MigrationRiskySet.php | 37 + .../Sets/PHPUnit75MigrationRiskySet.php | 37 + .../Sets/PHPUnit84MigrationRiskySet.php | 38 + .../src/RuleSet/Sets/PSR12RiskySet.php | 34 + .../src/RuleSet/Sets/PSR12Set.php | 70 + .../php-cs-fixer/src/RuleSet/Sets/PSR1Set.php | 34 + .../php-cs-fixer/src/RuleSet/Sets/PSR2Set.php | 62 + .../src/RuleSet/Sets/PhpCsFixerRiskySet.php | 58 + .../src/RuleSet/Sets/PhpCsFixerSet.php | 105 + .../src/RuleSet/Sets/SymfonyRiskySet.php | 91 + .../src/RuleSet/Sets/SymfonySet.php | 191 + .../php-cs-fixer/src/RuleSetInterface.php | 20 + .../src/Runner/FileCachingLintingIterator.php | 80 + .../src/Runner/FileFilterIterator.php | 122 + .../src/Runner/FileLintingIterator.php | 68 + .../php-cs-fixer/src/Runner/Runner.php | 337 + .../{Symfony/CS => src}/StdinFileInfo.php | 32 +- .../src/Test/AbstractFixerTestCase.php | 36 + .../src/Test/AbstractIntegrationTestCase.php | 36 + .../src/Test/AccessibleObject.php | 94 + .../php-cs-fixer/src/Test/IntegrationCase.php | 132 + .../Tokenizer/AbstractTransformer.php | 30 +- .../Analyzer/Analysis/ArgumentAnalysis.php | 108 + .../Analyzer/Analysis/CaseAnalysis.php | 42 + .../Analyzer/Analysis/NamespaceAnalysis.php | 127 + .../Analysis/NamespaceUseAnalysis.php | 155 + .../Analysis/StartEndTokenAwareAnalysis.php | 30 + .../Analyzer/Analysis/SwitchAnalysis.php | 72 + .../Analyzer/Analysis/TypeAnalysis.php | 125 + .../Tokenizer/Analyzer/ArgumentsAnalyzer.php | 159 + .../src/Tokenizer/Analyzer/BlocksAnalyzer.php | 67 + .../src/Tokenizer/Analyzer/ClassyAnalyzer.php | 82 + .../Tokenizer/Analyzer/CommentsAnalyzer.php | 322 + .../Tokenizer/Analyzer/FunctionsAnalyzer.php | 275 + .../Tokenizer/Analyzer/GotoLabelAnalyzer.php | 43 + .../Analyzer/NamespaceUsesAnalyzer.php | 122 + .../Tokenizer/Analyzer/NamespacesAnalyzer.php | 91 + .../Tokenizer/Analyzer/ReferenceAnalyzer.php | 52 + .../src/Tokenizer/Analyzer/SwitchAnalyzer.php | 140 + .../Analyzer/WhitespacesAnalyzer.php | 55 + .../php-cs-fixer/src/Tokenizer/CT.php | 101 + .../php-cs-fixer/src/Tokenizer/CodeHasher.php | 38 + .../NamespacedStringTokenGenerator.php | 43 + .../Resolver/TypeShortNameResolver.php | 94 + .../php-cs-fixer/src/Tokenizer/Token.php | 655 ++ .../php-cs-fixer/src/Tokenizer/Tokens.php | 1646 +++++ .../src/Tokenizer/TokensAnalyzer.php | 822 +++ .../Transformer/ArrayTypehintTransformer.php | 61 + .../Transformer/AttributeTransformer.php | 77 + .../BraceClassInstantiationTransformer.php | 88 + .../Transformer/ClassConstantTransformer.php | 64 + .../ConstructorPromotionTransformer.php | 78 + .../Transformer/CurlyBraceTransformer.php | 221 + .../Transformer/ImportTransformer.php | 67 + .../Transformer/NameQualifiedTransformer.php | 103 + .../Transformer/NamedArgumentTransformer.php | 85 + .../NamespaceOperatorTransformer.php | 60 + .../Transformer/NullableTypeTransformer.php | 83 + .../Transformer/ReturnRefTransformer.php | 62 + .../Transformer/SquareBraceTransformer.php | 196 + .../TypeAlternationTransformer.php | 117 + .../Transformer/TypeColonTransformer.php | 90 + .../Tokenizer/Transformer/UseTransformer.php | 110 + .../WhitespacyCommentTransformer.php | 71 + .../Tokenizer/TransformerInterface.php | 45 +- .../src/Tokenizer/Transformers.php | 113 + .../php-cs-fixer/src/ToolInfo.php | 111 + .../php-cs-fixer/src/ToolInfoInterface.php | 31 + .../friendsofphp/php-cs-fixer/src/Utils.php | 217 + .../src/WhitespacesFixerConfig.php | 63 + .../php-cs-fixer/src/WordMatcher.php | 57 + .../tests/Test/AbstractFixerTestCase.php | 584 ++ .../Test/AbstractIntegrationCaseFactory.php | 252 + .../Test/AbstractIntegrationTestCase.php | 410 ++ .../tests/Test/Assert/AssertTokensTrait.php | 52 + .../CS => tests}/Test/IntegrationCase.php | 137 +- .../tests/Test/IntegrationCaseFactory.php | 22 + .../Test/IntegrationCaseFactoryInterface.php | 28 + .../Test/InternalIntegrationCaseFactory.php | 35 + .../tests/Test/IsIdenticalConstraint.php | 56 + .../Test/TokensWithObservedTransformers.php | 68 + .../php-cs-fixer/tests/TestCase.php | 76 + vendor/guzzlehttp/guzzle/CHANGELOG.md | 334 +- vendor/guzzlehttp/guzzle/LICENSE | 10 +- vendor/guzzlehttp/guzzle/README.md | 85 +- vendor/guzzlehttp/guzzle/UPGRADING.md | 56 +- vendor/guzzlehttp/guzzle/composer.json | 95 +- .../guzzlehttp/guzzle/src/BodySummarizer.php | 28 + .../guzzle/src/BodySummarizerInterface.php | 13 + vendor/guzzlehttp/guzzle/src/Client.php | 323 +- .../guzzlehttp/guzzle/src/ClientInterface.php | 26 +- vendor/guzzlehttp/guzzle/src/ClientTrait.php | 241 + .../guzzle/src/Cookie/CookieJar.php | 155 +- .../guzzle/src/Cookie/CookieJarInterface.php | 29 +- .../guzzle/src/Cookie/FileCookieJar.php | 47 +- .../guzzle/src/Cookie/SessionCookieJar.php | 38 +- .../guzzle/src/Cookie/SetCookie.php | 309 +- .../src/Exception/BadResponseException.php | 30 +- .../guzzle/src/Exception/ClientException.php | 5 +- .../guzzle/src/Exception/ConnectException.php | 39 +- .../guzzle/src/Exception/GuzzleException.php | 16 +- .../Exception/InvalidArgumentException.php | 7 + .../guzzle/src/Exception/RequestException.php | 135 +- .../guzzle/src/Exception/SeekException.php | 27 - .../guzzle/src/Exception/ServerException.php | 5 +- .../Exception/TooManyRedirectsException.php | 5 +- .../src/Exception/TransferException.php | 5 +- .../guzzle/src/Handler/CurlFactory.php | 451 +- .../src/Handler/CurlFactoryInterface.php | 8 +- .../guzzle/src/Handler/CurlHandler.php | 26 +- .../guzzle/src/Handler/CurlMultiHandler.php | 154 +- .../guzzle/src/Handler/EasyHandle.php | 80 +- .../guzzle/src/Handler/HeaderProcessor.php | 42 + .../guzzle/src/Handler/MockHandler.php | 145 +- .../guzzlehttp/guzzle/src/Handler/Proxy.php | 40 +- .../guzzle/src/Handler/StreamHandler.php | 451 +- vendor/guzzlehttp/guzzle/src/HandlerStack.php | 150 +- .../guzzle/src/MessageFormatter.php | 97 +- .../guzzle/src/MessageFormatterInterface.php | 18 + vendor/guzzlehttp/guzzle/src/Middleware.php | 139 +- vendor/guzzlehttp/guzzle/src/Pool.php | 70 +- .../guzzle/src/PrepareBodyMiddleware.php | 35 +- .../guzzle/src/RedirectMiddleware.php | 157 +- .../guzzlehttp/guzzle/src/RequestOptions.php | 87 +- .../guzzlehttp/guzzle/src/RetryMiddleware.php | 91 +- .../guzzlehttp/guzzle/src/TransferStats.php | 67 +- vendor/guzzlehttp/guzzle/src/UriTemplate.php | 237 - vendor/guzzlehttp/guzzle/src/Utils.php | 385 + vendor/guzzlehttp/guzzle/src/functions.php | 280 +- .../guzzle/src/functions_include.php | 4 +- vendor/guzzlehttp/promises/CHANGELOG.md | 73 + vendor/guzzlehttp/promises/LICENSE | 7 +- vendor/guzzlehttp/promises/Makefile | 13 - vendor/guzzlehttp/promises/README.md | 129 +- vendor/guzzlehttp/promises/composer.json | 42 +- .../promises/src/AggregateException.php | 5 +- .../promises/src/CancellationException.php | 3 + vendor/guzzlehttp/promises/src/Coroutine.php | 57 +- vendor/guzzlehttp/promises/src/Create.php | 79 + vendor/guzzlehttp/promises/src/Each.php | 86 + .../guzzlehttp/promises/src/EachPromise.php | 97 +- .../promises/src/FulfilledPromise.php | 39 +- vendor/guzzlehttp/promises/src/Is.php | 40 + vendor/guzzlehttp/promises/src/Promise.php | 117 +- .../promises/src/PromiseInterface.php | 38 +- .../promises/src/PromisorInterface.php | 7 +- .../promises/src/RejectedPromise.php | 44 +- .../promises/src/RejectionException.php | 14 +- vendor/guzzlehttp/promises/src/TaskQueue.php | 21 +- .../promises/src/TaskQueueInterface.php | 13 +- vendor/guzzlehttp/promises/src/Utils.php | 259 + vendor/guzzlehttp/promises/src/functions.php | 457 -- .../promises/src/functions_include.php | 6 - .../vendor-bin/php-cs-fixer/composer.json | 9 + .../promises/vendor-bin/phpstan/composer.json | 10 + .../promises/vendor-bin/psalm/composer.json | 9 + vendor/guzzlehttp/psr7/CHANGELOG.md | 422 +- vendor/guzzlehttp/psr7/LICENSE | 9 +- vendor/guzzlehttp/psr7/README.md | 411 +- vendor/guzzlehttp/psr7/composer.json | 76 +- vendor/guzzlehttp/psr7/src/AppendStream.php | 81 +- vendor/guzzlehttp/psr7/src/BufferStream.php | 50 +- vendor/guzzlehttp/psr7/src/CachingStream.php | 49 +- vendor/guzzlehttp/psr7/src/DroppingStream.php | 13 +- .../src/Exception/MalformedUriException.php | 14 + vendor/guzzlehttp/psr7/src/FnStream.php | 87 +- vendor/guzzlehttp/psr7/src/Header.php | 134 + vendor/guzzlehttp/psr7/src/HttpFactory.php | 100 + vendor/guzzlehttp/psr7/src/InflateStream.php | 47 +- vendor/guzzlehttp/psr7/src/LazyOpenStream.php | 26 +- vendor/guzzlehttp/psr7/src/LimitStream.php | 40 +- vendor/guzzlehttp/psr7/src/Message.php | 246 + vendor/guzzlehttp/psr7/src/MessageTrait.php | 148 +- vendor/guzzlehttp/psr7/src/MimeType.php | 1237 ++++ .../guzzlehttp/psr7/src/MultipartStream.php | 64 +- vendor/guzzlehttp/psr7/src/NoSeekStream.php | 14 +- vendor/guzzlehttp/psr7/src/PumpStream.php | 78 +- vendor/guzzlehttp/psr7/src/Query.php | 113 + vendor/guzzlehttp/psr7/src/Request.php | 47 +- vendor/guzzlehttp/psr7/src/Response.php | 68 +- vendor/guzzlehttp/psr7/src/Rfc7230.php | 23 + vendor/guzzlehttp/psr7/src/ServerRequest.php | 136 +- vendor/guzzlehttp/psr7/src/Stream.php | 147 +- .../psr7/src/StreamDecoratorTrait.php | 66 +- vendor/guzzlehttp/psr7/src/StreamWrapper.php | 80 +- vendor/guzzlehttp/psr7/src/UploadedFile.php | 177 +- vendor/guzzlehttp/psr7/src/Uri.php | 412 +- vendor/guzzlehttp/psr7/src/UriComparator.php | 52 + vendor/guzzlehttp/psr7/src/UriNormalizer.php | 40 +- vendor/guzzlehttp/psr7/src/UriResolver.php | 24 +- vendor/guzzlehttp/psr7/src/Utils.php | 459 ++ vendor/guzzlehttp/psr7/src/functions.php | 828 --- .../guzzlehttp/psr7/src/functions_include.php | 6 - vendor/php-cs-fixer/diff/ChangeLog.md | 7 + vendor/php-cs-fixer/diff/LICENSE | 5 + vendor/php-cs-fixer/diff/LICENSE_DIFF | 31 + vendor/php-cs-fixer/diff/LICENSE_GECKO | 19 + vendor/php-cs-fixer/diff/README.md | 13 + vendor/php-cs-fixer/diff/composer.json | 41 + .../ConfigurationException.php | 36 + .../UnifiedDiffOutputBuilder.php | 295 + vendor/php-cs-fixer/diff/src/v1_4/Chunk.php | 103 + vendor/php-cs-fixer/diff/src/v1_4/Diff.php | 73 + vendor/php-cs-fixer/diff/src/v1_4/Differ.php | 399 + .../src/v1_4/LCS/LongestCommonSubsequence.php | 27 + ...LongestCommonSubsequenceImplementation.php | 95 + ...LongestCommonSubsequenceImplementation.php | 74 + vendor/php-cs-fixer/diff/src/v1_4/Line.php | 54 + vendor/php-cs-fixer/diff/src/v1_4/Parser.php | 110 + vendor/php-cs-fixer/diff/src/v2_0/Chunk.php | 78 + vendor/php-cs-fixer/diff/src/v2_0/Diff.php | 67 + vendor/php-cs-fixer/diff/src/v2_0/Differ.php | 321 + .../diff/src/v2_0/Exception/Exception.php | 15 + .../Exception/InvalidArgumentException.php | 15 + vendor/php-cs-fixer/diff/src/v2_0/Line.php | 44 + .../LongestCommonSubsequenceCalculator.php | 24 + ...ientLongestCommonSubsequenceCalculator.php | 81 + .../Output/AbstractChunkOutputBuilder.php | 56 + .../src/v2_0/Output/DiffOnlyOutputBuilder.php | 63 + .../Output/DiffOutputBuilderInterface.php | 19 + .../v2_0/Output/UnifiedDiffOutputBuilder.php | 165 + vendor/php-cs-fixer/diff/src/v2_0/Parser.php | 106 + ...ientLongestCommonSubsequenceCalculator.php | 66 + vendor/php-cs-fixer/diff/src/v3_0/Chunk.php | 78 + vendor/php-cs-fixer/diff/src/v3_0/Diff.php | 67 + vendor/php-cs-fixer/diff/src/v3_0/Differ.php | 329 + .../v3_0/Exception/ConfigurationException.php | 40 + .../diff/src/v3_0/Exception/Exception.php | 15 + .../Exception/InvalidArgumentException.php | 15 + vendor/php-cs-fixer/diff/src/v3_0/Line.php | 44 + .../LongestCommonSubsequenceCalculator.php | 24 + ...ientLongestCommonSubsequenceCalculator.php | 81 + .../Output/AbstractChunkOutputBuilder.php | 56 + .../src/v3_0/Output/DiffOnlyOutputBuilder.php | 66 + .../Output/DiffOutputBuilderInterface.php | 20 + .../Output/StrictUnifiedDiffOutputBuilder.php | 315 + .../v3_0/Output/UnifiedDiffOutputBuilder.php | 259 + vendor/php-cs-fixer/diff/src/v3_0/Parser.php | 106 + ...ientLongestCommonSubsequenceCalculator.php | 66 + .../reflection-common/.github/dependabot.yml | 7 + .../.github/workflows/push.yml | 223 + .../reflection-common/.travis.yml | 35 - .../phpdocumentor/reflection-common/README.md | 13 +- .../reflection-common/composer.json | 7 +- .../reflection-common/src/Element.php | 18 +- .../reflection-common/src/File.php | 17 +- .../reflection-common/src/Fqsen.php | 55 +- .../reflection-common/src/Location.php | 24 +- .../reflection-common/src/Project.php | 12 +- .../reflection-common/src/ProjectFactory.php | 13 +- .../reflection-docblock/.coveralls.yml | 3 - .../reflection-docblock/README.md | 16 +- .../reflection-docblock/composer.json | 36 +- .../easy-coding-standard.neon | 31 - .../reflection-docblock/src/DocBlock.php | 124 +- .../src/DocBlock/Description.php | 35 +- .../src/DocBlock/DescriptionFactory.php | 99 +- .../src/DocBlock/ExampleFinder.php | 67 +- .../src/DocBlock/Serializer.php | 126 +- .../src/DocBlock/StandardTagFactory.php | 243 +- .../reflection-docblock/src/DocBlock/Tag.php | 17 +- .../src/DocBlock/TagFactory.php | 71 +- .../src/DocBlock/Tags/Author.php | 58 +- .../src/DocBlock/Tags/BaseTag.php | 13 +- .../src/DocBlock/Tags/Covers.php | 76 +- .../src/DocBlock/Tags/Deprecated.php | 52 +- .../src/DocBlock/Tags/Example.php | 154 +- .../DocBlock/Tags/Factory/StaticMethod.php | 13 +- .../src/DocBlock/Tags/Factory/Strategy.php | 18 - .../src/DocBlock/Tags/Formatter.php | 11 +- .../Tags/Formatter/AlignFormatter.php | 25 +- .../Tags/Formatter/PassthroughFormatter.php | 15 +- .../src/DocBlock/Tags/Generic.php | 56 +- .../src/DocBlock/Tags/InvalidTag.php | 145 + .../src/DocBlock/Tags/Link.php | 63 +- .../src/DocBlock/Tags/Method.php | 177 +- .../src/DocBlock/Tags/Param.php | 171 +- .../src/DocBlock/Tags/Property.php | 119 +- .../src/DocBlock/Tags/PropertyRead.php | 119 +- .../src/DocBlock/Tags/PropertyWrite.php | 117 +- .../src/DocBlock/Tags/Reference/Fqsen.php | 20 +- .../src/DocBlock/Tags/Reference/Reference.php | 11 +- .../src/DocBlock/Tags/Reference/Url.php | 20 +- .../src/DocBlock/Tags/Return_.php | 60 +- .../src/DocBlock/Tags/See.php | 80 +- .../src/DocBlock/Tags/Since.php | 53 +- .../src/DocBlock/Tags/Source.php | 61 +- .../src/DocBlock/Tags/TagWithType.php | 66 + .../src/DocBlock/Tags/Throws.php | 58 +- .../src/DocBlock/Tags/Uses.php | 73 +- .../src/DocBlock/Tags/Var_.php | 112 +- .../src/DocBlock/Tags/Version.php | 62 +- .../src/DocBlockFactory.php | 112 +- .../src/DocBlockFactoryInterface.php | 20 +- .../src/Exception/PcreException.php | 44 + .../reflection-docblock/src/Utils.php | 62 + vendor/phpdocumentor/type-resolver/README.md | 65 +- .../phpdocumentor/type-resolver/composer.json | 32 +- .../type-resolver/src/FqsenResolver.php | 35 +- .../type-resolver/src/PseudoType.php | 19 + .../src/PseudoTypes/CallableString.php | 39 + .../type-resolver/src/PseudoTypes/False_.php | 40 + .../src/PseudoTypes/HtmlEscapedString.php | 39 + .../src/PseudoTypes/IntegerRange.php | 61 + .../type-resolver/src/PseudoTypes/List_.php | 50 + .../src/PseudoTypes/LiteralString.php | 39 + .../src/PseudoTypes/LowercaseString.php | 39 + .../src/PseudoTypes/NegativeInteger.php | 39 + .../PseudoTypes/NonEmptyLowercaseString.php | 39 + .../src/PseudoTypes/NonEmptyString.php | 39 + .../src/PseudoTypes/NumericString.php | 39 + .../src/PseudoTypes/Numeric_.php | 47 + .../src/PseudoTypes/PositiveInteger.php | 39 + .../src/PseudoTypes/TraitString.php | 39 + .../type-resolver/src/PseudoTypes/True_.php | 40 + .../phpdocumentor/type-resolver/src/Type.php | 13 +- .../type-resolver/src/TypeResolver.php | 636 +- .../type-resolver/src/Types/AbstractList.php | 83 + .../src/Types/AggregatedType.php | 125 + .../type-resolver/src/Types/ArrayKey.php | 42 + .../type-resolver/src/Types/Array_.php | 69 +- .../type-resolver/src/Types/Boolean.php | 13 +- .../type-resolver/src/Types/Callable_.php | 11 +- .../type-resolver/src/Types/ClassString.php | 62 + .../type-resolver/src/Types/Collection.php | 68 + .../type-resolver/src/Types/Compound.php | 71 +- .../type-resolver/src/Types/Context.php | 35 +- .../src/Types/ContextFactory.php | 356 +- .../type-resolver/src/Types/Expression.php | 51 + .../type-resolver/src/Types/Float_.php | 11 +- .../type-resolver/src/Types/Integer.php | 16 +- .../src/Types/InterfaceString.php | 56 + .../type-resolver/src/Types/Intersection.php | 37 + .../type-resolver/src/Types/Iterable_.php | 25 +- .../type-resolver/src/Types/Mixed_.php | 11 +- .../type-resolver/src/Types/Never_.php | 35 + .../type-resolver/src/Types/Null_.php | 11 +- .../type-resolver/src/Types/Nullable.php | 21 +- .../type-resolver/src/Types/Object_.php | 34 +- .../type-resolver/src/Types/Parent_.php | 11 +- .../type-resolver/src/Types/Resource_.php | 11 +- .../type-resolver/src/Types/Scalar.php | 11 +- .../type-resolver/src/Types/Self_.php | 11 +- .../type-resolver/src/Types/Static_.php | 11 +- .../type-resolver/src/Types/String_.php | 13 +- .../type-resolver/src/Types/This.php | 11 +- .../type-resolver/src/Types/Void_.php | 13 +- vendor/phpspec/prophecy/CHANGES.md | 35 + vendor/phpspec/prophecy/README.md | 15 +- vendor/phpspec/prophecy/composer.json | 14 +- .../Argument/Token/ExactValueToken.php | 4 +- .../prophecy/src/Prophecy/Call/CallCenter.php | 83 +- .../Prophecy/Comparator/ClosureComparator.php | 22 +- .../src/Prophecy/Doubler/CachedDoubler.php | 26 +- .../ClassPatch/DisableConstructorPatch.php | 4 + .../ClassPatch/ProphecySubjectPatch.php | 6 +- .../Doubler/Generator/ClassMirror.php | 4 +- .../PhpDocumentor/ClassTagRetriever.php | 10 +- .../src/Prophecy/Promise/ThrowPromise.php | 5 +- .../src/Prophecy/Prophecy/MethodProphecy.php | 36 +- .../src/Prophecy/Prophecy/ObjectProphecy.php | 7 +- .../phpspec/prophecy/src/Prophecy/Prophet.php | 11 +- .../prophecy/src/Prophecy/Util/ExportUtil.php | 4 +- vendor/psr/cache/CHANGELOG.md | 16 + vendor/psr/cache/LICENSE.txt | 19 + vendor/psr/cache/README.md | 9 + vendor/psr/cache/composer.json | 25 + vendor/psr/cache/src/CacheException.php | 10 + vendor/psr/cache/src/CacheItemInterface.php | 105 + .../psr/cache/src/CacheItemPoolInterface.php | 138 + .../cache/src/InvalidArgumentException.php | 13 + vendor/psr/container/.gitignore | 3 + vendor/psr/container/LICENSE | 21 + vendor/psr/container/README.md | 13 + vendor/psr/container/composer.json | 22 + .../src/ContainerExceptionInterface.php | 10 + .../psr/container/src/ContainerInterface.php | 36 + .../src/NotFoundExceptionInterface.php | 10 + vendor/psr/event-dispatcher/.editorconfig | 15 + vendor/psr/event-dispatcher/.gitignore | 2 + vendor/psr/event-dispatcher/LICENSE | 21 + vendor/psr/event-dispatcher/README.md | 6 + vendor/psr/event-dispatcher/composer.json | 26 + .../src/EventDispatcherInterface.php | 21 + .../src/ListenerProviderInterface.php | 19 + .../src/StoppableEventInterface.php | 26 + vendor/psr/http-client/CHANGELOG.md | 23 + vendor/psr/http-client/LICENSE | 19 + vendor/psr/http-client/README.md | 12 + vendor/psr/http-client/composer.json | 27 + .../src/ClientExceptionInterface.php | 10 + .../psr/http-client/src/ClientInterface.php | 20 + .../src/NetworkExceptionInterface.php | 24 + .../src/RequestExceptionInterface.php | 24 + vendor/psr/http-factory/LICENSE | 21 + vendor/psr/http-factory/README.md | 12 + vendor/psr/http-factory/composer.json | 35 + .../src/RequestFactoryInterface.php | 18 + .../src/ResponseFactoryInterface.php | 18 + .../src/ServerRequestFactoryInterface.php | 24 + .../src/StreamFactoryInterface.php | 45 + .../src/UploadedFileFactoryInterface.php | 34 + .../http-factory/src/UriFactoryInterface.php | 17 + vendor/psr/http-message/README.md | 5 +- vendor/psr/http-message/composer.json | 6 +- .../psr/http-message/docs/PSR7-Interfaces.md | 130 + vendor/psr/http-message/docs/PSR7-Usage.md | 159 + .../psr/http-message/src/MessageInterface.php | 22 +- .../psr/http-message/src/RequestInterface.php | 15 +- .../http-message/src/ResponseInterface.php | 6 +- .../src/ServerRequestInterface.php | 24 +- .../psr/http-message/src/StreamInterface.php | 30 +- .../src/UploadedFileInterface.php | 12 +- vendor/psr/http-message/src/UriInterface.php | 33 +- vendor/psr/log/.gitignore | 1 - vendor/psr/log/Psr/Log/AbstractLogger.php | 32 +- vendor/psr/log/Psr/Log/LoggerAwareTrait.php | 2 +- vendor/psr/log/Psr/Log/LoggerInterface.php | 40 +- vendor/psr/log/Psr/Log/LoggerTrait.php | 2 + vendor/psr/log/Psr/Log/NullLogger.php | 2 + vendor/psr/log/Psr/Log/Test/DummyTest.php | 18 + .../log/Psr/Log/Test/LoggerInterfaceTest.php | 14 +- vendor/psr/log/Psr/Log/Test/TestLogger.php | 147 + vendor/psr/log/README.md | 13 + vendor/psr/log/composer.json | 4 +- vendor/ralouphie/getallheaders/LICENSE | 21 + vendor/ralouphie/getallheaders/README.md | 27 + vendor/ralouphie/getallheaders/composer.json | 26 + .../getallheaders/src/getallheaders.php | 46 + .../squizlabs/php_codesniffer/CodeSniffer.php | 2 +- .../php_codesniffer/CodeSniffer/File.php | 4 +- .../CodeAnalysis/EmptyStatementSniff.php | 4 +- .../ControlSignatureSniff.php | 1 + .../Squiz/Sniffs/PHP/EmbeddedPhpSniff.php | 6 + .../Sniffs/Strings/DoubleQuoteUsageSniff.php | 1 + .../ControlStructureSpacingSniff.php | 2 + .../CodeSniffer/Tokenizers/CSS.php | 4 +- vendor/symfony/console/Application.php | 706 +- .../symfony/console/Attribute/AsCommand.php | 39 + vendor/symfony/console/CHANGELOG.md | 133 +- .../console/CI/GithubActionReporter.php | 99 + vendor/symfony/console/Color.php | 180 + vendor/symfony/console/Command/Command.php | 264 +- .../console/Command/CompleteCommand.php | 205 + .../console/Command/DumpCompletionCommand.php | 145 + .../symfony/console/Command/HelpCommand.php | 34 +- .../symfony/console/Command/LazyCommand.php | 218 + .../symfony/console/Command/ListCommand.php | 57 +- .../symfony/console/Command/LockableTrait.php | 17 +- .../Command/SignalableCommandInterface.php | 30 + .../CommandLoader/CommandLoaderInterface.php | 19 +- .../CommandLoader/ContainerCommandLoader.php | 16 +- .../CommandLoader/FactoryCommandLoader.php | 4 +- .../console/Completion/CompletionInput.php | 249 + .../Completion/CompletionSuggestions.php | 99 + .../Output/BashCompletionOutput.php | 33 + .../Output/CompletionOutputInterface.php | 25 + .../symfony/console/Completion/Suggestion.php | 37 + vendor/symfony/console/ConsoleEvents.php | 44 +- vendor/symfony/console/Cursor.php | 207 + .../AddConsoleCommandPass.php | 84 +- .../Descriptor/ApplicationDescription.php | 71 +- .../symfony/console/Descriptor/Descriptor.php | 29 +- .../Descriptor/DescriptorInterface.php | 9 +- .../console/Descriptor/JsonDescriptor.php | 107 +- .../console/Descriptor/MarkdownDescriptor.php | 60 +- .../console/Descriptor/TextDescriptor.php | 95 +- .../console/Descriptor/XmlDescriptor.php | 90 +- .../console/Event/ConsoleCommandEvent.php | 19 +- .../console/Event/ConsoleErrorEvent.php | 41 +- vendor/symfony/console/Event/ConsoleEvent.php | 10 +- .../console/Event/ConsoleExceptionEvent.php | 71 - .../console/Event/ConsoleSignalEvent.php | 35 + .../console/Event/ConsoleTerminateEvent.php | 25 +- .../console/EventListener/ErrorListener.php | 24 +- .../Exception/CommandNotFoundException.php | 12 +- .../console/Exception/ExceptionInterface.php | 2 +- .../Exception/InvalidOptionException.php | 2 +- .../Exception/MissingInputException.php | 21 + .../Exception/NamespaceNotFoundException.php | 21 + .../console/Formatter/NullOutputFormatter.php | 69 + .../Formatter/NullOutputFormatterStyle.php | 66 + .../console/Formatter/OutputFormatter.php | 167 +- .../Formatter/OutputFormatterInterface.php | 27 +- .../Formatter/OutputFormatterStyle.php | 182 +- .../OutputFormatterStyleInterface.php | 20 +- .../Formatter/OutputFormatterStyleStack.php | 7 +- .../WrappableOutputFormatterInterface.php | 25 + .../console/Helper/DebugFormatterHelper.php | 36 +- .../console/Helper/DescriptorHelper.php | 22 +- vendor/symfony/console/Helper/Dumper.php | 64 + .../console/Helper/FormatterHelper.php | 40 +- vendor/symfony/console/Helper/Helper.php | 94 +- .../console/Helper/HelperInterface.php | 4 +- vendor/symfony/console/Helper/HelperSet.php | 44 +- .../symfony/console/Helper/ProcessHelper.php | 63 +- vendor/symfony/console/Helper/ProgressBar.php | 422 +- .../console/Helper/ProgressIndicator.php | 106 +- .../symfony/console/Helper/QuestionHelper.php | 462 +- .../console/Helper/SymfonyQuestionHelper.php | 53 +- vendor/symfony/console/Helper/Table.php | 605 +- vendor/symfony/console/Helper/TableCell.php | 24 +- .../symfony/console/Helper/TableCellStyle.php | 89 + vendor/symfony/console/Helper/TableRows.php | 30 + .../symfony/console/Helper/TableSeparator.php | 2 +- vendor/symfony/console/Helper/TableStyle.php | 218 +- vendor/symfony/console/Input/ArgvInput.php | 144 +- vendor/symfony/console/Input/ArrayInput.php | 50 +- vendor/symfony/console/Input/Input.php | 50 +- .../symfony/console/Input/InputArgument.php | 30 +- .../console/Input/InputAwareInterface.php | 2 - .../symfony/console/Input/InputDefinition.php | 168 +- .../symfony/console/Input/InputInterface.php | 60 +- vendor/symfony/console/Input/InputOption.php | 69 +- vendor/symfony/console/Input/StringInput.php | 48 +- vendor/symfony/console/LICENSE | 2 +- .../symfony/console/Logger/ConsoleLogger.php | 33 +- .../symfony/console/Output/BufferedOutput.php | 4 +- .../symfony/console/Output/ConsoleOutput.php | 42 +- .../console/Output/ConsoleOutputInterface.php | 4 +- .../console/Output/ConsoleSectionOutput.php | 143 + vendor/symfony/console/Output/NullOutput.php | 17 +- vendor/symfony/console/Output/Output.php | 29 +- .../console/Output/OutputInterface.php | 50 +- .../symfony/console/Output/StreamOutput.php | 35 +- .../console/Output/TrimmedBufferOutput.php | 63 + .../console/Question/ChoiceQuestion.php | 46 +- .../console/Question/ConfirmationQuestion.php | 10 +- vendor/symfony/console/Question/Question.php | 129 +- vendor/symfony/console/README.md | 26 +- .../symfony/console/Resources/completion.bash | 84 + .../console/SignalRegistry/SignalRegistry.php | 65 + .../console/SingleCommandApplication.php | 72 + vendor/symfony/console/Style/OutputStyle.php | 16 +- .../symfony/console/Style/StyleInterface.php | 40 +- vendor/symfony/console/Style/SymfonyStyle.php | 219 +- vendor/symfony/console/Terminal.php | 110 +- .../console/Tester/ApplicationTester.php | 151 +- .../Tester/CommandCompletionTester.php | 56 + .../symfony/console/Tester/CommandTester.php | 108 +- .../Tester/Constraint/CommandIsSuccessful.php | 55 + vendor/symfony/console/Tester/TesterTrait.php | 197 + .../symfony/console/Tests/ApplicationTest.php | 1678 ----- .../console/Tests/Command/CommandTest.php | 434 -- .../console/Tests/Command/HelpCommandTest.php | 71 - .../console/Tests/Command/ListCommandTest.php | 113 - .../Tests/Command/LockableTraitTest.php | 67 - .../ContainerCommandLoaderTest.php | 61 - .../FactoryCommandLoaderTest.php | 60 - .../AddConsoleCommandPassTest.php | 262 - .../Descriptor/AbstractDescriptorTest.php | 107 - .../Tests/Descriptor/JsonDescriptorTest.php | 35 - .../Descriptor/MarkdownDescriptorTest.php | 45 - .../Tests/Descriptor/ObjectsProvider.php | 82 - .../Tests/Descriptor/TextDescriptorTest.php | 53 - .../Tests/Descriptor/XmlDescriptorTest.php | 27 - .../Tests/EventListener/ErrorListenerTest.php | 156 - .../console/Tests/Fixtures/BarBucCommand.php | 11 - .../Tests/Fixtures/DescriptorApplication2.php | 26 - .../DescriptorApplicationMbString.php | 24 - .../Tests/Fixtures/DescriptorCommand1.php | 27 - .../Tests/Fixtures/DescriptorCommand2.php | 32 - .../Tests/Fixtures/DescriptorCommand3.php | 27 - .../Tests/Fixtures/DescriptorCommand4.php | 25 - .../Fixtures/DescriptorCommandMbString.php | 32 - .../console/Tests/Fixtures/DummyOutput.php | 36 - .../console/Tests/Fixtures/Foo1Command.php | 26 - .../console/Tests/Fixtures/Foo2Command.php | 21 - .../console/Tests/Fixtures/Foo3Command.php | 29 - .../console/Tests/Fixtures/Foo4Command.php | 11 - .../console/Tests/Fixtures/Foo5Command.php | 10 - .../console/Tests/Fixtures/Foo6Command.php | 12 - .../console/Tests/Fixtures/FooCommand.php | 33 - .../Tests/Fixtures/FooLock2Command.php | 28 - .../console/Tests/Fixtures/FooLockCommand.php | 27 - .../console/Tests/Fixtures/FooOptCommand.php | 36 - .../Fixtures/FooSameCaseLowercaseCommand.php | 11 - .../Fixtures/FooSameCaseUppercaseCommand.php | 11 - .../Fixtures/FooSubnamespaced1Command.php | 26 - .../Fixtures/FooSubnamespaced2Command.php | 26 - .../console/Tests/Fixtures/FoobarCommand.php | 25 - .../Style/SymfonyStyle/command/command_0.php | 11 - .../Style/SymfonyStyle/command/command_1.php | 13 - .../Style/SymfonyStyle/command/command_10.php | 17 - .../Style/SymfonyStyle/command/command_11.php | 12 - .../Style/SymfonyStyle/command/command_12.php | 13 - .../Style/SymfonyStyle/command/command_13.php | 14 - .../Style/SymfonyStyle/command/command_14.php | 17 - .../Style/SymfonyStyle/command/command_15.php | 14 - .../Style/SymfonyStyle/command/command_16.php | 15 - .../Style/SymfonyStyle/command/command_17.php | 13 - .../Style/SymfonyStyle/command/command_2.php | 16 - .../Style/SymfonyStyle/command/command_3.php | 12 - .../Style/SymfonyStyle/command/command_4.php | 34 - .../Style/SymfonyStyle/command/command_5.php | 37 - .../Style/SymfonyStyle/command/command_6.php | 16 - .../Style/SymfonyStyle/command/command_7.php | 15 - .../Style/SymfonyStyle/command/command_8.php | 26 - .../Style/SymfonyStyle/command/command_9.php | 11 - .../command/interactive_command_1.php | 19 - .../output/interactive_output_1.txt | 7 - .../Style/SymfonyStyle/output/output_0.txt | 3 - .../Style/SymfonyStyle/output/output_1.txt | 9 - .../Style/SymfonyStyle/output/output_10.txt | 7 - .../Style/SymfonyStyle/output/output_11.txt | 4 - .../Style/SymfonyStyle/output/output_12.txt | 6 - .../Style/SymfonyStyle/output/output_13.txt | 7 - .../Style/SymfonyStyle/output/output_14.txt | 6 - .../Style/SymfonyStyle/output/output_15.txt | 7 - .../Style/SymfonyStyle/output/output_16.txt | 8 - .../Style/SymfonyStyle/output/output_17.txt | 7 - .../Style/SymfonyStyle/output/output_2.txt | 13 - .../Style/SymfonyStyle/output/output_3.txt | 7 - .../Style/SymfonyStyle/output/output_4.txt | 32 - .../Style/SymfonyStyle/output/output_5.txt | 18 - .../Style/SymfonyStyle/output/output_6.txt | 6 - .../Style/SymfonyStyle/output/output_7.txt | 5 - .../Style/SymfonyStyle/output/output_8.txt | 9 - .../Style/SymfonyStyle/output/output_9.txt | 5 - .../console/Tests/Fixtures/TestCommand.php | 28 - .../console/Tests/Fixtures/TestTiti.php | 21 - .../console/Tests/Fixtures/TestToto.php | 22 - .../console/Tests/Fixtures/application_1.json | 156 - .../console/Tests/Fixtures/application_1.md | 172 - .../console/Tests/Fixtures/application_1.txt | 17 - .../console/Tests/Fixtures/application_1.xml | 104 - .../console/Tests/Fixtures/application_2.json | 509 -- .../console/Tests/Fixtures/application_2.md | 431 -- .../console/Tests/Fixtures/application_2.txt | 21 - .../console/Tests/Fixtures/application_2.xml | 254 - .../application_filtered_namespace.txt | 16 - .../Tests/Fixtures/application_gethelp.txt | 1 - .../Tests/Fixtures/application_mbstring.md | 269 - .../Tests/Fixtures/application_mbstring.txt | 19 - .../Fixtures/application_renderexception1.txt | 5 - .../Fixtures/application_renderexception2.txt | 7 - .../Fixtures/application_renderexception3.txt | 18 - .../application_renderexception3decorated.txt | 18 - .../Fixtures/application_renderexception4.txt | 6 - ...plication_renderexception_doublewidth1.txt | 8 - ..._renderexception_doublewidth1decorated.txt | 8 - ...plication_renderexception_doublewidth2.txt | 9 - ...plication_renderexception_escapeslines.txt | 9 - ...application_renderexception_linebreaks.txt | 11 - .../Tests/Fixtures/application_run1.txt | 17 - .../Tests/Fixtures/application_run2.txt | 26 - .../Tests/Fixtures/application_run3.txt | 26 - .../Tests/Fixtures/application_run4.txt | 1 - .../console/Tests/Fixtures/command_1.json | 15 - .../console/Tests/Fixtures/command_1.md | 12 - .../console/Tests/Fixtures/command_1.txt | 7 - .../console/Tests/Fixtures/command_1.xml | 12 - .../console/Tests/Fixtures/command_2.json | 33 - .../console/Tests/Fixtures/command_2.md | 29 - .../console/Tests/Fixtures/command_2.txt | 13 - .../console/Tests/Fixtures/command_2.xml | 21 - .../Tests/Fixtures/command_mbstring.md | 29 - .../Tests/Fixtures/command_mbstring.txt | 13 - .../Tests/Fixtures/input_argument_1.json | 7 - .../Tests/Fixtures/input_argument_1.md | 5 - .../Tests/Fixtures/input_argument_1.txt | 1 - .../Tests/Fixtures/input_argument_1.xml | 5 - .../Tests/Fixtures/input_argument_2.json | 7 - .../Tests/Fixtures/input_argument_2.md | 7 - .../Tests/Fixtures/input_argument_2.txt | 1 - .../Tests/Fixtures/input_argument_2.xml | 5 - .../Tests/Fixtures/input_argument_3.json | 7 - .../Tests/Fixtures/input_argument_3.md | 7 - .../Tests/Fixtures/input_argument_3.txt | 1 - .../Tests/Fixtures/input_argument_3.xml | 7 - .../Tests/Fixtures/input_argument_4.json | 7 - .../Tests/Fixtures/input_argument_4.md | 8 - .../Tests/Fixtures/input_argument_4.txt | 2 - .../Tests/Fixtures/input_argument_4.xml | 6 - ...input_argument_with_default_inf_value.json | 7 - .../input_argument_with_default_inf_value.md | 7 - .../input_argument_with_default_inf_value.txt | 1 - .../input_argument_with_default_inf_value.xml | 7 - .../Fixtures/input_argument_with_style.json | 7 - .../Fixtures/input_argument_with_style.md | 7 - .../Fixtures/input_argument_with_style.txt | 1 - .../Fixtures/input_argument_with_style.xml | 7 - .../Tests/Fixtures/input_definition_1.json | 4 - .../Tests/Fixtures/input_definition_1.md | 0 .../Tests/Fixtures/input_definition_1.txt | 0 .../Tests/Fixtures/input_definition_1.xml | 5 - .../Tests/Fixtures/input_definition_2.json | 12 - .../Tests/Fixtures/input_definition_2.md | 7 - .../Tests/Fixtures/input_definition_2.txt | 2 - .../Tests/Fixtures/input_definition_2.xml | 10 - .../Tests/Fixtures/input_definition_3.json | 14 - .../Tests/Fixtures/input_definition_3.md | 8 - .../Tests/Fixtures/input_definition_3.txt | 2 - .../Tests/Fixtures/input_definition_3.xml | 9 - .../Tests/Fixtures/input_definition_4.json | 22 - .../Tests/Fixtures/input_definition_4.md | 16 - .../Tests/Fixtures/input_definition_4.txt | 5 - .../Tests/Fixtures/input_definition_4.xml | 14 - .../Tests/Fixtures/input_option_1.json | 9 - .../console/Tests/Fixtures/input_option_1.md | 6 - .../console/Tests/Fixtures/input_option_1.txt | 1 - .../console/Tests/Fixtures/input_option_1.xml | 4 - .../Tests/Fixtures/input_option_2.json | 9 - .../console/Tests/Fixtures/input_option_2.md | 8 - .../console/Tests/Fixtures/input_option_2.txt | 1 - .../console/Tests/Fixtures/input_option_2.xml | 7 - .../Tests/Fixtures/input_option_3.json | 9 - .../console/Tests/Fixtures/input_option_3.md | 8 - .../console/Tests/Fixtures/input_option_3.txt | 1 - .../console/Tests/Fixtures/input_option_3.xml | 5 - .../Tests/Fixtures/input_option_4.json | 9 - .../console/Tests/Fixtures/input_option_4.md | 8 - .../console/Tests/Fixtures/input_option_4.txt | 1 - .../console/Tests/Fixtures/input_option_4.xml | 5 - .../Tests/Fixtures/input_option_5.json | 9 - .../console/Tests/Fixtures/input_option_5.md | 9 - .../console/Tests/Fixtures/input_option_5.txt | 2 - .../console/Tests/Fixtures/input_option_5.xml | 6 - .../Tests/Fixtures/input_option_6.json | 9 - .../console/Tests/Fixtures/input_option_6.md | 8 - .../console/Tests/Fixtures/input_option_6.txt | 1 - .../console/Tests/Fixtures/input_option_6.xml | 5 - .../input_option_with_default_inf_value.json | 9 - .../input_option_with_default_inf_value.md | 8 - .../input_option_with_default_inf_value.txt | 1 - .../input_option_with_default_inf_value.xml | 7 - .../Fixtures/input_option_with_style.json | 9 - .../Tests/Fixtures/input_option_with_style.md | 8 - .../Fixtures/input_option_with_style.txt | 1 - .../Fixtures/input_option_with_style.xml | 7 - .../input_option_with_style_array.json | 12 - .../Fixtures/input_option_with_style_array.md | 8 - .../input_option_with_style_array.txt | 1 - .../input_option_with_style_array.xml | 8 - .../OutputFormatterStyleStackTest.php | 71 - .../Formatter/OutputFormatterStyleTest.php | 100 - .../Tests/Formatter/OutputFormatterTest.php | 344 - .../Helper/AbstractQuestionHelperTest.php | 34 - .../Tests/Helper/FormatterHelperTest.php | 129 - .../console/Tests/Helper/HelperSetTest.php | 127 - .../console/Tests/Helper/HelperTest.php | 55 - .../Tests/Helper/ProcessHelperTest.php | 118 - .../console/Tests/Helper/ProgressBarTest.php | 792 -- .../Tests/Helper/ProgressIndicatorTest.php | 183 - .../Tests/Helper/QuestionHelperTest.php | 959 --- .../Helper/SymfonyQuestionHelperTest.php | 156 - .../console/Tests/Helper/TableStyleTest.php | 28 - .../console/Tests/Helper/TableTest.php | 838 --- .../console/Tests/Input/ArgvInputTest.php | 453 -- .../console/Tests/Input/ArrayInputTest.php | 177 - .../console/Tests/Input/InputArgumentTest.php | 117 - .../Tests/Input/InputDefinitionTest.php | 406 -- .../console/Tests/Input/InputOptionTest.php | 210 - .../symfony/console/Tests/Input/InputTest.php | 149 - .../console/Tests/Input/StringInputTest.php | 87 - .../Tests/Logger/ConsoleLoggerTest.php | 215 - .../Tests/Output/ConsoleOutputTest.php | 42 - .../console/Tests/Output/NullOutputTest.php | 88 - .../console/Tests/Output/OutputTest.php | 176 - .../console/Tests/Output/StreamOutputTest.php | 61 - .../console/Tests/Style/SymfonyStyleTest.php | 116 - vendor/symfony/console/Tests/TerminalTest.php | 44 - .../Tests/Tester/ApplicationTesterTest.php | 70 - .../Tests/Tester/CommandTesterTest.php | 163 - vendor/symfony/console/composer.json | 45 +- vendor/symfony/console/phpunit.xml.dist | 41 - vendor/symfony/debug/BufferingLogger.php | 37 - vendor/symfony/debug/CHANGELOG.md | 70 - vendor/symfony/debug/Debug.php | 60 - vendor/symfony/debug/DebugClassLoader.php | 404 -- vendor/symfony/debug/ErrorHandler.php | 682 -- .../Exception/ClassNotFoundException.php | 36 - .../debug/Exception/FatalErrorException.php | 77 - .../debug/Exception/FatalThrowableError.php | 51 - .../debug/Exception/FlattenException.php | 276 - .../debug/Exception/SilencedErrorContext.php | 67 - .../Exception/UndefinedFunctionException.php | 36 - .../Exception/UndefinedMethodException.php | 36 - vendor/symfony/debug/ExceptionHandler.php | 440 -- .../ClassNotFoundFatalErrorHandler.php | 189 - .../FatalErrorHandlerInterface.php | 32 - .../UndefinedFunctionFatalErrorHandler.php | 84 - .../UndefinedMethodFatalErrorHandler.php | 66 - vendor/symfony/debug/README.md | 13 - .../debug/Tests/DebugClassLoaderTest.php | 333 - .../symfony/debug/Tests/ErrorHandlerTest.php | 504 -- .../Tests/Exception/FlattenExceptionTest.php | 340 - .../debug/Tests/ExceptionHandlerTest.php | 133 - .../ClassNotFoundFatalErrorHandlerTest.php | 176 - ...UndefinedFunctionFatalErrorHandlerTest.php | 81 - .../UndefinedMethodFatalErrorHandlerTest.php | 76 - .../debug/Tests/Fixtures/AnnotatedClass.php | 13 - .../debug/Tests/Fixtures/ClassAlias.php | 3 - .../debug/Tests/Fixtures/DeprecatedClass.php | 12 - .../Tests/Fixtures/DeprecatedInterface.php | 12 - .../Tests/Fixtures/ExtendedFinalMethod.php | 17 - .../debug/Tests/Fixtures/FinalClass.php | 10 - .../debug/Tests/Fixtures/FinalMethod.php | 17 - .../debug/Tests/Fixtures/InternalClass.php | 15 - .../Tests/Fixtures/InternalInterface.php | 10 - .../debug/Tests/Fixtures/InternalTrait.php | 10 - .../debug/Tests/Fixtures/InternalTrait2.php | 23 - .../Tests/Fixtures/NonDeprecatedInterface.php | 7 - .../debug/Tests/Fixtures/PEARClass.php | 5 - .../symfony/debug/Tests/Fixtures/Throwing.php | 3 - .../debug/Tests/Fixtures/ToStringThrower.php | 24 - .../debug/Tests/Fixtures/casemismatch.php | 7 - .../debug/Tests/Fixtures/notPsr0Bis.php | 7 - .../Tests/Fixtures/psr4/Psr4CaseMismatch.php | 7 - .../debug/Tests/Fixtures/reallyNotPsr0.php | 7 - .../debug/Tests/Fixtures2/RequiredTwice.php | 7 - vendor/symfony/debug/Tests/HeaderMock.php | 38 - .../debug/Tests/phpt/debug_class_loader.phpt | 26 - .../Tests/phpt/decorate_exception_hander.phpt | 47 - .../debug/Tests/phpt/exception_rethrown.phpt | 35 - .../phpt/fatal_with_nested_handlers.phpt | 42 - vendor/symfony/debug/composer.json | 40 - vendor/symfony/debug/phpunit.xml.dist | 33 - .../.gitignore | 0 .../deprecation-contracts/CHANGELOG.md | 5 + .../{debug => deprecation-contracts}/LICENSE | 2 +- .../symfony/deprecation-contracts/README.md | 26 + .../deprecation-contracts/composer.json | 35 + .../deprecation-contracts/function.php | 27 + .../.gitignore | 0 .../event-dispatcher-contracts/CHANGELOG.md | 5 + .../Event.php | 20 +- .../EventDispatcherInterface.php | 31 + .../event-dispatcher-contracts/LICENSE | 19 + .../event-dispatcher-contracts/README.md | 9 + .../event-dispatcher-contracts/composer.json | 38 + .../Attribute/AsEventListener.php | 29 + vendor/symfony/event-dispatcher/CHANGELOG.md | 63 +- .../ContainerAwareEventDispatcher.php | 197 - .../Debug/TraceableEventDispatcher.php | 196 +- .../TraceableEventDispatcherInterface.php | 36 - .../Debug/WrappedListener.php | 55 +- .../AddEventAliasesPass.php | 46 + .../RegisterListenersPass.php | 157 +- .../event-dispatcher/EventDispatcher.php | 142 +- .../EventDispatcherInterface.php | 51 +- .../EventSubscriberInterface.php | 13 +- .../symfony/event-dispatcher/GenericEvent.php | 41 +- .../ImmutableEventDispatcher.php | 14 +- vendor/symfony/event-dispatcher/LICENSE | 2 +- .../LegacyEventDispatcherProxy.php | 31 + vendor/symfony/event-dispatcher/README.md | 10 +- .../Tests/AbstractEventDispatcherTest.php | 442 -- .../ContainerAwareEventDispatcherTest.php | 210 - .../Debug/TraceableEventDispatcherTest.php | 257 - .../RegisterListenersPassTest.php | 154 - .../Tests/EventDispatcherTest.php | 22 - .../event-dispatcher/Tests/EventTest.php | 55 - .../Tests/GenericEventTest.php | 140 - .../Tests/ImmutableEventDispatcherTest.php | 106 - vendor/symfony/event-dispatcher/composer.json | 33 +- .../symfony/event-dispatcher/phpunit.xml.dist | 31 - vendor/symfony/filesystem/.gitignore | 3 - vendor/symfony/filesystem/CHANGELOG.md | 29 + .../Exception/ExceptionInterface.php | 2 +- .../Exception/FileNotFoundException.php | 2 +- .../filesystem/Exception/IOException.php | 2 +- .../Exception/IOExceptionInterface.php | 2 +- .../Exception/InvalidArgumentException.php | 19 + .../filesystem/Exception/RuntimeException.php | 19 + vendor/symfony/filesystem/Filesystem.php | 443 +- vendor/symfony/filesystem/LICENSE | 2 +- vendor/symfony/filesystem/LockHandler.php | 121 - vendor/symfony/filesystem/Path.php | 819 +++ vendor/symfony/filesystem/README.md | 10 +- .../filesystem/Tests/ExceptionTest.php | 47 - .../filesystem/Tests/FilesystemTest.php | 1638 ----- .../filesystem/Tests/FilesystemTestCase.php | 166 - .../Tests/Fixtures/MockStream/MockStream.php | 46 - .../filesystem/Tests/LockHandlerTest.php | 144 - vendor/symfony/filesystem/composer.json | 15 +- vendor/symfony/filesystem/phpunit.xml.dist | 30 - vendor/symfony/finder/.gitignore | 3 - vendor/symfony/finder/CHANGELOG.md | 32 + .../symfony/finder/Comparator/Comparator.php | 57 +- .../finder/Comparator/DateComparator.php | 7 +- .../finder/Comparator/NumberComparator.php | 11 +- .../Exception/DirectoryNotFoundException.php} | 8 +- .../finder/Exception/ExceptionInterface.php | 25 - vendor/symfony/finder/Finder.php | 295 +- vendor/symfony/finder/Gitignore.php | 93 + vendor/symfony/finder/Glob.php | 23 +- .../finder/Iterator/CustomFilterIterator.php | 15 +- .../Iterator/DateRangeFilterIterator.php | 13 +- .../Iterator/DepthRangeFilterIterator.php | 20 +- .../ExcludeDirectoryFilterIterator.php | 27 +- .../Iterator/FileTypeFilterIterator.php | 13 +- .../Iterator/FilecontentFilterIterator.php | 9 +- .../Iterator/FilenameFilterIterator.php | 9 +- .../finder/Iterator/FilterIterator.php | 60 - .../symfony/finder/Iterator/LazyIterator.php | 32 + .../Iterator/MultiplePcreFilterIterator.php | 41 +- .../finder/Iterator/PathFilterIterator.php | 9 +- .../Iterator/RecursiveDirectoryIterator.php | 66 +- .../Iterator/SizeRangeFilterIterator.php | 13 +- .../finder/Iterator/SortableIterator.php | 68 +- .../Iterator/VcsIgnoredFilterIterator.php | 151 + vendor/symfony/finder/LICENSE | 2 +- vendor/symfony/finder/README.md | 10 +- vendor/symfony/finder/SplFileInfo.php | 22 +- .../Tests/Comparator/ComparatorTest.php | 65 - .../Tests/Comparator/DateComparatorTest.php | 64 - .../Tests/Comparator/NumberComparatorTest.php | 108 - vendor/symfony/finder/Tests/FinderTest.php | 737 -- vendor/symfony/finder/Tests/Fixtures/.dot/a | 0 .../finder/Tests/Fixtures/.dot/b/c.neon | 0 .../finder/Tests/Fixtures/.dot/b/d.neon | 0 .../finder/Tests/Fixtures/A/B/C/abc.dat | 0 .../symfony/finder/Tests/Fixtures/A/B/ab.dat | 0 vendor/symfony/finder/Tests/Fixtures/A/a.dat | 0 .../Tests/Fixtures/copy/A/B/C/abc.dat.copy | 0 .../Tests/Fixtures/copy/A/B/ab.dat.copy | 0 .../finder/Tests/Fixtures/copy/A/a.dat.copy | 0 .../symfony/finder/Tests/Fixtures/dolor.txt | 2 - .../symfony/finder/Tests/Fixtures/ipsum.txt | 2 - .../symfony/finder/Tests/Fixtures/lorem.txt | 2 - vendor/symfony/finder/Tests/Fixtures/one/.dot | 1 - vendor/symfony/finder/Tests/Fixtures/one/a | 0 .../finder/Tests/Fixtures/one/b/c.neon | 0 .../finder/Tests/Fixtures/one/b/d.neon | 0 .../Fixtures/r+e.gex[c]a(r)s/dir/bar.dat | 0 .../finder/Tests/Fixtures/with space/foo.txt | 0 vendor/symfony/finder/Tests/GlobTest.php | 95 - .../Iterator/CustomFilterIteratorTest.php | 46 - .../Iterator/DateRangeFilterIteratorTest.php | 74 - .../Iterator/DepthRangeFilterIteratorTest.php | 83 - .../ExcludeDirectoryFilterIteratorTest.php | 80 - .../Iterator/FileTypeFilterIteratorTest.php | 73 - .../FilecontentFilterIteratorTest.php | 86 - .../Iterator/FilenameFilterIteratorTest.php | 54 - .../Tests/Iterator/FilterIteratorTest.php | 53 - .../finder/Tests/Iterator/Iterator.php | 55 - .../Tests/Iterator/IteratorTestCase.php | 100 - .../Tests/Iterator/MockFileListIterator.php | 21 - .../finder/Tests/Iterator/MockSplFileInfo.php | 132 - .../MultiplePcreFilterIteratorTest.php | 71 - .../Tests/Iterator/PathFilterIteratorTest.php | 82 - .../Tests/Iterator/RealIteratorTestCase.php | 119 - .../RecursiveDirectoryIteratorTest.php | 59 - .../Iterator/SizeRangeFilterIteratorTest.php | 69 - .../Tests/Iterator/SortableIteratorTest.php | 183 - vendor/symfony/finder/composer.json | 13 +- vendor/symfony/finder/phpunit.xml.dist | 30 - vendor/symfony/options-resolver/CHANGELOG.md | 81 + .../Debug/OptionsResolverIntrospector.php | 120 + .../Exception/AccessException.php | 22 + .../Exception/ExceptionInterface.php | 21 + .../Exception/InvalidArgumentException.php | 21 + .../Exception/InvalidOptionsException.php | 23 + .../Exception/MissingOptionsException.php | 23 + .../Exception/NoConfigurationException.php | 26 + .../Exception/NoSuchOptionException.php | 26 + .../Exception/OptionDefinitionException.php | 21 + .../Exception/UndefinedOptionsException.php | 24 + vendor/symfony/options-resolver/LICENSE | 19 + .../options-resolver/OptionConfigurator.php | 139 + vendor/symfony/options-resolver/Options.php | 22 + .../options-resolver/OptionsResolver.php | 1347 ++++ vendor/symfony/options-resolver/README.md | 15 + vendor/symfony/options-resolver/composer.json | 31 + vendor/symfony/polyfill-ctype/Ctype.php | 53 +- vendor/symfony/polyfill-ctype/LICENSE | 2 +- vendor/symfony/polyfill-ctype/README.md | 2 +- vendor/symfony/polyfill-ctype/bootstrap.php | 24 + vendor/symfony/polyfill-ctype/bootstrap80.php | 46 + vendor/symfony/polyfill-ctype/composer.json | 14 +- .../polyfill-intl-grapheme/Grapheme.php | 247 + vendor/symfony/polyfill-intl-grapheme/LICENSE | 19 + .../symfony/polyfill-intl-grapheme/README.md | 31 + .../polyfill-intl-grapheme/bootstrap.php | 58 + .../polyfill-intl-grapheme/bootstrap80.php | 50 + .../polyfill-intl-grapheme/composer.json | 38 + .../symfony/polyfill-intl-normalizer/LICENSE | 19 + .../polyfill-intl-normalizer/Normalizer.php | 310 + .../polyfill-intl-normalizer/README.md | 14 + .../Resources/stubs/Normalizer.php | 17 + .../unidata/canonicalComposition.php | 945 +++ .../unidata/canonicalDecomposition.php | 2065 ++++++ .../Resources/unidata/combiningClass.php | 876 +++ .../unidata/compatibilityDecomposition.php | 3695 ++++++++++ .../polyfill-intl-normalizer/bootstrap.php | 23 + .../polyfill-intl-normalizer/bootstrap80.php | 19 + .../polyfill-intl-normalizer/composer.json | 39 + vendor/symfony/polyfill-mbstring/LICENSE | 2 +- vendor/symfony/polyfill-mbstring/Mbstring.php | 211 +- vendor/symfony/polyfill-mbstring/README.md | 4 +- .../Resources/unidata/lowerCase.php | 310 +- .../Resources/unidata/titleCaseRegexp.php | 5 + .../Resources/unidata/upperCase.php | 446 +- .../symfony/polyfill-mbstring/bootstrap.php | 165 +- .../symfony/polyfill-mbstring/bootstrap80.php | 143 + .../symfony/polyfill-mbstring/composer.json | 11 +- vendor/symfony/polyfill-php72/LICENSE | 19 + vendor/symfony/polyfill-php72/Php72.php | 217 + vendor/symfony/polyfill-php72/README.md | 35 + vendor/symfony/polyfill-php72/bootstrap.php | 57 + vendor/symfony/polyfill-php72/composer.json | 35 + vendor/symfony/polyfill-php73/LICENSE | 19 + vendor/symfony/polyfill-php73/Php73.php | 43 + vendor/symfony/polyfill-php73/README.md | 18 + .../Resources/stubs/JsonException.php} | 12 +- vendor/symfony/polyfill-php73/bootstrap.php | 31 + vendor/symfony/polyfill-php73/composer.json | 36 + vendor/symfony/polyfill-php80/LICENSE | 19 + vendor/symfony/polyfill-php80/Php80.php | 115 + vendor/symfony/polyfill-php80/PhpToken.php | 103 + vendor/symfony/polyfill-php80/README.md | 25 + .../Resources/stubs/Attribute.php | 31 + .../Resources/stubs/PhpToken.php | 16 + .../Resources/stubs/Stringable.php | 20 + .../Resources/stubs/UnhandledMatchError.php | 16 + .../Resources/stubs/ValueError.php | 16 + vendor/symfony/polyfill-php80/bootstrap.php | 42 + vendor/symfony/polyfill-php80/composer.json | 40 + vendor/symfony/process/.gitignore | 3 - vendor/symfony/process/CHANGELOG.md | 59 + .../process/Exception/ExceptionInterface.php | 2 +- .../Exception/ProcessSignaledException.php | 41 + .../Exception/ProcessTimedOutException.php | 6 +- vendor/symfony/process/ExecutableFinder.php | 28 +- vendor/symfony/process/InputStream.php | 20 +- vendor/symfony/process/LICENSE | 2 +- .../symfony/process/PhpExecutableFinder.php | 51 +- vendor/symfony/process/PhpProcess.php | 34 +- .../symfony/process/Pipes/AbstractPipes.php | 38 +- .../symfony/process/Pipes/PipesInterface.php | 18 +- vendor/symfony/process/Pipes/UnixPipes.php | 74 +- vendor/symfony/process/Pipes/WindowsPipes.php | 122 +- vendor/symfony/process/Process.php | 769 +- vendor/symfony/process/ProcessBuilder.php | 280 - vendor/symfony/process/ProcessUtils.php | 62 +- vendor/symfony/process/README.md | 25 +- .../process/Tests/ExecutableFinderTest.php | 163 - .../process/Tests/NonStopableProcess.php | 47 - .../process/Tests/PhpExecutableFinderTest.php | 72 - .../symfony/process/Tests/PhpProcessTest.php | 48 - .../PipeStdinInStdoutStdErrStreamSelect.php | 72 - .../process/Tests/ProcessBuilderTest.php | 226 - .../Tests/ProcessFailedExceptionTest.php | 137 - vendor/symfony/process/Tests/ProcessTest.php | 1621 ----- .../process/Tests/ProcessUtilsTest.php | 53 - vendor/symfony/process/composer.json | 12 +- vendor/symfony/process/phpunit.xml.dist | 30 - .../.gitignore | 0 .../service-contracts/Attribute/Required.php | 25 + .../Attribute/SubscribedService.php | 33 + vendor/symfony/service-contracts/CHANGELOG.md | 5 + vendor/symfony/service-contracts/LICENSE | 19 + vendor/symfony/service-contracts/README.md | 9 + .../service-contracts/ResetInterface.php | 30 + .../service-contracts/ServiceLocatorTrait.php | 128 + .../ServiceProviderInterface.php | 36 + .../ServiceSubscriberInterface.php | 53 + .../ServiceSubscriberTrait.php | 109 + .../Test/ServiceLocatorTest.php | 95 + .../symfony/service-contracts/composer.json | 42 + vendor/symfony/stopwatch/.gitignore | 3 - vendor/symfony/stopwatch/CHANGELOG.md | 15 + vendor/symfony/stopwatch/LICENSE | 2 +- vendor/symfony/stopwatch/README.md | 39 +- vendor/symfony/stopwatch/Section.php | 61 +- vendor/symfony/stopwatch/Stopwatch.php | 46 +- vendor/symfony/stopwatch/StopwatchEvent.php | 80 +- vendor/symfony/stopwatch/StopwatchPeriod.php | 23 +- .../stopwatch/Tests/StopwatchEventTest.php | 176 - .../stopwatch/Tests/StopwatchPeriodTest.php | 67 - .../symfony/stopwatch/Tests/StopwatchTest.php | 180 - vendor/symfony/stopwatch/composer.json | 12 +- vendor/symfony/stopwatch/phpunit.xml.dist | 30 - vendor/symfony/string/AbstractString.php | 795 ++ .../symfony/string/AbstractUnicodeString.php | 623 ++ vendor/symfony/string/ByteString.php | 509 ++ vendor/symfony/string/CHANGELOG.md | 35 + vendor/symfony/string/CodePointString.php | 270 + .../Exception/ExceptionInterface.php} | 6 +- .../Exception/InvalidArgumentException.php} | 11 +- .../string/Exception/RuntimeException.php | 16 + .../string/Inflector/EnglishInflector.php | 517 ++ .../string/Inflector/FrenchInflector.php | 157 + .../string/Inflector/InflectorInterface.php | 33 + vendor/symfony/string/LICENSE | 19 + vendor/symfony/string/LazyString.php | 164 + vendor/symfony/string/README.md | 14 + .../Resources/data/wcswidth_table_wide.php | 1143 +++ .../Resources/data/wcswidth_table_zero.php | 1415 ++++ vendor/symfony/string/Resources/functions.php | 38 + .../symfony/string/Slugger/AsciiSlugger.php | 183 + .../string/Slugger/SluggerInterface.php | 27 + vendor/symfony/string/UnicodeString.php | 377 + vendor/symfony/string/composer.json | 43 + vendor/symfony/yaml/CHANGELOG.md | 2 +- vendor/symfony/yaml/Command/LintCommand.php | 25 +- vendor/symfony/yaml/Dumper.php | 40 +- vendor/symfony/yaml/Escaper.php | 14 +- .../symfony/yaml/Exception/ParseException.php | 2 +- vendor/symfony/yaml/Inline.php | 212 +- vendor/symfony/yaml/LICENSE | 2 +- vendor/symfony/yaml/Parser.php | 158 +- vendor/symfony/yaml/README.md | 2 +- .../yaml/Tests/Command/LintCommandTest.php | 26 +- vendor/symfony/yaml/Tests/DumperTest.php | 316 +- .../yaml/Tests/Fixtures/YtsAnchorAlias.yml | 4 +- .../yaml/Tests/Fixtures/YtsBasicTests.yml | 52 +- .../yaml/Tests/Fixtures/YtsBlockMapping.yml | 14 +- .../Tests/Fixtures/YtsDocumentSeparator.yml | 8 +- .../yaml/Tests/Fixtures/YtsErrorTests.yml | 2 +- .../Tests/Fixtures/YtsFlowCollections.yml | 16 +- .../yaml/Tests/Fixtures/YtsFoldedScalars.yml | 26 +- .../Tests/Fixtures/YtsNullsAndEmpties.yml | 8 +- .../Fixtures/YtsSpecificationExamples.yml | 204 +- .../yaml/Tests/Fixtures/YtsTypeTransfers.yml | 62 +- .../Tests/Fixtures/booleanMappingKeys.yml | 4 +- .../yaml/Tests/Fixtures/escapedCharacters.yml | 8 +- .../Fixtures/legacyBooleanMappingKeys.yml | 8 +- .../Tests/Fixtures/legacyNullMappingKey.yml | 4 +- ...nes_as_literal_block_for_tagged_values.yml | 2 + .../yaml/Tests/Fixtures/nullMappingKey.yml | 4 +- .../Tests/Fixtures/numericMappingKeys.yml | 6 +- .../yaml/Tests/Fixtures/sfComments.yml | 28 +- .../symfony/yaml/Tests/Fixtures/sfCompact.yml | 108 +- .../yaml/Tests/Fixtures/sfMergeKey.yml | 26 +- .../symfony/yaml/Tests/Fixtures/sfObjects.yml | 2 +- .../symfony/yaml/Tests/Fixtures/sfQuotes.yml | 10 +- .../symfony/yaml/Tests/Fixtures/sfTests.yml | 32 +- .../Tests/Fixtures/unindentedCollections.yml | 14 +- vendor/symfony/yaml/Tests/InlineTest.php | 693 +- vendor/symfony/yaml/Tests/ParserTest.php | 1011 +-- vendor/symfony/yaml/Tests/YamlTest.php | 18 +- vendor/symfony/yaml/Yaml.php | 19 +- vendor/symfony/yaml/composer.json | 7 +- vendor/symfony/yaml/phpunit.xml.dist | 2 +- vendor/webmozart/assert/.composer-auth.json | 7 - vendor/webmozart/assert/.styleci.yml | 11 - vendor/webmozart/assert/CHANGELOG.md | 156 +- vendor/webmozart/assert/README.md | 89 +- vendor/webmozart/assert/composer.json | 21 +- vendor/webmozart/assert/src/Assert.php | 1625 ++++- .../assert/src/InvalidArgumentException.php | 16 + vendor/webmozart/assert/src/Mixin.php | 5089 +++++++++++++ 2127 files changed, 170682 insertions(+), 64511 deletions(-) create mode 100644 vendor/bin/php-cs-fixer.bat create mode 100644 vendor/bin/phpcbf.bat create mode 100644 vendor/bin/phpcs.bat create mode 100644 vendor/bin/phpunit.bat create mode 100644 vendor/composer/InstalledVersions.php create mode 100644 vendor/composer/installed.php create mode 100644 vendor/composer/pcre/LICENSE create mode 100644 vendor/composer/pcre/README.md create mode 100644 vendor/composer/pcre/composer.json create mode 100644 vendor/composer/pcre/src/MatchAllResult.php create mode 100644 vendor/composer/pcre/src/MatchAllWithOffsetsResult.php create mode 100644 vendor/composer/pcre/src/MatchResult.php create mode 100644 vendor/composer/pcre/src/MatchWithOffsetsResult.php create mode 100644 vendor/composer/pcre/src/PcreException.php create mode 100644 vendor/composer/pcre/src/Preg.php create mode 100644 vendor/composer/pcre/src/Regex.php create mode 100644 vendor/composer/pcre/src/ReplaceResult.php create mode 100644 vendor/composer/platform_check.php create mode 100644 vendor/composer/semver/CHANGELOG.md create mode 100644 vendor/composer/semver/LICENSE create mode 100644 vendor/composer/semver/README.md create mode 100644 vendor/composer/semver/composer.json create mode 100644 vendor/composer/semver/src/Comparator.php create mode 100644 vendor/composer/semver/src/CompilingMatcher.php create mode 100644 vendor/composer/semver/src/Constraint/Bound.php create mode 100644 vendor/composer/semver/src/Constraint/Constraint.php create mode 100644 vendor/composer/semver/src/Constraint/ConstraintInterface.php create mode 100644 vendor/composer/semver/src/Constraint/MatchAllConstraint.php create mode 100644 vendor/composer/semver/src/Constraint/MatchNoneConstraint.php create mode 100644 vendor/composer/semver/src/Constraint/MultiConstraint.php create mode 100644 vendor/composer/semver/src/Interval.php create mode 100644 vendor/composer/semver/src/Intervals.php create mode 100644 vendor/composer/semver/src/Semver.php create mode 100644 vendor/composer/semver/src/VersionParser.php create mode 100644 vendor/composer/xdebug-handler/CHANGELOG.md create mode 100644 vendor/composer/xdebug-handler/LICENSE create mode 100644 vendor/composer/xdebug-handler/README.md create mode 100644 vendor/composer/xdebug-handler/UPGRADE.md create mode 100644 vendor/composer/xdebug-handler/composer.json create mode 100644 vendor/composer/xdebug-handler/src/PhpConfig.php create mode 100644 vendor/composer/xdebug-handler/src/Process.php create mode 100644 vendor/composer/xdebug-handler/src/Status.php create mode 100644 vendor/composer/xdebug-handler/src/XdebugHandler.php create mode 100644 vendor/doctrine/annotations/LICENSE create mode 100644 vendor/doctrine/annotations/README.md create mode 100644 vendor/doctrine/annotations/composer.json create mode 100644 vendor/doctrine/annotations/docs/en/annotations.rst create mode 100644 vendor/doctrine/annotations/docs/en/custom.rst create mode 100644 vendor/doctrine/annotations/docs/en/index.rst create mode 100644 vendor/doctrine/annotations/docs/en/sidebar.rst create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/NamedArgumentConstructorAnnotation.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php create mode 100644 vendor/doctrine/annotations/psalm.xml create mode 100644 vendor/doctrine/deprecations/LICENSE create mode 100644 vendor/doctrine/deprecations/README.md create mode 100644 vendor/doctrine/deprecations/composer.json create mode 100644 vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php create mode 100644 vendor/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php create mode 100644 vendor/doctrine/deprecations/phpcs.xml create mode 100644 vendor/doctrine/deprecations/phpstan.neon create mode 100644 vendor/doctrine/deprecations/psalm.xml create mode 100644 vendor/doctrine/instantiator/.doctrine-project.json create mode 100644 vendor/doctrine/instantiator/docs/en/index.rst create mode 100644 vendor/doctrine/instantiator/docs/en/sidebar.rst create mode 100644 vendor/doctrine/instantiator/psalm.xml create mode 100644 vendor/doctrine/lexer/LICENSE create mode 100644 vendor/doctrine/lexer/README.md create mode 100644 vendor/doctrine/lexer/UPGRADE.md create mode 100644 vendor/doctrine/lexer/composer.json create mode 100644 vendor/doctrine/lexer/src/AbstractLexer.php create mode 100644 vendor/doctrine/lexer/src/Token.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/.php_cs delete mode 100644 vendor/friendsofphp/php-cs-fixer/COOKBOOK-FIXERS.md create mode 100644 vendor/friendsofphp/php-cs-fixer/README.md delete mode 100644 vendor/friendsofphp/php-cs-fixer/README.rst delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractAnnotationRemovalFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractLinesBeforeNamespaceFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/Config.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/MagentoConfig.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/Symfony23Config.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigInterface.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationException/InvalidConfigurationException.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationException/InvalidFixerConfigurationException.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationResolver.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Application.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/FixCommand.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/ReadmeCommand.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/SelfUpdateCommand.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Annotation.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/DocBlock.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Tag.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/ErrorsManager.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/FileCacheManager.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/DefaultFinder.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/MagentoFinder.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/Symfony23Finder.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/AlignEqualsFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ClassKeywordRemoveFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ConcatWithSpacesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EchoToPrintFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EmptyReturnFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/HeaderCommentFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LogicalNotOperatorsWithSpacesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LogicalNotOperatorsWithSuccessorSpaceFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LongArraySyntaxFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/MbStrFunctionsFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/MultilineSpacesBeforeSemicolonFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NewlineAfterOpenTagFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoBlankLinesBeforeNamespaceFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoUselessElseFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/OrderedUseFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitConstructFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitDedicateAssertFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitStrictFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpdocVarToTypeFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ShortArraySyntaxFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ShortEchoTagFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/SilencedDeprecationErrorFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/StrictFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/StrictParamFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR0/Psr0Fixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR1/EncodingFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR1/ShortTagFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/BracesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ClassDefinitionFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ElseifFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/EofEndingFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/FunctionDeclarationFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/IndentationFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LineAfterNamespaceFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LinefeedFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LowercaseConstantsFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LowercaseKeywordsFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/MethodArgumentSpaceFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/MultipleUseFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/NoTrailingWhitespaceInCommentFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ParenthesisFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/PhpClosingTagFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SingleLineAfterImportsFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SwitchCaseSemicolonToColonFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SwitchCaseSpaceFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/TrailingSpacesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/VisibilityFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ArrayElementNoSpaceBeforeCommaFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ArrayElementWhiteSpaceAfterCommaFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/BlanklineAfterOpenTagFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ConcatWithoutSpacesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DeclareEqualNormalizeFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DoubleArrowMultilineWhitespacesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DuplicateSemicolonFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ExtraEmptyLinesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/FunctionTypehintSpaceFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/HashToSlashCommentFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/HeredocToNowdocFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/IncludeFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/JoinFunctionFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/LowercaseCastFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/MethodArgumentDefaultValueFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/MultilineArrayTrailingCommaFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NamespaceNoLeadingWhitespaceFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoBlankLinesAfterClassOpeningFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyCommentFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyLinesAfterPhpdocsFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyPhpdocFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyStatementFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ObjectOperatorFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/OperatorsSpacesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpUnitFqcnAnnotationFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocAnnotationWithoutDotFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocIndentFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocInlineTagFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoAccessFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoEmptyReturnFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoPackageFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocParamsFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocScalarFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocShortDescriptionFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocSingleLineVarSpacingFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocToCommentFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTrimFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTypeToVarFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTypesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocVarWithoutNameFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PreIncrementFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PrintToEchoFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/RemoveLeadingSlashUseFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/RemoveLinesBetweenUsesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ReturnFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SelfAccessorFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ShortBoolCastFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ShortScalarCastFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleBlankLineBeforeNamespaceFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleQuoteFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesAfterSemicolonFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesBeforeSemicolonFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesCastFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/StandardizeNotEqualFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/TernarySpacesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnalignDoubleArrowFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnalignEqualsFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnaryOperatorsSpacesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnneededControlParenthesesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnusedUseFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/WhitespacyLinesFixer.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/FixerFileProcessedEvent.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/LintManager.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Resources/phar-stub.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Test/IntegrationCaseFactory.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Token.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Tokens.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/ArrayTypehint.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/ClassConstant.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/CurlyClose.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DollarCloseCurlyBraces.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DynamicPropBrace.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DynamicVarBrace.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformers.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/ToolInfo.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/UniqueFileIterator.php delete mode 100644 vendor/friendsofphp/php-cs-fixer/Symfony/CS/Utils.php create mode 100644 vendor/friendsofphp/php-cs-fixer/UPGRADE.md delete mode 100644 vendor/friendsofphp/php-cs-fixer/benchmark.sh delete mode 100644 vendor/friendsofphp/php-cs-fixer/box.json create mode 100644 vendor/friendsofphp/php-cs-fixer/ci-integration.sh create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/config.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/cookbook_fixers.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/custom_rules.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/installation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/DoctrineAnnotation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP54Migration.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP56Migration.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP56MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP70Migration.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP70MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP71Migration.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP71MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP73Migration.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP74Migration.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP74MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP80Migration.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP80MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit30MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit32MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit35MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit43MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit48MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit50MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit52MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit54MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit55MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit56MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit57MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit60MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit75MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit84MigrationRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR1.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR12.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR12Risky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR2.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PhpCsFixer.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PhpCsFixerRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/Symfony.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/SymfonyRisky.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/ruleSets/index.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/alias/array_push.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/alias/backtick_to_shell_exec.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/alias/ereg_to_preg.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/alias/mb_str_functions.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_alias_functions.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_alias_language_construct_call.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_mixed_echo_print.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/alias/pow_to_exponentiation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/alias/random_api_migration.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/alias/set_type_to_cast.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/array_syntax.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_multiline_whitespace_around_double_arrow.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_trailing_comma_in_singleline_array.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_whitespace_before_comma_in_array.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/normalize_index_brace.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/trailing_comma_in_multiline_array.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/trim_array_spaces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/whitespace_after_comma_in_array.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/basic/braces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/basic/encoding.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/basic/non_printable_character.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr0.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr4.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr_autoloading.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/casing/constant_case.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_constants.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_keywords.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_static_reference.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/casing/magic_constant_casing.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/casing/magic_method_casing.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/casing/native_function_casing.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/casing/native_function_type_declaration_casing.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/cast_spaces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/lowercase_cast.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/modernize_types_casting.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/no_short_bool_cast.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/no_unset_cast.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/short_scalar_cast.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/class_attributes_separation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/class_definition.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_class.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_internal_class.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_public_method_for_abstract_class.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_static_access.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/method_separation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_blank_lines_after_class_opening.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_null_property_initialization.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_php4_constructor.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_unneeded_final_method.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_class_elements.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_interfaces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_traits.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/protected_to_private.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/self_accessor.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/self_static_accessor.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/single_class_element_per_statement.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/single_trait_insert_per_statement.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/visibility_required.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/class_usage/date_time_immutable.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/comment/comment_to_phpdoc.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/comment/hash_to_slash_comment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/comment/header_comment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/comment/multiline_comment_opening_closing.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/comment/no_empty_comment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/comment/no_trailing_whitespace_in_comment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/comment/single_line_comment_style.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/constant_notation/native_constant_invocation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/elseif.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/include.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_alternative_syntax.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_break_comment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_superfluous_elseif.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_trailing_comma_in_list_call.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_unneeded_control_parentheses.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_unneeded_curly_braces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_useless_else.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/simplified_if_return.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_case_semicolon_to_colon.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_case_space.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_continue_to_break.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/trailing_comma_in_multiline.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/yoda_style.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_array_assignment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_braces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_indentation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_spaces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/combine_nested_dirname.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/fopen_flag_order.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/fopen_flags.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/function_declaration.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/function_typehint_space.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/implode_call.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/lambda_not_used_import.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/method_argument_space.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/native_function_invocation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_spaces_after_function_name.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_unreachable_default_argument_value.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_useless_sprintf.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/nullable_type_declaration_for_default_null_value.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_param_type.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_property_type.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_return_type.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/regular_callable_call.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/return_type_declaration.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/single_line_throw.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/static_lambda.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/use_arrow_functions.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/void_return.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/import/fully_qualified_strict_types.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/import/global_namespace_import.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/import/group_import.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/import/no_leading_import_slash.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/import/no_unused_imports.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/import/ordered_imports.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/import/single_import_per_statement.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/import/single_line_after_imports.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/index.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/class_keyword_remove.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/combine_consecutive_issets.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/combine_consecutive_unsets.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/declare_equal_normalize.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/dir_constant.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/error_suppression.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/explicit_indirect_variable.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/function_to_constant.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/is_null.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/no_unset_on_property.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/silenced_deprecation_error.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/single_space_after_construct.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/list_notation/list_syntax.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/blank_line_after_namespace.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/clean_namespace.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/no_blank_lines_before_namespace.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/no_leading_namespace_whitespace.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/single_blank_line_before_namespace.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/naming/no_homoglyph_names.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/binary_operator_spaces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/concat_space.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/increment_style.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/logical_operators.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/new_with_braces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/not_operator_with_space.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/not_operator_with_successor_space.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/object_operator_without_whitespace.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/operator_linebreak.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/pre_increment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/standardize_increment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/standardize_not_equals.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_operator_spaces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_to_elvis_operator.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_to_null_coalescing.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/operator/unary_operator_spaces.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/blank_line_after_opening_tag.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/echo_tag_syntax.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/full_opening_tag.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/linebreak_after_opening_tag.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/no_closing_tag.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/no_short_echo_tag.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_construct.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_dedicate_assert.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_dedicate_assert_internal_type.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_expectation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_fqcn_annotation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_internal_class.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_method_casing.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_mock.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_mock_short_will_return.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_namespaced.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_no_expectation_annotation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_ordered_covers.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_set_up_tear_down_visibility.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_size_class.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_strict.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_annotation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_case_static_method_calls.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_class_requires_covers.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/align_multiline_comment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/general_phpdoc_annotation_remove.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/general_phpdoc_tag_rename.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_blank_lines_after_phpdoc.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_empty_phpdoc.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_superfluous_phpdoc_tags.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_add_missing_param_annotation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_align.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_annotation_without_dot.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_indent.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_inline_tag.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_inline_tag_normalizer.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_line_span.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_access.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_alias_tag.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_empty_return.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_package.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_useless_inheritdoc.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_order.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_order_by_value.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_return_self_reference.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_scalar.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_separation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_single_line_var_spacing.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_summary.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_tag_casing.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_tag_type.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_to_comment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_trim.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_trim_consecutive_blank_line_separation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_types.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_types_order.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_var_annotation_correct_order.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_var_without_name.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/blank_line_before_return.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/no_useless_return.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/return_assignment.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/simplified_null_return.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/multiline_whitespace_before_semicolons.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_empty_statement.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_multiline_whitespace_before_semicolons.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_singleline_whitespace_before_semicolons.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/semicolon_after_instruction.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/space_after_semicolon.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/strict/declare_strict_types.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/strict/strict_comparison.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/strict/strict_param.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/escape_implicit_backslashes.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/explicit_string_variable.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/heredoc_to_nowdoc.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/no_binary_string.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/no_trailing_whitespace_in_string.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/simple_to_complex_string_variable.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/single_quote.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/string_line_ending.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/array_indentation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/blank_line_before_statement.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/compact_nullable_typehint.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/heredoc_indentation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/indentation_type.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/line_ending.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/method_chaining_indentation.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_extra_blank_lines.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_extra_consecutive_blank_lines.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_spaces_around_offset.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_spaces_inside_parenthesis.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_trailing_whitespace.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_whitespace_in_blank_line.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/single_blank_line_at_eof.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/checkstyle.xsd create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/junit-10.xsd create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/schema.json create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/xml.xsd create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/schemas/list-sets/schema.json create mode 100644 vendor/friendsofphp/php-cs-fixer/doc/usage.rst create mode 100644 vendor/friendsofphp/php-cs-fixer/logo.md create mode 100644 vendor/friendsofphp/php-cs-fixer/logo.png rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/AbstractAlignFixer.php => src/AbstractAlignFixerHelper.php} (52%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/AbstractDoctrineAnnotationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/AbstractFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/AbstractFopenFlagFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/AbstractFunctionReferenceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/AbstractLinesBeforeNamespaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/AbstractNoUselessElseFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/AbstractPhpdocToTypeDeclarationFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => src}/AbstractPhpdocTypesFixer.php (70%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/AbstractProxyFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Cache/Cache.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Cache/CacheInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Cache/CacheManagerInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Cache/Directory.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/ConfigAwareInterface.php => src/Cache/DirectoryInterface.php} (56%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Cache/FileCacheManager.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Cache/FileHandler.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Cache/FileHandlerInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Cache/NullCacheManager.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Cache/Signature.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Cache/SignatureInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Config.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/ConfigInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidConfigurationException.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidFixerConfigurationException.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidForEnvFixerConfigurationException.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/RequiredFixerConfigurationException.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Application.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Command/DescribeCommand.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Command/DescribeNameNotFoundException.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Command/DocumentationCommand.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Command/FixCommand.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Command/FixCommandExitStatusCalculator.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Command/HelpCommand.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Command/ListFilesCommand.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Command/ListSetsCommand.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Command/SelfUpdateCommand.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/ConfigurationResolver.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Output/ErrorOutput.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Output/NullOutput.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Output/ProcessOutput.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/FinderInterface.php => src/Console/Output/ProcessOutputInterface.php} (68%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/CheckstyleReporter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/GitlabReporter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/JsonReporter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/JunitReporter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReportSummary.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReporterFactory.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReporterInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/TextReporter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/XmlReporter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/JsonReporter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReportSummary.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReporterFactory.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReporterInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/TextReporter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/GithubClient.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/GithubClientInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/NewVersionChecker.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/NewVersionCheckerInterface.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => src}/Console/WarningsDetector.php (51%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Differ/DiffConsoleFormatter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Differ/DifferInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Differ/FullDiffer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Differ/NullDiffer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Differ/SebastianBergmannDiffer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Differ/SebastianBergmannShortDiffer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Differ/UnifiedDiffer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/DocBlock/Annotation.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/DocBlock/DocBlock.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => src}/DocBlock/Line.php (84%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/DocBlock/ShortDescription.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/DocBlock/Tag.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => src}/DocBlock/TagComparator.php (70%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/DocBlock/TypeExpression.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Doctrine/Annotation/Token.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Doctrine/Annotation/Tokens.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Documentation/DocumentationGenerator.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Error/Error.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Error/ErrorsManager.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Event/Event.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FileReader.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => src}/FileRemoval.php (61%) rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => src}/Finder.php (83%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/AbstractIncrementOperatorFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/AbstractPhpUnitFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/ArrayPushFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/BacktickToShellExecFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Contrib => src/Fixer/Alias}/EregToPregFixer.php (58%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/MbStrFunctionsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoAliasFunctionsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoAliasLanguageConstructCallFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoMixedEchoPrintFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/PowToExponentiationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/RandomApiMigrationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/SetTypeToCastFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/ArraySyntaxFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoMultilineWhitespaceAroundDoubleArrowFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Symfony/SingleArrayNoTrailingCommaFixer.php => src/Fixer/ArrayNotation/NoTrailingCommaInSinglelineArrayFixer.php} (53%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoWhitespaceBeforeCommaInArrayFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NormalizeIndexBraceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/TrailingCommaInMultilineArrayFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Symfony => src/Fixer/ArrayNotation}/TrimArraySpacesFixer.php (52%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/WhitespaceAfterCommaInArrayFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/BracesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/EncodingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/NonPrintableCharacterFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/Psr0Fixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/Psr4Fixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/PsrAutoloadingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/ConstantCaseFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseConstantsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseKeywordsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseStaticReferenceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/MagicConstantCasingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/MagicMethodCasingFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Symfony => src/Fixer/Casing}/NativeFunctionCasingFixer.php (60%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/CastSpacesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/LowercaseCastFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/ModernizeTypesCastingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/NoShortBoolCastFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/NoUnsetCastFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/ShortScalarCastFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ClassAttributesSeparationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ClassDefinitionFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalClassFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalInternalClassFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalStaticAccessFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/MethodSeparationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoBlankLinesAfterClassOpeningFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoNullPropertyInitializationFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Contrib/Php4ConstructorFixer.php => src/Fixer/ClassNotation/NoPhp4ConstructorFixer.php} (55%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoUnneededFinalMethodFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedClassElementsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedInterfacesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedTraitsFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Contrib => src/Fixer/ClassNotation}/ProtectedToPrivateFixer.php (53%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SelfAccessorFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SelfStaticAccessorFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SingleClassElementPerStatementFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SingleTraitInsertPerStatementFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/VisibilityRequiredFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassUsage/DateTimeImmutableFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/CommentToPhpdocFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/HashToSlashCommentFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/HeaderCommentFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/MultilineCommentOpeningClosingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/NoEmptyCommentFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/NoTrailingWhitespaceInCommentFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/SingleLineCommentStyleFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ConfigurableFixerInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ConfigurationDefinitionFixerInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ConstantNotation/NativeConstantInvocationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/ElseifFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/IncludeFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoAlternativeSyntaxFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoBreakCommentFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoSuperfluousElseifFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Symfony/ListCommasFixer.php => src/Fixer/ControlStructure/NoTrailingCommaInListCallFixer.php} (65%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUnneededControlParenthesesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUnneededCurlyBracesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUselessElseFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SimplifiedIfReturnFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchCaseSpaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchContinueToBreakFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/TrailingCommaInMultilineFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/YodaStyleFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/DefinedFixerInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/DeprecatedFixerInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationArrayAssignmentFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationBracesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationIndentationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationSpacesFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => src/Fixer}/FixerInterface.php (53%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FopenFlagOrderFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FopenFlagsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FunctionDeclarationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FunctionTypehintSpaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/ImplodeCallFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/LambdaNotUsedImportFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NativeFunctionInvocationFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/PSR2/FunctionCallSpaceFixer.php => src/Fixer/FunctionNotation/NoSpacesAfterFunctionNameFixer.php} (52%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoUnreachableDefaultArgumentValueFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoUselessSprintfFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/RegularCallableCallFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/ReturnTypeDeclarationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/SingleLineThrowFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/StaticLambdaFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/UseArrowFunctionsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/VoidReturnFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/FullyQualifiedStrictTypesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/GlobalNamespaceImportFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/GroupImportFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/NoLeadingImportSlashFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/NoUnusedImportsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/OrderedImportsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/SingleImportPerStatementFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/SingleLineAfterImportsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ClassKeywordRemoveFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/CombineConsecutiveIssetsFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Contrib => src/Fixer/LanguageConstruct}/CombineConsecutiveUnsetsFixer.php (69%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/DeclareEqualNormalizeFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/DirConstantFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ErrorSuppressionFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ExplicitIndirectVariableFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/FunctionToConstantFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/IsNullFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/SilencedDeprecationErrorFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ListNotation/ListSyntaxFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/BlankLineAfterNamespaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/CleanNamespaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/NoLeadingNamespaceWhitespaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Naming/NoHomoglyphNamesFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Contrib/AlignDoubleArrowFixer.php => src/Fixer/Operator/AlignDoubleArrowFixerHelper.php} (64%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/AlignEqualsFixerHelper.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/BinaryOperatorSpacesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/ConcatSpaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/IncrementStyleFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/LogicalOperatorsFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Symfony => src/Fixer/Operator}/NewWithBracesFixer.php (50%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NotOperatorWithSpaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NotOperatorWithSuccessorSpaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/ObjectOperatorWithoutWhitespaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/OperatorLinebreakFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/PreIncrementFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/StandardizeIncrementFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/StandardizeNotEqualsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryOperatorSpacesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryToElvisOperatorFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryToNullCoalescingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/UnaryOperatorSpacesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/BlankLineAfterOpeningTagFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/EchoTagSyntaxFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/FullOpeningTagFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoClosingTagFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoShortEchoTagFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitConstructFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDedicateAssertInternalTypeFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitExpectationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitFqcnAnnotationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitInternalClassFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMethodCasingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMockFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitNoExpectationAnnotationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitOrderedCoversFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitSetUpTearDownVisibilityFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitSizeClassFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitStrictFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTargetVersion.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestClassRequiresCoversFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/AlignMultilineCommentFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/GeneralPhpdocAnnotationRemoveFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/GeneralPhpdocTagRenameFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoEmptyPhpdocFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAddMissingParamAnnotationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAlignFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocIndentFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocInlineTagFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocLineSpanFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoAccessFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoAliasTagFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoEmptyReturnFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoPackageFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocOrderByValueFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Contrib => src/Fixer/Phpdoc}/PhpdocOrderFixer.php (64%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocScalarFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Symfony => src/Fixer/Phpdoc}/PhpdocSeparationFixer.php (59%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSummaryFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTagCasingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTagTypeFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocToCommentFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTrimConsecutiveBlankLineSeparationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTrimFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTypesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTypesOrderFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocVarAnnotationCorrectOrderFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocVarWithoutNameFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/BlankLineBeforeReturnFixer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS/Fixer/Contrib => src/Fixer/ReturnNotation}/NoUselessReturnFixer.php (54%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/ReturnAssignmentFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/SimplifiedNullReturnFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/MultilineWhitespaceBeforeSemicolonsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoEmptyStatementFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoMultilineWhitespaceBeforeSemicolonsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/SemicolonAfterInstructionFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/SpaceAfterSemicolonFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/DeclareStrictTypesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/StrictComparisonFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/StrictParamFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/ExplicitStringVariableFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/HeredocToNowdocFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/NoBinaryStringFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/NoTrailingWhitespaceInStringFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/SimpleToComplexStringVariableFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/SingleQuoteFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/StringLineEndingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/ArrayIndentationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/BlankLineBeforeStatementFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/CompactNullableTypehintFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/HeredocIndentationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/IndentationTypeFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/LineEndingFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/MethodChainingIndentationFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoExtraBlankLinesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoExtraConsecutiveBlankLinesFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoSpacesAroundOffsetFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoSpacesInsideParenthesisFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoTrailingWhitespaceFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoWhitespaceInBlankLineFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/SingleBlankLineAtEofFixer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Fixer/WhitespacesAwareFixerInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AliasedFixerOption.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AliasedFixerOptionBuilder.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AllowedValueSubset.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/DeprecatedFixerOption.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/DeprecatedFixerOptionInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolver.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolverInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolverRootless.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOption.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOptionBuilder.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOptionInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/InvalidOptionsForEnvException.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/CodeSample.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/CodeSampleInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FileSpecificCodeSample.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FileSpecificCodeSampleInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FixerDefinition.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FixerDefinitionInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificCodeSample.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificCodeSampleInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecification.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificationInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerFactory.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerFileProcessedEvent.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/FixerNameValidator.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Indicator/PhpUnitTestCaseIndicator.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/CachingLinter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/Linter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/LinterInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/LintingException.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/LintingResultInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLinter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLinterProcessBuilder.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLintingResult.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/TokenizerLinter.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/TokenizerLintingResult.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Linter/UnavailableLinterException.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/PharChecker.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/PharCheckerInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Preg.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/PregException.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/AbstractRuleSetDescription.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSetDescriptionInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSetInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSets.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/DoctrineAnnotationSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP54MigrationSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP56MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP56MigrationSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP70MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP70MigrationSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP71MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP71MigrationSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP73MigrationSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP74MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP74MigrationSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP80MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP80MigrationSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit30MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit32MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit35MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit43MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit48MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit50MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit52MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit54MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit55MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit56MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit57MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12RiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12Set.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR1Set.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR2Set.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PhpCsFixerRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PhpCsFixerSet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/SymfonyRiskySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/SymfonySet.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/RuleSetInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Runner/FileCachingLintingIterator.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Runner/FileFilterIterator.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Runner/FileLintingIterator.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Runner/Runner.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => src}/StdinFileInfo.php (72%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Test/AbstractFixerTestCase.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Test/AbstractIntegrationTestCase.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Test/AccessibleObject.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Test/IntegrationCase.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => src}/Tokenizer/AbstractTransformer.php (52%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/ArgumentAnalysis.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/CaseAnalysis.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/NamespaceAnalysis.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/NamespaceUseAnalysis.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/StartEndTokenAwareAnalysis.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/SwitchAnalysis.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/TypeAnalysis.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ArgumentsAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/BlocksAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ClassyAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/CommentsAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/FunctionsAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/GotoLabelAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/NamespaceUsesAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/NamespacesAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ReferenceAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/SwitchAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/WhitespacesAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/CT.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/CodeHasher.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Generator/NamespacedStringTokenGenerator.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Resolver/TypeShortNameResolver.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Token.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Tokens.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/TokensAnalyzer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ArrayTypehintTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/AttributeTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/BraceClassInstantiationTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ClassConstantTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ConstructorPromotionTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/CurlyBraceTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ImportTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NameQualifiedTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NamedArgumentTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NamespaceOperatorTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NullableTypeTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ReturnRefTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/SquareBraceTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/TypeAlternationTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/TypeColonTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/UseTransformer.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/WhitespacyCommentTransformer.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => src}/Tokenizer/TransformerInterface.php (58%) create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformers.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/ToolInfo.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/ToolInfoInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/Utils.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/WhitespacesFixerConfig.php create mode 100644 vendor/friendsofphp/php-cs-fixer/src/WordMatcher.php create mode 100644 vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractFixerTestCase.php create mode 100644 vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationCaseFactory.php create mode 100644 vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationTestCase.php create mode 100644 vendor/friendsofphp/php-cs-fixer/tests/Test/Assert/AssertTokensTrait.php rename vendor/friendsofphp/php-cs-fixer/{Symfony/CS => tests}/Test/IntegrationCase.php (54%) create mode 100644 vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactory.php create mode 100644 vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactoryInterface.php create mode 100644 vendor/friendsofphp/php-cs-fixer/tests/Test/InternalIntegrationCaseFactory.php create mode 100644 vendor/friendsofphp/php-cs-fixer/tests/Test/IsIdenticalConstraint.php create mode 100644 vendor/friendsofphp/php-cs-fixer/tests/Test/TokensWithObservedTransformers.php create mode 100644 vendor/friendsofphp/php-cs-fixer/tests/TestCase.php create mode 100644 vendor/guzzlehttp/guzzle/src/BodySummarizer.php create mode 100644 vendor/guzzlehttp/guzzle/src/BodySummarizerInterface.php create mode 100644 vendor/guzzlehttp/guzzle/src/ClientTrait.php create mode 100644 vendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php delete mode 100644 vendor/guzzlehttp/guzzle/src/Exception/SeekException.php create mode 100644 vendor/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php create mode 100644 vendor/guzzlehttp/guzzle/src/MessageFormatterInterface.php delete mode 100644 vendor/guzzlehttp/guzzle/src/UriTemplate.php create mode 100644 vendor/guzzlehttp/guzzle/src/Utils.php delete mode 100644 vendor/guzzlehttp/promises/Makefile create mode 100644 vendor/guzzlehttp/promises/src/Create.php create mode 100644 vendor/guzzlehttp/promises/src/Each.php create mode 100644 vendor/guzzlehttp/promises/src/Is.php create mode 100644 vendor/guzzlehttp/promises/src/Utils.php delete mode 100644 vendor/guzzlehttp/promises/src/functions.php delete mode 100644 vendor/guzzlehttp/promises/src/functions_include.php create mode 100644 vendor/guzzlehttp/promises/vendor-bin/php-cs-fixer/composer.json create mode 100644 vendor/guzzlehttp/promises/vendor-bin/phpstan/composer.json create mode 100644 vendor/guzzlehttp/promises/vendor-bin/psalm/composer.json create mode 100644 vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php create mode 100644 vendor/guzzlehttp/psr7/src/Header.php create mode 100644 vendor/guzzlehttp/psr7/src/HttpFactory.php create mode 100644 vendor/guzzlehttp/psr7/src/Message.php create mode 100644 vendor/guzzlehttp/psr7/src/MimeType.php create mode 100644 vendor/guzzlehttp/psr7/src/Query.php create mode 100644 vendor/guzzlehttp/psr7/src/Rfc7230.php create mode 100644 vendor/guzzlehttp/psr7/src/UriComparator.php create mode 100644 vendor/guzzlehttp/psr7/src/Utils.php delete mode 100644 vendor/guzzlehttp/psr7/src/functions.php delete mode 100644 vendor/guzzlehttp/psr7/src/functions_include.php create mode 100644 vendor/php-cs-fixer/diff/ChangeLog.md create mode 100644 vendor/php-cs-fixer/diff/LICENSE create mode 100644 vendor/php-cs-fixer/diff/LICENSE_DIFF create mode 100644 vendor/php-cs-fixer/diff/LICENSE_GECKO create mode 100644 vendor/php-cs-fixer/diff/README.md create mode 100644 vendor/php-cs-fixer/diff/composer.json create mode 100644 vendor/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/ConfigurationException.php create mode 100644 vendor/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/UnifiedDiffOutputBuilder.php create mode 100644 vendor/php-cs-fixer/diff/src/v1_4/Chunk.php create mode 100644 vendor/php-cs-fixer/diff/src/v1_4/Diff.php create mode 100644 vendor/php-cs-fixer/diff/src/v1_4/Differ.php create mode 100644 vendor/php-cs-fixer/diff/src/v1_4/LCS/LongestCommonSubsequence.php create mode 100644 vendor/php-cs-fixer/diff/src/v1_4/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php create mode 100644 vendor/php-cs-fixer/diff/src/v1_4/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php create mode 100644 vendor/php-cs-fixer/diff/src/v1_4/Line.php create mode 100644 vendor/php-cs-fixer/diff/src/v1_4/Parser.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Chunk.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Diff.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Differ.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Exception/Exception.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Exception/InvalidArgumentException.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Line.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/LongestCommonSubsequenceCalculator.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/MemoryEfficientLongestCommonSubsequenceCalculator.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Output/AbstractChunkOutputBuilder.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Output/DiffOnlyOutputBuilder.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Output/DiffOutputBuilderInterface.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Output/UnifiedDiffOutputBuilder.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/Parser.php create mode 100644 vendor/php-cs-fixer/diff/src/v2_0/TimeEfficientLongestCommonSubsequenceCalculator.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Chunk.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Diff.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Differ.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Exception/ConfigurationException.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Exception/Exception.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Exception/InvalidArgumentException.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Line.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/LongestCommonSubsequenceCalculator.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/MemoryEfficientLongestCommonSubsequenceCalculator.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Output/AbstractChunkOutputBuilder.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Output/DiffOnlyOutputBuilder.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Output/DiffOutputBuilderInterface.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Output/StrictUnifiedDiffOutputBuilder.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Output/UnifiedDiffOutputBuilder.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/Parser.php create mode 100644 vendor/php-cs-fixer/diff/src/v3_0/TimeEfficientLongestCommonSubsequenceCalculator.php create mode 100644 vendor/phpdocumentor/reflection-common/.github/dependabot.yml create mode 100644 vendor/phpdocumentor/reflection-common/.github/workflows/push.yml delete mode 100644 vendor/phpdocumentor/reflection-common/.travis.yml delete mode 100644 vendor/phpdocumentor/reflection-docblock/.coveralls.yml delete mode 100644 vendor/phpdocumentor/reflection-docblock/easy-coding-standard.neon delete mode 100644 vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Strategy.php create mode 100644 vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php create mode 100644 vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php create mode 100644 vendor/phpdocumentor/reflection-docblock/src/Exception/PcreException.php create mode 100644 vendor/phpdocumentor/reflection-docblock/src/Utils.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoType.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/False_.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/List_.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.php create mode 100644 vendor/phpdocumentor/type-resolver/src/PseudoTypes/True_.php create mode 100644 vendor/phpdocumentor/type-resolver/src/Types/AbstractList.php create mode 100644 vendor/phpdocumentor/type-resolver/src/Types/AggregatedType.php create mode 100644 vendor/phpdocumentor/type-resolver/src/Types/ArrayKey.php create mode 100644 vendor/phpdocumentor/type-resolver/src/Types/ClassString.php create mode 100644 vendor/phpdocumentor/type-resolver/src/Types/Collection.php create mode 100644 vendor/phpdocumentor/type-resolver/src/Types/Expression.php create mode 100644 vendor/phpdocumentor/type-resolver/src/Types/InterfaceString.php create mode 100644 vendor/phpdocumentor/type-resolver/src/Types/Intersection.php create mode 100644 vendor/phpdocumentor/type-resolver/src/Types/Never_.php create mode 100644 vendor/psr/cache/CHANGELOG.md create mode 100644 vendor/psr/cache/LICENSE.txt create mode 100644 vendor/psr/cache/README.md create mode 100644 vendor/psr/cache/composer.json create mode 100644 vendor/psr/cache/src/CacheException.php create mode 100644 vendor/psr/cache/src/CacheItemInterface.php create mode 100644 vendor/psr/cache/src/CacheItemPoolInterface.php create mode 100644 vendor/psr/cache/src/InvalidArgumentException.php create mode 100644 vendor/psr/container/.gitignore create mode 100644 vendor/psr/container/LICENSE create mode 100644 vendor/psr/container/README.md create mode 100644 vendor/psr/container/composer.json create mode 100644 vendor/psr/container/src/ContainerExceptionInterface.php create mode 100644 vendor/psr/container/src/ContainerInterface.php create mode 100644 vendor/psr/container/src/NotFoundExceptionInterface.php create mode 100644 vendor/psr/event-dispatcher/.editorconfig create mode 100644 vendor/psr/event-dispatcher/.gitignore create mode 100644 vendor/psr/event-dispatcher/LICENSE create mode 100644 vendor/psr/event-dispatcher/README.md create mode 100644 vendor/psr/event-dispatcher/composer.json create mode 100644 vendor/psr/event-dispatcher/src/EventDispatcherInterface.php create mode 100644 vendor/psr/event-dispatcher/src/ListenerProviderInterface.php create mode 100644 vendor/psr/event-dispatcher/src/StoppableEventInterface.php create mode 100644 vendor/psr/http-client/CHANGELOG.md create mode 100644 vendor/psr/http-client/LICENSE create mode 100644 vendor/psr/http-client/README.md create mode 100644 vendor/psr/http-client/composer.json create mode 100644 vendor/psr/http-client/src/ClientExceptionInterface.php create mode 100644 vendor/psr/http-client/src/ClientInterface.php create mode 100644 vendor/psr/http-client/src/NetworkExceptionInterface.php create mode 100644 vendor/psr/http-client/src/RequestExceptionInterface.php create mode 100644 vendor/psr/http-factory/LICENSE create mode 100644 vendor/psr/http-factory/README.md create mode 100644 vendor/psr/http-factory/composer.json create mode 100644 vendor/psr/http-factory/src/RequestFactoryInterface.php create mode 100644 vendor/psr/http-factory/src/ResponseFactoryInterface.php create mode 100644 vendor/psr/http-factory/src/ServerRequestFactoryInterface.php create mode 100644 vendor/psr/http-factory/src/StreamFactoryInterface.php create mode 100644 vendor/psr/http-factory/src/UploadedFileFactoryInterface.php create mode 100644 vendor/psr/http-factory/src/UriFactoryInterface.php create mode 100644 vendor/psr/http-message/docs/PSR7-Interfaces.md create mode 100644 vendor/psr/http-message/docs/PSR7-Usage.md delete mode 100644 vendor/psr/log/.gitignore create mode 100644 vendor/psr/log/Psr/Log/Test/DummyTest.php create mode 100644 vendor/psr/log/Psr/Log/Test/TestLogger.php create mode 100644 vendor/ralouphie/getallheaders/LICENSE create mode 100644 vendor/ralouphie/getallheaders/README.md create mode 100644 vendor/ralouphie/getallheaders/composer.json create mode 100644 vendor/ralouphie/getallheaders/src/getallheaders.php create mode 100644 vendor/symfony/console/Attribute/AsCommand.php create mode 100644 vendor/symfony/console/CI/GithubActionReporter.php create mode 100644 vendor/symfony/console/Color.php create mode 100644 vendor/symfony/console/Command/CompleteCommand.php create mode 100644 vendor/symfony/console/Command/DumpCompletionCommand.php create mode 100644 vendor/symfony/console/Command/LazyCommand.php create mode 100644 vendor/symfony/console/Command/SignalableCommandInterface.php create mode 100644 vendor/symfony/console/Completion/CompletionInput.php create mode 100644 vendor/symfony/console/Completion/CompletionSuggestions.php create mode 100644 vendor/symfony/console/Completion/Output/BashCompletionOutput.php create mode 100644 vendor/symfony/console/Completion/Output/CompletionOutputInterface.php create mode 100644 vendor/symfony/console/Completion/Suggestion.php create mode 100644 vendor/symfony/console/Cursor.php delete mode 100644 vendor/symfony/console/Event/ConsoleExceptionEvent.php create mode 100644 vendor/symfony/console/Event/ConsoleSignalEvent.php create mode 100644 vendor/symfony/console/Exception/MissingInputException.php create mode 100644 vendor/symfony/console/Exception/NamespaceNotFoundException.php create mode 100644 vendor/symfony/console/Formatter/NullOutputFormatter.php create mode 100644 vendor/symfony/console/Formatter/NullOutputFormatterStyle.php create mode 100644 vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php create mode 100644 vendor/symfony/console/Helper/Dumper.php create mode 100644 vendor/symfony/console/Helper/TableCellStyle.php create mode 100644 vendor/symfony/console/Helper/TableRows.php create mode 100644 vendor/symfony/console/Output/ConsoleSectionOutput.php create mode 100644 vendor/symfony/console/Output/TrimmedBufferOutput.php create mode 100644 vendor/symfony/console/Resources/completion.bash create mode 100644 vendor/symfony/console/SignalRegistry/SignalRegistry.php create mode 100644 vendor/symfony/console/SingleCommandApplication.php create mode 100644 vendor/symfony/console/Tester/CommandCompletionTester.php create mode 100644 vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php create mode 100644 vendor/symfony/console/Tester/TesterTrait.php delete mode 100644 vendor/symfony/console/Tests/ApplicationTest.php delete mode 100644 vendor/symfony/console/Tests/Command/CommandTest.php delete mode 100644 vendor/symfony/console/Tests/Command/HelpCommandTest.php delete mode 100644 vendor/symfony/console/Tests/Command/ListCommandTest.php delete mode 100644 vendor/symfony/console/Tests/Command/LockableTraitTest.php delete mode 100644 vendor/symfony/console/Tests/CommandLoader/ContainerCommandLoaderTest.php delete mode 100644 vendor/symfony/console/Tests/CommandLoader/FactoryCommandLoaderTest.php delete mode 100644 vendor/symfony/console/Tests/DependencyInjection/AddConsoleCommandPassTest.php delete mode 100644 vendor/symfony/console/Tests/Descriptor/AbstractDescriptorTest.php delete mode 100644 vendor/symfony/console/Tests/Descriptor/JsonDescriptorTest.php delete mode 100644 vendor/symfony/console/Tests/Descriptor/MarkdownDescriptorTest.php delete mode 100644 vendor/symfony/console/Tests/Descriptor/ObjectsProvider.php delete mode 100644 vendor/symfony/console/Tests/Descriptor/TextDescriptorTest.php delete mode 100644 vendor/symfony/console/Tests/Descriptor/XmlDescriptorTest.php delete mode 100644 vendor/symfony/console/Tests/EventListener/ErrorListenerTest.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/BarBucCommand.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorApplication2.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorApplicationMbString.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorCommand1.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorCommand2.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorCommand3.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorCommand4.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/DescriptorCommandMbString.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/DummyOutput.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Foo1Command.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Foo2Command.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Foo3Command.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Foo4Command.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Foo5Command.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Foo6Command.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/FooCommand.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/FooLock2Command.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/FooLockCommand.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/FooOptCommand.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/FooSameCaseLowercaseCommand.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/FooSameCaseUppercaseCommand.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/FooSubnamespaced1Command.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/FooSubnamespaced2Command.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/FoobarCommand.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_0.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_1.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_12.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_13.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_14.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_15.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_16.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_17.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_2.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_3.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_4.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_5.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_6.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_7.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_8.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/interactive_command_1.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/interactive_output_1.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_0.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_1.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_10.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_12.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_14.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_15.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_16.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_17.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_2.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_3.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_4.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_5.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_6.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_7.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_8.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_9.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/TestCommand.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/TestTiti.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/TestToto.php delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_1.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_1.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_1.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_1.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_2.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_2.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_2.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_2.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_filtered_namespace.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_gethelp.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_mbstring.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_mbstring.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception1.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception2.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception3.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception3decorated.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception4.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth2.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception_escapeslines.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_renderexception_linebreaks.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_run1.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_run2.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_run3.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/application_run4.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/command_1.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/command_1.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/command_1.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/command_1.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/command_2.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/command_2.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/command_2.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/command_2.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/command_mbstring.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/command_mbstring.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_1.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_1.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_1.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_1.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_2.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_2.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_2.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_2.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_3.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_3.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_3.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_3.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_4.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_4.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_4.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_4.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_with_style.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_with_style.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_with_style.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_argument_with_style.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_1.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_1.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_1.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_1.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_2.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_2.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_2.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_2.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_3.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_3.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_3.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_3.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_4.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_4.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_4.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_definition_4.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_1.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_1.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_1.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_1.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_2.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_2.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_2.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_2.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_3.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_3.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_3.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_3.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_4.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_4.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_4.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_4.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_5.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_5.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_5.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_5.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_6.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_6.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_6.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_6.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_style.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_style.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_style.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_style.xml delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.json delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.md delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.txt delete mode 100644 vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.xml delete mode 100644 vendor/symfony/console/Tests/Formatter/OutputFormatterStyleStackTest.php delete mode 100644 vendor/symfony/console/Tests/Formatter/OutputFormatterStyleTest.php delete mode 100644 vendor/symfony/console/Tests/Formatter/OutputFormatterTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/AbstractQuestionHelperTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/FormatterHelperTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/HelperSetTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/HelperTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/ProcessHelperTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/ProgressBarTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/QuestionHelperTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/SymfonyQuestionHelperTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/TableStyleTest.php delete mode 100644 vendor/symfony/console/Tests/Helper/TableTest.php delete mode 100644 vendor/symfony/console/Tests/Input/ArgvInputTest.php delete mode 100644 vendor/symfony/console/Tests/Input/ArrayInputTest.php delete mode 100644 vendor/symfony/console/Tests/Input/InputArgumentTest.php delete mode 100644 vendor/symfony/console/Tests/Input/InputDefinitionTest.php delete mode 100644 vendor/symfony/console/Tests/Input/InputOptionTest.php delete mode 100644 vendor/symfony/console/Tests/Input/InputTest.php delete mode 100644 vendor/symfony/console/Tests/Input/StringInputTest.php delete mode 100644 vendor/symfony/console/Tests/Logger/ConsoleLoggerTest.php delete mode 100644 vendor/symfony/console/Tests/Output/ConsoleOutputTest.php delete mode 100644 vendor/symfony/console/Tests/Output/NullOutputTest.php delete mode 100644 vendor/symfony/console/Tests/Output/OutputTest.php delete mode 100644 vendor/symfony/console/Tests/Output/StreamOutputTest.php delete mode 100644 vendor/symfony/console/Tests/Style/SymfonyStyleTest.php delete mode 100644 vendor/symfony/console/Tests/TerminalTest.php delete mode 100644 vendor/symfony/console/Tests/Tester/ApplicationTesterTest.php delete mode 100644 vendor/symfony/console/Tests/Tester/CommandTesterTest.php delete mode 100644 vendor/symfony/console/phpunit.xml.dist delete mode 100644 vendor/symfony/debug/BufferingLogger.php delete mode 100644 vendor/symfony/debug/CHANGELOG.md delete mode 100644 vendor/symfony/debug/Debug.php delete mode 100644 vendor/symfony/debug/DebugClassLoader.php delete mode 100644 vendor/symfony/debug/ErrorHandler.php delete mode 100644 vendor/symfony/debug/Exception/ClassNotFoundException.php delete mode 100644 vendor/symfony/debug/Exception/FatalErrorException.php delete mode 100644 vendor/symfony/debug/Exception/FatalThrowableError.php delete mode 100644 vendor/symfony/debug/Exception/FlattenException.php delete mode 100644 vendor/symfony/debug/Exception/SilencedErrorContext.php delete mode 100644 vendor/symfony/debug/Exception/UndefinedFunctionException.php delete mode 100644 vendor/symfony/debug/Exception/UndefinedMethodException.php delete mode 100644 vendor/symfony/debug/ExceptionHandler.php delete mode 100644 vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php delete mode 100644 vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php delete mode 100644 vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php delete mode 100644 vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php delete mode 100644 vendor/symfony/debug/README.md delete mode 100644 vendor/symfony/debug/Tests/DebugClassLoaderTest.php delete mode 100644 vendor/symfony/debug/Tests/ErrorHandlerTest.php delete mode 100644 vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php delete mode 100644 vendor/symfony/debug/Tests/ExceptionHandlerTest.php delete mode 100644 vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php delete mode 100644 vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php delete mode 100644 vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/ClassAlias.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/FinalClass.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/FinalMethod.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/InternalClass.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/InternalInterface.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/InternalTrait.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/PEARClass.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/Throwing.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/casemismatch.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php delete mode 100644 vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php delete mode 100644 vendor/symfony/debug/Tests/HeaderMock.php delete mode 100644 vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt delete mode 100644 vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt delete mode 100644 vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt delete mode 100644 vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt delete mode 100644 vendor/symfony/debug/composer.json delete mode 100644 vendor/symfony/debug/phpunit.xml.dist rename vendor/symfony/{console => deprecation-contracts}/.gitignore (100%) create mode 100644 vendor/symfony/deprecation-contracts/CHANGELOG.md rename vendor/symfony/{debug => deprecation-contracts}/LICENSE (96%) create mode 100644 vendor/symfony/deprecation-contracts/README.md create mode 100644 vendor/symfony/deprecation-contracts/composer.json create mode 100644 vendor/symfony/deprecation-contracts/function.php rename vendor/symfony/{debug => event-dispatcher-contracts}/.gitignore (100%) create mode 100644 vendor/symfony/event-dispatcher-contracts/CHANGELOG.md rename vendor/symfony/{event-dispatcher => event-dispatcher-contracts}/Event.php (74%) create mode 100644 vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php create mode 100644 vendor/symfony/event-dispatcher-contracts/LICENSE create mode 100644 vendor/symfony/event-dispatcher-contracts/README.md create mode 100644 vendor/symfony/event-dispatcher-contracts/composer.json create mode 100644 vendor/symfony/event-dispatcher/Attribute/AsEventListener.php delete mode 100644 vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php delete mode 100644 vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php create mode 100644 vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php create mode 100644 vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php delete mode 100644 vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php delete mode 100644 vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php delete mode 100644 vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php delete mode 100644 vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php delete mode 100644 vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php delete mode 100644 vendor/symfony/event-dispatcher/Tests/EventTest.php delete mode 100644 vendor/symfony/event-dispatcher/Tests/GenericEventTest.php delete mode 100644 vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php delete mode 100644 vendor/symfony/event-dispatcher/phpunit.xml.dist delete mode 100644 vendor/symfony/filesystem/.gitignore create mode 100644 vendor/symfony/filesystem/Exception/InvalidArgumentException.php create mode 100644 vendor/symfony/filesystem/Exception/RuntimeException.php delete mode 100644 vendor/symfony/filesystem/LockHandler.php create mode 100644 vendor/symfony/filesystem/Path.php delete mode 100644 vendor/symfony/filesystem/Tests/ExceptionTest.php delete mode 100644 vendor/symfony/filesystem/Tests/FilesystemTest.php delete mode 100644 vendor/symfony/filesystem/Tests/FilesystemTestCase.php delete mode 100644 vendor/symfony/filesystem/Tests/Fixtures/MockStream/MockStream.php delete mode 100644 vendor/symfony/filesystem/Tests/LockHandlerTest.php delete mode 100644 vendor/symfony/filesystem/phpunit.xml.dist delete mode 100644 vendor/symfony/finder/.gitignore rename vendor/symfony/{debug/Exception/OutOfMemoryException.php => finder/Exception/DirectoryNotFoundException.php} (59%) delete mode 100644 vendor/symfony/finder/Exception/ExceptionInterface.php create mode 100644 vendor/symfony/finder/Gitignore.php delete mode 100644 vendor/symfony/finder/Iterator/FilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/LazyIterator.php create mode 100644 vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php delete mode 100644 vendor/symfony/finder/Tests/Comparator/ComparatorTest.php delete mode 100644 vendor/symfony/finder/Tests/Comparator/DateComparatorTest.php delete mode 100644 vendor/symfony/finder/Tests/Comparator/NumberComparatorTest.php delete mode 100644 vendor/symfony/finder/Tests/FinderTest.php delete mode 100644 vendor/symfony/finder/Tests/Fixtures/.dot/a delete mode 100644 vendor/symfony/finder/Tests/Fixtures/.dot/b/c.neon delete mode 100644 vendor/symfony/finder/Tests/Fixtures/.dot/b/d.neon delete mode 100644 vendor/symfony/finder/Tests/Fixtures/A/B/C/abc.dat delete mode 100644 vendor/symfony/finder/Tests/Fixtures/A/B/ab.dat delete mode 100644 vendor/symfony/finder/Tests/Fixtures/A/a.dat delete mode 100644 vendor/symfony/finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy delete mode 100644 vendor/symfony/finder/Tests/Fixtures/copy/A/B/ab.dat.copy delete mode 100644 vendor/symfony/finder/Tests/Fixtures/copy/A/a.dat.copy delete mode 100644 vendor/symfony/finder/Tests/Fixtures/dolor.txt delete mode 100644 vendor/symfony/finder/Tests/Fixtures/ipsum.txt delete mode 100644 vendor/symfony/finder/Tests/Fixtures/lorem.txt delete mode 100644 vendor/symfony/finder/Tests/Fixtures/one/.dot delete mode 100644 vendor/symfony/finder/Tests/Fixtures/one/a delete mode 100644 vendor/symfony/finder/Tests/Fixtures/one/b/c.neon delete mode 100644 vendor/symfony/finder/Tests/Fixtures/one/b/d.neon delete mode 100644 vendor/symfony/finder/Tests/Fixtures/r+e.gex[c]a(r)s/dir/bar.dat delete mode 100644 vendor/symfony/finder/Tests/Fixtures/with space/foo.txt delete mode 100644 vendor/symfony/finder/Tests/GlobTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/CustomFilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/DateRangeFilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/DepthRangeFilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/FileTypeFilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/FilecontentFilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/FilenameFilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/FilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/Iterator.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/IteratorTestCase.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/MockFileListIterator.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/MockSplFileInfo.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/PathFilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/SizeRangeFilterIteratorTest.php delete mode 100644 vendor/symfony/finder/Tests/Iterator/SortableIteratorTest.php delete mode 100644 vendor/symfony/finder/phpunit.xml.dist create mode 100644 vendor/symfony/options-resolver/CHANGELOG.md create mode 100644 vendor/symfony/options-resolver/Debug/OptionsResolverIntrospector.php create mode 100644 vendor/symfony/options-resolver/Exception/AccessException.php create mode 100644 vendor/symfony/options-resolver/Exception/ExceptionInterface.php create mode 100644 vendor/symfony/options-resolver/Exception/InvalidArgumentException.php create mode 100644 vendor/symfony/options-resolver/Exception/InvalidOptionsException.php create mode 100644 vendor/symfony/options-resolver/Exception/MissingOptionsException.php create mode 100644 vendor/symfony/options-resolver/Exception/NoConfigurationException.php create mode 100644 vendor/symfony/options-resolver/Exception/NoSuchOptionException.php create mode 100644 vendor/symfony/options-resolver/Exception/OptionDefinitionException.php create mode 100644 vendor/symfony/options-resolver/Exception/UndefinedOptionsException.php create mode 100644 vendor/symfony/options-resolver/LICENSE create mode 100644 vendor/symfony/options-resolver/OptionConfigurator.php create mode 100644 vendor/symfony/options-resolver/Options.php create mode 100644 vendor/symfony/options-resolver/OptionsResolver.php create mode 100644 vendor/symfony/options-resolver/README.md create mode 100644 vendor/symfony/options-resolver/composer.json create mode 100644 vendor/symfony/polyfill-ctype/bootstrap80.php create mode 100644 vendor/symfony/polyfill-intl-grapheme/Grapheme.php create mode 100644 vendor/symfony/polyfill-intl-grapheme/LICENSE create mode 100644 vendor/symfony/polyfill-intl-grapheme/README.md create mode 100644 vendor/symfony/polyfill-intl-grapheme/bootstrap.php create mode 100644 vendor/symfony/polyfill-intl-grapheme/bootstrap80.php create mode 100644 vendor/symfony/polyfill-intl-grapheme/composer.json create mode 100644 vendor/symfony/polyfill-intl-normalizer/LICENSE create mode 100644 vendor/symfony/polyfill-intl-normalizer/Normalizer.php create mode 100644 vendor/symfony/polyfill-intl-normalizer/README.md create mode 100644 vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php create mode 100644 vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php create mode 100644 vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php create mode 100644 vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php create mode 100644 vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php create mode 100644 vendor/symfony/polyfill-intl-normalizer/bootstrap.php create mode 100644 vendor/symfony/polyfill-intl-normalizer/bootstrap80.php create mode 100644 vendor/symfony/polyfill-intl-normalizer/composer.json create mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php create mode 100644 vendor/symfony/polyfill-mbstring/bootstrap80.php create mode 100644 vendor/symfony/polyfill-php72/LICENSE create mode 100644 vendor/symfony/polyfill-php72/Php72.php create mode 100644 vendor/symfony/polyfill-php72/README.md create mode 100644 vendor/symfony/polyfill-php72/bootstrap.php create mode 100644 vendor/symfony/polyfill-php72/composer.json create mode 100644 vendor/symfony/polyfill-php73/LICENSE create mode 100644 vendor/symfony/polyfill-php73/Php73.php create mode 100644 vendor/symfony/polyfill-php73/README.md rename vendor/symfony/{debug/Tests/MockExceptionHandler.php => polyfill-php73/Resources/stubs/JsonException.php} (52%) create mode 100644 vendor/symfony/polyfill-php73/bootstrap.php create mode 100644 vendor/symfony/polyfill-php73/composer.json create mode 100644 vendor/symfony/polyfill-php80/LICENSE create mode 100644 vendor/symfony/polyfill-php80/Php80.php create mode 100644 vendor/symfony/polyfill-php80/PhpToken.php create mode 100644 vendor/symfony/polyfill-php80/README.md create mode 100644 vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php create mode 100644 vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php create mode 100644 vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php create mode 100644 vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php create mode 100644 vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php create mode 100644 vendor/symfony/polyfill-php80/bootstrap.php create mode 100644 vendor/symfony/polyfill-php80/composer.json delete mode 100644 vendor/symfony/process/.gitignore create mode 100644 vendor/symfony/process/Exception/ProcessSignaledException.php delete mode 100644 vendor/symfony/process/ProcessBuilder.php delete mode 100644 vendor/symfony/process/Tests/ExecutableFinderTest.php delete mode 100644 vendor/symfony/process/Tests/NonStopableProcess.php delete mode 100644 vendor/symfony/process/Tests/PhpExecutableFinderTest.php delete mode 100644 vendor/symfony/process/Tests/PhpProcessTest.php delete mode 100644 vendor/symfony/process/Tests/PipeStdinInStdoutStdErrStreamSelect.php delete mode 100644 vendor/symfony/process/Tests/ProcessBuilderTest.php delete mode 100644 vendor/symfony/process/Tests/ProcessFailedExceptionTest.php delete mode 100644 vendor/symfony/process/Tests/ProcessTest.php delete mode 100644 vendor/symfony/process/Tests/ProcessUtilsTest.php delete mode 100644 vendor/symfony/process/phpunit.xml.dist rename vendor/symfony/{event-dispatcher => service-contracts}/.gitignore (100%) create mode 100644 vendor/symfony/service-contracts/Attribute/Required.php create mode 100644 vendor/symfony/service-contracts/Attribute/SubscribedService.php create mode 100644 vendor/symfony/service-contracts/CHANGELOG.md create mode 100644 vendor/symfony/service-contracts/LICENSE create mode 100644 vendor/symfony/service-contracts/README.md create mode 100644 vendor/symfony/service-contracts/ResetInterface.php create mode 100644 vendor/symfony/service-contracts/ServiceLocatorTrait.php create mode 100644 vendor/symfony/service-contracts/ServiceProviderInterface.php create mode 100644 vendor/symfony/service-contracts/ServiceSubscriberInterface.php create mode 100644 vendor/symfony/service-contracts/ServiceSubscriberTrait.php create mode 100644 vendor/symfony/service-contracts/Test/ServiceLocatorTest.php create mode 100644 vendor/symfony/service-contracts/composer.json delete mode 100644 vendor/symfony/stopwatch/.gitignore delete mode 100644 vendor/symfony/stopwatch/Tests/StopwatchEventTest.php delete mode 100644 vendor/symfony/stopwatch/Tests/StopwatchPeriodTest.php delete mode 100644 vendor/symfony/stopwatch/Tests/StopwatchTest.php delete mode 100644 vendor/symfony/stopwatch/phpunit.xml.dist create mode 100644 vendor/symfony/string/AbstractString.php create mode 100644 vendor/symfony/string/AbstractUnicodeString.php create mode 100644 vendor/symfony/string/ByteString.php create mode 100644 vendor/symfony/string/CHANGELOG.md create mode 100644 vendor/symfony/string/CodePointString.php rename vendor/symfony/{console/Tests/Fixtures/DescriptorApplication1.php => string/Exception/ExceptionInterface.php} (62%) rename vendor/symfony/{process/Tests/SignalListener.php => string/Exception/InvalidArgumentException.php} (60%) create mode 100644 vendor/symfony/string/Exception/RuntimeException.php create mode 100644 vendor/symfony/string/Inflector/EnglishInflector.php create mode 100644 vendor/symfony/string/Inflector/FrenchInflector.php create mode 100644 vendor/symfony/string/Inflector/InflectorInterface.php create mode 100644 vendor/symfony/string/LICENSE create mode 100644 vendor/symfony/string/LazyString.php create mode 100644 vendor/symfony/string/README.md create mode 100644 vendor/symfony/string/Resources/data/wcswidth_table_wide.php create mode 100644 vendor/symfony/string/Resources/data/wcswidth_table_zero.php create mode 100644 vendor/symfony/string/Resources/functions.php create mode 100644 vendor/symfony/string/Slugger/AsciiSlugger.php create mode 100644 vendor/symfony/string/Slugger/SluggerInterface.php create mode 100644 vendor/symfony/string/UnicodeString.php create mode 100644 vendor/symfony/string/composer.json create mode 100644 vendor/symfony/yaml/Tests/Fixtures/multiple_lines_as_literal_block_for_tagged_values.yml delete mode 100644 vendor/webmozart/assert/.composer-auth.json delete mode 100644 vendor/webmozart/assert/.styleci.yml create mode 100644 vendor/webmozart/assert/src/InvalidArgumentException.php create mode 100644 vendor/webmozart/assert/src/Mixin.php diff --git a/README.md b/README.md index 8af47d5..1058545 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ The validation APIs help you validate data. Check if an E-mail address is real. [Cloudmersive Validation API](https://www.cloudmersive.com/validate-api) provides data validation capabilities for validating email addresses, phone numbers, IP addresses, and many other types of business data. - API version: v1 -- Package version: 1.8.1 +- Package version: 3.0.1 ## Requirements diff --git a/build.ps1 b/build.ps1 index 57a5153..4ff37cf 100644 --- a/build.ps1 +++ b/build.ps1 @@ -13,5 +13,28 @@ Remove-Item –path ./cloudmersive_validate_api_client –recurse (Get-Content ./composer.json).replace('Swagger and contributors', 'Cloudmersive') | Set-Content ./composer.json (Get-Content ./composer.json).replace('https://github.com/swagger-api/swagger-codegen', 'https://cloudmersive.com') | Set-Content ./composer.json (Get-Content ./composer.json).replace('http://swagger.io', 'https://cloudmersive.com') | Set-Content ./composer.json +(Get-Content ./composer.json).replace('^6.2', '^7.5') | Set-Content ./composer.json +(Get-Content ./composer.json).replace('5.5', '7.2.5') | Set-Content ./composer.json + +$old = [regex]::Escape('\GuzzleHttp\Psr7\try_fopen') +$new = '\GuzzleHttp\Psr7\Utils::tryFopen' + +Get-ChildItem ./lib -Recurse -Filter *.php | ForEach-Object { + $text = Get-Content $_.FullName + $changed = $false + + $newText = @() + foreach ($line in $text) + { + $newLine = $line -replace $old, $new + if ($newLine -ne $line) { $changed = $true } + $newText += $newLine + } + + if ($changed) + { + [System.IO.File]::WriteAllLines($_.FullName, $newText) + } +} & php C:\Users\adm101\composer.phar install \ No newline at end of file diff --git a/composer.json b/composer.json index 66a6cac..fc95995 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "cloudmersive/cloudmersive_validate_api_client", - "version": "1.8.1", + "version": "3.0.1", "description": "", "keywords": [ "swagger", @@ -17,11 +17,11 @@ } ], "require": { - "php": ">=5.5", + "php": ">=7.2.5", "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "guzzlehttp/guzzle": "^6.2" + "guzzlehttp/guzzle": "^7.5" }, "require-dev": { "phpunit/phpunit": "^4.8", diff --git a/composer.lock b/composer.lock index 985e69b..d2d42ec 100644 --- a/composer.lock +++ b/composer.lock @@ -4,39 +4,51 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7766c8825a67760957988b86ef73b427", + "content-hash": "600e2133f4ba36ef4eeed3eeedc113ad", "packages": [ { "name": "guzzlehttp/guzzle", - "version": "6.3.3", + "version": "7.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", "shasum": "" }, "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.0" + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "6.3-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { @@ -52,157 +64,290 @@ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", "keywords": [ "client", "curl", "framework", "http", "http client", + "psr-18", + "psr-7", "rest", "web service" ], - "time": "2018-04-22T15:46:56+00:00" + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.7.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2023-05-21T14:04:53+00:00" }, { "name": "guzzlehttp/promises", - "version": "v1.3.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6", + "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6", "shasum": "" }, "require": { - "php": ">=5.5.0" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.0" + "bamarni/composer-bin-plugin": "^1.8.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.4-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { "psr-4": { "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], "description": "Guzzle promises library", "keywords": [ "promise" ], - "time": "2016-12-20T10:07:11+00:00" + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2023-05-21T13:50:22+00:00" }, { "name": "guzzlehttp/psr7", - "version": "1.4.2", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + "reference": "b635f279edd83fc275f822a1188157ffea568ff6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", + "reference": "b635f279edd83fc275f822a1188157ffea568ff6", "shasum": "" }, "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" }, "provide": { + "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "bamarni/composer-bin-plugin": "^1.8.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.4-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { "psr-4": { "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, { "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ "http", "message", + "psr-7", "request", "response", "stream", "uri", "url" ], - "time": "2017-03-20T17:10:46+00:00" + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.5.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-04-17T16:11:26+00:00" }, { - "name": "psr/http-message", - "version": "1.0.1", + "name": "psr/http-client", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/php-fig/http-client.git", + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -212,7 +357,7 @@ }, "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" + "Psr\\Http\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -222,56 +367,49 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", "keywords": [ "http", - "http-message", + "http-client", "psr", - "psr-7", - "request", - "response" + "psr-18" ], - "time": "2016-08-06T14:39:51+00:00" - } - ], - "packages-dev": [ + "support": { + "source": "https://github.com/php-fig/http-client/tree/1.0.2" + }, + "time": "2023-04-10T20:12:12+00:00" + }, { - "name": "doctrine/instantiator", - "version": "1.1.0", + "name": "psr/http-factory", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", "shasum": "" }, "require": { - "php": "^7.1" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "^6.2.3", - "squizlabs/php_codesniffer": "^3.0.2" + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -280,58 +418,52 @@ ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "description": "Common interfaces for PSR-7 HTTP message factories", "keywords": [ - "constructor", - "instantiate" + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" ], - "time": "2017-07-22T11:58:36+00:00" + "support": { + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + }, + "time": "2023-04-10T20:10:41+00:00" }, { - "name": "friendsofphp/php-cs-fixer", - "version": "v1.13.3", + "name": "psr/http-message", + "version": "2.0", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "387e4c86c9dc0e1e4c475291fc114ec45b98e624" + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/387e4c86c9dc0e1e4c475291fc114ec45b98e624", - "reference": "387e4c86c9dc0e1e4c475291fc114ec45b98e624", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^5.3.6 || >=7.0 <7.2", - "sebastian/diff": "^1.1", - "symfony/console": "^2.3 || ^3.0", - "symfony/event-dispatcher": "^2.1 || ^3.0", - "symfony/filesystem": "^2.1 || ^3.0", - "symfony/finder": "^2.1 || ^3.0", - "symfony/process": "^2.3 || ^3.0", - "symfony/stopwatch": "^2.5 || ^3.0" - }, - "conflict": { - "hhvm": "<3.9" + "php": "^7.2 || ^8.0" }, - "require-dev": { - "phpunit/phpunit": "^4.5|^5", - "satooshi/php-coveralls": "^1.0" + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", "autoload": { "psr-4": { - "Symfony\\CS\\": "Symfony/CS/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -340,49 +472,51 @@ ], "authors": [ { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "A tool to automatically fix PHP code style", - "time": "2017-09-11T14:11:16+00:00" + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" }, { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "name": "ralouphie/getallheaders", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", "shasum": "" }, "require": { - "php": ">=5.5" + "php": ">=5.6" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } + "files": [ + "src/getallheaders.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -390,58 +524,48 @@ ], "authors": [ { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" } ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2017-09-11T18:02:19+00:00" + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } + "files": [ + "function.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -449,46 +573,68 @@ ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-30T07:14:17+00:00" - }, + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + } + ], + "packages-dev": [ { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "name": "composer/pcre", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "url": "https://github.com/composer/pcre.git", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "1.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "Composer\\Pcre\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -497,46 +643,68 @@ ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/1.0.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" } ], - "time": "2017-07-14T14:27:02+00:00" + "time": "2022-01-21T20:24:37+00:00" }, { - "name": "phpspec/prophecy", - "version": "1.8.0", + "name": "composer/semver", + "version": "3.3.2", "source": { "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" + "url": "https://github.com/composer/semver.git", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "Composer\\Semver\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -545,379 +713,517 @@ ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" }, { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", + "description": "Semver library that offers utilities, version constraint parsing and validation.", "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" + "semantic", + "semver", + "validation", + "versioning" ], - "time": "2018-08-05T17:53:17+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "2.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-04-01T19:23:25+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", "shasum": "" }, "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" + "composer/pcre": "^1", + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1 || ^2 || ^3" }, "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" } ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "Restarts a process without Xdebug.", "keywords": [ - "coverage", - "testing", - "xunit" + "Xdebug", + "performance" ], - "time": "2015-10-06T15:47:00+00:00" + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-02-24T20:20:32+00:00" }, { - "name": "phpunit/php-file-iterator", - "version": "1.4.5", + "name": "doctrine/annotations", + "version": "1.14.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + "url": "https://github.com/doctrine/annotations.git", + "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", + "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", "shasum": "" }, "require": { - "php": ">=5.3.3" + "doctrine/lexer": "^1 || ^2", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } + "require-dev": { + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "vimeo/psalm": "^4.10" + }, + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" }, + "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", "keywords": [ - "filesystem", - "iterator" + "annotations", + "docblock", + "parser" ], - "time": "2017-11-27T13:52:08+00:00" + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/1.14.3" + }, + "time": "2023-02-01T09:20:38+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "doctrine/deprecations", + "version": "v1.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/doctrine/deprecations.git", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } }, "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" + "MIT" ], - "time": "2015-06-21T13:50:34+00:00" + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + }, + "time": "2023-06-03T09:27:29+00:00" }, { - "name": "phpunit/php-timer", - "version": "1.0.9", + "name": "doctrine/instantiator", + "version": "1.5.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.1 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "doctrine/coding-standard": "^9 || ^11", + "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.30 || ^5.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ - "timer" + "constructor", + "instantiate" ], - "time": "2017-02-26T11:10:40+00:00" + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + }, + "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-12-30T00:15:36+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "1.4.12", + "name": "doctrine/lexer", + "version": "2.1.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" + "url": "https://github.com/doctrine/lexer.git", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", "keywords": [ - "tokenizer" + "annotations", + "docblock", + "lexer", + "parser", + "php" ], - "time": "2017-12-04T08:55:13+00:00" + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/2.1.0" + }, + "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%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-12-14T08:49:07+00:00" }, { - "name": "phpunit/phpunit", - "version": "4.8.36", + "name": "friendsofphp/php-cs-fixer", + "version": "v2.19.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/75ac86f33fab4714ea5a39a396784d83ae3b5ed8", + "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8", "shasum": "" }, "require": { - "ext-dom": "*", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^1.2 || ^2.0", + "doctrine/annotations": "^1.2", "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.2.2", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" + "ext-tokenizer": "*", + "php": "^5.6 || ^7.0 || ^8.0", + "php-cs-fixer/diff": "^1.3", + "symfony/console": "^3.4.43 || ^4.1.6 || ^5.0", + "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", + "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^3.0 || ^4.0 || ^5.0", + "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^3.0 || ^4.0 || ^5.0", + "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" + }, + "require-dev": { + "justinrainbow/json-schema": "^5.0", + "keradus/cli-executor": "^1.4", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.4.2", + "php-cs-fixer/accessible-object": "^1.0", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", + "phpspec/prophecy-phpunit": "^1.1 || ^2.0", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.13 || ^9.5", + "phpunitgoodpractices/polyfill": "^1.5", + "phpunitgoodpractices/traits": "^1.9.1", + "sanmai/phpunit-legacy-adapter": "^6.4 || ^8.2.1", + "symfony/phpunit-bridge": "^5.2.1", + "symfony/yaml": "^3.0 || ^4.0 || ^5.0" }, "suggest": { - "phpunit/php-invoker": "~1.1" + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters.", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." }, "bin": [ - "phpunit" + "php-cs-fixer" ], - "type": "library", + "type": "application", "extra": { "branch-alias": { - "dev-master": "4.8.x-dev" + "dev-master": "2.19-dev" } }, "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, "classmap": [ - "src/" + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationCaseFactory.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/Assert/AssertTokensTrait.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php", + "tests/Test/IntegrationCaseFactoryInterface.php", + "tests/Test/InternalIntegrationCaseFactory.php", + "tests/Test/IsIdenticalConstraint.php", + "tests/Test/TokensWithObservedTransformers.php", + "tests/TestCase.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" + "description": "A tool to automatically fix PHP code style", + "support": { + "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", + "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.19.3" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } ], - "time": "2017-06-21T08:07:12+00:00" + "time": "2021-11-15T17:17:55+00:00" }, { - "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", + "name": "php-cs-fixer/diff", + "version": "v1.3.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + "url": "https://github.com/PHP-CS-Fixer/diff.git", + "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/dbd31aeb251639ac0b9e7e29405c1441907f5759", + "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" + "php": "^5.6 || ^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" + "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", + "symfony/process": "^3.3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3.x-dev" - } - }, "autoload": { "classmap": [ "src/" @@ -930,44 +1236,54 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "SpacePossum" } ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "description": "sebastian/diff v2 backport support for PHP5.6", + "homepage": "https://github.com/PHP-CS-Fixer", "keywords": [ - "mock", - "xunit" + "diff" ], - "time": "2015-10-02T06:51:40+00:00" + "support": { + "issues": "https://github.com/PHP-CS-Fixer/diff/issues", + "source": "https://github.com/PHP-CS-Fixer/diff/tree/v1.3.1" + }, + "abandoned": true, + "time": "2020-10-14T08:39:05+00:00" }, { - "name": "psr/log", - "version": "1.0.2", + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-2.x": "2.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "phpDocumentor\\Reflection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -976,211 +1292,234 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", "keywords": [ - "log", - "psr", - "psr-3" + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" ], - "time": "2016-10-10T12:19:37+00:00" + "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": "sebastian/comparator", - "version": "1.2.4", + "name": "phpdocumentor/reflection-docblock", + "version": "5.3.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "name": "Mike van Riel", + "email": "me@mikevanriel.com" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2017-01-29T09:50:25+00:00" + "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": "sebastian/diff", - "version": "1.4.3", + "name": "phpdocumentor/type-resolver", + "version": "1.6.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "77a32518733312af16a44300404e945338981de3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", + "reference": "77a32518733312af16a44300404e945338981de3", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "ext-tokenizer": "*", + "psalm/phar": "^4.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-1.x": "1.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Mike van Riel", + "email": "me@mikevanriel.com" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2017-05-22T07:24:03+00:00" + "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": "sebastian/environment", - "version": "1.3.8", + "name": "phpspec/prophecy", + "version": "v1.10.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + "url": "https://github.com/phpspec/prophecy.git", + "reference": "451c3cd1418cf640de218914901e51b064abb093" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" }, "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" + "phpspec/phpspec": "^2.5 || ^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "1.10.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Prophecy\\": "src/Prophecy" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", "keywords": [ - "Xdebug", - "environment", - "hhvm" + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" ], - "time": "2016-08-18T05:49:44+00:00" + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/v1.10.3" + }, + "time": "2020-03-05T15:02:03+00:00" }, { - "name": "sebastian/exporter", - "version": "1.2.2", + "name": "phpunit/php-code-coverage", + "version": "2.2.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", "shasum": "" }, "require": { "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.2.x-dev" } }, "autoload": { @@ -1193,62 +1532,47 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" + "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" ], - "time": "2016-06-17T09:04:28+00:00" + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/2.2" + }, + "time": "2015-10-06T15:47:00+00:00" }, { - "name": "sebastian/global-state", - "version": "1.1.1", + "name": "phpunit/php-file-iterator", + "version": "1.4.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.4.x-dev" } }, "autoload": { @@ -1263,42 +1587,41 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ - "global state" + "filesystem", + "iterator" ], - "time": "2015-10-12T03:26:01+00:00" + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5" + }, + "time": "2017-11-27T13:52:08+00:00" }, { - "name": "sebastian/recursion-context", - "version": "1.0.5", + "name": "phpunit/php-text-template", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "classmap": [ "src/" @@ -1309,38 +1632,49 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-10-03T07:41:43+00:00" + "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/1.2.1" + }, + "time": "2015-06-21T13:50:34+00:00" }, { - "name": "sebastian/version", - "version": "1.0.6", + "name": "phpunit/php-timer", + "version": "1.0.9", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1353,72 +1687,51 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", + "email": "sb@sebastian-bergmann.de", "role": "lead" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21T13:59:46+00:00" + "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/master" + }, + "time": "2017-02-26T11:10:40+00:00" }, { - "name": "squizlabs/php_codesniffer", - "version": "2.9.1", + "name": "phpunit/php-token-stream", + "version": "1.4.12", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", "shasum": "" }, "require": { - "ext-simplexml": "*", "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.1.2" + "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.2" }, - "bin": [ - "scripts/phpcs", - "scripts/phpcbf" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "1.4-dev" } }, "autoload": { "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1427,124 +1740,1655 @@ ], "authors": [ { - "name": "Greg Sherwood", - "role": "lead" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", "keywords": [ - "phpcs", - "standards" + "tokenizer" ], - "time": "2017-05-22T02:43:20+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/1.4" + }, + "abandoned": true, + "time": "2017-12-04T08:55:13+00:00" }, { - "name": "symfony/console", - "version": "v3.4.14", + "name": "phpunit/phpunit", + "version": "4.8.36", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "6b217594552b9323bcdcfc14f8a0ce126e84cd73" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6b217594552b9323bcdcfc14f8a0ce126e84cd73", - "reference": "6b217594552b9323bcdcfc14f8a0ce126e84cd73", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.3|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.3|~4.0" + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.2.2", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" }, "suggest": { - "psr/log-implementation": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "phpunit/php-invoker": "~1.1" }, + "bin": [ + "phpunit" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.8.x-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "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/4.8.36" + }, + "time": "2017-06-21T08:07:12+00:00" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", + "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/2.3" + }, + "abandoned": true, + "time": "2015-10-02T06:51:40+00:00" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/master" + }, + "time": "2016-08-06T20:24:11+00:00" + }, + { + "name": "psr/container", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" + }, + "time": "2021-03-05T17:36:06+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20: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/comparator", + "version": "1.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/1.2" + }, + "time": "2017-01-29T09:50:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/1.4" + }, + "time": "2017-05-22T07:24:03+00:00" + }, + { + "name": "sebastian/environment", + "version": "1.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-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/1.3" + }, + "time": "2016-08-18T05:49:44+00:00" + }, + { + "name": "sebastian/exporter", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/master" + }, + "time": "2016-06-17T09:04:28+00:00" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "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" + } + ], + "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/1.1.1" + }, + "time": "2015-10-12T03:26:01+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "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/master" + }, + "time": "2016-10-03T07:41:43+00:00" + }, + { + "name": "sebastian/version", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "shasum": "" + }, + "type": "library", + "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/1.0.6" + }, + "time": "2015-06-21T13:59:46+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "2.9.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "2acf168de78487db620ab4bc524135a13cfe6745" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/2acf168de78487db620ab4bc524135a13cfe6745", + "reference": "2acf168de78487db620ab4bc524135a13cfe6745", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "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": "http://www.squizlabs.com/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": "2018-11-07T22:31:41+00:00" + }, + { + "name": "symfony/console", + "version": "v5.4.24", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8", + "reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.4.24" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-05-26T05:13:16+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v5.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1df20e45d56da29a4b1d8259dd6e950acbf1b13f", + "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.22" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-17T11:31:58+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-01-02T09:53:40+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.4.25", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", + "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.4.25" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-05-31T13:04:02+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/078e9a5e1871fcfe6a5ce421b539344c21afef19", + "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-16T09:33:00+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v5.4.21", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-14T08:03:56+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/debug", - "version": "v4.1.3", + "name": "symfony/polyfill-php70", + "version": "v1.20.0", "source": { "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "9316545571f079c4dd183e674721d9dc783ce196" + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/9316545571f079c4dd183e674721d9dc783ce196", - "reference": "9316545571f079c4dd183e674721d9dc783ce196", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", "shasum": "" }, "require": { - "php": "^7.1.3", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": "<3.4" + "php": ">=7.1" }, - "require-dev": { - "symfony/http-kernel": "~3.4|~4.0" - }, - "type": "library", + "type": "metapackage", "extra": { "branch-alias": { - "dev-master": "4.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" + "dev-main": "1.20-dev" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1552,62 +3396,75 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Debug Component", + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", "homepage": "https://symfony.com", - "time": "2018-07-26T11:24:31+00:00" + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php70/tree/v1.20.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" }, { - "name": "symfony/event-dispatcher", - "version": "v3.4.14", + "name": "symfony/polyfill-php72", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb" + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "869329b1e9894268a8a61dabb69153029b7a8c97" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb", - "reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97", + "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/dependency-injection": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Php72\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1615,48 +3472,77 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony EventDispatcher Component", + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", "homepage": "https://symfony.com", - "time": "2018-07-26T09:06:28+00:00" + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/filesystem", - "version": "v3.4.14", + "name": "symfony/polyfill-php73", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6" + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/a59f917e3c5d82332514cb4538387638f5bde2d6", - "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Filesystem\\": "" + "Symfony\\Polyfill\\Php73\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1665,47 +3551,77 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Filesystem Component", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/finder", - "version": "v3.4.14", + "name": "symfony/polyfill-php80", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "8a84fcb207451df0013b2c74cbbf1b62d47b999a" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8a84fcb207451df0013b2c74cbbf1b62d47b999a", - "reference": "8a84fcb207451df0013b2c74cbbf1b62d47b999a", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Finder\\": "" + "Symfony\\Polyfill\\Php80\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1714,47 +3630,70 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.8.0", + "name": "symfony/process", + "version": "v5.4.24", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" + "url": "https://github.com/symfony/process.git", + "reference": "e3c46cc5689c8782944274bb30702106ecbe3b64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", - "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "url": "https://api.github.com/repos/symfony/process/zipball/e3c46cc5689c8782944274bb30702106ecbe3b64", + "reference": "e3c46cc5689c8782944274bb30702106ecbe3b64", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" + "Symfony\\Component\\Process\\": "" }, - "files": [ - "bootstrap.php" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1763,57 +3702,74 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" + "support": { + "source": "https://github.com/symfony/process/tree/v5.4.24" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2018-04-30T19:57:29+00:00" + "time": "2023-05-17T11:26:05+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.8.0", + "name": "symfony/service-contracts", + "version": "v2.5.2", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "3296adf6a6454a050679cde90f95350ad604b171" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", - "reference": "3296adf6a6454a050679cde90f95350ad604b171", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" }, "suggest": { - "ext-mbstring": "For best performance" + "symfony/service-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8-dev" + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] + "Symfony\\Contracts\\Service\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1829,43 +3785,57 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Generic abstractions related to writing services", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2018-04-26T10:06:28+00:00" + "time": "2022-05-30T19:17:29+00:00" }, { - "name": "symfony/process", - "version": "v3.4.14", + "name": "symfony/stopwatch", + "version": "v5.4.21", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "0414db29bd770ec5a4152683e655f55efd4fa60f" + "url": "https://github.com/symfony/stopwatch.git", + "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0414db29bd770ec5a4152683e655f55efd4fa60f", - "reference": "0414db29bd770ec5a4152683e655f55efd4fa60f", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee", + "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.2.5", + "symfony/service-contracts": "^1|^2|^3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Component\\Process\\": "" + "Symfony\\Component\\Stopwatch\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -1885,36 +3855,65 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Process Component", + "description": "Provides a way to profile code", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-02-14T08:03:56+00:00" }, { - "name": "symfony/stopwatch", - "version": "v3.4.14", + "name": "symfony/string", + "version": "v5.4.22", "source": { "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "deda2765e8dab2fc38492e926ea690f2a681f59d" + "url": "https://github.com/symfony/string.git", + "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/deda2765e8dab2fc38492e926ea690f2a681f59d", - "reference": "deda2765e8dab2fc38492e926ea690f2a681f59d", + "url": "https://api.github.com/repos/symfony/string/zipball/8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", + "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "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-php80": "~1.15" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } + "conflict": { + "symfony/translation-contracts": ">=3.0" }, + "require-dev": { + "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": { + "files": [ + "Resources/functions.php" + ], "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" + "Symfony\\Component\\String\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -1926,30 +3925,55 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Stopwatch Component", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", "homepage": "https://symfony.com", - "time": "2018-07-26T10:03:52+00:00" + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.22" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-03-14T06:11:53+00:00" }, { "name": "symfony/yaml", - "version": "v3.4.14", + "version": "v3.4.47", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2" + "reference": "88289caa3c166321883f67fe5130188ebbb47094" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/810af2d35fc72b6cf5c01116806d2b65ccaaf2e2", - "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2", + "url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094", + "reference": "88289caa3c166321883f67fe5130188ebbb47094", "shasum": "" }, "require": { @@ -1966,11 +3990,6 @@ "symfony/console": "For validating YAML files using the lint command" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Yaml\\": "" @@ -1995,33 +4014,54 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-07-26T11:19:56+00:00" + "support": { + "source": "https://github.com/symfony/yaml/tree/v3.4.47" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-24T10:57:07+00:00" }, { "name": "webmozart/assert", - "version": "1.3.0", + "version": "1.11.0", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "phpunit/phpunit": "^8.5.13" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.10-dev" } }, "autoload": { @@ -2045,7 +4085,11 @@ "check", "validate" ], - "time": "2018-01-29T19:49:41+00:00" + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" } ], "aliases": [], @@ -2054,10 +4098,11 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.5", + "php": ">=7.2.5", "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*" }, - "platform-dev": [] + "platform-dev": [], + "plugin-api-version": "2.3.0" } diff --git a/lib/Configuration.php b/lib/Configuration.php index 062ccfd..30f6080 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -88,7 +88,7 @@ class Configuration * * @var string */ - protected $userAgent = 'Swagger-Codegen/1.8.1/php'; + protected $userAgent = 'Swagger-Codegen/3.0.1/php'; /** * Debug switch (default set to false) @@ -397,7 +397,7 @@ public static function toDebugReport() $report .= ' OS: ' . php_uname() . PHP_EOL; $report .= ' PHP Version: ' . PHP_VERSION . PHP_EOL; $report .= ' OpenAPI Spec Version: v1' . PHP_EOL; - $report .= ' SDK Package Version: 1.8.1' . PHP_EOL; + $report .= ' SDK Package Version: 3.0.1' . PHP_EOL; $report .= ' Temp Folder Path: ' . self::getDefaultConfiguration()->getTempFolderPath() . PHP_EOL; return $report; diff --git a/packageconfig.json b/packageconfig.json index 24a5c50..9df6378 100644 --- a/packageconfig.json +++ b/packageconfig.json @@ -1,5 +1,5 @@ { - "artifactVersion": "1.8.1", + "artifactVersion": "3.0.1", "gitUserId": "Cloudmersive", "gitRepoId": "Cloudmersive.APIClient.PHP.Validate", "composerVendorName": "cloudmersive", diff --git a/vendor/autoload.php b/vendor/autoload.php index 85dfcbd..1204d64 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -2,6 +2,24 @@ // autoload.php @generated by Composer +if (PHP_VERSION_ID < 50600) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, $err); + } elseif (!headers_sent()) { + echo $err; + } + } + trigger_error( + $err, + E_USER_ERROR + ); +} + require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInitd34d355c260bb5a736a127816ecaf3bf::getLoader(); +return ComposerAutoloaderInit8e045aa3eb0169172b5c8585a1d97f8e::getLoader(); diff --git a/vendor/bin/php-cs-fixer b/vendor/bin/php-cs-fixer index 7f39b6c..d40411a 120000 --- a/vendor/bin/php-cs-fixer +++ b/vendor/bin/php-cs-fixer @@ -1 +1,119 @@ -../friendsofphp/php-cs-fixer/php-cs-fixer \ No newline at end of file +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/friendsofphp/php-cs-fixer/php-cs-fixer'); + } +} + +return include __DIR__ . '/..'.'/friendsofphp/php-cs-fixer/php-cs-fixer'; diff --git a/vendor/bin/php-cs-fixer.bat b/vendor/bin/php-cs-fixer.bat new file mode 100644 index 0000000..83db5d5 --- /dev/null +++ b/vendor/bin/php-cs-fixer.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/php-cs-fixer +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/bin/phpcbf b/vendor/bin/phpcbf index 9506967..a9b2dd2 120000 --- a/vendor/bin/phpcbf +++ b/vendor/bin/phpcbf @@ -1 +1,119 @@ -../squizlabs/php_codesniffer/scripts/phpcbf \ No newline at end of file +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/squizlabs/php_codesniffer/scripts/phpcbf'); + } +} + +return include __DIR__ . '/..'.'/squizlabs/php_codesniffer/scripts/phpcbf'; diff --git a/vendor/bin/phpcbf.bat b/vendor/bin/phpcbf.bat new file mode 100644 index 0000000..f489428 --- /dev/null +++ b/vendor/bin/phpcbf.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/phpcbf +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/bin/phpcs b/vendor/bin/phpcs index 1be0fae..bfdcbdd 120000 --- a/vendor/bin/phpcs +++ b/vendor/bin/phpcs @@ -1 +1,119 @@ -../squizlabs/php_codesniffer/scripts/phpcs \ No newline at end of file +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/squizlabs/php_codesniffer/scripts/phpcs'); + } +} + +return include __DIR__ . '/..'.'/squizlabs/php_codesniffer/scripts/phpcs'; diff --git a/vendor/bin/phpcs.bat b/vendor/bin/phpcs.bat new file mode 100644 index 0000000..ea984e9 --- /dev/null +++ b/vendor/bin/phpcs.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/phpcs +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/bin/phpunit b/vendor/bin/phpunit index 2c48930..b5b530a 120000 --- a/vendor/bin/phpunit +++ b/vendor/bin/phpunit @@ -1 +1,122 @@ -../phpunit/phpunit/phpunit \ No newline at end of file +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = 'phpvfscomposer://'.$this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + $data = str_replace('__DIR__', var_export(dirname($this->realpath), true), $data); + $data = str_replace('__FILE__', var_export($this->realpath, true), $data); + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpunit/phpunit/phpunit'); + } +} + +return include __DIR__ . '/..'.'/phpunit/phpunit/phpunit'; diff --git a/vendor/bin/phpunit.bat b/vendor/bin/phpunit.bat new file mode 100644 index 0000000..2a070cd --- /dev/null +++ b/vendor/bin/phpunit.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/phpunit +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index fce8549..7824d8f 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -37,57 +37,126 @@ * * @author Fabien Potencier * @author Jordi Boggiano - * @see http://www.php-fig.org/psr/psr-0/ - * @see http://www.php-fig.org/psr/psr-4/ + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ */ class ClassLoader { + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var string|null */ + private $vendorDir; + // PSR-4 + /** + * @var array> + */ private $prefixLengthsPsr4 = array(); + /** + * @var array> + */ private $prefixDirsPsr4 = array(); + /** + * @var list + */ private $fallbackDirsPsr4 = array(); // PSR-0 + /** + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> + */ private $prefixesPsr0 = array(); + /** + * @var list + */ private $fallbackDirsPsr0 = array(); + /** @var bool */ private $useIncludePath = false; + + /** + * @var array + */ private $classMap = array(); + + /** @var bool */ private $classMapAuthoritative = false; + + /** + * @var array + */ private $missingClasses = array(); + + /** @var string|null */ private $apcuPrefix; + /** + * @var array + */ + private static $registeredLoaders = array(); + + /** + * @param string|null $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); + } + + /** + * @return array> + */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', $this->prefixesPsr0); + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); } return array(); } + /** + * @return array> + */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } + /** + * @return list + */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } + /** + * @return list + */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } + /** + * @return array Array of classname => path + */ public function getClassMap() { return $this->classMap; } /** - * @param array $classMap Class to filename map + * @param array $classMap Class to filename map + * + * @return void */ public function addClassMap(array $classMap) { @@ -102,22 +171,25 @@ public function addClassMap(array $classMap) * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void */ public function add($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, - (array) $paths + $paths ); } @@ -126,19 +198,19 @@ public function add($prefix, $paths, $prepend = false) $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; + $this->prefixesPsr0[$first][$prefix] = $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], - (array) $paths + $paths ); } } @@ -147,25 +219,28 @@ public function add($prefix, $paths, $prepend = false) * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException + * + * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, - (array) $paths + $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { @@ -175,18 +250,18 @@ public function addPsr4($prefix, $paths, $prepend = false) throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; + $this->prefixDirsPsr4[$prefix] = $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], - (array) $paths + $paths ); } } @@ -195,8 +270,10 @@ public function addPsr4($prefix, $paths, $prepend = false) * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories + * + * @return void */ public function set($prefix, $paths) { @@ -211,10 +288,12 @@ public function set($prefix, $paths) * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException + * + * @return void */ public function setPsr4($prefix, $paths) { @@ -234,6 +313,8 @@ public function setPsr4($prefix, $paths) * Turns on searching the include path for class files. * * @param bool $useIncludePath + * + * @return void */ public function setUseIncludePath($useIncludePath) { @@ -256,6 +337,8 @@ public function getUseIncludePath() * that have not been registered with the class map. * * @param bool $classMapAuthoritative + * + * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -276,6 +359,8 @@ public function isClassMapAuthoritative() * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix + * + * @return void */ public function setApcuPrefix($apcuPrefix) { @@ -296,33 +381,55 @@ public function getApcuPrefix() * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } } /** * Unregisters this instance as an autoloader. + * + * @return void */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } } /** * Loads the given class or interface. * * @param string $class The name of the class - * @return bool|null True if loaded, null otherwise + * @return true|null True if loaded, null otherwise */ public function loadClass($class) { if ($file = $this->findFile($class)) { - includeFile($file); + $includeFile = self::$includeFile; + $includeFile($file); return true; } + + return null; } /** @@ -367,6 +474,21 @@ public function findFile($class) return $file; } + /** + * Returns the currently registered loaders keyed by their corresponding vendor directories. + * + * @return array + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup @@ -432,14 +554,26 @@ private function findFileWithExtension($class, $ext) return false; } -} -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - */ -function includeFile($file) -{ - include $file; + /** + * @return void + */ + private static function initializeIncludeClosure() + { + if (self::$includeFile !== null) { + return; + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + */ + self::$includeFile = \Closure::bind(static function($file) { + include $file; + }, null, null); + } } diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php new file mode 100644 index 0000000..51e734a --- /dev/null +++ b/vendor/composer/InstalledVersions.php @@ -0,0 +1,359 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints((string) $constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require $vendorDir.'/composer/installed.php'; + $installed[] = self::$installedByVendor[$vendorDir] = $required; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require __DIR__ . '/installed.php'; + self::$installed = $required; + } else { + self::$installed = array(); + } + } + + if (self::$installed !== array()) { + $installed[] = self::$installed; + } + + return $installed; + } +} diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 263ea35..9b96cd7 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -2,10 +2,12 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( + 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'File_Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php', 'File_Iterator_Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php', 'File_Iterator_Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php', @@ -71,6 +73,7 @@ 'Generic_Sniffs_WhiteSpace_DisallowSpaceIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php', 'Generic_Sniffs_WhiteSpace_DisallowTabIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/DisallowTabIndentSniff.php', 'Generic_Sniffs_WhiteSpace_ScopeIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php', + 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'MySource_Sniffs_CSS_BrowserSpecificStylesSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php', 'MySource_Sniffs_Channels_DisallowSelfActionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php', 'MySource_Sniffs_Channels_IncludeOwnSystemSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php', @@ -87,6 +90,7 @@ 'MySource_Sniffs_PHP_GetRequestDataSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php', 'MySource_Sniffs_PHP_ReturnFunctionValueSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php', 'MySource_Sniffs_Strings_JoinStringsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php', + 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'PEAR_Sniffs_Classes_ClassDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php', 'PEAR_Sniffs_Commenting_ClassCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php', 'PEAR_Sniffs_Commenting_FileCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php', @@ -563,6 +567,59 @@ 'PSR2_Sniffs_Methods_MethodDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php', 'PSR2_Sniffs_Namespaces_NamespaceDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php', 'PSR2_Sniffs_Namespaces_UseDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php', + 'PhpCsFixer\\Diff\\GeckoPackages\\DiffOutputBuilder\\ConfigurationException' => $vendorDir . '/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/ConfigurationException.php', + 'PhpCsFixer\\Diff\\GeckoPackages\\DiffOutputBuilder\\UnifiedDiffOutputBuilder' => $vendorDir . '/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/UnifiedDiffOutputBuilder.php', + 'PhpCsFixer\\Diff\\v1_4\\Chunk' => $vendorDir . '/php-cs-fixer/diff/src/v1_4/Chunk.php', + 'PhpCsFixer\\Diff\\v1_4\\Diff' => $vendorDir . '/php-cs-fixer/diff/src/v1_4/Diff.php', + 'PhpCsFixer\\Diff\\v1_4\\Differ' => $vendorDir . '/php-cs-fixer/diff/src/v1_4/Differ.php', + 'PhpCsFixer\\Diff\\v1_4\\LCS\\LongestCommonSubsequence' => $vendorDir . '/php-cs-fixer/diff/src/v1_4/LCS/LongestCommonSubsequence.php', + 'PhpCsFixer\\Diff\\v1_4\\LCS\\MemoryEfficientImplementation' => $vendorDir . '/php-cs-fixer/diff/src/v1_4/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php', + 'PhpCsFixer\\Diff\\v1_4\\LCS\\TimeEfficientImplementation' => $vendorDir . '/php-cs-fixer/diff/src/v1_4/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php', + 'PhpCsFixer\\Diff\\v1_4\\Line' => $vendorDir . '/php-cs-fixer/diff/src/v1_4/Line.php', + 'PhpCsFixer\\Diff\\v1_4\\Parser' => $vendorDir . '/php-cs-fixer/diff/src/v1_4/Parser.php', + 'PhpCsFixer\\Diff\\v2_0\\Chunk' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Chunk.php', + 'PhpCsFixer\\Diff\\v2_0\\Diff' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Diff.php', + 'PhpCsFixer\\Diff\\v2_0\\Differ' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Differ.php', + 'PhpCsFixer\\Diff\\v2_0\\Exception' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Exception/Exception.php', + 'PhpCsFixer\\Diff\\v2_0\\InvalidArgumentException' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Exception/InvalidArgumentException.php', + 'PhpCsFixer\\Diff\\v2_0\\Line' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Line.php', + 'PhpCsFixer\\Diff\\v2_0\\LongestCommonSubsequenceCalculator' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/LongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Diff\\v2_0\\MemoryEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/MemoryEfficientLongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Diff\\v2_0\\Output\\AbstractChunkOutputBuilder' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Output/AbstractChunkOutputBuilder.php', + 'PhpCsFixer\\Diff\\v2_0\\Output\\DiffOnlyOutputBuilder' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Output/DiffOnlyOutputBuilder.php', + 'PhpCsFixer\\Diff\\v2_0\\Output\\DiffOutputBuilderInterface' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Output/DiffOutputBuilderInterface.php', + 'PhpCsFixer\\Diff\\v2_0\\Output\\UnifiedDiffOutputBuilder' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Output/UnifiedDiffOutputBuilder.php', + 'PhpCsFixer\\Diff\\v2_0\\Parser' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/Parser.php', + 'PhpCsFixer\\Diff\\v2_0\\TimeEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/php-cs-fixer/diff/src/v2_0/TimeEfficientLongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Diff\\v3_0\\Chunk' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Chunk.php', + 'PhpCsFixer\\Diff\\v3_0\\ConfigurationException' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Exception/ConfigurationException.php', + 'PhpCsFixer\\Diff\\v3_0\\Diff' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Diff.php', + 'PhpCsFixer\\Diff\\v3_0\\Differ' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Differ.php', + 'PhpCsFixer\\Diff\\v3_0\\Exception' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Exception/Exception.php', + 'PhpCsFixer\\Diff\\v3_0\\InvalidArgumentException' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Exception/InvalidArgumentException.php', + 'PhpCsFixer\\Diff\\v3_0\\Line' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Line.php', + 'PhpCsFixer\\Diff\\v3_0\\LongestCommonSubsequenceCalculator' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/LongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Diff\\v3_0\\MemoryEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/MemoryEfficientLongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Diff\\v3_0\\Output\\AbstractChunkOutputBuilder' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Output/AbstractChunkOutputBuilder.php', + 'PhpCsFixer\\Diff\\v3_0\\Output\\DiffOnlyOutputBuilder' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Output/DiffOnlyOutputBuilder.php', + 'PhpCsFixer\\Diff\\v3_0\\Output\\DiffOutputBuilderInterface' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Output/DiffOutputBuilderInterface.php', + 'PhpCsFixer\\Diff\\v3_0\\Output\\StrictUnifiedDiffOutputBuilder' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Output/StrictUnifiedDiffOutputBuilder.php', + 'PhpCsFixer\\Diff\\v3_0\\Output\\UnifiedDiffOutputBuilder' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Output/UnifiedDiffOutputBuilder.php', + 'PhpCsFixer\\Diff\\v3_0\\Parser' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/Parser.php', + 'PhpCsFixer\\Diff\\v3_0\\TimeEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/php-cs-fixer/diff/src/v3_0/TimeEfficientLongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Tests\\InterimTestCase' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/TestCase.php', + 'PhpCsFixer\\Tests\\TestCase' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/TestCase.php', + 'PhpCsFixer\\Tests\\Test\\AbstractFixerTestCase' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/Test/AbstractFixerTestCase.php', + 'PhpCsFixer\\Tests\\Test\\AbstractIntegrationCaseFactory' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationCaseFactory.php', + 'PhpCsFixer\\Tests\\Test\\AbstractIntegrationTestCase' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationTestCase.php', + 'PhpCsFixer\\Tests\\Test\\Assert\\AssertTokensTrait' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/Test/Assert/AssertTokensTrait.php', + 'PhpCsFixer\\Tests\\Test\\IntegrationCase' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/Test/IntegrationCase.php', + 'PhpCsFixer\\Tests\\Test\\IntegrationCaseFactory' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactory.php', + 'PhpCsFixer\\Tests\\Test\\IntegrationCaseFactoryInterface' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactoryInterface.php', + 'PhpCsFixer\\Tests\\Test\\InternalIntegrationCaseFactory' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/Test/InternalIntegrationCaseFactory.php', + 'PhpCsFixer\\Tests\\Test\\IsIdenticalConstraint' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/Test/IsIdenticalConstraint.php', + 'PhpCsFixer\\Tests\\Test\\TokensWithObservedTransformers' => $vendorDir . '/friendsofphp/php-cs-fixer/tests/Test/TokensWithObservedTransformers.php', + 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'SebastianBergmann\\Comparator\\ArrayComparator' => $vendorDir . '/sebastian/comparator/src/ArrayComparator.php', 'SebastianBergmann\\Comparator\\Comparator' => $vendorDir . '/sebastian/comparator/src/Comparator.php', 'SebastianBergmann\\Comparator\\ComparisonFailure' => $vendorDir . '/sebastian/comparator/src/ComparisonFailure.php', @@ -699,7 +756,10 @@ 'Squiz_Sniffs_WhiteSpace_ScopeKeywordSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_SemicolonSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_SuperfluousWhitespaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php', + 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Text_Template' => $vendorDir . '/phpunit/php-text-template/src/Template.php', + 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', 'Zend_Sniffs_Debug_CodeAnalyzerSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php', 'Zend_Sniffs_Files_ClosingTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/Files/ClosingTagSniff.php', 'Zend_Sniffs_NamingConventions_ValidVariableNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php', diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index 71af620..d6d2289 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -2,13 +2,19 @@ // autoload_files.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( + 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', + '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', - 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', - 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', + '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', + 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', + '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', + 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', + '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', ); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index b24b217..15a2ff3 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -2,9 +2,8 @@ // autoload_namespaces.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( - 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'), ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 643b664..36fcf9f 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -2,28 +2,47 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( 'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'), 'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'), + 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), + 'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'), + 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), + 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'), + 'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'), 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), + 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), + 'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'), 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), + 'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), 'Symfony\\Component\\Stopwatch\\' => array($vendorDir . '/symfony/stopwatch'), 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), + 'Symfony\\Component\\OptionsResolver\\' => array($vendorDir . '/symfony/options-resolver'), 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'), 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), - 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), - 'Symfony\\CS\\' => array($vendorDir . '/friendsofphp/php-cs-fixer/Symfony/CS'), 'Swagger\\Client\\' => array($baseDir . '/lib', $baseDir . '/test'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), - 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), + 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'), + 'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'), + 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), + 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), + 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'), + 'PhpCsFixer\\' => array($vendorDir . '/friendsofphp/php-cs-fixer/src'), 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), 'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'), + 'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/lib/Doctrine/Deprecations'), + 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/src'), + 'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations'), + 'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'), + 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'), + 'Composer\\Pcre\\' => array($vendorDir . '/composer/pcre/src'), ); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 13831c0..c03ec59 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitd34d355c260bb5a736a127816ecaf3bf +class ComposerAutoloaderInit8e045aa3eb0169172b5c8585a1d97f8e { private static $loader; @@ -13,58 +13,38 @@ public static function loadClassLoader($class) } } + /** + * @return \Composer\Autoload\ClassLoader + */ public static function getLoader() { if (null !== self::$loader) { return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInitd34d355c260bb5a736a127816ecaf3bf', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInitd34d355c260bb5a736a127816ecaf3bf', 'loadClassLoader')); + require __DIR__ . '/platform_check.php'; - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require_once __DIR__ . '/autoload_static.php'; + spl_autoload_register(array('ComposerAutoloaderInit8e045aa3eb0169172b5c8585a1d97f8e', 'loadClassLoader'), true, true); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); + spl_autoload_unregister(array('ComposerAutoloaderInit8e045aa3eb0169172b5c8585a1d97f8e', 'loadClassLoader')); - call_user_func(\Composer\Autoload\ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf::getInitializer($loader)); - } else { - $map = require __DIR__ . '/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - $loader->set($namespace, $path); - } - - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } - - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - } + require __DIR__ . '/autoload_static.php'; + call_user_func(\Composer\Autoload\ComposerStaticInit8e045aa3eb0169172b5c8585a1d97f8e::getInitializer($loader)); $loader->register(true); - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } - foreach ($includeFiles as $fileIdentifier => $file) { - composerRequired34d355c260bb5a736a127816ecaf3bf($fileIdentifier, $file); + $filesToLoad = \Composer\Autoload\ComposerStaticInit8e045aa3eb0169172b5c8585a1d97f8e::$files; + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } + }, null, null); + foreach ($filesToLoad as $fileIdentifier => $file) { + $requireFile($fileIdentifier, $file); } return $loader; } } - -function composerRequired34d355c260bb5a736a127816ecaf3bf($fileIdentifier, $file) -{ - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - } -} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 6e6613d..2e114c7 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -4,13 +4,19 @@ namespace Composer\Autoload; -class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf +class ComposerStaticInit8e045aa3eb0169172b5c8585a1d97f8e { public static $files = array ( + 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', + '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', - 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php', - 'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', + '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', + 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', + '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', + 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', + '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', ); @@ -25,23 +31,36 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf ), 'S' => array ( + 'Symfony\\Polyfill\\Php80\\' => 23, + 'Symfony\\Polyfill\\Php73\\' => 23, + 'Symfony\\Polyfill\\Php72\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, + 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33, + 'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31, 'Symfony\\Polyfill\\Ctype\\' => 23, + 'Symfony\\Contracts\\Service\\' => 26, + 'Symfony\\Contracts\\EventDispatcher\\' => 34, 'Symfony\\Component\\Yaml\\' => 23, + 'Symfony\\Component\\String\\' => 25, 'Symfony\\Component\\Stopwatch\\' => 28, 'Symfony\\Component\\Process\\' => 26, + 'Symfony\\Component\\OptionsResolver\\' => 34, 'Symfony\\Component\\Finder\\' => 25, 'Symfony\\Component\\Filesystem\\' => 29, 'Symfony\\Component\\EventDispatcher\\' => 34, - 'Symfony\\Component\\Debug\\' => 24, 'Symfony\\Component\\Console\\' => 26, - 'Symfony\\CS\\' => 11, 'Swagger\\Client\\' => 15, ), 'P' => array ( 'Psr\\Log\\' => 8, 'Psr\\Http\\Message\\' => 17, + 'Psr\\Http\\Client\\' => 16, + 'Psr\\EventDispatcher\\' => 20, + 'Psr\\Container\\' => 14, + 'Psr\\Cache\\' => 10, + 'Prophecy\\' => 9, + 'PhpCsFixer\\' => 11, ), 'G' => array ( @@ -52,6 +71,15 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf 'D' => array ( 'Doctrine\\Instantiator\\' => 22, + 'Doctrine\\Deprecations\\' => 22, + 'Doctrine\\Common\\Lexer\\' => 22, + 'Doctrine\\Common\\Annotations\\' => 28, + ), + 'C' => + array ( + 'Composer\\XdebugHandler\\' => 23, + 'Composer\\Semver\\' => 16, + 'Composer\\Pcre\\' => 14, ), ); @@ -66,18 +94,50 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf array ( 0 => __DIR__ . '/..' . '/webmozart/assert/src', ), + 'Symfony\\Polyfill\\Php80\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', + ), + 'Symfony\\Polyfill\\Php73\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', + ), + 'Symfony\\Polyfill\\Php72\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php72', + ), 'Symfony\\Polyfill\\Mbstring\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', ), + 'Symfony\\Polyfill\\Intl\\Normalizer\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer', + ), + 'Symfony\\Polyfill\\Intl\\Grapheme\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme', + ), 'Symfony\\Polyfill\\Ctype\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', ), + 'Symfony\\Contracts\\Service\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/service-contracts', + ), + 'Symfony\\Contracts\\EventDispatcher\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts', + ), 'Symfony\\Component\\Yaml\\' => array ( 0 => __DIR__ . '/..' . '/symfony/yaml', ), + 'Symfony\\Component\\String\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/string', + ), 'Symfony\\Component\\Stopwatch\\' => array ( 0 => __DIR__ . '/..' . '/symfony/stopwatch', @@ -86,6 +146,10 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf array ( 0 => __DIR__ . '/..' . '/symfony/process', ), + 'Symfony\\Component\\OptionsResolver\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/options-resolver', + ), 'Symfony\\Component\\Finder\\' => array ( 0 => __DIR__ . '/..' . '/symfony/finder', @@ -98,18 +162,10 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf array ( 0 => __DIR__ . '/..' . '/symfony/event-dispatcher', ), - 'Symfony\\Component\\Debug\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/debug', - ), 'Symfony\\Component\\Console\\' => array ( 0 => __DIR__ . '/..' . '/symfony/console', ), - 'Symfony\\CS\\' => - array ( - 0 => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/Symfony/CS', - ), 'Swagger\\Client\\' => array ( 0 => __DIR__ . '/../..' . '/lib', @@ -121,7 +177,32 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf ), 'Psr\\Http\\Message\\' => array ( - 0 => __DIR__ . '/..' . '/psr/http-message/src', + 0 => __DIR__ . '/..' . '/psr/http-factory/src', + 1 => __DIR__ . '/..' . '/psr/http-message/src', + ), + 'Psr\\Http\\Client\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/http-client/src', + ), + 'Psr\\EventDispatcher\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/event-dispatcher/src', + ), + 'Psr\\Container\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/container/src', + ), + 'Psr\\Cache\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/cache/src', + ), + 'Prophecy\\' => + array ( + 0 => __DIR__ . '/..' . '/phpspec/prophecy/src/Prophecy', + ), + 'PhpCsFixer\\' => + array ( + 0 => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src', ), 'GuzzleHttp\\Psr7\\' => array ( @@ -139,19 +220,35 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf array ( 0 => __DIR__ . '/..' . '/doctrine/instantiator/src/Doctrine/Instantiator', ), - ); - - public static $prefixesPsr0 = array ( - 'P' => + 'Doctrine\\Deprecations\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/deprecations/lib/Doctrine/Deprecations', + ), + 'Doctrine\\Common\\Lexer\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/lexer/src', + ), + 'Doctrine\\Common\\Annotations\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations', + ), + 'Composer\\XdebugHandler\\' => + array ( + 0 => __DIR__ . '/..' . '/composer/xdebug-handler/src', + ), + 'Composer\\Semver\\' => + array ( + 0 => __DIR__ . '/..' . '/composer/semver/src', + ), + 'Composer\\Pcre\\' => array ( - 'Prophecy\\' => - array ( - 0 => __DIR__ . '/..' . '/phpspec/prophecy/src', - ), + 0 => __DIR__ . '/..' . '/composer/pcre/src', ), ); public static $classMap = array ( + 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'File_Iterator' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Iterator.php', 'File_Iterator_Facade' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Facade.php', 'File_Iterator_Factory' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Factory.php', @@ -217,6 +314,7 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf 'Generic_Sniffs_WhiteSpace_DisallowSpaceIndentSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php', 'Generic_Sniffs_WhiteSpace_DisallowTabIndentSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/DisallowTabIndentSniff.php', 'Generic_Sniffs_WhiteSpace_ScopeIndentSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php', + 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'MySource_Sniffs_CSS_BrowserSpecificStylesSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php', 'MySource_Sniffs_Channels_DisallowSelfActionsSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php', 'MySource_Sniffs_Channels_IncludeOwnSystemSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php', @@ -233,6 +331,7 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf 'MySource_Sniffs_PHP_GetRequestDataSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php', 'MySource_Sniffs_PHP_ReturnFunctionValueSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php', 'MySource_Sniffs_Strings_JoinStringsSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php', + 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'PEAR_Sniffs_Classes_ClassDeclarationSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php', 'PEAR_Sniffs_Commenting_ClassCommentSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php', 'PEAR_Sniffs_Commenting_FileCommentSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php', @@ -709,6 +808,59 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf 'PSR2_Sniffs_Methods_MethodDeclarationSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php', 'PSR2_Sniffs_Namespaces_NamespaceDeclarationSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php', 'PSR2_Sniffs_Namespaces_UseDeclarationSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php', + 'PhpCsFixer\\Diff\\GeckoPackages\\DiffOutputBuilder\\ConfigurationException' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/ConfigurationException.php', + 'PhpCsFixer\\Diff\\GeckoPackages\\DiffOutputBuilder\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/UnifiedDiffOutputBuilder.php', + 'PhpCsFixer\\Diff\\v1_4\\Chunk' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v1_4/Chunk.php', + 'PhpCsFixer\\Diff\\v1_4\\Diff' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v1_4/Diff.php', + 'PhpCsFixer\\Diff\\v1_4\\Differ' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v1_4/Differ.php', + 'PhpCsFixer\\Diff\\v1_4\\LCS\\LongestCommonSubsequence' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v1_4/LCS/LongestCommonSubsequence.php', + 'PhpCsFixer\\Diff\\v1_4\\LCS\\MemoryEfficientImplementation' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v1_4/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php', + 'PhpCsFixer\\Diff\\v1_4\\LCS\\TimeEfficientImplementation' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v1_4/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php', + 'PhpCsFixer\\Diff\\v1_4\\Line' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v1_4/Line.php', + 'PhpCsFixer\\Diff\\v1_4\\Parser' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v1_4/Parser.php', + 'PhpCsFixer\\Diff\\v2_0\\Chunk' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Chunk.php', + 'PhpCsFixer\\Diff\\v2_0\\Diff' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Diff.php', + 'PhpCsFixer\\Diff\\v2_0\\Differ' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Differ.php', + 'PhpCsFixer\\Diff\\v2_0\\Exception' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Exception/Exception.php', + 'PhpCsFixer\\Diff\\v2_0\\InvalidArgumentException' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Exception/InvalidArgumentException.php', + 'PhpCsFixer\\Diff\\v2_0\\Line' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Line.php', + 'PhpCsFixer\\Diff\\v2_0\\LongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/LongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Diff\\v2_0\\MemoryEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/MemoryEfficientLongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Diff\\v2_0\\Output\\AbstractChunkOutputBuilder' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Output/AbstractChunkOutputBuilder.php', + 'PhpCsFixer\\Diff\\v2_0\\Output\\DiffOnlyOutputBuilder' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Output/DiffOnlyOutputBuilder.php', + 'PhpCsFixer\\Diff\\v2_0\\Output\\DiffOutputBuilderInterface' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Output/DiffOutputBuilderInterface.php', + 'PhpCsFixer\\Diff\\v2_0\\Output\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Output/UnifiedDiffOutputBuilder.php', + 'PhpCsFixer\\Diff\\v2_0\\Parser' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/Parser.php', + 'PhpCsFixer\\Diff\\v2_0\\TimeEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v2_0/TimeEfficientLongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Diff\\v3_0\\Chunk' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Chunk.php', + 'PhpCsFixer\\Diff\\v3_0\\ConfigurationException' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Exception/ConfigurationException.php', + 'PhpCsFixer\\Diff\\v3_0\\Diff' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Diff.php', + 'PhpCsFixer\\Diff\\v3_0\\Differ' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Differ.php', + 'PhpCsFixer\\Diff\\v3_0\\Exception' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Exception/Exception.php', + 'PhpCsFixer\\Diff\\v3_0\\InvalidArgumentException' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Exception/InvalidArgumentException.php', + 'PhpCsFixer\\Diff\\v3_0\\Line' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Line.php', + 'PhpCsFixer\\Diff\\v3_0\\LongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/LongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Diff\\v3_0\\MemoryEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/MemoryEfficientLongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Diff\\v3_0\\Output\\AbstractChunkOutputBuilder' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Output/AbstractChunkOutputBuilder.php', + 'PhpCsFixer\\Diff\\v3_0\\Output\\DiffOnlyOutputBuilder' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Output/DiffOnlyOutputBuilder.php', + 'PhpCsFixer\\Diff\\v3_0\\Output\\DiffOutputBuilderInterface' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Output/DiffOutputBuilderInterface.php', + 'PhpCsFixer\\Diff\\v3_0\\Output\\StrictUnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Output/StrictUnifiedDiffOutputBuilder.php', + 'PhpCsFixer\\Diff\\v3_0\\Output\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Output/UnifiedDiffOutputBuilder.php', + 'PhpCsFixer\\Diff\\v3_0\\Parser' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/Parser.php', + 'PhpCsFixer\\Diff\\v3_0\\TimeEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/php-cs-fixer/diff/src/v3_0/TimeEfficientLongestCommonSubsequenceCalculator.php', + 'PhpCsFixer\\Tests\\InterimTestCase' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/TestCase.php', + 'PhpCsFixer\\Tests\\TestCase' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/TestCase.php', + 'PhpCsFixer\\Tests\\Test\\AbstractFixerTestCase' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/Test/AbstractFixerTestCase.php', + 'PhpCsFixer\\Tests\\Test\\AbstractIntegrationCaseFactory' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationCaseFactory.php', + 'PhpCsFixer\\Tests\\Test\\AbstractIntegrationTestCase' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationTestCase.php', + 'PhpCsFixer\\Tests\\Test\\Assert\\AssertTokensTrait' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/Test/Assert/AssertTokensTrait.php', + 'PhpCsFixer\\Tests\\Test\\IntegrationCase' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/Test/IntegrationCase.php', + 'PhpCsFixer\\Tests\\Test\\IntegrationCaseFactory' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactory.php', + 'PhpCsFixer\\Tests\\Test\\IntegrationCaseFactoryInterface' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactoryInterface.php', + 'PhpCsFixer\\Tests\\Test\\InternalIntegrationCaseFactory' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/Test/InternalIntegrationCaseFactory.php', + 'PhpCsFixer\\Tests\\Test\\IsIdenticalConstraint' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/Test/IsIdenticalConstraint.php', + 'PhpCsFixer\\Tests\\Test\\TokensWithObservedTransformers' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/tests/Test/TokensWithObservedTransformers.php', + 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'SebastianBergmann\\Comparator\\ArrayComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ArrayComparator.php', 'SebastianBergmann\\Comparator\\Comparator' => __DIR__ . '/..' . '/sebastian/comparator/src/Comparator.php', 'SebastianBergmann\\Comparator\\ComparisonFailure' => __DIR__ . '/..' . '/sebastian/comparator/src/ComparisonFailure.php', @@ -845,7 +997,10 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf 'Squiz_Sniffs_WhiteSpace_ScopeKeywordSpacingSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_SemicolonSpacingSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_SuperfluousWhitespaceSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php', + 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Text_Template' => __DIR__ . '/..' . '/phpunit/php-text-template/src/Template.php', + 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', 'Zend_Sniffs_Debug_CodeAnalyzerSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php', 'Zend_Sniffs_Files_ClosingTagSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/Files/ClosingTagSniff.php', 'Zend_Sniffs_NamingConventions_ValidVariableNameSniff' => __DIR__ . '/..' . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php', @@ -854,10 +1009,9 @@ class ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf::$prefixDirsPsr4; - $loader->prefixesPsr0 = ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf::$prefixesPsr0; - $loader->classMap = ComposerStaticInitd34d355c260bb5a736a127816ecaf3bf::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInit8e045aa3eb0169172b5c8585a1d97f8e::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit8e045aa3eb0169172b5c8585a1d97f8e::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit8e045aa3eb0169172b5c8585a1d97f8e::$classMap; }, null, ClassLoader::class); } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index b1c9f96..9aea264 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,2115 +1,4321 @@ -[ - { - "name": "doctrine/instantiator", - "version": "1.1.0", - "version_normalized": "1.1.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "^6.2.3", - "squizlabs/php_codesniffer": "^3.0.2" - }, - "time": "2017-07-22T11:58:36+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "installation-source": "dist", - "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": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ] - }, - { - "name": "friendsofphp/php-cs-fixer", - "version": "v1.13.3", - "version_normalized": "1.13.3.0", - "source": { - "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "387e4c86c9dc0e1e4c475291fc114ec45b98e624" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/387e4c86c9dc0e1e4c475291fc114ec45b98e624", - "reference": "387e4c86c9dc0e1e4c475291fc114ec45b98e624", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": "^5.3.6 || >=7.0 <7.2", - "sebastian/diff": "^1.1", - "symfony/console": "^2.3 || ^3.0", - "symfony/event-dispatcher": "^2.1 || ^3.0", - "symfony/filesystem": "^2.1 || ^3.0", - "symfony/finder": "^2.1 || ^3.0", - "symfony/process": "^2.3 || ^3.0", - "symfony/stopwatch": "^2.5 || ^3.0" - }, - "conflict": { - "hhvm": "<3.9" - }, - "require-dev": { - "phpunit/phpunit": "^4.5|^5", - "satooshi/php-coveralls": "^1.0" - }, - "time": "2017-09-11T14:11:16+00:00", - "bin": [ - "php-cs-fixer" - ], - "type": "application", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\CS\\": "Symfony/CS/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "A tool to automatically fix PHP code style" - }, - { - "name": "guzzlehttp/guzzle", - "version": "6.3.3", - "version_normalized": "6.3.3.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "time": "2018-04-22T15:46:56+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.3-dev" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ] - }, - { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "version_normalized": "1.3.1.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "time": "2016-12-20T10:07:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ] - }, - { - "name": "guzzlehttp/psr7", - "version": "1.4.2", - "version_normalized": "1.4.2.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "time": "2017-03-20T17:10:46+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Schultze", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "request", - "response", - "stream", - "uri", - "url" - ] - }, - { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" - }, - "time": "2017-09-11T18:02:19+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" +{ + "packages": [ + { + "name": "composer/pcre", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "reference": "67a32d7d6f9f560b726ab25a061b38ff3a80c560", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "time": "2022-01-21T20:24:37+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/1.0.1" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "install-path": "./pcre" + }, + { + "name": "composer/semver", + "version": "3.3.2", + "version_normalized": "3.3.2.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "time": "2022-04-01T19:23:25+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "install-path": "./semver" + }, + { + "name": "composer/xdebug-handler", + "version": "2.0.5", + "version_normalized": "2.0.5.0", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/9e36aeed4616366d2b690bdce11f71e9178c579a", + "reference": "9e36aeed4616366d2b690bdce11f71e9178c579a", + "shasum": "" + }, + "require": { + "composer/pcre": "^1", + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" + }, + "time": "2022-02-24T20:20:32+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/2.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "install-path": "./xdebug-handler" + }, + { + "name": "doctrine/annotations", + "version": "1.14.3", + "version_normalized": "1.14.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", + "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^1 || ^2", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" + }, + "require-dev": { + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "vimeo/psalm": "^4.10" + }, + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" + }, + "time": "2023-02-01T09:20:38+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/1.14.3" + }, + "install-path": "../doctrine/annotations" + }, + { + "name": "doctrine/deprecations", + "version": "v1.1.1", + "version_normalized": "1.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "time": "2023-06-03T09:27:29+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + }, + "install-path": "../doctrine/deprecations" + }, + { + "name": "doctrine/instantiator", + "version": "1.5.0", + "version_normalized": "1.5.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^11", + "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.30 || ^5.4" + }, + "time": "2022-12-30T00:15:36+00:00", + "type": "library", + "installation-source": "dist", + "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.5.0" + }, + "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" + } + ], + "install-path": "../doctrine/instantiator" + }, + { + "name": "doctrine/lexer", + "version": "2.1.0", + "version_normalized": "2.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" + }, + "time": "2022-12-14T08:49:07+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/2.1.0" + }, + "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%2Flexer", + "type": "tidelift" + } + ], + "install-path": "../doctrine/lexer" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v2.19.3", + "version_normalized": "2.19.3.0", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/75ac86f33fab4714ea5a39a396784d83ae3b5ed8", + "reference": "75ac86f33fab4714ea5a39a396784d83ae3b5ed8", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^1.2 || ^2.0", + "doctrine/annotations": "^1.2", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^5.6 || ^7.0 || ^8.0", + "php-cs-fixer/diff": "^1.3", + "symfony/console": "^3.4.43 || ^4.1.6 || ^5.0", + "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", + "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^3.0 || ^4.0 || ^5.0", + "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^3.0 || ^4.0 || ^5.0", + "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" + }, + "require-dev": { + "justinrainbow/json-schema": "^5.0", + "keradus/cli-executor": "^1.4", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.4.2", + "php-cs-fixer/accessible-object": "^1.0", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", + "phpspec/prophecy-phpunit": "^1.1 || ^2.0", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.13 || ^9.5", + "phpunitgoodpractices/polyfill": "^1.5", + "phpunitgoodpractices/traits": "^1.9.1", + "sanmai/phpunit-legacy-adapter": "^6.4 || ^8.2.1", + "symfony/phpunit-bridge": "^5.2.1", + "symfony/yaml": "^3.0 || ^4.0 || ^5.0" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters.", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "time": "2021-11-15T17:17:55+00:00", + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "extra": { + "branch-alias": { + "dev-master": "2.19-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "classmap": [ + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationCaseFactory.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/Assert/AssertTokensTrait.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php", + "tests/Test/IntegrationCaseFactoryInterface.php", + "tests/Test/InternalIntegrationCaseFactory.php", + "tests/Test/IsIdenticalConstraint.php", + "tests/Test/TokensWithObservedTransformers.php", + "tests/TestCase.php" ] - } - }, - "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" - ] - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", - "version_normalized": "4.3.0.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", - "shasum": "" - }, - "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" - }, - "time": "2017-11-30T07:14:17+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "support": { + "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", + "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.19.3" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "install-path": "../friendsofphp/php-cs-fixer" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.7.0", + "version_normalized": "7.7.0.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "time": "2023-05-21T14:04:53+00:00", + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.7.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "install-path": "../guzzlehttp/guzzle" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.0", + "version_normalized": "2.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6", + "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "time": "2023-05-21T13:50:22+00:00", + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "install-path": "../guzzlehttp/promises" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.5.0", + "version_normalized": "2.5.0.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "b635f279edd83fc275f822a1188157ffea568ff6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", + "reference": "b635f279edd83fc275f822a1188157ffea568ff6", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "time": "2023-04-17T16:11:26+00:00", + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.5.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "install-path": "../guzzlehttp/psr7" + }, + { + "name": "php-cs-fixer/diff", + "version": "v1.3.1", + "version_normalized": "1.3.1.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/diff.git", + "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/dbd31aeb251639ac0b9e7e29405c1441907f5759", + "reference": "dbd31aeb251639ac0b9e7e29405c1441907f5759", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", + "symfony/process": "^3.3" + }, + "time": "2020-10-14T08:39:05+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ "src/" ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock." - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", - "version_normalized": "0.4.0.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", - "shasum": "" - }, - "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" - }, - "time": "2017-07-14T14:27:02+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ + }, + "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" + }, + { + "name": "SpacePossum" + } + ], + "description": "sebastian/diff v2 backport support for PHP5.6", + "homepage": "https://github.com/PHP-CS-Fixer", + "keywords": [ + "diff" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/diff/issues", + "source": "https://github.com/PHP-CS-Fixer/diff/tree/v1.3.1" + }, + "abandoned": true, + "install-path": "../php-cs-fixer/diff" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "version_normalized": "2.2.0.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" + }, + "time": "2020-06-27T09:03:43+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "installation-source": "dist", + "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" + }, + "install-path": "../phpdocumentor/reflection-common" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.3.0", + "version_normalized": "5.3.0.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" + }, + "time": "2021-10-19T17:43:47+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "installation-source": "dist", + "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" + }, + "install-path": "../phpdocumentor/reflection-docblock" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.6.1", + "version_normalized": "1.6.1.0", + "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" + }, + "time": "2022-03-15T21:29:03+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "installation-source": "dist", + "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" + }, + "install-path": "../phpdocumentor/type-resolver" + }, + { + "name": "phpspec/prophecy", + "version": "v1.10.3", + "version_normalized": "1.10.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "451c3cd1418cf640de218914901e51b064abb093" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5 || ^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "time": "2020-03-05T15:02:03+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10.x-dev" + } + }, + "installation-source": "dist", + "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.10.3" + }, + "install-path": "../phpspec/prophecy" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.2.4", + "version_normalized": "2.2.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "time": "2015-10-06T15:47:00+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ "src/" ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ] - }, - { - "name": "phpspec/prophecy", - "version": "1.8.0", - "version_normalized": "1.8.0.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" - }, - "time": "2018-08-05T17:53:17+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "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" - ] - }, - { - "name": "phpunit/php-code-coverage", - "version": "2.2.4", - "version_normalized": "2.2.4.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" - }, - "time": "2015-10-06T15:47:00+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.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" - ] - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.5", - "version_normalized": "1.4.5.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "time": "2017-11-27T13:52:08+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.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" - ] - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "version_normalized": "1.2.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "time": "2015-06-21T13:50:34+00:00", - "type": "library", - "installation-source": "dist", - "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" - ] - }, - { - "name": "phpunit/php-timer", - "version": "1.0.9", - "version_normalized": "1.0.9.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "time": "2017-02-26T11:10:40+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ] - }, - { - "name": "phpunit/php-token-stream", - "version": "1.4.12", - "version_normalized": "1.4.12.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "time": "2017-12-04T08:55:13+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ] - }, - { - "name": "phpunit/phpunit", - "version": "4.8.36", - "version_normalized": "4.8.36.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.2.2", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" - }, - "suggest": { - "phpunit/php-invoker": "~1.1" - }, - "time": "2017-06-21T08:07:12+00:00", - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.8.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "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" - ] - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", - "version_normalized": "2.3.8.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" - }, - "time": "2015-10-02T06:51:40+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ] - }, - { - "name": "psr/http-message", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2016-08-06T14:39:51+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ] - }, - { - "name": "psr/log", - "version": "1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2016-10-10T12:19:37+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ] - }, - { - "name": "sebastian/comparator", - "version": "1.2.4", - "version_normalized": "1.2.4.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "time": "2017-01-29T09:50:25+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ] - }, - { - "name": "sebastian/diff", - "version": "1.4.3", - "version_normalized": "1.4.3.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "time": "2017-05-22T07:24:03+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ] - }, - { - "name": "sebastian/environment", - "version": "1.3.8", - "version_normalized": "1.3.8.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" - }, - "time": "2016-08-18T05:49:44+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "installation-source": "dist", - "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" - ] - }, - { - "name": "sebastian/exporter", - "version": "1.2.2", - "version_normalized": "1.2.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" - }, - "time": "2016-06-17T09:04:28+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ] - }, - { - "name": "sebastian/global-state", - "version": "1.1.1", - "version_normalized": "1.1.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" - }, - "time": "2015-10-12T03:26:01+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "installation-source": "dist", - "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" - ] - }, - { - "name": "sebastian/recursion-context", - "version": "1.0.5", - "version_normalized": "1.0.5.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "time": "2016-10-03T07:41:43+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context" - }, - { - "name": "sebastian/version", - "version": "1.0.6", - "version_normalized": "1.0.6.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "shasum": "" - }, - "time": "2015-06-21T13:59:46+00:00", - "type": "library", - "installation-source": "dist", - "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" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "2.9.1", - "version_normalized": "2.9.1.0", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "time": "2017-05-22T02:43:20+00:00", - "bin": [ - "scripts/phpcs", - "scripts/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, - "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": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ] - }, - { - "name": "symfony/console", - "version": "v3.4.14", - "version_normalized": "3.4.14.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "6b217594552b9323bcdcfc14f8a0ce126e84cd73" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6b217594552b9323bcdcfc14f8a0ce126e84cd73", - "reference": "6b217594552b9323bcdcfc14f8a0ce126e84cd73", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.3|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.3|~4.0" - }, - "suggest": { - "psr/log-implementation": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "time": "2018-07-26T11:19:56+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/debug", - "version": "v4.1.3", - "version_normalized": "4.1.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "9316545571f079c4dd183e674721d9dc783ce196" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/9316545571f079c4dd183e674721d9dc783ce196", - "reference": "9316545571f079c4dd183e674721d9dc783ce196", - "shasum": "" - }, - "require": { - "php": "^7.1.3", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": "<3.4" - }, - "require-dev": { - "symfony/http-kernel": "~3.4|~4.0" - }, - "time": "2018-07-26T11:24:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.1-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Debug Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/event-dispatcher", - "version": "v3.4.14", - "version_normalized": "3.4.14.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb", - "reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/dependency-injection": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "time": "2018-07-26T09:06:28+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/filesystem", - "version": "v3.4.14", - "version_normalized": "3.4.14.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/a59f917e3c5d82332514cb4538387638f5bde2d6", - "reference": "a59f917e3c5d82332514cb4538387638f5bde2d6", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" - }, - "time": "2018-07-26T11:19:56+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/finder", - "version": "v3.4.14", - "version_normalized": "3.4.14.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "8a84fcb207451df0013b2c74cbbf1b62d47b999a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8a84fcb207451df0013b2c74cbbf1b62d47b999a", - "reference": "8a84fcb207451df0013b2c74cbbf1b62d47b999a", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "time": "2018-07-26T11:19:56+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.8.0", - "version_normalized": "1.8.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", - "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "time": "2018-04-30T19:57:29+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ] - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.8.0", - "version_normalized": "1.8.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "3296adf6a6454a050679cde90f95350ad604b171" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", - "reference": "3296adf6a6454a050679cde90f95350ad604b171", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "time": "2018-04-26T10:06:28+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ] - }, - { - "name": "symfony/process", - "version": "v3.4.14", - "version_normalized": "3.4.14.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "0414db29bd770ec5a4152683e655f55efd4fa60f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0414db29bd770ec5a4152683e655f55efd4fa60f", - "reference": "0414db29bd770ec5a4152683e655f55efd4fa60f", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "time": "2018-07-26T11:19:56+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Process Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/stopwatch", - "version": "v3.4.14", - "version_normalized": "3.4.14.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "deda2765e8dab2fc38492e926ea690f2a681f59d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/deda2765e8dab2fc38492e926ea690f2a681f59d", - "reference": "deda2765e8dab2fc38492e926ea690f2a681f59d", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "time": "2018-07-26T10:03:52+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Stopwatch Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/yaml", - "version": "v3.4.14", - "version_normalized": "3.4.14.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/810af2d35fc72b6cf5c01116806d2b65ccaaf2e2", - "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "time": "2018-07-26T11:19:56+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com" - }, - { - "name": "webmozart/assert", - "version": "1.3.0", - "version_normalized": "1.3.0.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "time": "2018-01-29T19:49:41+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "installation-source": "dist", - "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" - ] - } -] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.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": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/2.2" + }, + "install-path": "../phpunit/php-code-coverage" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.5", + "version_normalized": "1.4.5.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2017-11-27T13:52:08+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.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": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5" + }, + "install-path": "../phpunit/php-file-iterator" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "version_normalized": "1.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2015-06-21T13:50:34+00:00", + "type": "library", + "installation-source": "dist", + "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/1.2.1" + }, + "install-path": "../phpunit/php-text-template" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "version_normalized": "1.0.9.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "time": "2017-02-26T11:10:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.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/master" + }, + "install-path": "../phpunit/php-timer" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.12", + "version_normalized": "1.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "time": "2017-12-04T08:55:13+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/1.4" + }, + "abandoned": true, + "install-path": "../phpunit/php-token-stream" + }, + { + "name": "phpunit/phpunit", + "version": "4.8.36", + "version_normalized": "4.8.36.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.2.2", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "time": "2017-06-21T08:07:12+00:00", + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.8.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "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/4.8.36" + }, + "install-path": "../phpunit/phpunit" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.8", + "version_normalized": "2.3.8.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "time": "2015-10-02T06:51:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", + "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/2.3" + }, + "abandoned": true, + "install-path": "../phpunit/phpunit-mock-objects" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2016-08-06T20:24:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/master" + }, + "install-path": "../psr/cache" + }, + { + "name": "psr/container", + "version": "1.1.1", + "version_normalized": "1.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "time": "2021-03-05T17:36:06+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" + }, + "install-path": "../psr/container" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "time": "2019-01-08T18:20:26+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "install-path": "../psr/event-dispatcher" + }, + { + "name": "psr/http-client", + "version": "1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "time": "2023-04-10T20:12:12+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/1.0.2" + }, + "install-path": "../psr/http-client" + }, + { + "name": "psr/http-factory", + "version": "1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "time": "2023-04-10T20:10:41+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + }, + "install-path": "../psr/http-factory" + }, + { + "name": "psr/http-message", + "version": "2.0", + "version_normalized": "2.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "time": "2023-04-04T09:54:51+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "install-path": "../psr/http-message" + }, + { + "name": "psr/log", + "version": "1.1.4", + "version_normalized": "1.1.4.0", + "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" + }, + "time": "2021-05-03T11:20:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "installation-source": "dist", + "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" + }, + "install-path": "../psr/log" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "version_normalized": "3.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "time": "2019-03-08T08:55:37+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "install-path": "../ralouphie/getallheaders" + }, + { + "name": "sebastian/comparator", + "version": "1.2.4", + "version_normalized": "1.2.4.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "time": "2017-01-29T09:50:25+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/1.2" + }, + "install-path": "../sebastian/comparator" + }, + { + "name": "sebastian/diff", + "version": "1.4.3", + "version_normalized": "1.4.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "time": "2017-05-22T07:24:03+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/1.4" + }, + "install-path": "../sebastian/diff" + }, + { + "name": "sebastian/environment", + "version": "1.3.8", + "version_normalized": "1.3.8.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "time": "2016-08-18T05:49:44+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "installation-source": "dist", + "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/1.3" + }, + "install-path": "../sebastian/environment" + }, + { + "name": "sebastian/exporter", + "version": "1.2.2", + "version_normalized": "1.2.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "time": "2016-06-17T09:04:28+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/master" + }, + "install-path": "../sebastian/exporter" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "version_normalized": "1.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "time": "2015-10-12T03:26:01+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "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/1.1.1" + }, + "install-path": "../sebastian/global-state" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.5", + "version_normalized": "1.0.5.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "time": "2016-10-03T07:41:43+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "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/master" + }, + "install-path": "../sebastian/recursion-context" + }, + { + "name": "sebastian/version", + "version": "1.0.6", + "version_normalized": "1.0.6.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "shasum": "" + }, + "time": "2015-06-21T13:59:46+00:00", + "type": "library", + "installation-source": "dist", + "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/1.0.6" + }, + "install-path": "../sebastian/version" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "2.9.2", + "version_normalized": "2.9.2.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "2acf168de78487db620ab4bc524135a13cfe6745" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/2acf168de78487db620ab4bc524135a13cfe6745", + "reference": "2acf168de78487db620ab4bc524135a13cfe6745", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "time": "2018-11-07T22:31:41+00:00", + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "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": "http://www.squizlabs.com/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" + }, + "install-path": "../squizlabs/php_codesniffer" + }, + { + "name": "symfony/console", + "version": "v5.4.24", + "version_normalized": "5.4.24.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8", + "reference": "560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "time": "2023-05-26T05:13:16+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.4.24" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/console" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2022-01-02T09:53:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/deprecation-contracts" + }, + { + "name": "symfony/event-dispatcher", + "version": "v5.4.22", + "version_normalized": "5.4.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1df20e45d56da29a4b1d8259dd6e950acbf1b13f", + "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^4.4|^5.0|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "time": "2023-03-17T11:31:58+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.22" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/event-dispatcher" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", + "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "time": "2022-01-02T09:53:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/event-dispatcher-contracts" + }, + { + "name": "symfony/filesystem", + "version": "v5.4.25", + "version_normalized": "5.4.25.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", + "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "time": "2023-05-31T13:04:02+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.4.25" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/filesystem" + }, + { + "name": "symfony/finder", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/078e9a5e1871fcfe6a5ce421b539344c21afef19", + "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "time": "2023-02-16T09:33:00+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/finder" + }, + { + "name": "symfony/options-resolver", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "time": "2023-02-14T08:03:56+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/options-resolver" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", + "version_normalized": "1.27.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "time": "2022-11-03T14:55:06+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-ctype" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", + "version_normalized": "1.27.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "time": "2022-11-03T14:55:06+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-intl-grapheme" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", + "version_normalized": "1.27.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "time": "2022-11-03T14:55:06+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-intl-normalizer" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", + "version_normalized": "1.27.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "time": "2022-11-03T14:55:06+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-mbstring" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.20.0", + "version_normalized": "1.20.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2020-10-23T14:02:19+00:00", + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php70/tree/v1.20.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": null + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.27.0", + "version_normalized": "1.27.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "869329b1e9894268a8a61dabb69153029b7a8c97" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97", + "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2022-11-03T14:55:06+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php72" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.27.0", + "version_normalized": "1.27.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2022-11-03T14:55:06+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php73" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.27.0", + "version_normalized": "1.27.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2022-11-03T14:55:06+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php80" + }, + { + "name": "symfony/process", + "version": "v5.4.24", + "version_normalized": "5.4.24.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "e3c46cc5689c8782944274bb30702106ecbe3b64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/e3c46cc5689c8782944274bb30702106ecbe3b64", + "reference": "e3c46cc5689c8782944274bb30702106ecbe3b64", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "time": "2023-05-17T11:26:05+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v5.4.24" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/process" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "time": "2022-05-30T19:17:29+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/service-contracts" + }, + { + "name": "symfony/stopwatch", + "version": "v5.4.21", + "version_normalized": "5.4.21.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee", + "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/service-contracts": "^1|^2|^3" + }, + "time": "2023-02-14T08:03:56+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v5.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/stopwatch" + }, + { + "name": "symfony/string", + "version": "v5.4.22", + "version_normalized": "5.4.22.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", + "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", + "shasum": "" + }, + "require": { + "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-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, + "require-dev": { + "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": "2023-03-14T06:11:53+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.22" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/string" + }, + { + "name": "symfony/yaml", + "version": "v3.4.47", + "version_normalized": "3.4.47.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "88289caa3c166321883f67fe5130188ebbb47094" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/88289caa3c166321883f67fe5130188ebbb47094", + "reference": "88289caa3c166321883f67fe5130188ebbb47094", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "time": "2020-10-24T10:57:07+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v3.4.47" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/yaml" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "version_normalized": "1.11.0.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "time": "2022-06-03T18:03:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "installation-source": "dist", + "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.11.0" + }, + "install-path": "../webmozart/assert" + } + ], + "dev": true, + "dev-package-names": [ + "composer/pcre", + "composer/semver", + "composer/xdebug-handler", + "doctrine/annotations", + "doctrine/deprecations", + "doctrine/instantiator", + "doctrine/lexer", + "friendsofphp/php-cs-fixer", + "php-cs-fixer/diff", + "phpdocumentor/reflection-common", + "phpdocumentor/reflection-docblock", + "phpdocumentor/type-resolver", + "phpspec/prophecy", + "phpunit/php-code-coverage", + "phpunit/php-file-iterator", + "phpunit/php-text-template", + "phpunit/php-timer", + "phpunit/php-token-stream", + "phpunit/phpunit", + "phpunit/phpunit-mock-objects", + "psr/cache", + "psr/container", + "psr/event-dispatcher", + "psr/log", + "sebastian/comparator", + "sebastian/diff", + "sebastian/environment", + "sebastian/exporter", + "sebastian/global-state", + "sebastian/recursion-context", + "sebastian/version", + "squizlabs/php_codesniffer", + "symfony/console", + "symfony/event-dispatcher", + "symfony/event-dispatcher-contracts", + "symfony/filesystem", + "symfony/finder", + "symfony/options-resolver", + "symfony/polyfill-ctype", + "symfony/polyfill-intl-grapheme", + "symfony/polyfill-intl-normalizer", + "symfony/polyfill-mbstring", + "symfony/polyfill-php70", + "symfony/polyfill-php72", + "symfony/polyfill-php73", + "symfony/polyfill-php80", + "symfony/process", + "symfony/service-contracts", + "symfony/stopwatch", + "symfony/string", + "symfony/yaml", + "webmozart/assert" + ] +} diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php new file mode 100644 index 0000000..798d913 --- /dev/null +++ b/vendor/composer/installed.php @@ -0,0 +1,599 @@ + array( + 'name' => 'cloudmersive/cloudmersive_validate_api_client', + 'pretty_version' => '3.0.1', + 'version' => '3.0.1.0', + 'reference' => NULL, + 'type' => 'library', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev' => true, + ), + 'versions' => array( + 'cloudmersive/cloudmersive_validate_api_client' => array( + 'pretty_version' => '3.0.1', + 'version' => '3.0.1.0', + 'reference' => NULL, + 'type' => 'library', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'composer/pcre' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'reference' => '67a32d7d6f9f560b726ab25a061b38ff3a80c560', + 'type' => 'library', + 'install_path' => __DIR__ . '/./pcre', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'composer/semver' => array( + 'pretty_version' => '3.3.2', + 'version' => '3.3.2.0', + 'reference' => '3953f23262f2bff1919fc82183ad9acb13ff62c9', + 'type' => 'library', + 'install_path' => __DIR__ . '/./semver', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'composer/xdebug-handler' => array( + 'pretty_version' => '2.0.5', + 'version' => '2.0.5.0', + 'reference' => '9e36aeed4616366d2b690bdce11f71e9178c579a', + 'type' => 'library', + 'install_path' => __DIR__ . '/./xdebug-handler', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'doctrine/annotations' => array( + 'pretty_version' => '1.14.3', + 'version' => '1.14.3.0', + 'reference' => 'fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af', + 'type' => 'library', + 'install_path' => __DIR__ . '/../doctrine/annotations', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'doctrine/deprecations' => array( + 'pretty_version' => 'v1.1.1', + 'version' => '1.1.1.0', + 'reference' => '612a3ee5ab0d5dd97b7cf3874a6efe24325efac3', + 'type' => 'library', + 'install_path' => __DIR__ . '/../doctrine/deprecations', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'doctrine/instantiator' => array( + 'pretty_version' => '1.5.0', + 'version' => '1.5.0.0', + 'reference' => '0a0fa9780f5d4e507415a065172d26a98d02047b', + 'type' => 'library', + 'install_path' => __DIR__ . '/../doctrine/instantiator', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'doctrine/lexer' => array( + 'pretty_version' => '2.1.0', + 'version' => '2.1.0.0', + 'reference' => '39ab8fcf5a51ce4b85ca97c7a7d033eb12831124', + 'type' => 'library', + 'install_path' => __DIR__ . '/../doctrine/lexer', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'friendsofphp/php-cs-fixer' => array( + 'pretty_version' => 'v2.19.3', + 'version' => '2.19.3.0', + 'reference' => '75ac86f33fab4714ea5a39a396784d83ae3b5ed8', + 'type' => 'application', + 'install_path' => __DIR__ . '/../friendsofphp/php-cs-fixer', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'guzzlehttp/guzzle' => array( + 'pretty_version' => '7.7.0', + 'version' => '7.7.0.0', + 'reference' => 'fb7566caccf22d74d1ab270de3551f72a58399f5', + 'type' => 'library', + 'install_path' => __DIR__ . '/../guzzlehttp/guzzle', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'guzzlehttp/promises' => array( + 'pretty_version' => '2.0.0', + 'version' => '2.0.0.0', + 'reference' => '3a494dc7dc1d7d12e511890177ae2d0e6c107da6', + 'type' => 'library', + 'install_path' => __DIR__ . '/../guzzlehttp/promises', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'guzzlehttp/psr7' => array( + 'pretty_version' => '2.5.0', + 'version' => '2.5.0.0', + 'reference' => 'b635f279edd83fc275f822a1188157ffea568ff6', + 'type' => 'library', + 'install_path' => __DIR__ . '/../guzzlehttp/psr7', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'php-cs-fixer/diff' => array( + 'pretty_version' => 'v1.3.1', + 'version' => '1.3.1.0', + 'reference' => 'dbd31aeb251639ac0b9e7e29405c1441907f5759', + 'type' => 'library', + 'install_path' => __DIR__ . '/../php-cs-fixer/diff', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpdocumentor/reflection-common' => array( + 'pretty_version' => '2.2.0', + 'version' => '2.2.0.0', + 'reference' => '1d01c49d4ed62f25aa84a747ad35d5a16924662b', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpdocumentor/reflection-common', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpdocumentor/reflection-docblock' => array( + 'pretty_version' => '5.3.0', + 'version' => '5.3.0.0', + 'reference' => '622548b623e81ca6d78b721c5e029f4ce664f170', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpdocumentor/reflection-docblock', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpdocumentor/type-resolver' => array( + 'pretty_version' => '1.6.1', + 'version' => '1.6.1.0', + 'reference' => '77a32518733312af16a44300404e945338981de3', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpdocumentor/type-resolver', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpspec/prophecy' => array( + 'pretty_version' => 'v1.10.3', + 'version' => '1.10.3.0', + 'reference' => '451c3cd1418cf640de218914901e51b064abb093', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpspec/prophecy', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/php-code-coverage' => array( + 'pretty_version' => '2.2.4', + 'version' => '2.2.4.0', + 'reference' => 'eabf68b476ac7d0f73793aada060f1c1a9bf8979', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-code-coverage', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/php-file-iterator' => array( + 'pretty_version' => '1.4.5', + 'version' => '1.4.5.0', + 'reference' => '730b01bc3e867237eaac355e06a36b85dd93a8b4', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-file-iterator', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/php-text-template' => array( + 'pretty_version' => '1.2.1', + 'version' => '1.2.1.0', + 'reference' => '31f8b717e51d9a2afca6c9f046f5d69fc27c8686', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-text-template', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/php-timer' => array( + 'pretty_version' => '1.0.9', + 'version' => '1.0.9.0', + 'reference' => '3dcf38ca72b158baf0bc245e9184d3fdffa9c46f', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-timer', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/php-token-stream' => array( + 'pretty_version' => '1.4.12', + 'version' => '1.4.12.0', + 'reference' => '1ce90ba27c42e4e44e6d8458241466380b51fa16', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-token-stream', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/phpunit' => array( + 'pretty_version' => '4.8.36', + 'version' => '4.8.36.0', + 'reference' => '46023de9a91eec7dfb06cc56cb4e260017298517', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/phpunit', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/phpunit-mock-objects' => array( + 'pretty_version' => '2.3.8', + 'version' => '2.3.8.0', + 'reference' => 'ac8e7a3db35738d56ee9a76e78a4e03d97628983', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/phpunit-mock-objects', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'psr/cache' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/cache', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'psr/container' => array( + 'pretty_version' => '1.1.1', + 'version' => '1.1.1.0', + 'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/container', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'psr/event-dispatcher' => array( + 'pretty_version' => '1.0.0', + 'version' => '1.0.0.0', + 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/event-dispatcher', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'psr/event-dispatcher-implementation' => array( + 'dev_requirement' => true, + 'provided' => array( + 0 => '1.0', + ), + ), + 'psr/http-client' => array( + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'reference' => '0955afe48220520692d2d09f7ab7e0f93ffd6a31', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-client', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-client-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0', + ), + ), + 'psr/http-factory' => array( + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'reference' => 'e616d01114759c4c489f93b099585439f795fe35', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-factory', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-factory-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0', + ), + ), + 'psr/http-message' => array( + 'pretty_version' => '2.0', + 'version' => '2.0.0.0', + 'reference' => '402d35bcb92c70c026d1a6a9883f06b2ead23d71', + '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' => array( + 'pretty_version' => '1.1.4', + 'version' => '1.1.4.0', + 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/log', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'psr/log-implementation' => array( + 'dev_requirement' => true, + 'provided' => array( + 0 => '1.0|2.0', + ), + ), + 'ralouphie/getallheaders' => array( + 'pretty_version' => '3.0.3', + 'version' => '3.0.3.0', + 'reference' => '120b605dfeb996808c31b6477290a714d356e822', + 'type' => 'library', + 'install_path' => __DIR__ . '/../ralouphie/getallheaders', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'sebastian/comparator' => array( + 'pretty_version' => '1.2.4', + 'version' => '1.2.4.0', + 'reference' => '2b7424b55f5047b47ac6e5ccb20b2aea4011d9be', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/comparator', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/diff' => array( + 'pretty_version' => '1.4.3', + 'version' => '1.4.3.0', + 'reference' => '7f066a26a962dbe58ddea9f72a4e82874a3975a4', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/diff', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/environment' => array( + 'pretty_version' => '1.3.8', + 'version' => '1.3.8.0', + 'reference' => 'be2c607e43ce4c89ecd60e75c6a85c126e754aea', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/environment', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/exporter' => array( + 'pretty_version' => '1.2.2', + 'version' => '1.2.2.0', + 'reference' => '42c4c2eec485ee3e159ec9884f95b431287edde4', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/exporter', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/global-state' => array( + 'pretty_version' => '1.1.1', + 'version' => '1.1.1.0', + 'reference' => 'bc37d50fea7d017d3d340f230811c9f1d7280af4', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/global-state', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/recursion-context' => array( + 'pretty_version' => '1.0.5', + 'version' => '1.0.5.0', + 'reference' => 'b19cc3298482a335a95f3016d2f8a6950f0fbcd7', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/recursion-context', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/version' => array( + 'pretty_version' => '1.0.6', + 'version' => '1.0.6.0', + 'reference' => '58b3a85e7999757d6ad81c787a1fbf5ff6c628c6', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/version', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'squizlabs/php_codesniffer' => array( + 'pretty_version' => '2.9.2', + 'version' => '2.9.2.0', + 'reference' => '2acf168de78487db620ab4bc524135a13cfe6745', + 'type' => 'library', + 'install_path' => __DIR__ . '/../squizlabs/php_codesniffer', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/console' => array( + 'pretty_version' => 'v5.4.24', + 'version' => '5.4.24.0', + 'reference' => '560fc3ed7a43e6d30ea94a07d77f9a60b8ed0fb8', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/console', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/deprecation-contracts' => array( + 'pretty_version' => 'v2.5.2', + 'version' => '2.5.2.0', + 'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/event-dispatcher' => array( + 'pretty_version' => 'v5.4.22', + 'version' => '5.4.22.0', + 'reference' => '1df20e45d56da29a4b1d8259dd6e950acbf1b13f', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/event-dispatcher', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/event-dispatcher-contracts' => array( + 'pretty_version' => 'v2.5.2', + 'version' => '2.5.2.0', + 'reference' => 'f98b54df6ad059855739db6fcbc2d36995283fe1', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/event-dispatcher-implementation' => array( + 'dev_requirement' => true, + 'provided' => array( + 0 => '2.0', + ), + ), + 'symfony/filesystem' => array( + 'pretty_version' => 'v5.4.25', + 'version' => '5.4.25.0', + 'reference' => '0ce3a62c9579a53358d3a7eb6b3dfb79789a6364', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/filesystem', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/finder' => array( + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => '078e9a5e1871fcfe6a5ce421b539344c21afef19', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/finder', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/options-resolver' => array( + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => '4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/options-resolver', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/polyfill-ctype' => array( + 'pretty_version' => 'v1.27.0', + 'version' => '1.27.0.0', + 'reference' => '5bbc823adecdae860bb64756d639ecfec17b050a', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/polyfill-intl-grapheme' => array( + 'pretty_version' => 'v1.27.0', + 'version' => '1.27.0.0', + 'reference' => '511a08c03c1960e08a883f4cffcacd219b758354', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/polyfill-intl-normalizer' => array( + 'pretty_version' => 'v1.27.0', + 'version' => '1.27.0.0', + 'reference' => '19bd1e4fcd5b91116f14d8533c57831ed00571b6', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/polyfill-mbstring' => array( + 'pretty_version' => 'v1.27.0', + 'version' => '1.27.0.0', + 'reference' => '8ad114f6b39e2c98a8b0e3bd907732c207c2b534', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/polyfill-php70' => array( + 'pretty_version' => 'v1.20.0', + 'version' => '1.20.0.0', + 'reference' => '5f03a781d984aae42cebd18e7912fa80f02ee644', + 'type' => 'metapackage', + 'install_path' => NULL, + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/polyfill-php72' => array( + 'pretty_version' => 'v1.27.0', + 'version' => '1.27.0.0', + 'reference' => '869329b1e9894268a8a61dabb69153029b7a8c97', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php72', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/polyfill-php73' => array( + 'pretty_version' => 'v1.27.0', + 'version' => '1.27.0.0', + 'reference' => '9e8ecb5f92152187c4799efd3c96b78ccab18ff9', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php73', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/polyfill-php80' => array( + 'pretty_version' => 'v1.27.0', + 'version' => '1.27.0.0', + 'reference' => '7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php80', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/process' => array( + 'pretty_version' => 'v5.4.24', + 'version' => '5.4.24.0', + 'reference' => 'e3c46cc5689c8782944274bb30702106ecbe3b64', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/process', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/service-contracts' => array( + 'pretty_version' => 'v2.5.2', + 'version' => '2.5.2.0', + 'reference' => '4b426aac47d6427cc1a1d0f7e2ac724627f5966c', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/service-contracts', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/stopwatch' => array( + 'pretty_version' => 'v5.4.21', + 'version' => '5.4.21.0', + 'reference' => 'f83692cd869a6f2391691d40a01e8acb89e76fee', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/stopwatch', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/string' => array( + 'pretty_version' => 'v5.4.22', + 'version' => '5.4.22.0', + 'reference' => '8036a4c76c0dd29e60b6a7cafcacc50cf088ea62', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/string', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'symfony/yaml' => array( + 'pretty_version' => 'v3.4.47', + 'version' => '3.4.47.0', + 'reference' => '88289caa3c166321883f67fe5130188ebbb47094', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/yaml', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'webmozart/assert' => array( + 'pretty_version' => '1.11.0', + 'version' => '1.11.0.0', + 'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991', + 'type' => 'library', + 'install_path' => __DIR__ . '/../webmozart/assert', + 'aliases' => array(), + 'dev_requirement' => true, + ), + ), +); diff --git a/vendor/composer/pcre/LICENSE b/vendor/composer/pcre/LICENSE new file mode 100644 index 0000000..c5a282f --- /dev/null +++ b/vendor/composer/pcre/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2021 Composer + +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/vendor/composer/pcre/README.md b/vendor/composer/pcre/README.md new file mode 100644 index 0000000..2ddaf74 --- /dev/null +++ b/vendor/composer/pcre/README.md @@ -0,0 +1,134 @@ +composer/pcre +============= + +PCRE wrapping library that offers type-safe `preg_*` replacements. + +This library gives you a way to ensure `preg_*` functions do not fail silently, returning +unexpected `null`s that may not be handled. + +It also makes it easier ot work with static analysis tools like PHPStan or Psalm as it +simplifies and reduces the possible return values from all the `preg_*` functions which +are quite packed with edge cases. + +This library is a thin wrapper around `preg_*` functions with [some limitations](#restrictions--limitations). +If you are looking for a richer API to handle regular expressions have a look at +[rawr/t-regx](https://packagist.org/packages/rawr/t-regx) instead. + +[![Continuous Integration](https://github.com/composer/pcre/workflows/Continuous%20Integration/badge.svg?branch=main)](https://github.com/composer/pcre/actions) + + +Installation +------------ + +Install the latest version with: + +```bash +$ composer require composer/pcre +``` + + +Requirements +------------ + +* PHP 5.3.2 is required but using the latest version of PHP is highly recommended. + + +Basic usage +----------- + +Instead of: + +```php +if (preg_match('{fo+}', $string, $matches)) { ... } +if (preg_match('{fo+}', $string, $matches, PREG_OFFSET_CAPTURE)) { ... } +if (preg_match_all('{fo+}', $string, $matches)) { ... } +$newString = preg_replace('{fo+}', 'bar', $string); +$newString = preg_replace_callback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string); +$newString = preg_replace_callback_array(['{fo+}' => fn ($match) => strtoupper($match[0])], $string); +$filtered = preg_grep('{[a-z]}', $elements); +$array = preg_split('{[a-z]+}', $string); +``` + +You can now call these on the `Preg` class: + +```php +use Composer\Pcre\Preg; + +if (Preg::match('{fo+}', $string, $matches)) { ... } +if (Preg::matchWithOffsets('{fo+}', $string, $matches)) { ... } +if (Preg::matchAll('{fo+}', $string, $matches)) { ... } +$newString = Preg::replace('{fo+}', 'bar', $string); +$newString = Preg::replaceCallback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string); +$newString = Preg::replaceCallbackArray(['{fo+}' => fn ($match) => strtoupper($match[0])], $string); +$filtered = Preg::grep('{[a-z]}', $elements); +$array = Preg::split('{[a-z]+}', $string); +``` + +The main difference is if anything fails to match/replace/.., it will throw a `Composer\Pcre\PcreException` +instead of returning `null` (or false in some cases), so you can now use the return values safely relying on +the fact that they can only be strings (for replace), ints (for match) or arrays (for grep/split). + +Additionally the `Preg` class provides match methods that return `bool` rather than `int`, for stricter type safety +when the number of pattern matches is not useful: + +```php +use Composer\Pcre\Preg; + +if (Preg::isMatch('{fo+}', $string, $matches)) // bool +if (Preg::isMatchAll('{fo+}', $string, $matches)) // bool +``` + +If you would prefer a slightly more verbose usage, replacing by-ref arguments by result objects, you can use the `Regex` class: + +```php +use Composer\Pcre\Regex; + +// this is useful when you are just interested in knowing if something matched +// as it returns a bool instead of int(1/0) for match +$bool = Regex::isMatch('{fo+}', $string); + +$result = Regex::match('{fo+}', $string); +if ($result->matched) { something($result->matches); } + +$result = Regex::matchWithOffsets('{fo+}', $string); +if ($result->matched) { something($result->matches); } + +$result = Regex::matchAll('{fo+}', $string); +if ($result->matched && $result->count > 3) { something($result->matches); } + +$newString = Regex::replace('{fo+}', 'bar', $string)->result; +$newString = Regex::replaceCallback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string)->result; +$newString = Regex::replaceCallbackArray(['{fo+}' => fn ($match) => strtoupper($match[0])], $string)->result; +``` + +Note that `preg_grep` and `preg_split` are only callable via the `Preg` class as they do not have +complex return types warranting a specific result object. + +See the [MatchResult](src/MatchResult.php), [MatchWithOffsetsResult](src/MatchWithOffsetsResult.php), [MatchAllResult](src/MatchAllResult.php), +[MatchAllWithOffsetsResult](src/MatchAllWithOffsetsResult.php), and [ReplaceResult](src/ReplaceResult.php) class sources for more details. + +Restrictions / Limitations +-------------------------- + +Due to type safety requirements a few restrictions are in place.matchWithOffsets + +- matching using `PREG_OFFSET_CAPTURE` is made available via `matchWithOffsets` and `matchAllWithOffsets`. + You cannot pass the flag to `match`/`matchAll`. +- `Preg::split` will also reject `PREG_SPLIT_OFFSET_CAPTURE` and you should use `splitWithOffsets` + instead. +- `matchAll` rejects `PREG_SET_ORDER` as it also changes the shape of the returned matches. There + is no alternative provided as you can fairly easily code around it. +- `preg_filter` is not supported as it has a rather crazy API, most likely you should rather + use `Preg::grep` in combination with some loop and `Preg::replace`. +- `replace`, `replaceCallback` and `replaceCallbackArray` do not support an array `$subject`, + only simple strings. +- in 2.x, we plan to always implicitly use `PREG_UNMATCHED_AS_NULL` for matching, which offers much + saner/predictable results. This is currently not doable due to the PHP version requirement and to + keep things working the same across all PHP versions. If you use the library on a PHP 7.2+ project + however we highly recommend using `PREG_UNMATCHED_AS_NULL` with all `match*` and `replaceCallback*` + methods. + +License +------- + +composer/pcre is licensed under the MIT License, see the LICENSE file for details. diff --git a/vendor/composer/pcre/composer.json b/vendor/composer/pcre/composer.json new file mode 100644 index 0000000..e49047c --- /dev/null +++ b/vendor/composer/pcre/composer.json @@ -0,0 +1,46 @@ +{ + "name": "composer/pcre", + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "type": "library", + "license": "MIT", + "keywords": [ + "pcre", + "regex", + "preg", + "regular expression" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.2 || ^5", + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1" + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Composer\\Pcre\\": "tests" + } + }, + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "scripts": { + "test": "SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor/bin/simple-phpunit", + "phpstan": "phpstan analyse" + } +} diff --git a/vendor/composer/pcre/src/MatchAllResult.php b/vendor/composer/pcre/src/MatchAllResult.php new file mode 100644 index 0000000..4c367b0 --- /dev/null +++ b/vendor/composer/pcre/src/MatchAllResult.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Pcre; + +final class MatchAllResult +{ + /** + * An array of match group => list of matched strings + * + * @readonly + * @var array> + */ + public $matches; + + /** + * @readonly + * @var 0|positive-int + */ + public $count; + + /** + * @readonly + * @var bool + */ + public $matched; + + /** + * @param 0|positive-int $count + * @param array> $matches + */ + public function __construct($count, array $matches) + { + $this->matches = $matches; + $this->matched = (bool) $count; + $this->count = $count; + } +} diff --git a/vendor/composer/pcre/src/MatchAllWithOffsetsResult.php b/vendor/composer/pcre/src/MatchAllWithOffsetsResult.php new file mode 100644 index 0000000..4e893fe --- /dev/null +++ b/vendor/composer/pcre/src/MatchAllWithOffsetsResult.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Pcre; + +final class MatchAllWithOffsetsResult +{ + /** + * An array of match group => list of matches, every match being a pair of string matched + offset in bytes (or -1 if no match) + * + * @readonly + * @var array> + * @phpstan-var array}>> + */ + public $matches; + + /** + * @readonly + * @var 0|positive-int + */ + public $count; + + /** + * @readonly + * @var bool + */ + public $matched; + + /** + * @param 0|positive-int $count + * @param array> $matches + * @phpstan-param array}>> $matches + */ + public function __construct($count, array $matches) + { + $this->matches = $matches; + $this->matched = (bool) $count; + $this->count = $count; + } +} diff --git a/vendor/composer/pcre/src/MatchResult.php b/vendor/composer/pcre/src/MatchResult.php new file mode 100644 index 0000000..d8e3460 --- /dev/null +++ b/vendor/composer/pcre/src/MatchResult.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Pcre; + +final class MatchResult +{ + /** + * An array of match group => string matched + * + * @readonly + * @var array + */ + public $matches; + + /** + * @readonly + * @var bool + */ + public $matched; + + /** + * @param 0|positive-int $count + * @param array $matches + */ + public function __construct($count, array $matches) + { + $this->matches = $matches; + $this->matched = (bool) $count; + } +} diff --git a/vendor/composer/pcre/src/MatchWithOffsetsResult.php b/vendor/composer/pcre/src/MatchWithOffsetsResult.php new file mode 100644 index 0000000..9bd813b --- /dev/null +++ b/vendor/composer/pcre/src/MatchWithOffsetsResult.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Pcre; + +final class MatchWithOffsetsResult +{ + /** + * An array of match group => pair of string matched + offset in bytes (or -1 if no match) + * + * @readonly + * @var array + * @phpstan-var array}> + */ + public $matches; + + /** + * @readonly + * @var bool + */ + public $matched; + + /** + * @param 0|positive-int $count + * @param array $matches + * @phpstan-param array}> $matches + */ + public function __construct($count, array $matches) + { + $this->matches = $matches; + $this->matched = (bool) $count; + } +} diff --git a/vendor/composer/pcre/src/PcreException.php b/vendor/composer/pcre/src/PcreException.php new file mode 100644 index 0000000..f62e681 --- /dev/null +++ b/vendor/composer/pcre/src/PcreException.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Pcre; + +class PcreException extends \RuntimeException +{ + /** + * @param string $function + * @param string|string[] $pattern + * @return self + */ + public static function fromFunction($function, $pattern) + { + $code = preg_last_error(); + + if (is_array($pattern)) { + $pattern = implode(', ', $pattern); + } + + return new PcreException($function.'(): failed executing "'.$pattern.'": '.self::pcreLastErrorMessage($code), $code); + } + + /** + * @param int $code + * @return string + */ + private static function pcreLastErrorMessage($code) + { + if (PHP_VERSION_ID >= 80000) { + return preg_last_error_msg(); + } + + // older php versions did not set the code properly in all cases + if (PHP_VERSION_ID < 70201 && $code === 0) { + return 'UNDEFINED_ERROR'; + } + + $constants = get_defined_constants(true); + if (!isset($constants['pcre'])) { + return 'UNDEFINED_ERROR'; + } + + foreach ($constants['pcre'] as $const => $val) { + if ($val === $code && substr($const, -6) === '_ERROR') { + return $const; + } + } + + return 'UNDEFINED_ERROR'; + } +} diff --git a/vendor/composer/pcre/src/Preg.php b/vendor/composer/pcre/src/Preg.php new file mode 100644 index 0000000..278bc89 --- /dev/null +++ b/vendor/composer/pcre/src/Preg.php @@ -0,0 +1,303 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Pcre; + +class Preg +{ + const ARRAY_MSG = '$subject as an array is not supported. You can use \'foreach\' instead.'; + + /** + * @param non-empty-string $pattern + * @param string $subject + * @param array $matches Set by method + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return 0|1 + */ + public static function match($pattern, $subject, &$matches = null, $flags = 0, $offset = 0) + { + if (($flags & PREG_OFFSET_CAPTURE) !== 0) { + throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the type of $matches, use matchWithOffsets() instead'); + } + + $result = preg_match($pattern, $subject, $matches, $flags, $offset); + if ($result === false) { + throw PcreException::fromFunction('preg_match', $pattern); + } + + return $result; + } + + /** + * Runs preg_match with PREG_OFFSET_CAPTURE + * + * @param non-empty-string $pattern + * @param string $subject + * @param array $matches Set by method + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return 0|1 + * + * @phpstan-param array}> $matches + */ + public static function matchWithOffsets($pattern, $subject, &$matches, $flags = 0, $offset = 0) + { + $result = preg_match($pattern, $subject, $matches, $flags | PREG_OFFSET_CAPTURE, $offset); + if ($result === false) { + throw PcreException::fromFunction('preg_match', $pattern); + } + + return $result; + } + + /** + * @param non-empty-string $pattern + * @param string $subject + * @param array> $matches Set by method + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return 0|positive-int + */ + public static function matchAll($pattern, $subject, &$matches = null, $flags = 0, $offset = 0) + { + if (($flags & PREG_OFFSET_CAPTURE) !== 0) { + throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the type of $matches, use matchAllWithOffsets() instead'); + } + + if (($flags & PREG_SET_ORDER) !== 0) { + throw new \InvalidArgumentException('PREG_SET_ORDER is not supported as it changes the type of $matches'); + } + + $result = preg_match_all($pattern, $subject, $matches, $flags, $offset); + if ($result === false || $result === null) { + throw PcreException::fromFunction('preg_match_all', $pattern); + } + + return $result; + } + + /** + * Runs preg_match_all with PREG_OFFSET_CAPTURE + * + * @param non-empty-string $pattern + * @param string $subject + * @param array> $matches Set by method + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return 0|positive-int + * + * @phpstan-param array}>> $matches + */ + public static function matchAllWithOffsets($pattern, $subject, &$matches, $flags = 0, $offset = 0) + { + $result = preg_match_all($pattern, $subject, $matches, $flags | PREG_OFFSET_CAPTURE, $offset); + if ($result === false || $result === null) { + throw PcreException::fromFunction('preg_match_all', $pattern); + } + + return $result; + } + + /** + * @param string|string[] $pattern + * @param string|string[] $replacement + * @param string $subject + * @param int $limit + * @param int $count Set by method + * @return string + */ + public static function replace($pattern, $replacement, $subject, $limit = -1, &$count = null) + { + if (is_array($subject)) { // @phpstan-ignore-line + throw new \InvalidArgumentException(static::ARRAY_MSG); + } + + $result = preg_replace($pattern, $replacement, $subject, $limit, $count); + if ($result === null) { + throw PcreException::fromFunction('preg_replace', $pattern); + } + + return $result; + } + + /** + * @param string|string[] $pattern + * @param callable $replacement + * @param string $subject + * @param int $limit + * @param int $count Set by method + * @param int $flags PREG_OFFSET_CAPTURE or PREG_UNMATCHED_AS_NULL, only available on PHP 7.4+ + * @return string + */ + public static function replaceCallback($pattern, $replacement, $subject, $limit = -1, &$count = null, $flags = 0) + { + if (is_array($subject)) { // @phpstan-ignore-line + throw new \InvalidArgumentException(static::ARRAY_MSG); + } + + if (PHP_VERSION_ID >= 70400) { + $result = preg_replace_callback($pattern, $replacement, $subject, $limit, $count, $flags); + } else { + $result = preg_replace_callback($pattern, $replacement, $subject, $limit, $count); + } + if ($result === null) { + throw PcreException::fromFunction('preg_replace_callback', $pattern); + } + + return $result; + } + + /** + * Available from PHP 7.0 + * + * @param array $pattern + * @param string $subject + * @param int $limit + * @param int $count Set by method + * @param int $flags PREG_OFFSET_CAPTURE or PREG_UNMATCHED_AS_NULL, only available on PHP 7.4+ + * @return string + */ + public static function replaceCallbackArray(array $pattern, $subject, $limit = -1, &$count = null, $flags = 0) + { + if (is_array($subject)) { // @phpstan-ignore-line + throw new \InvalidArgumentException(static::ARRAY_MSG); + } + + if (PHP_VERSION_ID >= 70400) { + $result = preg_replace_callback_array($pattern, $subject, $limit, $count, $flags); + } else { + $result = preg_replace_callback_array($pattern, $subject, $limit, $count); + } + if ($result === null) { + $pattern = array_keys($pattern); + throw PcreException::fromFunction('preg_replace_callback_array', $pattern); + } + + return $result; + } + + /** + * @param string $pattern + * @param string $subject + * @param int $limit + * @param int $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE + * @return list + */ + public static function split($pattern, $subject, $limit = -1, $flags = 0) + { + if (($flags & PREG_SPLIT_OFFSET_CAPTURE) !== 0) { + throw new \InvalidArgumentException('PREG_SPLIT_OFFSET_CAPTURE is not supported as it changes the type of $matches, use splitWithOffsets() instead'); + } + + $result = preg_split($pattern, $subject, $limit, $flags); + if ($result === false) { + throw PcreException::fromFunction('preg_split', $pattern); + } + + return $result; + } + + /** + * @param string $pattern + * @param string $subject + * @param int $limit + * @param int $flags PREG_SPLIT_NO_EMPTY or PREG_SPLIT_DELIM_CAPTURE + * @return list + * @phpstan-return list}> + */ + public static function splitWithOffsets($pattern, $subject, $limit = -1, $flags = 0) + { + $result = preg_split($pattern, $subject, $limit, $flags | PREG_SPLIT_OFFSET_CAPTURE); + if ($result === false) { + throw PcreException::fromFunction('preg_split', $pattern); + } + + return $result; + } + + /** + * @template T of string|\Stringable + * @param string $pattern + * @param array $array + * @param int $flags PREG_GREP_INVERT + * @return array + */ + public static function grep($pattern, array $array, $flags = 0) + { + $result = preg_grep($pattern, $array, $flags); + if ($result === false) { + throw PcreException::fromFunction('preg_grep', $pattern); + } + + return $result; + } + + /** + * @param non-empty-string $pattern + * @param string $subject + * @param array $matches Set by method + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return bool + */ + public static function isMatch($pattern, $subject, &$matches = null, $flags = 0, $offset = 0) + { + return (bool) static::match($pattern, $subject, $matches, $flags, $offset); + } + + /** + * @param non-empty-string $pattern + * @param string $subject + * @param array> $matches Set by method + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return bool + */ + public static function isMatchAll($pattern, $subject, &$matches = null, $flags = 0, $offset = 0) + { + return (bool) static::matchAll($pattern, $subject, $matches, $flags, $offset); + } + + /** + * Runs preg_match with PREG_OFFSET_CAPTURE + * + * @param non-empty-string $pattern + * @param string $subject + * @param array $matches Set by method + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return bool + * + * @phpstan-param array}> $matches + */ + public static function isMatchWithOffsets($pattern, $subject, &$matches, $flags = 0, $offset = 0) + { + return (bool) static::matchWithOffsets($pattern, $subject, $matches, $flags, $offset); + } + + /** + * Runs preg_match_all with PREG_OFFSET_CAPTURE + * + * @param non-empty-string $pattern + * @param string $subject + * @param array> $matches Set by method + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return bool + * + * @phpstan-param array}>> $matches + */ + public static function isMatchAllWithOffsets($pattern, $subject, &$matches, $flags = 0, $offset = 0) + { + return (bool) static::matchAllWithOffsets($pattern, $subject, $matches, $flags, $offset); + } +} diff --git a/vendor/composer/pcre/src/Regex.php b/vendor/composer/pcre/src/Regex.php new file mode 100644 index 0000000..008dca8 --- /dev/null +++ b/vendor/composer/pcre/src/Regex.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Pcre; + +class Regex +{ + /** + * @param non-empty-string $pattern + * @param string $subject + * @param int $offset + * @return bool + */ + public static function isMatch($pattern, $subject, $offset = 0) + { + return (bool) Preg::match($pattern, $subject, $matches, 0, $offset); + } + + /** + * @param non-empty-string $pattern + * @param string $subject + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return MatchResult + */ + public static function match($pattern, $subject, $flags = 0, $offset = 0) + { + if (($flags & PREG_OFFSET_CAPTURE) !== 0) { + throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the return type, use matchWithOffsets() instead'); + } + + $count = Preg::match($pattern, $subject, $matches, $flags, $offset); + + return new MatchResult($count, $matches); + } + + /** + * Runs preg_match with PREG_OFFSET_CAPTURE + * + * @param non-empty-string $pattern + * @param string $subject + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return MatchWithOffsetsResult + */ + public static function matchWithOffsets($pattern, $subject, $flags = 0, $offset = 0) + { + $count = Preg::matchWithOffsets($pattern, $subject, $matches, $flags, $offset); + + return new MatchWithOffsetsResult($count, $matches); + } + + /** + * @param non-empty-string $pattern + * @param string $subject + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return MatchAllResult + */ + public static function matchAll($pattern, $subject, $flags = 0, $offset = 0) + { + if (($flags & PREG_OFFSET_CAPTURE) !== 0) { + throw new \InvalidArgumentException('PREG_OFFSET_CAPTURE is not supported as it changes the return type, use matchAllWithOffsets() instead'); + } + + if (($flags & PREG_SET_ORDER) !== 0) { + throw new \InvalidArgumentException('PREG_SET_ORDER is not supported as it changes the return type'); + } + + $count = Preg::matchAll($pattern, $subject, $matches, $flags, $offset); + + return new MatchAllResult($count, $matches); + } + + /** + * Runs preg_match_all with PREG_OFFSET_CAPTURE + * + * @param non-empty-string $pattern + * @param string $subject + * @param int $flags PREG_UNMATCHED_AS_NULL, only available on PHP 7.2+ + * @param int $offset + * @return MatchAllWithOffsetsResult + */ + public static function matchAllWithOffsets($pattern, $subject, $flags = 0, $offset = 0) + { + $count = Preg::matchAllWithOffsets($pattern, $subject, $matches, $flags, $offset); + + return new MatchAllWithOffsetsResult($count, $matches); + } + /** + * @param string|string[] $pattern + * @param string|string[] $replacement + * @param string $subject + * @param int $limit + * @return ReplaceResult + */ + public static function replace($pattern, $replacement, $subject, $limit = -1) + { + $result = Preg::replace($pattern, $replacement, $subject, $limit, $count); + + return new ReplaceResult($count, $result); + } + + /** + * @param string|string[] $pattern + * @param callable $replacement + * @param string $subject + * @param int $limit + * @param int $flags PREG_OFFSET_CAPTURE or PREG_UNMATCHED_AS_NULL, only available on PHP 7.4+ + * @return ReplaceResult + */ + public static function replaceCallback($pattern, $replacement, $subject, $limit = -1, $flags = 0) + { + $result = Preg::replaceCallback($pattern, $replacement, $subject, $limit, $count, $flags); + + return new ReplaceResult($count, $result); + } + + /** + * Available from PHP 7.0 + * + * @param array $pattern + * @param string $subject + * @param int $limit + * @param int $flags PREG_OFFSET_CAPTURE or PREG_UNMATCHED_AS_NULL, only available on PHP 7.4+ + * @return ReplaceResult + */ + public static function replaceCallbackArray($pattern, $subject, $limit = -1, $flags = 0) + { + $result = Preg::replaceCallbackArray($pattern, $subject, $limit, $count, $flags); + + return new ReplaceResult($count, $result); + } +} diff --git a/vendor/composer/pcre/src/ReplaceResult.php b/vendor/composer/pcre/src/ReplaceResult.php new file mode 100644 index 0000000..0ac0840 --- /dev/null +++ b/vendor/composer/pcre/src/ReplaceResult.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Pcre; + +final class ReplaceResult +{ + /** + * @readonly + * @var string + */ + public $result; + + /** + * @readonly + * @var 0|positive-int + */ + public $count; + + /** + * @readonly + * @var bool + */ + public $matched; + + /** + * @param 0|positive-int $count + * @param string $result + */ + public function __construct($count, $result) + { + $this->count = $count; + $this->matched = (bool) $count; + $this->result = $result; + } +} diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php new file mode 100644 index 0000000..a8b98d5 --- /dev/null +++ b/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 70205)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". 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/vendor/composer/semver/CHANGELOG.md b/vendor/composer/semver/CHANGELOG.md new file mode 100644 index 0000000..c951477 --- /dev/null +++ b/vendor/composer/semver/CHANGELOG.md @@ -0,0 +1,209 @@ +# Change Log + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +### [3.3.2] 2022-04-01 + + * Fixed handling of non-string values (#134) + +### [3.3.1] 2022-03-16 + + * Fixed possible cache key clash in the CompilingMatcher memoization (#132) + +### [3.3.0] 2022-03-15 + + * Improved performance of CompilingMatcher by memoizing more (#131) + * Added CompilingMatcher::clear to clear all memoization caches + +### [3.2.9] 2022-02-04 + + * Revert #129 (Fixed MultiConstraint with MatchAllConstraint) which caused regressions + +### [3.2.8] 2022-02-04 + + * Updates to latest phpstan / CI by @Seldaek in https://github.com/composer/semver/pull/130 + * Fixed MultiConstraint with MatchAllConstraint by @Toflar in https://github.com/composer/semver/pull/129 + +### [3.2.7] 2022-01-04 + + * Fixed: typo in type definition of Intervals class causing issues with Psalm scanning vendors + +### [3.2.6] 2021-10-25 + + * Fixed: type improvements to parseStability + +### [3.2.5] 2021-05-24 + + * Fixed: issue comparing disjunctive MultiConstraints to conjunctive ones (#127) + * Fixed: added complete type information using phpstan annotations + +### [3.2.4] 2020-11-13 + + * Fixed: code clean-up + +### [3.2.3] 2020-11-12 + + * Fixed: constraints in the form of `X || Y, >=Y.1` and other such complex constructs were in some cases being optimized into a more restrictive constraint + +### [3.2.2] 2020-10-14 + + * Fixed: internal code cleanups + +### [3.2.1] 2020-09-27 + + * Fixed: accidental validation of broken constraints combining ^/~ and wildcards, and -dev suffix allowing weird cases + * Fixed: normalization of beta0 and such which was dropping the 0 + +### [3.2.0] 2020-09-09 + + * Added: support for `x || @dev`, not very useful but seen in the wild and failed to validate with 1.5.2/1.6.0 + * Added: support for `foobar-dev` being equal to `dev-foobar`, dev-foobar is the official way to write it but we need to support the other for BC and convenience + +### [3.1.0] 2020-09-08 + + * Added: support for constraints like `^2.x-dev` and `~2.x-dev`, not very useful but seen in the wild and failed to validate with 3.0.1 + * Fixed: invalid aliases will no longer throw, unless explicitly validated by Composer in the root package + +### [3.0.1] 2020-09-08 + + * Fixed: handling of some invalid -dev versions which were seen as valid + +### [3.0.0] 2020-05-26 + + * Break: Renamed `EmptyConstraint`, replace it with `MatchAllConstraint` + * Break: Unlikely to affect anyone but strictly speaking a breaking change, `*.*` and such variants will not match all `dev-*` versions anymore, only `*` does + * Break: ConstraintInterface is now considered internal/private and not meant to be implemented by third parties anymore + * Added `Intervals` class to check if a constraint is a subsets of another one, and allow compacting complex MultiConstraints into simpler ones + * Added `CompilingMatcher` class to speed up constraint matching against simple Constraint instances + * Added `MatchAllConstraint` and `MatchNoneConstraint` which match everything and nothing + * Added more advanced optimization of contiguous constraints inside MultiConstraint + * Added tentative support for PHP 8 + * Fixed ConstraintInterface::matches to be commutative in all cases + +### [2.0.0] 2020-04-21 + + * Break: `dev-master`, `dev-trunk` and `dev-default` now normalize to `dev-master`, `dev-trunk` and `dev-default` instead of `9999999-dev` in 1.x + * Break: Removed the deprecated `AbstractConstraint` + * Added `getUpperBound` and `getLowerBound` to ConstraintInterface. They return `Composer\Semver\Constraint\Bound` instances + * Added `MultiConstraint::create` to create the most-optimal form of ConstraintInterface from an array of constraint strings + +### [1.7.2] 2020-12-03 + + * Fixed: Allow installing on php 8 + +### [1.7.1] 2020-09-27 + + * Fixed: accidental validation of broken constraints combining ^/~ and wildcards, and -dev suffix allowing weird cases + * Fixed: normalization of beta0 and such which was dropping the 0 + +### [1.7.0] 2020-09-09 + + * Added: support for `x || @dev`, not very useful but seen in the wild and failed to validate with 1.5.2/1.6.0 + * Added: support for `foobar-dev` being equal to `dev-foobar`, dev-foobar is the official way to write it but we need to support the other for BC and convenience + +### [1.6.0] 2020-09-08 + + * Added: support for constraints like `^2.x-dev` and `~2.x-dev`, not very useful but seen in the wild and failed to validate with 1.5.2 + * Fixed: invalid aliases will no longer throw, unless explicitly validated by Composer in the root package + +### [1.5.2] 2020-09-08 + + * Fixed: handling of some invalid -dev versions which were seen as valid + * Fixed: some doctypes + +### [1.5.1] 2020-01-13 + + * Fixed: Parsing of aliased version was not validating the alias to be a valid version + +### [1.5.0] 2019-03-19 + + * Added: some support for date versions (e.g. 201903) in `~` operator + * Fixed: support for stabilities in `~` operator was inconsistent + +### [1.4.2] 2016-08-30 + + * Fixed: collapsing of complex constraints lead to buggy constraints + +### [1.4.1] 2016-06-02 + + * Changed: branch-like requirements no longer strip build metadata - [composer/semver#38](https://github.com/composer/semver/pull/38). + +### [1.4.0] 2016-03-30 + + * Added: getters on MultiConstraint - [composer/semver#35](https://github.com/composer/semver/pull/35). + +### [1.3.0] 2016-02-25 + + * Fixed: stability parsing - [composer/composer#1234](https://github.com/composer/composer/issues/4889). + * Changed: collapse contiguous constraints when possible. + +### [1.2.0] 2015-11-10 + + * Changed: allow multiple numerical identifiers in 'pre-release' version part. + * Changed: add more 'v' prefix support. + +### [1.1.0] 2015-11-03 + + * Changed: dropped redundant `test` namespace. + * Changed: minor adjustment in datetime parsing normalization. + * Changed: `ConstraintInterface` relaxed, setPrettyString is not required anymore. + * Changed: `AbstractConstraint` marked deprecated, will be removed in 2.0. + * Changed: `Constraint` is now extensible. + +### [1.0.0] 2015-09-21 + + * Break: `VersionConstraint` renamed to `Constraint`. + * Break: `SpecificConstraint` renamed to `AbstractConstraint`. + * Break: `LinkConstraintInterface` renamed to `ConstraintInterface`. + * Break: `VersionParser::parseNameVersionPairs` was removed. + * Changed: `VersionParser::parseConstraints` allows (but ignores) build metadata now. + * Changed: `VersionParser::parseConstraints` allows (but ignores) prefixing numeric versions with a 'v' now. + * Changed: Fixed namespace(s) of test files. + * Changed: `Comparator::compare` no longer throws `InvalidArgumentException`. + * Changed: `Constraint` now throws `InvalidArgumentException`. + +### [0.1.0] 2015-07-23 + + * Added: `Composer\Semver\Comparator`, various methods to compare versions. + * Added: various documents such as README.md, LICENSE, etc. + * Added: configuration files for Git, Travis, php-cs-fixer, phpunit. + * Break: the following namespaces were renamed: + - Namespace: `Composer\Package\Version` -> `Composer\Semver` + - Namespace: `Composer\Package\LinkConstraint` -> `Composer\Semver\Constraint` + - Namespace: `Composer\Test\Package\Version` -> `Composer\Test\Semver` + - Namespace: `Composer\Test\Package\LinkConstraint` -> `Composer\Test\Semver\Constraint` + * Changed: code style using php-cs-fixer. + +[3.3.2]: https://github.com/composer/semver/compare/3.3.1...3.3.2 +[3.3.1]: https://github.com/composer/semver/compare/3.3.0...3.3.1 +[3.3.0]: https://github.com/composer/semver/compare/3.2.9...3.3.0 +[3.2.9]: https://github.com/composer/semver/compare/3.2.8...3.2.9 +[3.2.8]: https://github.com/composer/semver/compare/3.2.7...3.2.8 +[3.2.7]: https://github.com/composer/semver/compare/3.2.6...3.2.7 +[3.2.6]: https://github.com/composer/semver/compare/3.2.5...3.2.6 +[3.2.5]: https://github.com/composer/semver/compare/3.2.4...3.2.5 +[3.2.4]: https://github.com/composer/semver/compare/3.2.3...3.2.4 +[3.2.3]: https://github.com/composer/semver/compare/3.2.2...3.2.3 +[3.2.2]: https://github.com/composer/semver/compare/3.2.1...3.2.2 +[3.2.1]: https://github.com/composer/semver/compare/3.2.0...3.2.1 +[3.2.0]: https://github.com/composer/semver/compare/3.1.0...3.2.0 +[3.1.0]: https://github.com/composer/semver/compare/3.0.1...3.1.0 +[3.0.1]: https://github.com/composer/semver/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/composer/semver/compare/2.0.0...3.0.0 +[2.0.0]: https://github.com/composer/semver/compare/1.5.1...2.0.0 +[1.7.2]: https://github.com/composer/semver/compare/1.7.1...1.7.2 +[1.7.1]: https://github.com/composer/semver/compare/1.7.0...1.7.1 +[1.7.0]: https://github.com/composer/semver/compare/1.6.0...1.7.0 +[1.6.0]: https://github.com/composer/semver/compare/1.5.2...1.6.0 +[1.5.2]: https://github.com/composer/semver/compare/1.5.1...1.5.2 +[1.5.1]: https://github.com/composer/semver/compare/1.5.0...1.5.1 +[1.5.0]: https://github.com/composer/semver/compare/1.4.2...1.5.0 +[1.4.2]: https://github.com/composer/semver/compare/1.4.1...1.4.2 +[1.4.1]: https://github.com/composer/semver/compare/1.4.0...1.4.1 +[1.4.0]: https://github.com/composer/semver/compare/1.3.0...1.4.0 +[1.3.0]: https://github.com/composer/semver/compare/1.2.0...1.3.0 +[1.2.0]: https://github.com/composer/semver/compare/1.1.0...1.2.0 +[1.1.0]: https://github.com/composer/semver/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/composer/semver/compare/0.1.0...1.0.0 +[0.1.0]: https://github.com/composer/semver/compare/5e0b9a4da...0.1.0 diff --git a/vendor/composer/semver/LICENSE b/vendor/composer/semver/LICENSE new file mode 100644 index 0000000..4669758 --- /dev/null +++ b/vendor/composer/semver/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2015 Composer + +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/vendor/composer/semver/README.md b/vendor/composer/semver/README.md new file mode 100644 index 0000000..35db99a --- /dev/null +++ b/vendor/composer/semver/README.md @@ -0,0 +1,98 @@ +composer/semver +=============== + +Semver (Semantic Versioning) library that offers utilities, version constraint parsing and validation. + +Originally written as part of [composer/composer](https://github.com/composer/composer), +now extracted and made available as a stand-alone library. + +[![Continuous Integration](https://github.com/composer/semver/workflows/Continuous%20Integration/badge.svg?branch=main)](https://github.com/composer/semver/actions) + + +Installation +------------ + +Install the latest version with: + +```bash +$ composer require composer/semver +``` + + +Requirements +------------ + +* PHP 5.3.2 is required but using the latest version of PHP is highly recommended. + + +Version Comparison +------------------ + +For details on how versions are compared, refer to the [Versions](https://getcomposer.org/doc/articles/versions.md) +article in the documentation section of the [getcomposer.org](https://getcomposer.org) website. + + +Basic usage +----------- + +### Comparator + +The [`Composer\Semver\Comparator`](https://github.com/composer/semver/blob/main/src/Comparator.php) class provides the following methods for comparing versions: + +* greaterThan($v1, $v2) +* greaterThanOrEqualTo($v1, $v2) +* lessThan($v1, $v2) +* lessThanOrEqualTo($v1, $v2) +* equalTo($v1, $v2) +* notEqualTo($v1, $v2) + +Each function takes two version strings as arguments and returns a boolean. For example: + +```php +use Composer\Semver\Comparator; + +Comparator::greaterThan('1.25.0', '1.24.0'); // 1.25.0 > 1.24.0 +``` + +### Semver + +The [`Composer\Semver\Semver`](https://github.com/composer/semver/blob/main/src/Semver.php) class provides the following methods: + +* satisfies($version, $constraints) +* satisfiedBy(array $versions, $constraint) +* sort($versions) +* rsort($versions) + +### Intervals + +The [`Composer\Semver\Intervals`](https://github.com/composer/semver/blob/main/src/Intervals.php) static class provides +a few utilities to work with complex constraints or read version intervals from a constraint: + +```php +use Composer\Semver\Intervals; + +// Checks whether $candidate is a subset of $constraint +Intervals::isSubsetOf(ConstraintInterface $candidate, ConstraintInterface $constraint); + +// Checks whether $a and $b have any intersection, equivalent to $a->matches($b) +Intervals::haveIntersections(ConstraintInterface $a, ConstraintInterface $b); + +// Optimizes a complex multi constraint by merging all intervals down to the smallest +// possible multi constraint. The drawbacks are this is not very fast, and the resulting +// multi constraint will have no human readable prettyConstraint configured on it +Intervals::compactConstraint(ConstraintInterface $constraint); + +// Creates an array of numeric intervals and branch constraints representing a given constraint +Intervals::get(ConstraintInterface $constraint); + +// Clears the memoization cache when you are done processing constraints +Intervals::clear() +``` + +See the class docblocks for more details. + + +License +------- + +composer/semver is licensed under the MIT License, see the LICENSE file for details. diff --git a/vendor/composer/semver/composer.json b/vendor/composer/semver/composer.json new file mode 100644 index 0000000..ba78676 --- /dev/null +++ b/vendor/composer/semver/composer.json @@ -0,0 +1,59 @@ +{ + "name": "composer/semver", + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "type": "library", + "license": "MIT", + "keywords": [ + "semver", + "semantic", + "versioning", + "validation" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.2 || ^5", + "phpstan/phpstan": "^1.4" + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Composer\\Semver\\": "tests" + } + }, + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "scripts": { + "test": "SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor/bin/simple-phpunit", + "phpstan": "@php vendor/bin/phpstan analyse" + } +} diff --git a/vendor/composer/semver/src/Comparator.php b/vendor/composer/semver/src/Comparator.php new file mode 100644 index 0000000..38f483a --- /dev/null +++ b/vendor/composer/semver/src/Comparator.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver; + +use Composer\Semver\Constraint\Constraint; + +class Comparator +{ + /** + * Evaluates the expression: $version1 > $version2. + * + * @param string $version1 + * @param string $version2 + * + * @return bool + */ + public static function greaterThan($version1, $version2) + { + return self::compare($version1, '>', $version2); + } + + /** + * Evaluates the expression: $version1 >= $version2. + * + * @param string $version1 + * @param string $version2 + * + * @return bool + */ + public static function greaterThanOrEqualTo($version1, $version2) + { + return self::compare($version1, '>=', $version2); + } + + /** + * Evaluates the expression: $version1 < $version2. + * + * @param string $version1 + * @param string $version2 + * + * @return bool + */ + public static function lessThan($version1, $version2) + { + return self::compare($version1, '<', $version2); + } + + /** + * Evaluates the expression: $version1 <= $version2. + * + * @param string $version1 + * @param string $version2 + * + * @return bool + */ + public static function lessThanOrEqualTo($version1, $version2) + { + return self::compare($version1, '<=', $version2); + } + + /** + * Evaluates the expression: $version1 == $version2. + * + * @param string $version1 + * @param string $version2 + * + * @return bool + */ + public static function equalTo($version1, $version2) + { + return self::compare($version1, '==', $version2); + } + + /** + * Evaluates the expression: $version1 != $version2. + * + * @param string $version1 + * @param string $version2 + * + * @return bool + */ + public static function notEqualTo($version1, $version2) + { + return self::compare($version1, '!=', $version2); + } + + /** + * Evaluates the expression: $version1 $operator $version2. + * + * @param string $version1 + * @param string $operator + * @param string $version2 + * + * @return bool + * + * @phpstan-param Constraint::STR_OP_* $operator + */ + public static function compare($version1, $operator, $version2) + { + $constraint = new Constraint($operator, $version2); + + return $constraint->matchSpecific(new Constraint('==', $version1), true); + } +} diff --git a/vendor/composer/semver/src/CompilingMatcher.php b/vendor/composer/semver/src/CompilingMatcher.php new file mode 100644 index 0000000..45bce70 --- /dev/null +++ b/vendor/composer/semver/src/CompilingMatcher.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver; + +use Composer\Semver\Constraint\Constraint; +use Composer\Semver\Constraint\ConstraintInterface; + +/** + * Helper class to evaluate constraint by compiling and reusing the code to evaluate + */ +class CompilingMatcher +{ + /** + * @var array + * @phpstan-var array + */ + private static $compiledCheckerCache = array(); + /** + * @var array + * @phpstan-var array + */ + private static $resultCache = array(); + + /** @var bool */ + private static $enabled; + + /** + * @phpstan-var array + */ + private static $transOpInt = array( + Constraint::OP_EQ => Constraint::STR_OP_EQ, + Constraint::OP_LT => Constraint::STR_OP_LT, + Constraint::OP_LE => Constraint::STR_OP_LE, + Constraint::OP_GT => Constraint::STR_OP_GT, + Constraint::OP_GE => Constraint::STR_OP_GE, + Constraint::OP_NE => Constraint::STR_OP_NE, + ); + + /** + * Clears the memoization cache once you are done + * + * @return void + */ + public static function clear() + { + self::$resultCache = array(); + self::$compiledCheckerCache = array(); + } + + /** + * Evaluates the expression: $constraint match $operator $version + * + * @param ConstraintInterface $constraint + * @param int $operator + * @phpstan-param Constraint::OP_* $operator + * @param string $version + * + * @return mixed + */ + public static function match(ConstraintInterface $constraint, $operator, $version) + { + $resultCacheKey = $operator.$constraint.';'.$version; + + if (isset(self::$resultCache[$resultCacheKey])) { + return self::$resultCache[$resultCacheKey]; + } + + if (self::$enabled === null) { + self::$enabled = !\in_array('eval', explode(',', (string) ini_get('disable_functions')), true); + } + if (!self::$enabled) { + return self::$resultCache[$resultCacheKey] = $constraint->matches(new Constraint(self::$transOpInt[$operator], $version)); + } + + $cacheKey = $operator.$constraint; + if (!isset(self::$compiledCheckerCache[$cacheKey])) { + $code = $constraint->compile($operator); + self::$compiledCheckerCache[$cacheKey] = $function = eval('return function($v, $b){return '.$code.';};'); + } else { + $function = self::$compiledCheckerCache[$cacheKey]; + } + + return self::$resultCache[$resultCacheKey] = $function($version, strpos($version, 'dev-') === 0); + } +} diff --git a/vendor/composer/semver/src/Constraint/Bound.php b/vendor/composer/semver/src/Constraint/Bound.php new file mode 100644 index 0000000..7effb11 --- /dev/null +++ b/vendor/composer/semver/src/Constraint/Bound.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver\Constraint; + +class Bound +{ + /** + * @var string + */ + private $version; + + /** + * @var bool + */ + private $isInclusive; + + /** + * @param string $version + * @param bool $isInclusive + */ + public function __construct($version, $isInclusive) + { + $this->version = $version; + $this->isInclusive = $isInclusive; + } + + /** + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * @return bool + */ + public function isInclusive() + { + return $this->isInclusive; + } + + /** + * @return bool + */ + public function isZero() + { + return $this->getVersion() === '0.0.0.0-dev' && $this->isInclusive(); + } + + /** + * @return bool + */ + public function isPositiveInfinity() + { + return $this->getVersion() === PHP_INT_MAX.'.0.0.0' && !$this->isInclusive(); + } + + /** + * Compares a bound to another with a given operator. + * + * @param Bound $other + * @param string $operator + * + * @return bool + */ + public function compareTo(Bound $other, $operator) + { + if (!\in_array($operator, array('<', '>'), true)) { + throw new \InvalidArgumentException('Does not support any other operator other than > or <.'); + } + + // If they are the same it doesn't matter + if ($this == $other) { + return false; + } + + $compareResult = version_compare($this->getVersion(), $other->getVersion()); + + // Not the same version means we don't need to check if the bounds are inclusive or not + if (0 !== $compareResult) { + return (('>' === $operator) ? 1 : -1) === $compareResult; + } + + // Question we're answering here is "am I higher than $other?" + return '>' === $operator ? $other->isInclusive() : !$other->isInclusive(); + } + + public function __toString() + { + return sprintf( + '%s [%s]', + $this->getVersion(), + $this->isInclusive() ? 'inclusive' : 'exclusive' + ); + } + + /** + * @return self + */ + public static function zero() + { + return new Bound('0.0.0.0-dev', true); + } + + /** + * @return self + */ + public static function positiveInfinity() + { + return new Bound(PHP_INT_MAX.'.0.0.0', false); + } +} diff --git a/vendor/composer/semver/src/Constraint/Constraint.php b/vendor/composer/semver/src/Constraint/Constraint.php new file mode 100644 index 0000000..dc39482 --- /dev/null +++ b/vendor/composer/semver/src/Constraint/Constraint.php @@ -0,0 +1,435 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver\Constraint; + +/** + * Defines a constraint. + */ +class Constraint implements ConstraintInterface +{ + /* operator integer values */ + const OP_EQ = 0; + const OP_LT = 1; + const OP_LE = 2; + const OP_GT = 3; + const OP_GE = 4; + const OP_NE = 5; + + /* operator string values */ + const STR_OP_EQ = '=='; + const STR_OP_EQ_ALT = '='; + const STR_OP_LT = '<'; + const STR_OP_LE = '<='; + const STR_OP_GT = '>'; + const STR_OP_GE = '>='; + const STR_OP_NE = '!='; + const STR_OP_NE_ALT = '<>'; + + /** + * Operator to integer translation table. + * + * @var array + * @phpstan-var array + */ + private static $transOpStr = array( + '=' => self::OP_EQ, + '==' => self::OP_EQ, + '<' => self::OP_LT, + '<=' => self::OP_LE, + '>' => self::OP_GT, + '>=' => self::OP_GE, + '<>' => self::OP_NE, + '!=' => self::OP_NE, + ); + + /** + * Integer to operator translation table. + * + * @var array + * @phpstan-var array + */ + private static $transOpInt = array( + self::OP_EQ => '==', + self::OP_LT => '<', + self::OP_LE => '<=', + self::OP_GT => '>', + self::OP_GE => '>=', + self::OP_NE => '!=', + ); + + /** + * @var int + * @phpstan-var self::OP_* + */ + protected $operator; + + /** @var string */ + protected $version; + + /** @var string|null */ + protected $prettyString; + + /** @var Bound */ + protected $lowerBound; + + /** @var Bound */ + protected $upperBound; + + /** + * Sets operator and version to compare with. + * + * @param string $operator + * @param string $version + * + * @throws \InvalidArgumentException if invalid operator is given. + * + * @phpstan-param self::STR_OP_* $operator + */ + public function __construct($operator, $version) + { + if (!isset(self::$transOpStr[$operator])) { + throw new \InvalidArgumentException(sprintf( + 'Invalid operator "%s" given, expected one of: %s', + $operator, + implode(', ', self::getSupportedOperators()) + )); + } + + $this->operator = self::$transOpStr[$operator]; + $this->version = $version; + } + + /** + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * @return string + * + * @phpstan-return self::STR_OP_* + */ + public function getOperator() + { + return self::$transOpInt[$this->operator]; + } + + /** + * @param ConstraintInterface $provider + * + * @return bool + */ + public function matches(ConstraintInterface $provider) + { + if ($provider instanceof self) { + return $this->matchSpecific($provider); + } + + // turn matching around to find a match + return $provider->matches($this); + } + + /** + * {@inheritDoc} + */ + public function setPrettyString($prettyString) + { + $this->prettyString = $prettyString; + } + + /** + * {@inheritDoc} + */ + public function getPrettyString() + { + if ($this->prettyString) { + return $this->prettyString; + } + + return $this->__toString(); + } + + /** + * Get all supported comparison operators. + * + * @return array + * + * @phpstan-return list + */ + public static function getSupportedOperators() + { + return array_keys(self::$transOpStr); + } + + /** + * @param string $operator + * @return int + * + * @phpstan-param self::STR_OP_* $operator + * @phpstan-return self::OP_* + */ + public static function getOperatorConstant($operator) + { + return self::$transOpStr[$operator]; + } + + /** + * @param string $a + * @param string $b + * @param string $operator + * @param bool $compareBranches + * + * @throws \InvalidArgumentException if invalid operator is given. + * + * @return bool + * + * @phpstan-param self::STR_OP_* $operator + */ + public function versionCompare($a, $b, $operator, $compareBranches = false) + { + if (!isset(self::$transOpStr[$operator])) { + throw new \InvalidArgumentException(sprintf( + 'Invalid operator "%s" given, expected one of: %s', + $operator, + implode(', ', self::getSupportedOperators()) + )); + } + + $aIsBranch = strpos($a, 'dev-') === 0; + $bIsBranch = strpos($b, 'dev-') === 0; + + if ($operator === '!=' && ($aIsBranch || $bIsBranch)) { + return $a !== $b; + } + + if ($aIsBranch && $bIsBranch) { + return $operator === '==' && $a === $b; + } + + // when branches are not comparable, we make sure dev branches never match anything + if (!$compareBranches && ($aIsBranch || $bIsBranch)) { + return false; + } + + return \version_compare($a, $b, $operator); + } + + /** + * {@inheritDoc} + */ + public function compile($otherOperator) + { + if (strpos($this->version, 'dev-') === 0) { + if (self::OP_EQ === $this->operator) { + if (self::OP_EQ === $otherOperator) { + return sprintf('$b && $v === %s', \var_export($this->version, true)); + } + if (self::OP_NE === $otherOperator) { + return sprintf('!$b || $v !== %s', \var_export($this->version, true)); + } + return 'false'; + } + + if (self::OP_NE === $this->operator) { + if (self::OP_EQ === $otherOperator) { + return sprintf('!$b || $v !== %s', \var_export($this->version, true)); + } + if (self::OP_NE === $otherOperator) { + return 'true'; + } + return '!$b'; + } + + return 'false'; + } + + if (self::OP_EQ === $this->operator) { + if (self::OP_EQ === $otherOperator) { + return sprintf('\version_compare($v, %s, \'==\')', \var_export($this->version, true)); + } + if (self::OP_NE === $otherOperator) { + return sprintf('$b || \version_compare($v, %s, \'!=\')', \var_export($this->version, true)); + } + + return sprintf('!$b && \version_compare(%s, $v, \'%s\')', \var_export($this->version, true), self::$transOpInt[$otherOperator]); + } + + if (self::OP_NE === $this->operator) { + if (self::OP_EQ === $otherOperator) { + return sprintf('$b || (!$b && \version_compare($v, %s, \'!=\'))', \var_export($this->version, true)); + } + + if (self::OP_NE === $otherOperator) { + return 'true'; + } + return '!$b'; + } + + if (self::OP_LT === $this->operator || self::OP_LE === $this->operator) { + if (self::OP_LT === $otherOperator || self::OP_LE === $otherOperator) { + return '!$b'; + } + } else { // $this->operator must be self::OP_GT || self::OP_GE here + if (self::OP_GT === $otherOperator || self::OP_GE === $otherOperator) { + return '!$b'; + } + } + + if (self::OP_NE === $otherOperator) { + return 'true'; + } + + $codeComparison = sprintf('\version_compare($v, %s, \'%s\')', \var_export($this->version, true), self::$transOpInt[$this->operator]); + if ($this->operator === self::OP_LE) { + if ($otherOperator === self::OP_GT) { + return sprintf('!$b && \version_compare($v, %s, \'!=\') && ', \var_export($this->version, true)) . $codeComparison; + } + } elseif ($this->operator === self::OP_GE) { + if ($otherOperator === self::OP_LT) { + return sprintf('!$b && \version_compare($v, %s, \'!=\') && ', \var_export($this->version, true)) . $codeComparison; + } + } + + return sprintf('!$b && %s', $codeComparison); + } + + /** + * @param Constraint $provider + * @param bool $compareBranches + * + * @return bool + */ + public function matchSpecific(Constraint $provider, $compareBranches = false) + { + $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]); + $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]); + + $isEqualOp = self::OP_EQ === $this->operator; + $isNonEqualOp = self::OP_NE === $this->operator; + $isProviderEqualOp = self::OP_EQ === $provider->operator; + $isProviderNonEqualOp = self::OP_NE === $provider->operator; + + // '!=' operator is match when other operator is not '==' operator or version is not match + // these kinds of comparisons always have a solution + if ($isNonEqualOp || $isProviderNonEqualOp) { + if ($isNonEqualOp && !$isProviderNonEqualOp && !$isProviderEqualOp && strpos($provider->version, 'dev-') === 0) { + return false; + } + + if ($isProviderNonEqualOp && !$isNonEqualOp && !$isEqualOp && strpos($this->version, 'dev-') === 0) { + return false; + } + + if (!$isEqualOp && !$isProviderEqualOp) { + return true; + } + return $this->versionCompare($provider->version, $this->version, '!=', $compareBranches); + } + + // an example for the condition is <= 2.0 & < 1.0 + // these kinds of comparisons always have a solution + if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) { + return !(strpos($this->version, 'dev-') === 0 || strpos($provider->version, 'dev-') === 0); + } + + $version1 = $isEqualOp ? $this->version : $provider->version; + $version2 = $isEqualOp ? $provider->version : $this->version; + $operator = $isEqualOp ? $provider->operator : $this->operator; + + if ($this->versionCompare($version1, $version2, self::$transOpInt[$operator], $compareBranches)) { + // special case, e.g. require >= 1.0 and provide < 1.0 + // 1.0 >= 1.0 but 1.0 is outside of the provided interval + + return !(self::$transOpInt[$provider->operator] === $providerNoEqualOp + && self::$transOpInt[$this->operator] !== $noEqualOp + && \version_compare($provider->version, $this->version, '==')); + } + + return false; + } + + /** + * @return string + */ + public function __toString() + { + return self::$transOpInt[$this->operator] . ' ' . $this->version; + } + + /** + * {@inheritDoc} + */ + public function getLowerBound() + { + $this->extractBounds(); + + return $this->lowerBound; + } + + /** + * {@inheritDoc} + */ + public function getUpperBound() + { + $this->extractBounds(); + + return $this->upperBound; + } + + /** + * @return void + */ + private function extractBounds() + { + if (null !== $this->lowerBound) { + return; + } + + // Branches + if (strpos($this->version, 'dev-') === 0) { + $this->lowerBound = Bound::zero(); + $this->upperBound = Bound::positiveInfinity(); + + return; + } + + switch ($this->operator) { + case self::OP_EQ: + $this->lowerBound = new Bound($this->version, true); + $this->upperBound = new Bound($this->version, true); + break; + case self::OP_LT: + $this->lowerBound = Bound::zero(); + $this->upperBound = new Bound($this->version, false); + break; + case self::OP_LE: + $this->lowerBound = Bound::zero(); + $this->upperBound = new Bound($this->version, true); + break; + case self::OP_GT: + $this->lowerBound = new Bound($this->version, false); + $this->upperBound = Bound::positiveInfinity(); + break; + case self::OP_GE: + $this->lowerBound = new Bound($this->version, true); + $this->upperBound = Bound::positiveInfinity(); + break; + case self::OP_NE: + $this->lowerBound = Bound::zero(); + $this->upperBound = Bound::positiveInfinity(); + break; + } + } +} diff --git a/vendor/composer/semver/src/Constraint/ConstraintInterface.php b/vendor/composer/semver/src/Constraint/ConstraintInterface.php new file mode 100644 index 0000000..389b935 --- /dev/null +++ b/vendor/composer/semver/src/Constraint/ConstraintInterface.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver\Constraint; + +/** + * DO NOT IMPLEMENT this interface. It is only meant for usage as a type hint + * in libraries relying on composer/semver but creating your own constraint class + * that implements this interface is not a supported use case and will cause the + * composer/semver components to return unexpected results. + */ +interface ConstraintInterface +{ + /** + * Checks whether the given constraint intersects in any way with this constraint + * + * @param ConstraintInterface $provider + * + * @return bool + */ + public function matches(ConstraintInterface $provider); + + /** + * Provides a compiled version of the constraint for the given operator + * The compiled version must be a PHP expression. + * Executor of compile version must provide 2 variables: + * - $v = the string version to compare with + * - $b = whether or not the version is a non-comparable branch (starts with "dev-") + * + * @see Constraint::OP_* for the list of available operators. + * @example return '!$b && version_compare($v, '1.0', '>')'; + * + * @param int $otherOperator one Constraint::OP_* + * + * @return string + * + * @phpstan-param Constraint::OP_* $otherOperator + */ + public function compile($otherOperator); + + /** + * @return Bound + */ + public function getUpperBound(); + + /** + * @return Bound + */ + public function getLowerBound(); + + /** + * @return string + */ + public function getPrettyString(); + + /** + * @param string|null $prettyString + * + * @return void + */ + public function setPrettyString($prettyString); + + /** + * @return string + */ + public function __toString(); +} diff --git a/vendor/composer/semver/src/Constraint/MatchAllConstraint.php b/vendor/composer/semver/src/Constraint/MatchAllConstraint.php new file mode 100644 index 0000000..5e51af9 --- /dev/null +++ b/vendor/composer/semver/src/Constraint/MatchAllConstraint.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver\Constraint; + +/** + * Defines the absence of a constraint. + * + * This constraint matches everything. + */ +class MatchAllConstraint implements ConstraintInterface +{ + /** @var string|null */ + protected $prettyString; + + /** + * @param ConstraintInterface $provider + * + * @return bool + */ + public function matches(ConstraintInterface $provider) + { + return true; + } + + /** + * {@inheritDoc} + */ + public function compile($otherOperator) + { + return 'true'; + } + + /** + * {@inheritDoc} + */ + public function setPrettyString($prettyString) + { + $this->prettyString = $prettyString; + } + + /** + * {@inheritDoc} + */ + public function getPrettyString() + { + if ($this->prettyString) { + return $this->prettyString; + } + + return (string) $this; + } + + /** + * {@inheritDoc} + */ + public function __toString() + { + return '*'; + } + + /** + * {@inheritDoc} + */ + public function getUpperBound() + { + return Bound::positiveInfinity(); + } + + /** + * {@inheritDoc} + */ + public function getLowerBound() + { + return Bound::zero(); + } +} diff --git a/vendor/composer/semver/src/Constraint/MatchNoneConstraint.php b/vendor/composer/semver/src/Constraint/MatchNoneConstraint.php new file mode 100644 index 0000000..dadcf62 --- /dev/null +++ b/vendor/composer/semver/src/Constraint/MatchNoneConstraint.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver\Constraint; + +/** + * Blackhole of constraints, nothing escapes it + */ +class MatchNoneConstraint implements ConstraintInterface +{ + /** @var string|null */ + protected $prettyString; + + /** + * @param ConstraintInterface $provider + * + * @return bool + */ + public function matches(ConstraintInterface $provider) + { + return false; + } + + /** + * {@inheritDoc} + */ + public function compile($otherOperator) + { + return 'false'; + } + + /** + * {@inheritDoc} + */ + public function setPrettyString($prettyString) + { + $this->prettyString = $prettyString; + } + + /** + * {@inheritDoc} + */ + public function getPrettyString() + { + if ($this->prettyString) { + return $this->prettyString; + } + + return (string) $this; + } + + /** + * {@inheritDoc} + */ + public function __toString() + { + return '[]'; + } + + /** + * {@inheritDoc} + */ + public function getUpperBound() + { + return new Bound('0.0.0.0-dev', false); + } + + /** + * {@inheritDoc} + */ + public function getLowerBound() + { + return new Bound('0.0.0.0-dev', false); + } +} diff --git a/vendor/composer/semver/src/Constraint/MultiConstraint.php b/vendor/composer/semver/src/Constraint/MultiConstraint.php new file mode 100644 index 0000000..1f4c006 --- /dev/null +++ b/vendor/composer/semver/src/Constraint/MultiConstraint.php @@ -0,0 +1,325 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver\Constraint; + +/** + * Defines a conjunctive or disjunctive set of constraints. + */ +class MultiConstraint implements ConstraintInterface +{ + /** + * @var ConstraintInterface[] + * @phpstan-var non-empty-array + */ + protected $constraints; + + /** @var string|null */ + protected $prettyString; + + /** @var string|null */ + protected $string; + + /** @var bool */ + protected $conjunctive; + + /** @var Bound|null */ + protected $lowerBound; + + /** @var Bound|null */ + protected $upperBound; + + /** + * @param ConstraintInterface[] $constraints A set of constraints + * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive + * + * @throws \InvalidArgumentException If less than 2 constraints are passed + */ + public function __construct(array $constraints, $conjunctive = true) + { + if (\count($constraints) < 2) { + throw new \InvalidArgumentException( + 'Must provide at least two constraints for a MultiConstraint. Use '. + 'the regular Constraint class for one constraint only or MatchAllConstraint for none. You may use '. + 'MultiConstraint::create() which optimizes and handles those cases automatically.' + ); + } + + $this->constraints = $constraints; + $this->conjunctive = $conjunctive; + } + + /** + * @return ConstraintInterface[] + */ + public function getConstraints() + { + return $this->constraints; + } + + /** + * @return bool + */ + public function isConjunctive() + { + return $this->conjunctive; + } + + /** + * @return bool + */ + public function isDisjunctive() + { + return !$this->conjunctive; + } + + /** + * {@inheritDoc} + */ + public function compile($otherOperator) + { + $parts = array(); + foreach ($this->constraints as $constraint) { + $code = $constraint->compile($otherOperator); + if ($code === 'true') { + if (!$this->conjunctive) { + return 'true'; + } + } elseif ($code === 'false') { + if ($this->conjunctive) { + return 'false'; + } + } else { + $parts[] = '('.$code.')'; + } + } + + if (!$parts) { + return $this->conjunctive ? 'true' : 'false'; + } + + return $this->conjunctive ? implode('&&', $parts) : implode('||', $parts); + } + + /** + * @param ConstraintInterface $provider + * + * @return bool + */ + public function matches(ConstraintInterface $provider) + { + if (false === $this->conjunctive) { + foreach ($this->constraints as $constraint) { + if ($provider->matches($constraint)) { + return true; + } + } + + return false; + } + + // when matching a conjunctive and a disjunctive multi constraint we have to iterate over the disjunctive one + // otherwise we'd return true if different parts of the disjunctive constraint match the conjunctive one + // which would lead to incorrect results, e.g. [>1 and <2] would match [<1 or >2] although they do not intersect + if ($provider instanceof MultiConstraint && $provider->isDisjunctive()) { + return $provider->matches($this); + } + + foreach ($this->constraints as $constraint) { + if (!$provider->matches($constraint)) { + return false; + } + } + + return true; + } + + /** + * {@inheritDoc} + */ + public function setPrettyString($prettyString) + { + $this->prettyString = $prettyString; + } + + /** + * {@inheritDoc} + */ + public function getPrettyString() + { + if ($this->prettyString) { + return $this->prettyString; + } + + return (string) $this; + } + + /** + * {@inheritDoc} + */ + public function __toString() + { + if ($this->string !== null) { + return $this->string; + } + + $constraints = array(); + foreach ($this->constraints as $constraint) { + $constraints[] = (string) $constraint; + } + + return $this->string = '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']'; + } + + /** + * {@inheritDoc} + */ + public function getLowerBound() + { + $this->extractBounds(); + + if (null === $this->lowerBound) { + throw new \LogicException('extractBounds should have populated the lowerBound property'); + } + + return $this->lowerBound; + } + + /** + * {@inheritDoc} + */ + public function getUpperBound() + { + $this->extractBounds(); + + if (null === $this->upperBound) { + throw new \LogicException('extractBounds should have populated the upperBound property'); + } + + return $this->upperBound; + } + + /** + * Tries to optimize the constraints as much as possible, meaning + * reducing/collapsing congruent constraints etc. + * Does not necessarily return a MultiConstraint instance if + * things can be reduced to a simple constraint + * + * @param ConstraintInterface[] $constraints A set of constraints + * @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive + * + * @return ConstraintInterface + */ + public static function create(array $constraints, $conjunctive = true) + { + if (0 === \count($constraints)) { + return new MatchAllConstraint(); + } + + if (1 === \count($constraints)) { + return $constraints[0]; + } + + $optimized = self::optimizeConstraints($constraints, $conjunctive); + if ($optimized !== null) { + list($constraints, $conjunctive) = $optimized; + if (\count($constraints) === 1) { + return $constraints[0]; + } + } + + return new self($constraints, $conjunctive); + } + + /** + * @param ConstraintInterface[] $constraints + * @param bool $conjunctive + * @return ?array + * + * @phpstan-return array{0: list, 1: bool}|null + */ + private static function optimizeConstraints(array $constraints, $conjunctive) + { + // parse the two OR groups and if they are contiguous we collapse + // them into one constraint + // [>= 1 < 2] || [>= 2 < 3] || [>= 3 < 4] => [>= 1 < 4] + if (!$conjunctive) { + $left = $constraints[0]; + $mergedConstraints = array(); + $optimized = false; + for ($i = 1, $l = \count($constraints); $i < $l; $i++) { + $right = $constraints[$i]; + if ( + $left instanceof self + && $left->conjunctive + && $right instanceof self + && $right->conjunctive + && \count($left->constraints) === 2 + && \count($right->constraints) === 2 + && ($left0 = (string) $left->constraints[0]) + && $left0[0] === '>' && $left0[1] === '=' + && ($left1 = (string) $left->constraints[1]) + && $left1[0] === '<' + && ($right0 = (string) $right->constraints[0]) + && $right0[0] === '>' && $right0[1] === '=' + && ($right1 = (string) $right->constraints[1]) + && $right1[0] === '<' + && substr($left1, 2) === substr($right0, 3) + ) { + $optimized = true; + $left = new MultiConstraint( + array( + $left->constraints[0], + $right->constraints[1], + ), + true); + } else { + $mergedConstraints[] = $left; + $left = $right; + } + } + if ($optimized) { + $mergedConstraints[] = $left; + return array($mergedConstraints, false); + } + } + + // TODO: Here's the place to put more optimizations + + return null; + } + + /** + * @return void + */ + private function extractBounds() + { + if (null !== $this->lowerBound) { + return; + } + + foreach ($this->constraints as $constraint) { + if (null === $this->lowerBound || null === $this->upperBound) { + $this->lowerBound = $constraint->getLowerBound(); + $this->upperBound = $constraint->getUpperBound(); + continue; + } + + if ($constraint->getLowerBound()->compareTo($this->lowerBound, $this->isConjunctive() ? '>' : '<')) { + $this->lowerBound = $constraint->getLowerBound(); + } + + if ($constraint->getUpperBound()->compareTo($this->upperBound, $this->isConjunctive() ? '<' : '>')) { + $this->upperBound = $constraint->getUpperBound(); + } + } + } +} diff --git a/vendor/composer/semver/src/Interval.php b/vendor/composer/semver/src/Interval.php new file mode 100644 index 0000000..43d5a4f --- /dev/null +++ b/vendor/composer/semver/src/Interval.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver; + +use Composer\Semver\Constraint\Constraint; + +class Interval +{ + /** @var Constraint */ + private $start; + /** @var Constraint */ + private $end; + + public function __construct(Constraint $start, Constraint $end) + { + $this->start = $start; + $this->end = $end; + } + + /** + * @return Constraint + */ + public function getStart() + { + return $this->start; + } + + /** + * @return Constraint + */ + public function getEnd() + { + return $this->end; + } + + /** + * @return Constraint + */ + public static function fromZero() + { + static $zero; + + if (null === $zero) { + $zero = new Constraint('>=', '0.0.0.0-dev'); + } + + return $zero; + } + + /** + * @return Constraint + */ + public static function untilPositiveInfinity() + { + static $positiveInfinity; + + if (null === $positiveInfinity) { + $positiveInfinity = new Constraint('<', PHP_INT_MAX.'.0.0.0'); + } + + return $positiveInfinity; + } + + /** + * @return self + */ + public static function any() + { + return new self(self::fromZero(), self::untilPositiveInfinity()); + } + + /** + * @return array{'names': string[], 'exclude': bool} + */ + public static function anyDev() + { + // any == exclude nothing + return array('names' => array(), 'exclude' => true); + } + + /** + * @return array{'names': string[], 'exclude': bool} + */ + public static function noDev() + { + // nothing == no names included + return array('names' => array(), 'exclude' => false); + } +} diff --git a/vendor/composer/semver/src/Intervals.php b/vendor/composer/semver/src/Intervals.php new file mode 100644 index 0000000..d889d0a --- /dev/null +++ b/vendor/composer/semver/src/Intervals.php @@ -0,0 +1,478 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver; + +use Composer\Semver\Constraint\Constraint; +use Composer\Semver\Constraint\ConstraintInterface; +use Composer\Semver\Constraint\MatchAllConstraint; +use Composer\Semver\Constraint\MatchNoneConstraint; +use Composer\Semver\Constraint\MultiConstraint; + +/** + * Helper class generating intervals from constraints + * + * This contains utilities for: + * + * - compacting an existing constraint which can be used to combine several into one + * by creating a MultiConstraint out of the many constraints you have. + * + * - checking whether one subset is a subset of another. + * + * Note: You should call clear to free memoization memory usage when you are done using this class + */ +class Intervals +{ + /** + * @phpstan-var array + */ + private static $intervalsCache = array(); + + /** + * @phpstan-var array + */ + private static $opSortOrder = array( + '>=' => -3, + '<' => -2, + '>' => 2, + '<=' => 3, + ); + + /** + * Clears the memoization cache once you are done + * + * @return void + */ + public static function clear() + { + self::$intervalsCache = array(); + } + + /** + * Checks whether $candidate is a subset of $constraint + * + * @return bool + */ + public static function isSubsetOf(ConstraintInterface $candidate, ConstraintInterface $constraint) + { + if ($constraint instanceof MatchAllConstraint) { + return true; + } + + if ($candidate instanceof MatchNoneConstraint || $constraint instanceof MatchNoneConstraint) { + return false; + } + + $intersectionIntervals = self::get(new MultiConstraint(array($candidate, $constraint), true)); + $candidateIntervals = self::get($candidate); + if (\count($intersectionIntervals['numeric']) !== \count($candidateIntervals['numeric'])) { + return false; + } + + foreach ($intersectionIntervals['numeric'] as $index => $interval) { + if (!isset($candidateIntervals['numeric'][$index])) { + return false; + } + + if ((string) $candidateIntervals['numeric'][$index]->getStart() !== (string) $interval->getStart()) { + return false; + } + + if ((string) $candidateIntervals['numeric'][$index]->getEnd() !== (string) $interval->getEnd()) { + return false; + } + } + + if ($intersectionIntervals['branches']['exclude'] !== $candidateIntervals['branches']['exclude']) { + return false; + } + if (\count($intersectionIntervals['branches']['names']) !== \count($candidateIntervals['branches']['names'])) { + return false; + } + foreach ($intersectionIntervals['branches']['names'] as $index => $name) { + if ($name !== $candidateIntervals['branches']['names'][$index]) { + return false; + } + } + + return true; + } + + /** + * Checks whether $a and $b have any intersection, equivalent to $a->matches($b) + * + * @return bool + */ + public static function haveIntersections(ConstraintInterface $a, ConstraintInterface $b) + { + if ($a instanceof MatchAllConstraint || $b instanceof MatchAllConstraint) { + return true; + } + + if ($a instanceof MatchNoneConstraint || $b instanceof MatchNoneConstraint) { + return false; + } + + $intersectionIntervals = self::generateIntervals(new MultiConstraint(array($a, $b), true), true); + + return \count($intersectionIntervals['numeric']) > 0 || $intersectionIntervals['branches']['exclude'] || \count($intersectionIntervals['branches']['names']) > 0; + } + + /** + * Attempts to optimize a MultiConstraint + * + * When merging MultiConstraints together they can get very large, this will + * compact it by looking at the real intervals covered by all the constraints + * and then creates a new constraint containing only the smallest amount of rules + * to match the same intervals. + * + * @return ConstraintInterface + */ + public static function compactConstraint(ConstraintInterface $constraint) + { + if (!$constraint instanceof MultiConstraint) { + return $constraint; + } + + $intervals = self::generateIntervals($constraint); + $constraints = array(); + $hasNumericMatchAll = false; + + if (\count($intervals['numeric']) === 1 && (string) $intervals['numeric'][0]->getStart() === (string) Interval::fromZero() && (string) $intervals['numeric'][0]->getEnd() === (string) Interval::untilPositiveInfinity()) { + $constraints[] = $intervals['numeric'][0]->getStart(); + $hasNumericMatchAll = true; + } else { + $unEqualConstraints = array(); + for ($i = 0, $count = \count($intervals['numeric']); $i < $count; $i++) { + $interval = $intervals['numeric'][$i]; + + // if current interval ends with < N and next interval begins with > N we can swap this out for != N + // but this needs to happen as a conjunctive expression together with the start of the current interval + // and end of next interval, so [>=M, N, [>=M, !=N, getEnd()->getOperator() === '<' && $i+1 < $count) { + $nextInterval = $intervals['numeric'][$i+1]; + if ($interval->getEnd()->getVersion() === $nextInterval->getStart()->getVersion() && $nextInterval->getStart()->getOperator() === '>') { + // only add a start if we didn't already do so, can be skipped if we're looking at second + // interval in [>=M, N, P, =M, !=N] already and we only want to add !=P right now + if (\count($unEqualConstraints) === 0 && (string) $interval->getStart() !== (string) Interval::fromZero()) { + $unEqualConstraints[] = $interval->getStart(); + } + $unEqualConstraints[] = new Constraint('!=', $interval->getEnd()->getVersion()); + continue; + } + } + + if (\count($unEqualConstraints) > 0) { + // this is where the end of the following interval of a != constraint is added as explained above + if ((string) $interval->getEnd() !== (string) Interval::untilPositiveInfinity()) { + $unEqualConstraints[] = $interval->getEnd(); + } + + // count is 1 if entire constraint is just one != expression + if (\count($unEqualConstraints) > 1) { + $constraints[] = new MultiConstraint($unEqualConstraints, true); + } else { + $constraints[] = $unEqualConstraints[0]; + } + + $unEqualConstraints = array(); + continue; + } + + // convert back >= x - <= x intervals to == x + if ($interval->getStart()->getVersion() === $interval->getEnd()->getVersion() && $interval->getStart()->getOperator() === '>=' && $interval->getEnd()->getOperator() === '<=') { + $constraints[] = new Constraint('==', $interval->getStart()->getVersion()); + continue; + } + + if ((string) $interval->getStart() === (string) Interval::fromZero()) { + $constraints[] = $interval->getEnd(); + } elseif ((string) $interval->getEnd() === (string) Interval::untilPositiveInfinity()) { + $constraints[] = $interval->getStart(); + } else { + $constraints[] = new MultiConstraint(array($interval->getStart(), $interval->getEnd()), true); + } + } + } + + $devConstraints = array(); + + if (0 === \count($intervals['branches']['names'])) { + if ($intervals['branches']['exclude']) { + if ($hasNumericMatchAll) { + return new MatchAllConstraint; + } + // otherwise constraint should contain a != operator and already cover this + } + } else { + foreach ($intervals['branches']['names'] as $branchName) { + if ($intervals['branches']['exclude']) { + $devConstraints[] = new Constraint('!=', $branchName); + } else { + $devConstraints[] = new Constraint('==', $branchName); + } + } + + // excluded branches, e.g. != dev-foo are conjunctive with the interval, so + // > 2.0 != dev-foo must return a conjunctive constraint + if ($intervals['branches']['exclude']) { + if (\count($constraints) > 1) { + return new MultiConstraint(array_merge( + array(new MultiConstraint($constraints, false)), + $devConstraints + ), true); + } + + if (\count($constraints) === 1 && (string)$constraints[0] === (string)Interval::fromZero()) { + if (\count($devConstraints) > 1) { + return new MultiConstraint($devConstraints, true); + } + return $devConstraints[0]; + } + + return new MultiConstraint(array_merge($constraints, $devConstraints), true); + } + + // otherwise devConstraints contains a list of == operators for branches which are disjunctive with the + // rest of the constraint + $constraints = array_merge($constraints, $devConstraints); + } + + if (\count($constraints) > 1) { + return new MultiConstraint($constraints, false); + } + + if (\count($constraints) === 1) { + return $constraints[0]; + } + + return new MatchNoneConstraint; + } + + /** + * Creates an array of numeric intervals and branch constraints representing a given constraint + * + * if the returned numeric array is empty it means the constraint matches nothing in the numeric range (0 - +inf) + * if the returned branches array is empty it means no dev-* versions are matched + * if a constraint matches all possible dev-* versions, branches will contain Interval::anyDev() + * + * @return array + * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} + */ + public static function get(ConstraintInterface $constraint) + { + $key = (string) $constraint; + + if (!isset(self::$intervalsCache[$key])) { + self::$intervalsCache[$key] = self::generateIntervals($constraint); + } + + return self::$intervalsCache[$key]; + } + + /** + * @param bool $stopOnFirstValidInterval + * + * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} + */ + private static function generateIntervals(ConstraintInterface $constraint, $stopOnFirstValidInterval = false) + { + if ($constraint instanceof MatchAllConstraint) { + return array('numeric' => array(new Interval(Interval::fromZero(), Interval::untilPositiveInfinity())), 'branches' => Interval::anyDev()); + } + + if ($constraint instanceof MatchNoneConstraint) { + return array('numeric' => array(), 'branches' => array('names' => array(), 'exclude' => false)); + } + + if ($constraint instanceof Constraint) { + return self::generateSingleConstraintIntervals($constraint); + } + + if (!$constraint instanceof MultiConstraint) { + throw new \UnexpectedValueException('The constraint passed in should be an MatchAllConstraint, Constraint or MultiConstraint instance, got '.\get_class($constraint).'.'); + } + + $constraints = $constraint->getConstraints(); + + $numericGroups = array(); + $constraintBranches = array(); + foreach ($constraints as $c) { + $res = self::get($c); + $numericGroups[] = $res['numeric']; + $constraintBranches[] = $res['branches']; + } + + if ($constraint->isDisjunctive()) { + $branches = Interval::noDev(); + foreach ($constraintBranches as $b) { + if ($b['exclude']) { + if ($branches['exclude']) { + // disjunctive constraint, so only exclude what's excluded in all constraints + // !=a,!=b || !=b,!=c => !=b + $branches['names'] = array_intersect($branches['names'], $b['names']); + } else { + // disjunctive constraint so exclude all names which are not explicitly included in the alternative + // (==b || ==c) || !=a,!=b => !=a + $branches['exclude'] = true; + $branches['names'] = array_diff($b['names'], $branches['names']); + } + } else { + if ($branches['exclude']) { + // disjunctive constraint so exclude all names which are not explicitly included in the alternative + // !=a,!=b || (==b || ==c) => !=a + $branches['names'] = array_diff($branches['names'], $b['names']); + } else { + // disjunctive constraint, so just add all the other branches + // (==a || ==b) || ==c => ==a || ==b || ==c + $branches['names'] = array_merge($branches['names'], $b['names']); + } + } + } + } else { + $branches = Interval::anyDev(); + foreach ($constraintBranches as $b) { + if ($b['exclude']) { + if ($branches['exclude']) { + // conjunctive, so just add all branch names to be excluded + // !=a && !=b => !=a,!=b + $branches['names'] = array_merge($branches['names'], $b['names']); + } else { + // conjunctive, so only keep included names which are not excluded + // (==a||==c) && !=a,!=b => ==c + $branches['names'] = array_diff($branches['names'], $b['names']); + } + } else { + if ($branches['exclude']) { + // conjunctive, so only keep included names which are not excluded + // !=a,!=b && (==a||==c) => ==c + $branches['names'] = array_diff($b['names'], $branches['names']); + $branches['exclude'] = false; + } else { + // conjunctive, so only keep names that are included in both + // (==a||==b) && (==a||==c) => ==a + $branches['names'] = array_intersect($branches['names'], $b['names']); + } + } + } + } + + $branches['names'] = array_unique($branches['names']); + + if (\count($numericGroups) === 1) { + return array('numeric' => $numericGroups[0], 'branches' => $branches); + } + + $borders = array(); + foreach ($numericGroups as $group) { + foreach ($group as $interval) { + $borders[] = array('version' => $interval->getStart()->getVersion(), 'operator' => $interval->getStart()->getOperator(), 'side' => 'start'); + $borders[] = array('version' => $interval->getEnd()->getVersion(), 'operator' => $interval->getEnd()->getOperator(), 'side' => 'end'); + } + } + + $opSortOrder = self::$opSortOrder; + usort($borders, function ($a, $b) use ($opSortOrder) { + $order = version_compare($a['version'], $b['version']); + if ($order === 0) { + return $opSortOrder[$a['operator']] - $opSortOrder[$b['operator']]; + } + + return $order; + }); + + $activeIntervals = 0; + $intervals = array(); + $index = 0; + $activationThreshold = $constraint->isConjunctive() ? \count($numericGroups) : 1; + $start = null; + foreach ($borders as $border) { + if ($border['side'] === 'start') { + $activeIntervals++; + } else { + $activeIntervals--; + } + if (!$start && $activeIntervals >= $activationThreshold) { + $start = new Constraint($border['operator'], $border['version']); + } elseif ($start && $activeIntervals < $activationThreshold) { + // filter out invalid intervals like > x - <= x, or >= x - < x + if ( + version_compare($start->getVersion(), $border['version'], '=') + && ( + ($start->getOperator() === '>' && $border['operator'] === '<=') + || ($start->getOperator() === '>=' && $border['operator'] === '<') + ) + ) { + unset($intervals[$index]); + } else { + $intervals[$index] = new Interval($start, new Constraint($border['operator'], $border['version'])); + $index++; + + if ($stopOnFirstValidInterval) { + break; + } + } + + $start = null; + } + } + + return array('numeric' => $intervals, 'branches' => $branches); + } + + /** + * @phpstan-return array{'numeric': Interval[], 'branches': array{'names': string[], 'exclude': bool}} + */ + private static function generateSingleConstraintIntervals(Constraint $constraint) + { + $op = $constraint->getOperator(); + + // handle branch constraints first + if (strpos($constraint->getVersion(), 'dev-') === 0) { + $intervals = array(); + $branches = array('names' => array(), 'exclude' => false); + + // != dev-foo means any numeric version may match, we treat >/< like != they are not really defined for branches + if ($op === '!=') { + $intervals[] = new Interval(Interval::fromZero(), Interval::untilPositiveInfinity()); + $branches = array('names' => array($constraint->getVersion()), 'exclude' => true); + } elseif ($op === '==') { + $branches['names'][] = $constraint->getVersion(); + } + + return array( + 'numeric' => $intervals, + 'branches' => $branches, + ); + } + + if ($op[0] === '>') { // > & >= + return array('numeric' => array(new Interval($constraint, Interval::untilPositiveInfinity())), 'branches' => Interval::noDev()); + } + if ($op[0] === '<') { // < & <= + return array('numeric' => array(new Interval(Interval::fromZero(), $constraint)), 'branches' => Interval::noDev()); + } + if ($op === '!=') { + // convert !=x to intervals of 0 - x - +inf + dev* + return array('numeric' => array( + new Interval(Interval::fromZero(), new Constraint('<', $constraint->getVersion())), + new Interval(new Constraint('>', $constraint->getVersion()), Interval::untilPositiveInfinity()), + ), 'branches' => Interval::anyDev()); + } + + // convert ==x to an interval of >=x - <=x + return array('numeric' => array( + new Interval(new Constraint('>=', $constraint->getVersion()), new Constraint('<=', $constraint->getVersion())), + ), 'branches' => Interval::noDev()); + } +} diff --git a/vendor/composer/semver/src/Semver.php b/vendor/composer/semver/src/Semver.php new file mode 100644 index 0000000..4d6de3c --- /dev/null +++ b/vendor/composer/semver/src/Semver.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver; + +use Composer\Semver\Constraint\Constraint; + +class Semver +{ + const SORT_ASC = 1; + const SORT_DESC = -1; + + /** @var VersionParser */ + private static $versionParser; + + /** + * Determine if given version satisfies given constraints. + * + * @param string $version + * @param string $constraints + * + * @return bool + */ + public static function satisfies($version, $constraints) + { + if (null === self::$versionParser) { + self::$versionParser = new VersionParser(); + } + + $versionParser = self::$versionParser; + $provider = new Constraint('==', $versionParser->normalize($version)); + $parsedConstraints = $versionParser->parseConstraints($constraints); + + return $parsedConstraints->matches($provider); + } + + /** + * Return all versions that satisfy given constraints. + * + * @param string[] $versions + * @param string $constraints + * + * @return string[] + */ + public static function satisfiedBy(array $versions, $constraints) + { + $versions = array_filter($versions, function ($version) use ($constraints) { + return Semver::satisfies($version, $constraints); + }); + + return array_values($versions); + } + + /** + * Sort given array of versions. + * + * @param string[] $versions + * + * @return string[] + */ + public static function sort(array $versions) + { + return self::usort($versions, self::SORT_ASC); + } + + /** + * Sort given array of versions in reverse. + * + * @param string[] $versions + * + * @return string[] + */ + public static function rsort(array $versions) + { + return self::usort($versions, self::SORT_DESC); + } + + /** + * @param string[] $versions + * @param int $direction + * + * @return string[] + */ + private static function usort(array $versions, $direction) + { + if (null === self::$versionParser) { + self::$versionParser = new VersionParser(); + } + + $versionParser = self::$versionParser; + $normalized = array(); + + // Normalize outside of usort() scope for minor performance increase. + // Creates an array of arrays: [[normalized, key], ...] + foreach ($versions as $key => $version) { + $normalizedVersion = $versionParser->normalize($version); + $normalizedVersion = $versionParser->normalizeDefaultBranch($normalizedVersion); + $normalized[] = array($normalizedVersion, $key); + } + + usort($normalized, function (array $left, array $right) use ($direction) { + if ($left[0] === $right[0]) { + return 0; + } + + if (Comparator::lessThan($left[0], $right[0])) { + return -$direction; + } + + return $direction; + }); + + // Recreate input array, using the original indexes which are now in sorted order. + $sorted = array(); + foreach ($normalized as $item) { + $sorted[] = $versions[$item[1]]; + } + + return $sorted; + } +} diff --git a/vendor/composer/semver/src/VersionParser.php b/vendor/composer/semver/src/VersionParser.php new file mode 100644 index 0000000..202ce24 --- /dev/null +++ b/vendor/composer/semver/src/VersionParser.php @@ -0,0 +1,586 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Semver; + +use Composer\Semver\Constraint\ConstraintInterface; +use Composer\Semver\Constraint\MatchAllConstraint; +use Composer\Semver\Constraint\MultiConstraint; +use Composer\Semver\Constraint\Constraint; + +/** + * Version parser. + * + * @author Jordi Boggiano + */ +class VersionParser +{ + /** + * Regex to match pre-release data (sort of). + * + * Due to backwards compatibility: + * - Instead of enforcing hyphen, an underscore, dot or nothing at all are also accepted. + * - Only stabilities as recognized by Composer are allowed to precede a numerical identifier. + * - Numerical-only pre-release identifiers are not supported, see tests. + * + * |--------------| + * [major].[minor].[patch] -[pre-release] +[build-metadata] + * + * @var string + */ + private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?'; + + /** @var string */ + private static $stabilitiesRegex = 'stable|RC|beta|alpha|dev'; + + /** + * Returns the stability of a version. + * + * @param string $version + * + * @return string + * @phpstan-return 'stable'|'RC'|'beta'|'alpha'|'dev' + */ + public static function parseStability($version) + { + $version = (string) preg_replace('{#.+$}', '', (string) $version); + + if (strpos($version, 'dev-') === 0 || '-dev' === substr($version, -4)) { + return 'dev'; + } + + preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match); + + if (!empty($match[3])) { + return 'dev'; + } + + if (!empty($match[1])) { + if ('beta' === $match[1] || 'b' === $match[1]) { + return 'beta'; + } + if ('alpha' === $match[1] || 'a' === $match[1]) { + return 'alpha'; + } + if ('rc' === $match[1]) { + return 'RC'; + } + } + + return 'stable'; + } + + /** + * @param string $stability + * + * @return string + */ + public static function normalizeStability($stability) + { + $stability = strtolower((string) $stability); + + return $stability === 'rc' ? 'RC' : $stability; + } + + /** + * Normalizes a version string to be able to perform comparisons on it. + * + * @param string $version + * @param ?string $fullVersion optional complete version string to give more context + * + * @throws \UnexpectedValueException + * + * @return string + */ + public function normalize($version, $fullVersion = null) + { + $version = trim((string) $version); + $origVersion = $version; + if (null === $fullVersion) { + $fullVersion = $version; + } + + // strip off aliasing + if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) { + $version = $match[1]; + } + + // strip off stability flag + if (preg_match('{@(?:' . self::$stabilitiesRegex . ')$}i', $version, $match)) { + $version = substr($version, 0, strlen($version) - strlen($match[0])); + } + + // normalize master/trunk/default branches to dev-name for BC with 1.x as these used to be valid constraints + if (\in_array($version, array('master', 'trunk', 'default'), true)) { + $version = 'dev-' . $version; + } + + // if requirement is branch-like, use full name + if (stripos($version, 'dev-') === 0) { + return 'dev-' . substr($version, 4); + } + + // strip off build metadata + if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) { + $version = $match[1]; + } + + // match classical versioning + if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) { + $version = $matches[1] + . (!empty($matches[2]) ? $matches[2] : '.0') + . (!empty($matches[3]) ? $matches[3] : '.0') + . (!empty($matches[4]) ? $matches[4] : '.0'); + $index = 5; + // match date(time) based versioning + } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) { + $version = preg_replace('{\D}', '.', $matches[1]); + $index = 2; + } + + // add version modifiers if a version was matched + if (isset($index)) { + if (!empty($matches[$index])) { + if ('stable' === $matches[$index]) { + return $version; + } + $version .= '-' . $this->expandStability($matches[$index]) . (isset($matches[$index + 1]) && '' !== $matches[$index + 1] ? ltrim($matches[$index + 1], '.-') : ''); + } + + if (!empty($matches[$index + 2])) { + $version .= '-dev'; + } + + return $version; + } + + // match dev branches + if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) { + try { + $normalized = $this->normalizeBranch($match[1]); + // a branch ending with -dev is only valid if it is numeric + // if it gets prefixed with dev- it means the branch name should + // have had a dev- prefix already when passed to normalize + if (strpos($normalized, 'dev-') === false) { + return $normalized; + } + } catch (\Exception $e) { + } + } + + $extraMessage = ''; + if (preg_match('{ +as +' . preg_quote($version) . '(?:@(?:'.self::$stabilitiesRegex.'))?$}', $fullVersion)) { + $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version'; + } elseif (preg_match('{^' . preg_quote($version) . '(?:@(?:'.self::$stabilitiesRegex.'))? +as +}', $fullVersion)) { + $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-'; + } + + throw new \UnexpectedValueException('Invalid version string "' . $origVersion . '"' . $extraMessage); + } + + /** + * Extract numeric prefix from alias, if it is in numeric format, suitable for version comparison. + * + * @param string $branch Branch name (e.g. 2.1.x-dev) + * + * @return string|false Numeric prefix if present (e.g. 2.1.) or false + */ + public function parseNumericAliasPrefix($branch) + { + if (preg_match('{^(?P(\d++\\.)*\d++)(?:\.x)?-dev$}i', (string) $branch, $matches)) { + return $matches['version'] . '.'; + } + + return false; + } + + /** + * Normalizes a branch name to be able to perform comparisons on it. + * + * @param string $name + * + * @return string + */ + public function normalizeBranch($name) + { + $name = trim((string) $name); + + if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) { + $version = ''; + for ($i = 1; $i < 5; ++$i) { + $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x'; + } + + return str_replace('x', '9999999', $version) . '-dev'; + } + + return 'dev-' . $name; + } + + /** + * Normalizes a default branch name (i.e. master on git) to 9999999-dev. + * + * @param string $name + * + * @return string + * + * @deprecated No need to use this anymore in theory, Composer 2 does not normalize any branch names to 9999999-dev anymore + */ + public function normalizeDefaultBranch($name) + { + if ($name === 'dev-master' || $name === 'dev-default' || $name === 'dev-trunk') { + return '9999999-dev'; + } + + return (string) $name; + } + + /** + * Parses a constraint string into MultiConstraint and/or Constraint objects. + * + * @param string $constraints + * + * @return ConstraintInterface + */ + public function parseConstraints($constraints) + { + $prettyConstraint = (string) $constraints; + + $orConstraints = preg_split('{\s*\|\|?\s*}', trim((string) $constraints)); + if (false === $orConstraints) { + throw new \RuntimeException('Failed to preg_split string: '.$constraints); + } + $orGroups = array(); + + foreach ($orConstraints as $constraints) { + $andConstraints = preg_split('{(?< ,]) *(? 1) { + $constraintObjects = array(); + foreach ($andConstraints as $constraint) { + foreach ($this->parseConstraint($constraint) as $parsedConstraint) { + $constraintObjects[] = $parsedConstraint; + } + } + } else { + $constraintObjects = $this->parseConstraint($andConstraints[0]); + } + + if (1 === \count($constraintObjects)) { + $constraint = $constraintObjects[0]; + } else { + $constraint = new MultiConstraint($constraintObjects); + } + + $orGroups[] = $constraint; + } + + $constraint = MultiConstraint::create($orGroups, false); + + $constraint->setPrettyString($prettyConstraint); + + return $constraint; + } + + /** + * @param string $constraint + * + * @throws \UnexpectedValueException + * + * @return array + * + * @phpstan-return non-empty-array + */ + private function parseConstraint($constraint) + { + // strip off aliasing + if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $constraint, $match)) { + $constraint = $match[1]; + } + + // strip @stability flags, and keep it for later use + if (preg_match('{^([^,\s]*?)@(' . self::$stabilitiesRegex . ')$}i', $constraint, $match)) { + $constraint = '' !== $match[1] ? $match[1] : '*'; + if ($match[2] !== 'stable') { + $stabilityModifier = $match[2]; + } + } + + // get rid of #refs as those are used by composer only + if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraint, $match)) { + $constraint = $match[1]; + } + + if (preg_match('{^(v)?[xX*](\.[xX*])*$}i', $constraint, $match)) { + if (!empty($match[1]) || !empty($match[2])) { + return array(new Constraint('>=', '0.0.0.0-dev')); + } + + return array(new MatchAllConstraint()); + } + + $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?(?:' . self::$modifierRegex . '|\.([xX*][.-]?dev))(?:\+[^\s]+)?'; + + // Tilde Range + // + // Like wildcard constraints, unsuffixed tilde constraints say that they must be greater than the previous + // version, to ensure that unstable instances of the current version are allowed. However, if a stability + // suffix is added to the constraint, then a >= match on the current version is used instead. + if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) { + if (strpos($constraint, '~>') === 0) { + throw new \UnexpectedValueException( + 'Could not parse version constraint ' . $constraint . ': ' . + 'Invalid operator "~>", you probably meant to use the "~" operator' + ); + } + + // Work out which position in the version we are operating at + if (isset($matches[4]) && '' !== $matches[4] && null !== $matches[4]) { + $position = 4; + } elseif (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { + $position = 3; + } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { + $position = 2; + } else { + $position = 1; + } + + // when matching 2.x-dev or 3.0.x-dev we have to shift the second or third number, despite no second/third number matching above + if (!empty($matches[8])) { + $position++; + } + + // Calculate the stability suffix + $stabilitySuffix = ''; + if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) { + $stabilitySuffix .= '-dev'; + } + + $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1)); + $lowerBound = new Constraint('>=', $lowVersion); + + // For upper bound, we increment the position of one more significance, + // but highPosition = 0 would be illegal + $highPosition = max(1, $position - 1); + $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev'; + $upperBound = new Constraint('<', $highVersion); + + return array( + $lowerBound, + $upperBound, + ); + } + + // Caret Range + // + // Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple. + // In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for + // versions 0.X >=0.1.0, and no updates for versions 0.0.X + if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) { + // Work out which position in the version we are operating at + if ('0' !== $matches[1] || '' === $matches[2] || null === $matches[2]) { + $position = 1; + } elseif ('0' !== $matches[2] || '' === $matches[3] || null === $matches[3]) { + $position = 2; + } else { + $position = 3; + } + + // Calculate the stability suffix + $stabilitySuffix = ''; + if (empty($matches[5]) && empty($matches[7]) && empty($matches[8])) { + $stabilitySuffix .= '-dev'; + } + + $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1)); + $lowerBound = new Constraint('>=', $lowVersion); + + // For upper bound, we increment the position of one more significance, + // but highPosition = 0 would be illegal + $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; + $upperBound = new Constraint('<', $highVersion); + + return array( + $lowerBound, + $upperBound, + ); + } + + // X Range + // + // Any of X, x, or * may be used to "stand in" for one of the numeric values in the [major, minor, patch] tuple. + // A partial version range is treated as an X-Range, so the special character is in fact optional. + if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) { + if (isset($matches[3]) && '' !== $matches[3] && null !== $matches[3]) { + $position = 3; + } elseif (isset($matches[2]) && '' !== $matches[2] && null !== $matches[2]) { + $position = 2; + } else { + $position = 1; + } + + $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev'; + $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev'; + + if ($lowVersion === '0.0.0.0-dev') { + return array(new Constraint('<', $highVersion)); + } + + return array( + new Constraint('>=', $lowVersion), + new Constraint('<', $highVersion), + ); + } + + // Hyphen Range + // + // Specifies an inclusive set. If a partial version is provided as the first version in the inclusive range, + // then the missing pieces are replaced with zeroes. If a partial version is provided as the second version in + // the inclusive range, then all versions that start with the supplied parts of the tuple are accepted, but + // nothing that would be greater than the provided tuple parts. + if (preg_match('{^(?P' . $versionRegex . ') +- +(?P' . $versionRegex . ')($)}i', $constraint, $matches)) { + // Calculate the stability suffix + $lowStabilitySuffix = ''; + if (empty($matches[6]) && empty($matches[8]) && empty($matches[9])) { + $lowStabilitySuffix = '-dev'; + } + + $lowVersion = $this->normalize($matches['from']); + $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix); + + $empty = function ($x) { + return ($x === 0 || $x === '0') ? false : empty($x); + }; + + if ((!$empty($matches[12]) && !$empty($matches[13])) || !empty($matches[15]) || !empty($matches[17]) || !empty($matches[18])) { + $highVersion = $this->normalize($matches['to']); + $upperBound = new Constraint('<=', $highVersion); + } else { + $highMatch = array('', $matches[11], $matches[12], $matches[13], $matches[14]); + + // validate to version + $this->normalize($matches['to']); + + $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[12]) ? 1 : 2, 1) . '-dev'; + $upperBound = new Constraint('<', $highVersion); + } + + return array( + $lowerBound, + $upperBound, + ); + } + + // Basic Comparators + if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) { + try { + try { + $version = $this->normalize($matches[2]); + } catch (\UnexpectedValueException $e) { + // recover from an invalid constraint like foobar-dev which should be dev-foobar + // except if the constraint uses a known operator, in which case it must be a parse error + if (substr($matches[2], -4) === '-dev' && preg_match('{^[0-9a-zA-Z-./]+$}', $matches[2])) { + $version = $this->normalize('dev-'.substr($matches[2], 0, -4)); + } else { + throw $e; + } + } + + $op = $matches[1] ?: '='; + + if ($op !== '==' && $op !== '=' && !empty($stabilityModifier) && self::parseStability($version) === 'stable') { + $version .= '-' . $stabilityModifier; + } elseif ('<' === $op || '>=' === $op) { + if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) { + if (strpos($matches[2], 'dev-') !== 0) { + $version .= '-dev'; + } + } + } + + return array(new Constraint($matches[1] ?: '=', $version)); + } catch (\Exception $e) { + } + } + + $message = 'Could not parse version constraint ' . $constraint; + if (isset($e)) { + $message .= ': ' . $e->getMessage(); + } + + throw new \UnexpectedValueException($message); + } + + /** + * Increment, decrement, or simply pad a version number. + * + * Support function for {@link parseConstraint()} + * + * @param array $matches Array with version parts in array indexes 1,2,3,4 + * @param int $position 1,2,3,4 - which segment of the version to increment/decrement + * @param int $increment + * @param string $pad The string to pad version parts after $position + * + * @return string|null The new version + * + * @phpstan-param string[] $matches + */ + private function manipulateVersionString(array $matches, $position, $increment = 0, $pad = '0') + { + for ($i = 4; $i > 0; --$i) { + if ($i > $position) { + $matches[$i] = $pad; + } elseif ($i === $position && $increment) { + $matches[$i] += $increment; + // If $matches[$i] was 0, carry the decrement + if ($matches[$i] < 0) { + $matches[$i] = $pad; + --$position; + + // Return null on a carry overflow + if ($i === 1) { + return null; + } + } + } + } + + return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4]; + } + + /** + * Expand shorthand stability string to long version. + * + * @param string $stability + * + * @return string + */ + private function expandStability($stability) + { + $stability = strtolower($stability); + + switch ($stability) { + case 'a': + return 'alpha'; + case 'b': + return 'beta'; + case 'p': + case 'pl': + return 'patch'; + case 'rc': + return 'RC'; + default: + return $stability; + } + } +} diff --git a/vendor/composer/xdebug-handler/CHANGELOG.md b/vendor/composer/xdebug-handler/CHANGELOG.md new file mode 100644 index 0000000..a3a170c --- /dev/null +++ b/vendor/composer/xdebug-handler/CHANGELOG.md @@ -0,0 +1,124 @@ +## [Unreleased] + +## [2.0.5] - 2022-02-24 + * Fixed: regression in 2.0.4 affecting Xdebug 2. + +## [2.0.4] - 2022-01-04 + * Fixed: allow calling `isXdebugActive` before class instantiation. + +## [2.0.3] - 2021-12-08 + * Added: support, type annotations and refactoring for stricter PHPStan analysis. + +## [2.0.2] - 2021-07-31 + * Added: support for `xdebug_info('mode')` in Xdebug 3.1. + * Added: support for Psr\Log versions 2 and 3. + * Fixed: remove ini directives from non-cli HOST/PATH sections. + +## [2.0.1] - 2021-05-05 + * Fixed: don't restart if the cwd is a UNC path and cmd.exe will be invoked. + +## [2.0.0] - 2021-04-09 + * Break: this is a major release, see [UPGRADE.md](UPGRADE.md) for more information. + * Break: removed optional `$colorOption` constructor param and passthru fallback. + * Break: renamed `requiresRestart` param from `$isLoaded` to `$default`. + * Break: changed `restart` param `$command` from a string to an array. + * Added: support for Xdebug3 to only restart if Xdebug is not running with `xdebug.mode=off`. + * Added: `isXdebugActive()` method to determine if Xdebug is still running in the restart. + * Added: feature to bypass the shell in PHP-7.4+ by giving `proc_open` an array of arguments. + * Added: Process utility class to the API. + +## [1.4.6] - 2021-03-25 + * Fixed: fail restart if `proc_open` has been disabled in `disable_functions`. + * Fixed: enable Windows CTRL event handling in the restarted process. + +## [1.4.5] - 2020-11-13 + * Fixed: use `proc_open` when available for correct FD forwarding to the restarted process. + +## [1.4.4] - 2020-10-24 + * Fixed: exception if 'pcntl_signal' is disabled. + +## [1.4.3] - 2020-08-19 + * Fixed: restore SIGINT to default handler in restarted process if no other handler exists. + +## [1.4.2] - 2020-06-04 + * Fixed: ignore SIGINTs to let the restarted process handle them. + +## [1.4.1] - 2020-03-01 + * Fixed: restart fails if an ini file is empty. + +## [1.4.0] - 2019-11-06 + * Added: support for `NO_COLOR` environment variable: https://no-color.org + * Added: color support for Hyper terminal: https://github.com/zeit/hyper + * Fixed: correct capitalization of Xdebug (apparently). + * Fixed: improved handling for uopz extension. + +## [1.3.3] - 2019-05-27 + * Fixed: add environment changes to `$_ENV` if it is being used. + +## [1.3.2] - 2019-01-28 + * Fixed: exit call being blocked by uopz extension, resulting in application code running twice. + +## [1.3.1] - 2018-11-29 + * Fixed: fail restart if `passthru` has been disabled in `disable_functions`. + * Fixed: fail restart if an ini file cannot be opened, otherwise settings will be missing. + +## [1.3.0] - 2018-08-31 + * Added: `setPersistent` method to use environment variables for the restart. + * Fixed: improved debugging by writing output to stderr. + * Fixed: no restart when `php_ini_scanned_files` is not functional and is needed. + +## [1.2.1] - 2018-08-23 + * Fixed: fatal error with apc, when using `apc.mmap_file_mask`. + +## [1.2.0] - 2018-08-16 + * Added: debug information using `XDEBUG_HANDLER_DEBUG`. + * Added: fluent interface for setters. + * Added: `PhpConfig` helper class for calling PHP sub-processes. + * Added: `PHPRC` original value to restart stettings, for use in a restarted process. + * Changed: internal procedure to disable ini-scanning, using `-n` command-line option. + * Fixed: replaced `escapeshellarg` usage to avoid locale problems. + * Fixed: improved color-option handling to respect double-dash delimiter. + * Fixed: color-option handling regression from main script changes. + * Fixed: improved handling when checking main script. + * Fixed: handling for standard input, that never actually did anything. + * Fixed: fatal error when ctype extension is not available. + +## [1.1.0] - 2018-04-11 + * Added: `getRestartSettings` method for calling PHP processes in a restarted process. + * Added: API definition and @internal class annotations. + * Added: protected `requiresRestart` method for extending classes. + * Added: `setMainScript` method for applications that change the working directory. + * Changed: private `tmpIni` variable to protected for extending classes. + * Fixed: environment variables not available in $_SERVER when restored in the restart. + * Fixed: relative path problems caused by Phar::interceptFileFuncs. + * Fixed: incorrect handling when script file cannot be found. + +## [1.0.0] - 2018-03-08 + * Added: PSR3 logging for optional status output. + * Added: existing ini settings are merged to catch command-line overrides. + * Added: code, tests and other artefacts to decouple from Composer. + * Break: the following class was renamed: + - `Composer\XdebugHandler` -> `Composer\XdebugHandler\XdebugHandler` + +[Unreleased]: https://github.com/composer/xdebug-handler/compare/2.0.5...HEAD +[2.0.5]: https://github.com/composer/xdebug-handler/compare/2.0.4...2.0.5 +[2.0.4]: https://github.com/composer/xdebug-handler/compare/2.0.3...2.0.4 +[2.0.3]: https://github.com/composer/xdebug-handler/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/composer/xdebug-handler/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/composer/xdebug-handler/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/composer/xdebug-handler/compare/1.4.6...2.0.0 +[1.4.6]: https://github.com/composer/xdebug-handler/compare/1.4.5...1.4.6 +[1.4.5]: https://github.com/composer/xdebug-handler/compare/1.4.4...1.4.5 +[1.4.4]: https://github.com/composer/xdebug-handler/compare/1.4.3...1.4.4 +[1.4.3]: https://github.com/composer/xdebug-handler/compare/1.4.2...1.4.3 +[1.4.2]: https://github.com/composer/xdebug-handler/compare/1.4.1...1.4.2 +[1.4.1]: https://github.com/composer/xdebug-handler/compare/1.4.0...1.4.1 +[1.4.0]: https://github.com/composer/xdebug-handler/compare/1.3.3...1.4.0 +[1.3.3]: https://github.com/composer/xdebug-handler/compare/1.3.2...1.3.3 +[1.3.2]: https://github.com/composer/xdebug-handler/compare/1.3.1...1.3.2 +[1.3.1]: https://github.com/composer/xdebug-handler/compare/1.3.0...1.3.1 +[1.3.0]: https://github.com/composer/xdebug-handler/compare/1.2.1...1.3.0 +[1.2.1]: https://github.com/composer/xdebug-handler/compare/1.2.0...1.2.1 +[1.2.0]: https://github.com/composer/xdebug-handler/compare/1.1.0...1.2.0 +[1.1.0]: https://github.com/composer/xdebug-handler/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/composer/xdebug-handler/compare/d66f0d15cb57...1.0.0 diff --git a/vendor/composer/xdebug-handler/LICENSE b/vendor/composer/xdebug-handler/LICENSE new file mode 100644 index 0000000..963618a --- /dev/null +++ b/vendor/composer/xdebug-handler/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Composer + +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/vendor/composer/xdebug-handler/README.md b/vendor/composer/xdebug-handler/README.md new file mode 100644 index 0000000..557d100 --- /dev/null +++ b/vendor/composer/xdebug-handler/README.md @@ -0,0 +1,291 @@ +# composer/xdebug-handler + +[![packagist](https://img.shields.io/badge/packagist-v2.0.4-blue)](https://packagist.org/packages/composer/xdebug-handler#2.0.4) +[![Continuous Integration](https://github.com/composer/xdebug-handler/actions/workflows/continuous-integration.yml/badge.svg?branch=2.0)](https://github.com/composer/xdebug-handler/actions?query=branch:2.0) +![license](https://img.shields.io/github/license/composer/xdebug-handler.svg) +![php](https://img.shields.io/packagist/php-v/composer/xdebug-handler/2.0.2?colorB=8892BF) + +Restart a CLI process without loading the Xdebug extension, unless `xdebug.mode=off`. + +Originally written as part of [composer/composer](https://github.com/composer/composer), +now extracted and made available as a stand-alone library. + +### Version 2 + +Support added for Xdebug3. See [UPGRADE](UPGRADE.md) for more information. + +## Installation + +Install the latest version with: + +```bash +$ composer require composer/xdebug-handler +``` + +## Requirements + +* PHP 5.3.2 minimum, although functionality is disabled below PHP 5.4.0. Using the latest PHP version is highly recommended. + +## Basic Usage +```php +use Composer\XdebugHandler\XdebugHandler; + +$xdebug = new XdebugHandler('myapp'); +$xdebug->check(); +unset($xdebug); +``` + +The constructor takes a single parameter, `$envPrefix`, which is upper-cased and prepended to default base values to create two distinct environment variables. The above example enables the use of: + +- `MYAPP_ALLOW_XDEBUG=1` to override automatic restart and allow Xdebug +- `MYAPP_ORIGINAL_INIS` to obtain ini file locations in a restarted process + +## Advanced Usage + +* [How it works](#how-it-works) +* [Limitations](#limitations) +* [Helper methods](#helper-methods) +* [Setter methods](#setter-methods) +* [Process configuration](#process-configuration) +* [Troubleshooting](#troubleshooting) +* [Extending the library](#extending-the-library) + +### How it works + +A temporary ini file is created from the loaded (and scanned) ini files, with any references to the Xdebug extension commented out. Current ini settings are merged, so that most ini settings made on the command-line or by the application are included (see [Limitations](#limitations)) + +* `MYAPP_ALLOW_XDEBUG` is set with internal data to flag and use in the restart. +* The command-line and environment are [configured](#process-configuration) for the restart. +* The application is restarted in a new process. + * The restart settings are stored in the environment. + * `MYAPP_ALLOW_XDEBUG` is unset. + * The application runs and exits. +* The main process exits with the exit code from the restarted process. + +#### Signal handling +From PHP 7.1 with the pcntl extension loaded, asynchronous signal handling is automatically enabled. `SIGINT` is set to `SIG_IGN` in the parent +process and restored to `SIG_DFL` in the restarted process (if no other handler has been set). + +From PHP 7.4 on Windows, `CTRL+C` and `CTRL+BREAK` handling is ignored in the parent process and automatically enabled in the restarted process. + +### Limitations +There are a few things to be aware of when running inside a restarted process. + +* Extensions set on the command-line will not be loaded. +* Ini file locations will be reported as per the restart - see [getAllIniFiles()](#getallinifiles). +* Php sub-processes may be loaded with Xdebug enabled - see [Process configuration](#process-configuration). + +### Helper methods +These static methods provide information from the current process, regardless of whether it has been restarted or not. + +#### _getAllIniFiles()_ +Returns an array of the original ini file locations. Use this instead of calling `php_ini_loaded_file` and `php_ini_scanned_files`, which will report the wrong values in a restarted process. + +```php +use Composer\XdebugHandler\XdebugHandler; + +$files = XdebugHandler::getAllIniFiles(); + +# $files[0] always exists, it could be an empty string +$loadedIni = array_shift($files); +$scannedInis = $files; +``` + +These locations are also available in the `MYAPP_ORIGINAL_INIS` environment variable. This is a path-separated string comprising the location returned from `php_ini_loaded_file`, which could be empty, followed by locations parsed from calling `php_ini_scanned_files`. + +#### _getRestartSettings()_ +Returns an array of settings that can be used with PHP [sub-processes](#sub-processes), or null if the process was not restarted. + +```php +use Composer\XdebugHandler\XdebugHandler; + +$settings = XdebugHandler::getRestartSettings(); +/** + * $settings: array (if the current process was restarted, + * or called with the settings from a previous restart), or null + * + * 'tmpIni' => the temporary ini file used in the restart (string) + * 'scannedInis' => if there were any scanned inis (bool) + * 'scanDir' => the original PHP_INI_SCAN_DIR value (false|string) + * 'phprc' => the original PHPRC value (false|string) + * 'inis' => the original inis from getAllIniFiles (array) + * 'skipped' => the skipped version from getSkippedVersion (string) + */ +``` + +#### _getSkippedVersion()_ +Returns the Xdebug version string that was skipped by the restart, or an empty value if there was no restart (or Xdebug is still loaded, perhaps by an extending class restarting for a reason other than removing Xdebug). + +```php +use Composer\XdebugHandler\XdebugHandler; + +$version = XdebugHandler::getSkippedVersion(); +# $version: '2.6.0' (for example), or an empty string +``` + +#### _isXdebugActive()_ +Returns true if Xdebug is loaded and is running in an active mode (if it supports modes). Returns false if Xdebug is not loaded, or it is running with `xdebug.mode=off`. + +### Setter methods +These methods implement a fluent interface and must be called before the main `check()` method. + +#### _setLogger($logger)_ +Enables the output of status messages to an external PSR3 logger. All messages are reported with either `DEBUG` or `WARNING` log levels. For example (showing the level and message): + +``` +// Restart overridden +DEBUG Checking MYAPP_ALLOW_XDEBUG +DEBUG The Xdebug extension is loaded (2.5.0) +DEBUG No restart (MYAPP_ALLOW_XDEBUG=1) + +// Failed restart +DEBUG Checking MYAPP_ALLOW_XDEBUG +DEBUG The Xdebug extension is loaded (2.5.0) +WARNING No restart (Unable to create temp ini file at: ...) +``` + +Status messages can also be output with `XDEBUG_HANDLER_DEBUG`. See [Troubleshooting](#troubleshooting). + +#### _setMainScript($script)_ +Sets the location of the main script to run in the restart. This is only needed in more esoteric use-cases, or if the `argv[0]` location is inaccessible. The script name `--` is supported for standard input. + +#### _setPersistent()_ +Configures the restart using [persistent settings](#persistent-settings), so that Xdebug is not loaded in any sub-process. + +Use this method if your application invokes one or more PHP sub-process and the Xdebug extension is not needed. This avoids the overhead of implementing specific [sub-process](#sub-processes) strategies. + +Alternatively, this method can be used to set up a default _Xdebug-free_ environment which can be changed if a sub-process requires Xdebug, then restored afterwards: + +```php +function SubProcessWithXdebug() +{ + $phpConfig = new Composer\XdebugHandler\PhpConfig(); + + # Set the environment to the original configuration + $phpConfig->useOriginal(); + + # run the process with Xdebug loaded + ... + + # Restore Xdebug-free environment + $phpConfig->usePersistent(); +} +``` + +### Process configuration +The library offers two strategies to invoke a new PHP process without loading Xdebug, using either _standard_ or _persistent_ settings. Note that this is only important if the application calls a PHP sub-process. + +#### Standard settings +Uses command-line options to remove Xdebug from the new process only. + +* The -n option is added to the command-line. This tells PHP not to scan for additional inis. +* The temporary ini is added to the command-line with the -c option. + +>_If the new process calls a PHP sub-process, Xdebug will be loaded in that sub-process (unless it implements xdebug-handler, in which case there will be another restart)._ + +This is the default strategy used in the restart. + +#### Persistent settings +Uses environment variables to remove Xdebug from the new process and persist these settings to any sub-process. + +* `PHP_INI_SCAN_DIR` is set to an empty string. This tells PHP not to scan for additional inis. +* `PHPRC` is set to the temporary ini. + +>_If the new process calls a PHP sub-process, Xdebug will not be loaded in that sub-process._ + +This strategy can be used in the restart by calling [setPersistent()](#setpersistent). + +#### Sub-processes +The `PhpConfig` helper class makes it easy to invoke a PHP sub-process (with or without Xdebug loaded), regardless of whether there has been a restart. + +Each of its methods returns an array of PHP options (to add to the command-line) and sets up the environment for the required strategy. The [getRestartSettings()](#getrestartsettings) method is used internally. + +* `useOriginal()` - Xdebug will be loaded in the new process. +* `useStandard()` - Xdebug will **not** be loaded in the new process - see [standard settings](#standard-settings). +* `userPersistent()` - Xdebug will **not** be loaded in the new process - see [persistent settings](#persistent-settings) + +If there was no restart, an empty options array is returned and the environment is not changed. + +```php +use Composer\XdebugHandler\PhpConfig; + +$config = new PhpConfig; + +$options = $config->useOriginal(); +# $options: empty array +# environment: PHPRC and PHP_INI_SCAN_DIR set to original values + +$options = $config->useStandard(); +# $options: [-n, -c, tmpIni] +# environment: PHPRC and PHP_INI_SCAN_DIR set to original values + +$options = $config->usePersistent(); +# $options: empty array +# environment: PHPRC=tmpIni, PHP_INI_SCAN_DIR='' +``` + +### Troubleshooting +The following environment settings can be used to troubleshoot unexpected behavior: + +* `XDEBUG_HANDLER_DEBUG=1` Outputs status messages to `STDERR`, if it is defined, irrespective of any PSR3 logger. Each message is prefixed `xdebug-handler[pid]`, where pid is the process identifier. + +* `XDEBUG_HANDLER_DEBUG=2` As above, but additionally saves the temporary ini file and reports its location in a status message. + +### Extending the library +The API is defined by classes and their accessible elements that are not annotated as @internal. The main class has two protected methods that can be overridden to provide additional functionality: + +#### _requiresRestart($default)_ +By default the process will restart if Xdebug is loaded and not running with `xdebug.mode=off`. Extending this method allows an application to decide, by returning a boolean (or equivalent) value. +It is only called if `MYAPP_ALLOW_XDEBUG` is empty, so it will not be called in the restarted process (where this variable contains internal data), or if the restart has been overridden. + +Note that the [setMainScript()](#setmainscriptscript) and [setPersistent()](#setpersistent) setters can be used here, if required. + +#### _restart($command)_ +An application can extend this to modify the temporary ini file, its location given in the `tmpIni` property. New settings can be safely appended to the end of the data, which is `PHP_EOL` terminated. + +The `$command` parameter is an array of unescaped command-line arguments that will be used for the new process. + +Remember to finish with `parent::restart($command)`. + +#### Example +This example demonstrates two ways to extend basic functionality: + +* To avoid the overhead of spinning up a new process, the restart is skipped if a simple help command is requested. + +* The application needs write-access to phar files, so it will force a restart if `phar.readonly` is set (regardless of whether Xdebug is loaded) and change this value in the temporary ini file. + +```php +use Composer\XdebugHandler\XdebugHandler; +use MyApp\Command; + +class MyRestarter extends XdebugHandler +{ + private $required; + + protected function requiresRestart($default) + { + if (Command::isHelp()) { + # No need to disable Xdebug for this + return false; + } + + $this->required = (bool) ini_get('phar.readonly'); + return $this->required || $default; + } + + protected function restart($command) + { + if ($this->required) { + # Add required ini setting to tmpIni + $content = file_get_contents($this->tmpIni); + $content .= 'phar.readonly=0'.PHP_EOL; + file_put_contents($this->tmpIni, $content); + } + + parent::restart($command); + } +} +``` + +## License +composer/xdebug-handler is licensed under the MIT License, see the LICENSE file for details. diff --git a/vendor/composer/xdebug-handler/UPGRADE.md b/vendor/composer/xdebug-handler/UPGRADE.md new file mode 100644 index 0000000..3d62e17 --- /dev/null +++ b/vendor/composer/xdebug-handler/UPGRADE.md @@ -0,0 +1,30 @@ +## Upgrading from 1.x + +The default behaviour has changed from always restarting if Xdebug is loaded, to only restarting if +Xdebug is _active_. This has been introduced to support Xdebug3 +[modes](https://xdebug.org/docs/all_settings#mode). Xdebug is considered active if it is loaded, and +for Xdebug3, if it is running in a mode other than `xdebug.mode=off`. + +* Break: removed optional `$colorOption` constructor param and passthru fallback. + + Just use `new XdebugHandler('myapp')` to instantiate the class and color support will be +detectable in the restarted process. + +* Added: `isXdebugActive()` method to determine if Xdebug is still running in the restart. + + Returns true if Xdebug is loaded and is running in an active mode (if it supports modes). +Returns false if Xdebug is not loaded, or it is running with `xdebug.mode=off`. + +### Extending classes + +* Break: renamed `requiresRestart` param from `$isLoaded` to `$default`. + + This reflects the new default behaviour which is to restart only if Xdebug is active. + +* Break: changed `restart` param `$command` from a string to an array. + + Only important if you modified the string. `$command` is now an array of unescaped arguments. + +* Added: Process utility class to the API. + + This class was previously annotated as @internal and has been refactored due to recent changes. diff --git a/vendor/composer/xdebug-handler/composer.json b/vendor/composer/xdebug-handler/composer.json new file mode 100644 index 0000000..ccd33ef --- /dev/null +++ b/vendor/composer/xdebug-handler/composer.json @@ -0,0 +1,44 @@ +{ + "name": "composer/xdebug-handler", + "description": "Restarts a process without Xdebug.", + "type": "library", + "license": "MIT", + "keywords": [ + "xdebug", + "performance" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1 || ^2 || ^3", + "composer/pcre": "^1" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1" + }, + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Composer\\XdebugHandler\\Tests\\": "tests" + } + }, + "scripts": { + "test": "vendor/bin/simple-phpunit", + "phpstan": "vendor/bin/phpstan analyse" + } +} diff --git a/vendor/composer/xdebug-handler/src/PhpConfig.php b/vendor/composer/xdebug-handler/src/PhpConfig.php new file mode 100644 index 0000000..15c3d6f --- /dev/null +++ b/vendor/composer/xdebug-handler/src/PhpConfig.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\XdebugHandler; + +/** + * @author John Stevenson + * + * @phpstan-type restartData array{tmpIni: string, scannedInis: bool, scanDir: false|string, phprc: false|string, inis: string[], skipped: string} + */ +class PhpConfig +{ + /** + * Use the original PHP configuration + * + * @return string[] Empty array of PHP cli options + */ + public function useOriginal() + { + $this->getDataAndReset(); + return array(); + } + + /** + * Use standard restart settings + * + * @return string[] PHP cli options + */ + public function useStandard() + { + $data = $this->getDataAndReset(); + if ($data !== null) { + return array('-n', '-c', $data['tmpIni']); + } + + return array(); + } + + /** + * Use environment variables to persist settings + * + * @return string[] Empty array of PHP cli options + */ + public function usePersistent() + { + $data = $this->getDataAndReset(); + if ($data !== null) { + $this->updateEnv('PHPRC', $data['tmpIni']); + $this->updateEnv('PHP_INI_SCAN_DIR', ''); + } + + return array(); + } + + /** + * Returns restart data if available and resets the environment + * + * @return array|null + * @phpstan-return restartData|null + */ + private function getDataAndReset() + { + $data = XdebugHandler::getRestartSettings(); + if ($data !== null) { + $this->updateEnv('PHPRC', $data['phprc']); + $this->updateEnv('PHP_INI_SCAN_DIR', $data['scanDir']); + } + + return $data; + } + + /** + * Updates a restart settings value in the environment + * + * @param string $name + * @param string|false $value + * + * @return void + */ + private function updateEnv($name, $value) + { + Process::setEnv($name, false !== $value ? $value : null); + } +} diff --git a/vendor/composer/xdebug-handler/src/Process.php b/vendor/composer/xdebug-handler/src/Process.php new file mode 100644 index 0000000..3167239 --- /dev/null +++ b/vendor/composer/xdebug-handler/src/Process.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\XdebugHandler; + +use Composer\Pcre\Preg; + +/** + * Process utility functions + * + * @author John Stevenson + */ +class Process +{ + /** + * Escapes a string to be used as a shell argument. + * + * From https://github.com/johnstevenson/winbox-args + * MIT Licensed (c) John Stevenson + * + * @param string $arg The argument to be escaped + * @param bool $meta Additionally escape cmd.exe meta characters + * @param bool $module The argument is the module to invoke + * + * @return string The escaped argument + */ + public static function escape($arg, $meta = true, $module = false) + { + if (!defined('PHP_WINDOWS_VERSION_BUILD')) { + return "'".str_replace("'", "'\\''", $arg)."'"; + } + + $quote = strpbrk($arg, " \t") !== false || $arg === ''; + + $arg = Preg::replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes); + + if ($meta) { + $meta = $dquotes || Preg::isMatch('/%[^%]+%/', $arg); + + if (!$meta) { + $quote = $quote || strpbrk($arg, '^&|<>()') !== false; + } elseif ($module && !$dquotes && $quote) { + $meta = false; + } + } + + if ($quote) { + $arg = '"'.(Preg::replace('/(\\\\*)$/', '$1$1', $arg)).'"'; + } + + if ($meta) { + $arg = Preg::replace('/(["^&|<>()%])/', '^$1', $arg); + } + + return $arg; + } + + /** + * Escapes an array of arguments that make up a shell command + * + * @param string[] $args Argument list, with the module name first + * + * @return string The escaped command line + */ + public static function escapeShellCommand(array $args) + { + $command = ''; + $module = array_shift($args); + + if ($module !== null) { + $command = self::escape($module, true, true); + + foreach ($args as $arg) { + $command .= ' '.self::escape($arg); + } + } + + return $command; + } + + /** + * Makes putenv environment changes available in $_SERVER and $_ENV + * + * @param string $name + * @param string|null $value A null value unsets the variable + * + * @return bool Whether the environment variable was set + */ + public static function setEnv($name, $value = null) + { + $unset = null === $value; + + if (!putenv($unset ? $name : $name.'='.$value)) { + return false; + } + + if ($unset) { + unset($_SERVER[$name]); + } else { + $_SERVER[$name] = $value; + } + + // Update $_ENV if it is being used + if (false !== stripos((string) ini_get('variables_order'), 'E')) { + if ($unset) { + unset($_ENV[$name]); + } else { + $_ENV[$name] = $value; + } + } + + return true; + } +} diff --git a/vendor/composer/xdebug-handler/src/Status.php b/vendor/composer/xdebug-handler/src/Status.php new file mode 100644 index 0000000..b7aad7b --- /dev/null +++ b/vendor/composer/xdebug-handler/src/Status.php @@ -0,0 +1,224 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\XdebugHandler; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; + +/** + * @author John Stevenson + * @internal + */ +class Status +{ + const ENV_RESTART = 'XDEBUG_HANDLER_RESTART'; + const CHECK = 'Check'; + const ERROR = 'Error'; + const INFO = 'Info'; + const NORESTART = 'NoRestart'; + const RESTART = 'Restart'; + const RESTARTING = 'Restarting'; + const RESTARTED = 'Restarted'; + + /** @var bool */ + private $debug; + + /** @var string */ + private $envAllowXdebug; + + /** @var string|null */ + private $loaded; + + /** @var LoggerInterface|null */ + private $logger; + + /** @var bool */ + private $modeOff; + + /** @var float */ + private $time; + + /** + * Constructor + * + * @param string $envAllowXdebug Prefixed _ALLOW_XDEBUG name + * @param bool $debug Whether debug output is required + */ + public function __construct($envAllowXdebug, $debug) + { + $start = getenv(self::ENV_RESTART); + Process::setEnv(self::ENV_RESTART); + $this->time = is_numeric($start) ? round((microtime(true) - $start) * 1000) : 0; + + $this->envAllowXdebug = $envAllowXdebug; + $this->debug = $debug && defined('STDERR'); + $this->modeOff = false; + } + + /** + * @param LoggerInterface $logger + * + * @return void + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } + + /** + * Calls a handler method to report a message + * + * @param string $op The handler constant + * @param null|string $data Data required by the handler + * + * @return void + * @throws \InvalidArgumentException If $op is not known + */ + public function report($op, $data) + { + if ($this->logger !== null || $this->debug) { + $callable = array($this, 'report'.$op); + + if (!is_callable($callable)) { + throw new \InvalidArgumentException('Unknown op handler: '.$op); + } + + $params = $data !== null ? $data : array(); + call_user_func_array($callable, array($params)); + } + } + + /** + * Outputs a status message + * + * @param string $text + * @param string $level + * + * @return void + */ + private function output($text, $level = null) + { + if ($this->logger !== null) { + $this->logger->log($level !== null ? $level: LogLevel::DEBUG, $text); + } + + if ($this->debug) { + fwrite(STDERR, sprintf('xdebug-handler[%d] %s', getmypid(), $text.PHP_EOL)); + } + } + + /** + * @param string $loaded + * + * @return void + */ + private function reportCheck($loaded) + { + list($version, $mode) = explode('|', $loaded); + + if ($version !== '') { + $this->loaded = '('.$version.')'.($mode !== '' ? ' mode='.$mode : ''); + } + $this->modeOff = $mode === 'off'; + $this->output('Checking '.$this->envAllowXdebug); + } + + /** + * @param string $error + * + * @return void + */ + private function reportError($error) + { + $this->output(sprintf('No restart (%s)', $error), LogLevel::WARNING); + } + + /** + * @param string $info + * + * @return void + */ + private function reportInfo($info) + { + $this->output($info); + } + + /** + * @return void + */ + private function reportNoRestart() + { + $this->output($this->getLoadedMessage()); + + if ($this->loaded !== null) { + $text = sprintf('No restart (%s)', $this->getEnvAllow()); + if (!((bool) getenv($this->envAllowXdebug))) { + $text .= ' Allowed by '.($this->modeOff ? 'mode' : 'application'); + } + $this->output($text); + } + } + + /** + * @return void + */ + private function reportRestart() + { + $this->output($this->getLoadedMessage()); + Process::setEnv(self::ENV_RESTART, (string) microtime(true)); + } + + /** + * @return void + */ + private function reportRestarted() + { + $loaded = $this->getLoadedMessage(); + $text = sprintf('Restarted (%d ms). %s', $this->time, $loaded); + $level = $this->loaded !== null ? LogLevel::WARNING : null; + $this->output($text, $level); + } + + /** + * @param string $command + * + * @return void + */ + private function reportRestarting($command) + { + $text = sprintf('Process restarting (%s)', $this->getEnvAllow()); + $this->output($text); + $text = 'Running '.$command; + $this->output($text); + } + + /** + * Returns the _ALLOW_XDEBUG environment variable as name=value + * + * @return string + */ + private function getEnvAllow() + { + return $this->envAllowXdebug.'='.getenv($this->envAllowXdebug); + } + + /** + * Returns the Xdebug status and version + * + * @return string + */ + private function getLoadedMessage() + { + $loaded = $this->loaded !== null ? sprintf('loaded %s', $this->loaded) : 'not loaded'; + return 'The Xdebug extension is '.$loaded; + } +} diff --git a/vendor/composer/xdebug-handler/src/XdebugHandler.php b/vendor/composer/xdebug-handler/src/XdebugHandler.php new file mode 100644 index 0000000..413a2fa --- /dev/null +++ b/vendor/composer/xdebug-handler/src/XdebugHandler.php @@ -0,0 +1,745 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\XdebugHandler; + +use Composer\Pcre\Preg; +use Psr\Log\LoggerInterface; + +/** + * @author John Stevenson + * + * @phpstan-import-type restartData from PhpConfig + */ +class XdebugHandler +{ + const SUFFIX_ALLOW = '_ALLOW_XDEBUG'; + const SUFFIX_INIS = '_ORIGINAL_INIS'; + const RESTART_ID = 'internal'; + const RESTART_SETTINGS = 'XDEBUG_HANDLER_SETTINGS'; + const DEBUG = 'XDEBUG_HANDLER_DEBUG'; + + /** @var string|null */ + protected $tmpIni; + + /** @var bool */ + private static $inRestart; + + /** @var string */ + private static $name; + + /** @var string|null */ + private static $skipped; + + /** @var bool */ + private static $xdebugActive; + + /** @var string|null */ + private static $xdebugMode; + + /** @var string|null */ + private static $xdebugVersion; + + /** @var bool */ + private $cli; + + /** @var string|null */ + private $debug; + + /** @var string */ + private $envAllowXdebug; + + /** @var string */ + private $envOriginalInis; + + /** @var bool */ + private $persistent; + + /** @var string|null */ + private $script; + + /** @var Status */ + private $statusWriter; + + /** + * Constructor + * + * The $envPrefix is used to create distinct environment variables. It is + * uppercased and prepended to the default base values. For example 'myapp' + * would result in MYAPP_ALLOW_XDEBUG and MYAPP_ORIGINAL_INIS. + * + * @param string $envPrefix Value used in environment variables + * @throws \RuntimeException If the parameter is invalid + */ + public function __construct($envPrefix) + { + if (!is_string($envPrefix) || $envPrefix === '') { + throw new \RuntimeException('Invalid constructor parameter'); + } + + self::$name = strtoupper($envPrefix); + $this->envAllowXdebug = self::$name.self::SUFFIX_ALLOW; + $this->envOriginalInis = self::$name.self::SUFFIX_INIS; + + self::setXdebugDetails(); + self::$inRestart = false; + + if ($this->cli = PHP_SAPI === 'cli') { + $this->debug = (string) getenv(self::DEBUG); + } + + $this->statusWriter = new Status($this->envAllowXdebug, (bool) $this->debug); + } + + /** + * Activates status message output to a PSR3 logger + * + * @param LoggerInterface $logger + * + * @return $this + */ + public function setLogger(LoggerInterface $logger) + { + $this->statusWriter->setLogger($logger); + return $this; + } + + /** + * Sets the main script location if it cannot be called from argv + * + * @param string $script + * + * @return $this + */ + public function setMainScript($script) + { + $this->script = $script; + return $this; + } + + /** + * Persist the settings to keep Xdebug out of sub-processes + * + * @return $this + */ + public function setPersistent() + { + $this->persistent = true; + return $this; + } + + /** + * Checks if Xdebug is loaded and the process needs to be restarted + * + * This behaviour can be disabled by setting the MYAPP_ALLOW_XDEBUG + * environment variable to 1. This variable is used internally so that + * the restarted process is created only once. + * + * @return void + */ + public function check() + { + $this->notify(Status::CHECK, self::$xdebugVersion.'|'.self::$xdebugMode); + $envArgs = explode('|', (string) getenv($this->envAllowXdebug)); + + if (!((bool) $envArgs[0]) && $this->requiresRestart(self::$xdebugActive)) { + // Restart required + $this->notify(Status::RESTART); + + if ($this->prepareRestart()) { + $command = $this->getCommand(); + $this->restart($command); + } + return; + } + + if (self::RESTART_ID === $envArgs[0] && count($envArgs) === 5) { + // Restarted, so unset environment variable and use saved values + $this->notify(Status::RESTARTED); + + Process::setEnv($this->envAllowXdebug); + self::$inRestart = true; + + if (self::$xdebugVersion === null) { + // Skipped version is only set if Xdebug is not loaded + self::$skipped = $envArgs[1]; + } + + $this->tryEnableSignals(); + + // Put restart settings in the environment + $this->setEnvRestartSettings($envArgs); + return; + } + + $this->notify(Status::NORESTART); + $settings = self::getRestartSettings(); + + if ($settings !== null) { + // Called with existing settings, so sync our settings + $this->syncSettings($settings); + } + } + + /** + * Returns an array of php.ini locations with at least one entry + * + * The equivalent of calling php_ini_loaded_file then php_ini_scanned_files. + * The loaded ini location is the first entry and may be empty. + * + * @return string[] + */ + public static function getAllIniFiles() + { + if (self::$name !== null) { + $env = getenv(self::$name.self::SUFFIX_INIS); + + if (false !== $env) { + return explode(PATH_SEPARATOR, $env); + } + } + + $paths = array((string) php_ini_loaded_file()); + $scanned = php_ini_scanned_files(); + + if ($scanned !== false) { + $paths = array_merge($paths, array_map('trim', explode(',', $scanned))); + } + + return $paths; + } + + /** + * Returns an array of restart settings or null + * + * Settings will be available if the current process was restarted, or + * called with the settings from an existing restart. + * + * @return array|null + * @phpstan-return restartData|null + */ + public static function getRestartSettings() + { + $envArgs = explode('|', (string) getenv(self::RESTART_SETTINGS)); + + if (count($envArgs) !== 6 + || (!self::$inRestart && php_ini_loaded_file() !== $envArgs[0])) { + return null; + } + + return array( + 'tmpIni' => $envArgs[0], + 'scannedInis' => (bool) $envArgs[1], + 'scanDir' => '*' === $envArgs[2] ? false : $envArgs[2], + 'phprc' => '*' === $envArgs[3] ? false : $envArgs[3], + 'inis' => explode(PATH_SEPARATOR, $envArgs[4]), + 'skipped' => $envArgs[5], + ); + } + + /** + * Returns the Xdebug version that triggered a successful restart + * + * @return string + */ + public static function getSkippedVersion() + { + return (string) self::$skipped; + } + + /** + * Returns whether Xdebug is loaded and active + * + * true: if Xdebug is loaded and is running in an active mode. + * false: if Xdebug is not loaded, or it is running with xdebug.mode=off. + * + * @return bool + */ + public static function isXdebugActive() + { + self::setXdebugDetails(); + return self::$xdebugActive; + } + + /** + * Allows an extending class to decide if there should be a restart + * + * The default is to restart if Xdebug is loaded and its mode is not "off". + * Do not typehint for 1.x compatibility. + * + * @param bool $default The default behaviour + * + * @return bool Whether the process should restart + */ + protected function requiresRestart($default) + { + return $default; + } + + /** + * Allows an extending class to access the tmpIni + * + * Do not typehint for 1.x compatibility + * + * @param string[] $command + * + * @return void + */ + protected function restart($command) + { + $this->doRestart($command); + } + + /** + * Executes the restarted command then deletes the tmp ini + * + * @param string[] $command + * + * @return void + * @phpstan-return never + */ + private function doRestart(array $command) + { + $this->tryEnableSignals(); + $this->notify(Status::RESTARTING, implode(' ', $command)); + + if (PHP_VERSION_ID >= 70400) { + $cmd = $command; + } else { + $cmd = Process::escapeShellCommand($command); + if (defined('PHP_WINDOWS_VERSION_BUILD')) { + // Outer quotes required on cmd string below PHP 8 + $cmd = '"'.$cmd.'"'; + } + } + + $process = proc_open($cmd, array(), $pipes); + if (is_resource($process)) { + $exitCode = proc_close($process); + } + + if (!isset($exitCode)) { + // Unlikely that php or the default shell cannot be invoked + $this->notify(Status::ERROR, 'Unable to restart process'); + $exitCode = -1; + } else { + $this->notify(Status::INFO, 'Restarted process exited '.$exitCode); + } + + if ($this->debug === '2') { + $this->notify(Status::INFO, 'Temp ini saved: '.$this->tmpIni); + } else { + @unlink((string) $this->tmpIni); + } + + exit($exitCode); + } + + /** + * Returns true if everything was written for the restart + * + * If any of the following fails (however unlikely) we must return false to + * stop potential recursion: + * - tmp ini file creation + * - environment variable creation + * + * @return bool + */ + private function prepareRestart() + { + $error = null; + $iniFiles = self::getAllIniFiles(); + $scannedInis = count($iniFiles) > 1; + $tmpDir = sys_get_temp_dir(); + + if (!$this->cli) { + $error = 'Unsupported SAPI: '.PHP_SAPI; + } elseif (!defined('PHP_BINARY')) { + $error = 'PHP version is too old: '.PHP_VERSION; + } elseif (!$this->checkConfiguration($info)) { + $error = $info; + } elseif (!$this->checkScanDirConfig()) { + $error = 'PHP version does not report scanned inis: '.PHP_VERSION; + } elseif (!$this->checkMainScript()) { + $error = 'Unable to access main script: '.$this->script; + } elseif (!$this->writeTmpIni($iniFiles, $tmpDir, $error)) { + $error = $error !== null ? $error : 'Unable to create temp ini file at: '.$tmpDir; + } elseif (!$this->setEnvironment($scannedInis, $iniFiles)) { + $error = 'Unable to set environment variables'; + } + + if ($error !== null) { + $this->notify(Status::ERROR, $error); + } + + return $error === null; + } + + /** + * Returns true if the tmp ini file was written + * + * @param string[] $iniFiles All ini files used in the current process + * @param string $tmpDir The system temporary directory + * @param null|string $error Set by method if ini file cannot be read + * + * @return bool + */ + private function writeTmpIni(array $iniFiles, $tmpDir, &$error) + { + if (($tmpfile = @tempnam($tmpDir, '')) === false) { + return false; + } + + $this->tmpIni = $tmpfile; + + // $iniFiles has at least one item and it may be empty + if ($iniFiles[0] === '') { + array_shift($iniFiles); + } + + $content = ''; + $sectionRegex = '/^\s*\[(?:PATH|HOST)\s*=/mi'; + $xdebugRegex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi'; + + foreach ($iniFiles as $file) { + // Check for inaccessible ini files + if (($data = @file_get_contents($file)) === false) { + $error = 'Unable to read ini: '.$file; + return false; + } + // Check and remove directives after HOST and PATH sections + if (Preg::isMatchWithOffsets($sectionRegex, $data, $matches, PREG_OFFSET_CAPTURE)) { + $data = substr($data, 0, $matches[0][1]); + } + $content .= Preg::replace($xdebugRegex, ';$1', $data).PHP_EOL; + } + + // Merge loaded settings into our ini content, if it is valid + $config = parse_ini_string($content); + $loaded = ini_get_all(null, false); + + if (false === $config || false === $loaded) { + $error = 'Unable to parse ini data'; + return false; + } + + $content .= $this->mergeLoadedConfig($loaded, $config); + + // Work-around for https://bugs.php.net/bug.php?id=75932 + $content .= 'opcache.enable_cli=0'.PHP_EOL; + + return (bool) @file_put_contents($this->tmpIni, $content); + } + + /** + * Returns the command line arguments for the restart + * + * @return string[] + */ + private function getCommand() + { + $php = array(PHP_BINARY); + $args = array_slice($_SERVER['argv'], 1); + + if (!$this->persistent) { + // Use command-line options + array_push($php, '-n', '-c', $this->tmpIni); + } + + return array_merge($php, array($this->script), $args); + } + + /** + * Returns true if the restart environment variables were set + * + * No need to update $_SERVER since this is set in the restarted process. + * + * @param bool $scannedInis Whether there were scanned ini files + * @param string[] $iniFiles All ini files used in the current process + * + * @return bool + */ + private function setEnvironment($scannedInis, array $iniFiles) + { + $scanDir = getenv('PHP_INI_SCAN_DIR'); + $phprc = getenv('PHPRC'); + + // Make original inis available to restarted process + if (!putenv($this->envOriginalInis.'='.implode(PATH_SEPARATOR, $iniFiles))) { + return false; + } + + if ($this->persistent) { + // Use the environment to persist the settings + if (!putenv('PHP_INI_SCAN_DIR=') || !putenv('PHPRC='.$this->tmpIni)) { + return false; + } + } + + // Flag restarted process and save values for it to use + $envArgs = array( + self::RESTART_ID, + self::$xdebugVersion, + (int) $scannedInis, + false === $scanDir ? '*' : $scanDir, + false === $phprc ? '*' : $phprc, + ); + + return putenv($this->envAllowXdebug.'='.implode('|', $envArgs)); + } + + /** + * Logs status messages + * + * @param string $op Status handler constant + * @param null|string $data Optional data + * + * @return void + */ + private function notify($op, $data = null) + { + $this->statusWriter->report($op, $data); + } + + /** + * Returns default, changed and command-line ini settings + * + * @param mixed[] $loadedConfig All current ini settings + * @param mixed[] $iniConfig Settings from user ini files + * + * @return string + */ + private function mergeLoadedConfig(array $loadedConfig, array $iniConfig) + { + $content = ''; + + foreach ($loadedConfig as $name => $value) { + // Value will either be null, string or array (HHVM only) + if (!is_string($value) + || strpos($name, 'xdebug') === 0 + || $name === 'apc.mmap_file_mask') { + continue; + } + + if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) { + // Double-quote escape each value + $content .= $name.'="'.addcslashes($value, '\\"').'"'.PHP_EOL; + } + } + + return $content; + } + + /** + * Returns true if the script name can be used + * + * @return bool + */ + private function checkMainScript() + { + if (null !== $this->script) { + // Allow an application to set -- for standard input + return file_exists($this->script) || '--' === $this->script; + } + + if (file_exists($this->script = $_SERVER['argv'][0])) { + return true; + } + + // Use a backtrace to resolve Phar and chdir issues. + $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + $main = end($trace); + + if ($main !== false && isset($main['file'])) { + return file_exists($this->script = $main['file']); + } + + return false; + } + + /** + * Adds restart settings to the environment + * + * @param string[] $envArgs + * + * @return void + */ + private function setEnvRestartSettings($envArgs) + { + $settings = array( + php_ini_loaded_file(), + $envArgs[2], + $envArgs[3], + $envArgs[4], + getenv($this->envOriginalInis), + self::$skipped, + ); + + Process::setEnv(self::RESTART_SETTINGS, implode('|', $settings)); + } + + /** + * Syncs settings and the environment if called with existing settings + * + * @param array $settings + * @phpstan-param restartData $settings + * + * @return void + */ + private function syncSettings(array $settings) + { + if (false === getenv($this->envOriginalInis)) { + // Called by another app, so make original inis available + Process::setEnv($this->envOriginalInis, implode(PATH_SEPARATOR, $settings['inis'])); + } + + self::$skipped = $settings['skipped']; + $this->notify(Status::INFO, 'Process called with existing restart settings'); + } + + /** + * Returns true if there are scanned inis and PHP is able to report them + * + * php_ini_scanned_files will fail when PHP_CONFIG_FILE_SCAN_DIR is empty. + * Fixed in 7.1.13 and 7.2.1 + * + * @return bool + */ + private function checkScanDirConfig() + { + if (PHP_VERSION_ID >= 70113 && PHP_VERSION_ID !== 70200) { + return true; + } + + return ((string) getenv('PHP_INI_SCAN_DIR') === '') + || PHP_CONFIG_FILE_SCAN_DIR !== ''; + } + + /** + * Returns true if there are no known configuration issues + * + * @param string $info Set by method + * @return bool + */ + private function checkConfiguration(&$info) + { + if (!function_exists('proc_open')) { + $info = 'proc_open function is disabled'; + return false; + } + + if (extension_loaded('uopz') && !((bool) ini_get('uopz.disable'))) { + // uopz works at opcode level and disables exit calls + if (function_exists('uopz_allow_exit')) { + @uopz_allow_exit(true); + } else { + $info = 'uopz extension is not compatible'; + return false; + } + } + + // Check UNC paths when using cmd.exe + if (defined('PHP_WINDOWS_VERSION_BUILD') && PHP_VERSION_ID < 70400) { + $workingDir = getcwd(); + + if ($workingDir === false) { + $info = 'unable to determine working directory'; + return false; + } + + if (0 === strpos($workingDir, '\\\\')) { + $info = 'cmd.exe does not support UNC paths: '.$workingDir; + return false; + } + } + + return true; + } + + /** + * Enables async signals and control interrupts in the restarted process + * + * Available on Unix PHP 7.1+ with the pcntl extension and Windows PHP 7.4+. + * + * @return void + */ + private function tryEnableSignals() + { + if (function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) { + pcntl_async_signals(true); + $message = 'Async signals enabled'; + + if (!self::$inRestart) { + // Restarting, so ignore SIGINT in parent + pcntl_signal(SIGINT, SIG_IGN); + } elseif (is_int(pcntl_signal_get_handler(SIGINT))) { + // Restarted, no handler set so force default action + pcntl_signal(SIGINT, SIG_DFL); + } + } + + if (!self::$inRestart && function_exists('sapi_windows_set_ctrl_handler')) { + // Restarting, so set a handler to ignore CTRL events in the parent. + // This ensures that CTRL+C events will be available in the child + // process without having to enable them there, which is unreliable. + sapi_windows_set_ctrl_handler(function ($evt) {}); + } + } + + /** + * Sets static properties $xdebugActive, $xdebugVersion and $xdebugMode + * + * @return void + */ + private static function setXdebugDetails() + { + if (self::$xdebugActive !== null) { + return; + } + + self::$xdebugActive = false; + if (!extension_loaded('xdebug')) { + return; + } + + $version = phpversion('xdebug'); + self::$xdebugVersion = $version !== false ? $version : 'unknown'; + + if (version_compare(self::$xdebugVersion, '3.1', '>=')) { + $modes = xdebug_info('mode'); + self::$xdebugMode = count($modes) === 0 ? 'off' : implode(',', $modes); + self::$xdebugActive = self::$xdebugMode !== 'off'; + return; + } + + // See if xdebug.mode is supported in this version + $iniMode = ini_get('xdebug.mode'); + if ($iniMode === false) { + self::$xdebugActive = true; + return; + } + + // Environment value wins but cannot be empty + $envMode = (string) getenv('XDEBUG_MODE'); + if ($envMode !== '') { + self::$xdebugMode = $envMode; + } else { + self::$xdebugMode = $iniMode !== '' ? $iniMode : 'off'; + } + + // An empty comma-separated list is treated as mode 'off' + if (Preg::isMatch('/^,+$/', str_replace(' ', '', self::$xdebugMode))) { + self::$xdebugMode = 'off'; + } + + self::$xdebugActive = self::$xdebugMode !== 'off'; + } +} diff --git a/vendor/doctrine/annotations/LICENSE b/vendor/doctrine/annotations/LICENSE new file mode 100644 index 0000000..5e781fc --- /dev/null +++ b/vendor/doctrine/annotations/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2013 Doctrine Project + +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/vendor/doctrine/annotations/README.md b/vendor/doctrine/annotations/README.md new file mode 100644 index 0000000..6b8c035 --- /dev/null +++ b/vendor/doctrine/annotations/README.md @@ -0,0 +1,24 @@ +⚠️ PHP 8 introduced +[attributes](https://www.php.net/manual/en/language.attributes.overview.php), +which are a native replacement for annotations. As such, this library is +considered feature complete, and should receive exclusively bugfixes and +security fixes. + +# Doctrine Annotations + +[![Build Status](https://github.com/doctrine/annotations/workflows/Continuous%20Integration/badge.svg?label=build)](https://github.com/doctrine/persistence/actions) +[![Dependency Status](https://www.versioneye.com/package/php--doctrine--annotations/badge.png)](https://www.versioneye.com/package/php--doctrine--annotations) +[![Reference Status](https://www.versioneye.com/php/doctrine:annotations/reference_badge.svg)](https://www.versioneye.com/php/doctrine:annotations/references) +[![Total Downloads](https://poser.pugx.org/doctrine/annotations/downloads.png)](https://packagist.org/packages/doctrine/annotations) +[![Latest Stable Version](https://img.shields.io/packagist/v/doctrine/annotations.svg?label=stable)](https://packagist.org/packages/doctrine/annotations) + +Docblock Annotations Parser library (extracted from [Doctrine Common](https://github.com/doctrine/common)). + +## Documentation + +See the [doctrine-project website](https://www.doctrine-project.org/projects/doctrine-annotations/en/latest/index.html). + +## Contributing + +When making a pull request, make sure your changes follow the +[Coding Standard Guidelines](https://www.doctrine-project.org/projects/doctrine-coding-standard/en/current/reference/index.html#introduction). diff --git a/vendor/doctrine/annotations/composer.json b/vendor/doctrine/annotations/composer.json new file mode 100644 index 0000000..e322d82 --- /dev/null +++ b/vendor/doctrine/annotations/composer.json @@ -0,0 +1,72 @@ +{ + "name": "doctrine/annotations", + "description": "Docblock Annotations Parser", + "license": "MIT", + "type": "library", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "require": { + "php": "^7.1 || ^8.0", + "ext-tokenizer": "*", + "doctrine/lexer": "^1 || ^2", + "psr/cache": "^1 || ^2 || ^3" + }, + "require-dev": { + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "vimeo/psalm": "^4.10" + }, + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Performance\\Common\\Annotations\\": "tests/Doctrine/Performance/Common/Annotations", + "Doctrine\\Tests\\Common\\Annotations\\": "tests/Doctrine/Tests/Common/Annotations" + }, + "files": [ + "tests/Doctrine/Tests/Common/Annotations/Fixtures/functions.php", + "tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php" + ] + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + }, + "sort-packages": true + } +} diff --git a/vendor/doctrine/annotations/docs/en/annotations.rst b/vendor/doctrine/annotations/docs/en/annotations.rst new file mode 100644 index 0000000..2c3c428 --- /dev/null +++ b/vendor/doctrine/annotations/docs/en/annotations.rst @@ -0,0 +1,252 @@ +Handling Annotations +==================== + +There are several different approaches to handling annotations in PHP. +Doctrine Annotations maps docblock annotations to PHP classes. Because +not all docblock annotations are used for metadata purposes a filter is +applied to ignore or skip classes that are not Doctrine annotations. + +Take a look at the following code snippet: + +.. code-block:: php + + namespace MyProject\Entities; + + use Doctrine\ORM\Mapping AS ORM; + use Symfony\Component\Validator\Constraints AS Assert; + + /** + * @author Benjamin Eberlei + * @ORM\Entity + * @MyProject\Annotations\Foobarable + */ + class User + { + /** + * @ORM\Id @ORM\Column @ORM\GeneratedValue + * @dummy + * @var int + */ + private $id; + + /** + * @ORM\Column(type="string") + * @Assert\NotEmpty + * @Assert\Email + * @var string + */ + private $email; + } + +In this snippet you can see a variety of different docblock annotations: + +- Documentation annotations such as ``@var`` and ``@author``. These + annotations are ignored and never considered for throwing an + exception due to wrongly used annotations. +- Annotations imported through use statements. The statement ``use + Doctrine\ORM\Mapping AS ORM`` makes all classes under that namespace + available as ``@ORM\ClassName``. Same goes for the import of + ``@Assert``. +- The ``@dummy`` annotation. It is not a documentation annotation and + not ignored. For Doctrine Annotations it is not entirely clear how + to handle this annotation. Depending on the configuration an exception + (unknown annotation) will be thrown when parsing this annotation. +- The fully qualified annotation ``@MyProject\Annotations\Foobarable``. + This is transformed directly into the given class name. + +How are these annotations loaded? From looking at the code you could +guess that the ORM Mapping, Assert Validation and the fully qualified +annotation can just be loaded using +the defined PHP autoloaders. This is not the case however: For error +handling reasons every check for class existence inside the +``AnnotationReader`` sets the second parameter $autoload +of ``class_exists($name, $autoload)`` to false. To work flawlessly the +``AnnotationReader`` requires silent autoloaders which many autoloaders are +not. Silent autoloading is NOT part of the `PSR-0 specification +`_ +for autoloading. + +This is why Doctrine Annotations uses its own autoloading mechanism +through a global registry. If you are wondering about the annotation +registry being global, there is no other way to solve the architectural +problems of autoloading annotation classes in a straightforward fashion. +Additionally if you think about PHP autoloading then you recognize it is +a global as well. + +To anticipate the configuration section, making the above PHP class work +with Doctrine Annotations requires this setup: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\AnnotationRegistry; + + AnnotationRegistry::registerFile("/path/to/doctrine/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php"); + AnnotationRegistry::registerAutoloadNamespace("Symfony\Component\Validator\Constraint", "/path/to/symfony/src"); + AnnotationRegistry::registerAutoloadNamespace("MyProject\Annotations", "/path/to/myproject/src"); + + $reader = new AnnotationReader(); + AnnotationReader::addGlobalIgnoredName('dummy'); + +The second block with the annotation registry calls registers all the +three different annotation namespaces that are used. +Doctrine Annotations saves all its annotations in a single file, that is +why ``AnnotationRegistry#registerFile`` is used in contrast to +``AnnotationRegistry#registerAutoloadNamespace`` which creates a PSR-0 +compatible loading mechanism for class to file names. + +In the third block, we create the actual ``AnnotationReader`` instance. +Note that we also add ``dummy`` to the global list of ignored +annotations for which we do not throw exceptions. Setting this is +necessary in our example case, otherwise ``@dummy`` would trigger an +exception to be thrown during the parsing of the docblock of +``MyProject\Entities\User#id``. + +Setup and Configuration +----------------------- + +To use the annotations library is simple, you just need to create a new +``AnnotationReader`` instance: + +.. code-block:: php + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + +This creates a simple annotation reader with no caching other than in +memory (in php arrays). Since parsing docblocks can be expensive you +should cache this process by using a caching reader. + +To cache annotations, you can create a ``Doctrine\Common\Annotations\PsrCachedReader``. +This reader decorates the original reader and stores all annotations in a PSR-6 +cache: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\PsrCachedReader; + + $cache = ... // instantiate a PSR-6 Cache pool + + $reader = new PsrCachedReader( + new AnnotationReader(), + $cache, + $debug = true + ); + +The ``debug`` flag is used here as well to invalidate the cache files +when the PHP class with annotations changed and should be used during +development. + +.. warning :: + + The ``AnnotationReader`` works and caches under the + assumption that all annotations of a doc-block are processed at + once. That means that annotation classes that do not exist and + aren't loaded and cannot be autoloaded (using the + AnnotationRegistry) would never be visible and not accessible if a + cache is used unless the cache is cleared and the annotations + requested again, this time with all annotations defined. + +By default the annotation reader returns a list of annotations with +numeric indexes. If you want your annotations to be indexed by their +class name you can wrap the reader in an ``IndexedReader``: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\IndexedReader; + + $reader = new IndexedReader(new AnnotationReader()); + +.. warning:: + + You should never wrap the indexed reader inside a cached reader, + only the other way around. This way you can re-use the cache with + indexed or numeric keys, otherwise your code may experience failures + due to caching in a numerical or indexed format. + +Registering Annotations +~~~~~~~~~~~~~~~~~~~~~~~ + +As explained in the introduction, Doctrine Annotations uses its own +autoloading mechanism to determine if a given annotation has a +corresponding PHP class that can be autoloaded. For annotation +autoloading you have to configure the +``Doctrine\Common\Annotations\AnnotationRegistry``. There are three +different mechanisms to configure annotation autoloading: + +- Calling ``AnnotationRegistry#registerFile($file)`` to register a file + that contains one or more annotation classes. +- Calling ``AnnotationRegistry#registerNamespace($namespace, $dirs = + null)`` to register that the given namespace contains annotations and + that their base directory is located at the given $dirs or in the + include path if ``NULL`` is passed. The given directories should *NOT* + be the directory where classes of the namespace are in, but the base + directory of the root namespace. The AnnotationRegistry uses a + namespace to directory separator approach to resolve the correct path. +- Calling ``AnnotationRegistry#registerLoader($callable)`` to register + an autoloader callback. The callback accepts the class as first and + only parameter and has to return ``true`` if the corresponding file + was found and included. + +.. note:: + + Loaders have to fail silently, if a class is not found even if it + matches for example the namespace prefix of that loader. Never is a + loader to throw a warning or exception if the loading failed + otherwise parsing doc block annotations will become a huge pain. + +A sample loader callback could look like: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationRegistry; + use Symfony\Component\ClassLoader\UniversalClassLoader; + + AnnotationRegistry::registerLoader(function($class) { + $file = str_replace("\\", DIRECTORY_SEPARATOR, $class) . ".php"; + + if (file_exists("/my/base/path/" . $file)) { + // file_exists() makes sure that the loader fails silently + require "/my/base/path/" . $file; + } + }); + + $loader = new UniversalClassLoader(); + AnnotationRegistry::registerLoader(array($loader, "loadClass")); + + +Ignoring missing exceptions +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default an exception is thrown from the ``AnnotationReader`` if an +annotation was found that: + +- is not part of the list of ignored "documentation annotations"; +- was not imported through a use statement; +- is not a fully qualified class that exists. + +You can disable this behavior for specific names if your docblocks do +not follow strict requirements: + +.. code-block:: php + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + AnnotationReader::addGlobalIgnoredName('foo'); + +PHP Imports +~~~~~~~~~~~ + +By default the annotation reader parses the use-statement of a php file +to gain access to the import rules and register them for the annotation +processing. Only if you are using PHP Imports can you validate the +correct usage of annotations and throw exceptions if you misspelled an +annotation. This mechanism is enabled by default. + +To ease the upgrade path, we still allow you to disable this mechanism. +Note however that we will remove this in future versions: + +.. code-block:: php + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + $reader->setEnabledPhpImports(false); diff --git a/vendor/doctrine/annotations/docs/en/custom.rst b/vendor/doctrine/annotations/docs/en/custom.rst new file mode 100644 index 0000000..e8f79af --- /dev/null +++ b/vendor/doctrine/annotations/docs/en/custom.rst @@ -0,0 +1,443 @@ +Custom Annotation Classes +========================= + +If you want to define your own annotations, you just have to group them +in a namespace and register this namespace in the ``AnnotationRegistry``. +Annotation classes have to contain a class-level docblock with the text +``@Annotation``: + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** @Annotation */ + class Bar + { + // some code + } + +Inject annotation values +------------------------ + +The annotation parser checks if the annotation constructor has arguments, +if so then it will pass the value array, otherwise it will try to inject +values into public properties directly: + + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * + * Some Annotation using a constructor + */ + class Bar + { + private $foo; + + public function __construct(array $values) + { + $this->foo = $values['foo']; + } + } + + /** + * @Annotation + * + * Some Annotation without a constructor + */ + class Foo + { + public $bar; + } + +Optional: Constructors with Named Parameters +-------------------------------------------- + +Starting with Annotations v1.11 a new annotation instantiation strategy +is available that aims at compatibility of Annotation classes with the PHP 8 +attribute feature. You need to declare a constructor with regular parameter +names that match the named arguments in the annotation syntax. + +To enable this feature, you can tag your annotation class with +``@NamedArgumentConstructor`` (available from v1.12) or implement the +``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation`` interface +(available from v1.11 and deprecated as of v1.12). +When using the ``@NamedArgumentConstructor`` tag, the first argument of the +constructor is considered as the default one. + + +Usage with the ``@NamedArgumentConstructor`` tag + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * @NamedArgumentConstructor + */ + class Bar implements NamedArgumentConstructorAnnotation + { + private $foo; + + public function __construct(string $foo) + { + $this->foo = $foo; + } + } + + /** Usable with @Bar(foo="baz") */ + /** Usable with @Bar("baz") */ + +In combination with PHP 8's constructor property promotion feature +you can simplify this to: + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * @NamedArgumentConstructor + */ + class Bar implements NamedArgumentConstructorAnnotation + { + public function __construct(private string $foo) {} + } + + +Usage with the +``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation`` +interface (v1.11, deprecated as of v1.12): +.. code-block:: php + + namespace MyCompany\Annotations; + + use Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation; + + /** @Annotation */ + class Bar implements NamedArgumentConstructorAnnotation + { + private $foo; + + public function __construct(private string $foo) {} + } + + /** Usable with @Bar(foo="baz") */ + +Annotation Target +----------------- + +``@Target`` indicates the kinds of class elements to which an annotation +type is applicable. Then you could define one or more targets: + +- ``CLASS`` Allowed in class docblocks +- ``PROPERTY`` Allowed in property docblocks +- ``METHOD`` Allowed in the method docblocks +- ``FUNCTION`` Allowed in function dockblocks +- ``ALL`` Allowed in class, property, method and function docblocks +- ``ANNOTATION`` Allowed inside other annotations + +If the annotations is not allowed in the current context, an +``AnnotationException`` is thrown. + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * @Target({"METHOD","PROPERTY"}) + */ + class Bar + { + // some code + } + + /** + * @Annotation + * @Target("CLASS") + */ + class Foo + { + // some code + } + +Attribute types +--------------- + +The annotation parser checks the given parameters using the phpdoc +annotation ``@var``, The data type could be validated using the ``@var`` +annotation on the annotation properties or using the ``@Attributes`` and +``@Attribute`` annotations. + +If the data type does not match you get an ``AnnotationException`` + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * @Target({"METHOD","PROPERTY"}) + */ + class Bar + { + /** @var mixed */ + public $mixed; + + /** @var boolean */ + public $boolean; + + /** @var bool */ + public $bool; + + /** @var float */ + public $float; + + /** @var string */ + public $string; + + /** @var integer */ + public $integer; + + /** @var array */ + public $array; + + /** @var SomeAnnotationClass */ + public $annotation; + + /** @var array */ + public $arrayOfIntegers; + + /** @var array */ + public $arrayOfAnnotations; + } + + /** + * @Annotation + * @Target({"METHOD","PROPERTY"}) + * @Attributes({ + * @Attribute("stringProperty", type = "string"), + * @Attribute("annotProperty", type = "SomeAnnotationClass"), + * }) + */ + class Foo + { + public function __construct(array $values) + { + $this->stringProperty = $values['stringProperty']; + $this->annotProperty = $values['annotProperty']; + } + + // some code + } + +Annotation Required +------------------- + +``@Required`` indicates that the field must be specified when the +annotation is used. If it is not used you get an ``AnnotationException`` +stating that this value can not be null. + +Declaring a required field: + +.. code-block:: php + + /** + * @Annotation + * @Target("ALL") + */ + class Foo + { + /** @Required */ + public $requiredField; + } + +Usage: + +.. code-block:: php + + /** @Foo(requiredField="value") */ + public $direction; // Valid + + /** @Foo */ + public $direction; // Required field missing, throws an AnnotationException + + +Enumerated values +----------------- + +- An annotation property marked with ``@Enum`` is a field that accepts a + fixed set of scalar values. +- You should use ``@Enum`` fields any time you need to represent fixed + values. +- The annotation parser checks the given value and throws an + ``AnnotationException`` if the value does not match. + + +Declaring an enumerated property: + +.. code-block:: php + + /** + * @Annotation + * @Target("ALL") + */ + class Direction + { + /** + * @Enum({"NORTH", "SOUTH", "EAST", "WEST"}) + */ + public $value; + } + +Annotation usage: + +.. code-block:: php + + /** @Direction("NORTH") */ + public $direction; // Valid value + + /** @Direction("NORTHEAST") */ + public $direction; // Invalid value, throws an AnnotationException + + +Constants +--------- + +The use of constants and class constants is available on the annotations +parser. + +The following usages are allowed: + +.. code-block:: php + + namespace MyCompany\Entity; + + use MyCompany\Annotations\Foo; + use MyCompany\Annotations\Bar; + use MyCompany\Entity\SomeClass; + + /** + * @Foo(PHP_EOL) + * @Bar(Bar::FOO) + * @Foo({SomeClass::FOO, SomeClass::BAR}) + * @Bar({SomeClass::FOO_KEY = SomeClass::BAR_VALUE}) + */ + class User + { + } + + +Be careful with constants and the cache ! + +.. note:: + + The cached reader will not re-evaluate each time an annotation is + loaded from cache. When a constant is changed the cache must be + cleaned. + + +Usage +----- + +Using the library API is simple. Using the annotations described in the +previous section, you can now annotate other classes with your +annotations: + +.. code-block:: php + + namespace MyCompany\Entity; + + use MyCompany\Annotations\Foo; + use MyCompany\Annotations\Bar; + + /** + * @Foo(bar="foo") + * @Bar(foo="bar") + */ + class User + { + } + +Now we can write a script to get the annotations above: + +.. code-block:: php + + $reflClass = new ReflectionClass('MyCompany\Entity\User'); + $classAnnotations = $reader->getClassAnnotations($reflClass); + + foreach ($classAnnotations AS $annot) { + if ($annot instanceof \MyCompany\Annotations\Foo) { + echo $annot->bar; // prints "foo"; + } else if ($annot instanceof \MyCompany\Annotations\Bar) { + echo $annot->foo; // prints "bar"; + } + } + +You have a complete API for retrieving annotation class instances from a +class, property or method docblock: + + +Reader API +~~~~~~~~~~ + +Access all annotations of a class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getClassAnnotations(\ReflectionClass $class); + +Access one annotation of a class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getClassAnnotation(\ReflectionClass $class, $annotationName); + +Access all annotations of a method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getMethodAnnotations(\ReflectionMethod $method); + +Access one annotation of a method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getMethodAnnotation(\ReflectionMethod $method, $annotationName); + +Access all annotations of a property +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getPropertyAnnotations(\ReflectionProperty $property); + +Access one annotation of a property +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName); + +Access all annotations of a function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getFunctionAnnotations(\ReflectionFunction $property); + +Access one annotation of a function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getFunctionAnnotation(\ReflectionFunction $property, $annotationName); diff --git a/vendor/doctrine/annotations/docs/en/index.rst b/vendor/doctrine/annotations/docs/en/index.rst new file mode 100644 index 0000000..7caffb5 --- /dev/null +++ b/vendor/doctrine/annotations/docs/en/index.rst @@ -0,0 +1,110 @@ +Deprecation notice +================== + +PHP 8 introduced `attributes +`_, +which are a native replacement for annotations. As such, this library is +considered feature complete, and should receive exclusively bugfixes and +security fixes. + +Introduction +============ + +Doctrine Annotations allows to implement custom annotation +functionality for PHP classes and functions. + +.. code-block:: php + + class Foo + { + /** + * @MyAnnotation(myProperty="value") + */ + private $bar; + } + +Annotations aren't implemented in PHP itself which is why this component +offers a way to use the PHP doc-blocks as a place for the well known +annotation syntax using the ``@`` char. + +Annotations in Doctrine are used for the ORM configuration to build the +class mapping, but it can be used in other projects for other purposes +too. + +Installation +============ + +You can install the Annotation component with composer: + +.. code-block:: + +   $ composer require doctrine/annotations + +Create an annotation class +========================== + +An annotation class is a representation of the later used annotation +configuration in classes. The annotation class of the previous example +looks like this: + +.. code-block:: php + + /** + * @Annotation + */ + final class MyAnnotation + { + public $myProperty; + } + +The annotation class is declared as an annotation by ``@Annotation``. + +:ref:`Read more about custom annotations. ` + +Reading annotations +=================== + +The access to the annotations happens by reflection of the class or function +containing them. There are multiple reader-classes implementing the +``Doctrine\Common\Annotations\Reader`` interface, that can access the +annotations of a class. A common one is +``Doctrine\Common\Annotations\AnnotationReader``: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\AnnotationRegistry; + + // Deprecated and will be removed in 2.0 but currently needed + AnnotationRegistry::registerLoader('class_exists'); + + $reflectionClass = new ReflectionClass(Foo::class); + $property = $reflectionClass->getProperty('bar'); + + $reader = new AnnotationReader(); + $myAnnotation = $reader->getPropertyAnnotation( + $property, + MyAnnotation::class + ); + + echo $myAnnotation->myProperty; // result: "value" + +Note that ``AnnotationRegistry::registerLoader('class_exists')`` only works +if you already have an autoloader configured (i.e. composer autoloader). +Otherwise, :ref:`please take a look to the other annotation autoload mechanisms `. + +A reader has multiple methods to access the annotations of a class or +function. + +:ref:`Read more about handling annotations. ` + +IDE Support +----------- + +Some IDEs already provide support for annotations: + +- Eclipse via the `Symfony2 Plugin `_ +- PhpStorm via the `PHP Annotations Plugin `_ or the `Symfony Plugin `_ + +.. _Read more about handling annotations.: annotations +.. _Read more about custom annotations.: custom diff --git a/vendor/doctrine/annotations/docs/en/sidebar.rst b/vendor/doctrine/annotations/docs/en/sidebar.rst new file mode 100644 index 0000000..6f5d13c --- /dev/null +++ b/vendor/doctrine/annotations/docs/en/sidebar.rst @@ -0,0 +1,6 @@ +.. toctree:: + :depth: 3 + + index + annotations + custom diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php new file mode 100644 index 0000000..9cae3da --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php @@ -0,0 +1,57 @@ + $data Key-value for properties to be defined in this class. */ + final public function __construct(array $data) + { + foreach ($data as $key => $value) { + $this->$key = $value; + } + } + + /** + * Error handler for unknown property accessor in Annotation class. + * + * @param string $name Unknown property name. + * + * @throws BadMethodCallException + */ + public function __get($name) + { + throw new BadMethodCallException( + sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class) + ); + } + + /** + * Error handler for unknown property mutator in Annotation class. + * + * @param string $name Unknown property name. + * @param mixed $value Property value. + * + * @throws BadMethodCallException + */ + public function __set($name, $value) + { + throw new BadMethodCallException( + sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class) + ); + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php new file mode 100644 index 0000000..b1f8514 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php @@ -0,0 +1,21 @@ + */ + public $value; +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php new file mode 100644 index 0000000..6f24d9f --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php @@ -0,0 +1,69 @@ + */ + public $value; + + /** + * Literal target declaration. + * + * @var mixed[] + */ + public $literal; + + /** + * @phpstan-param array{literal?: mixed[], value: list} $values + * + * @throws InvalidArgumentException + */ + public function __construct(array $values) + { + if (! isset($values['literal'])) { + $values['literal'] = []; + } + + foreach ($values['value'] as $var) { + if (! is_scalar($var)) { + throw new InvalidArgumentException(sprintf( + '@Enum supports only scalar values "%s" given.', + is_object($var) ? get_class($var) : gettype($var) + )); + } + } + + foreach ($values['literal'] as $key => $var) { + if (! in_array($key, $values['value'])) { + throw new InvalidArgumentException(sprintf( + 'Undefined enumerator value "%s" for literal "%s".', + $key, + $var + )); + } + } + + $this->value = $values['value']; + $this->literal = $values['literal']; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php new file mode 100644 index 0000000..97a15c2 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php @@ -0,0 +1,43 @@ + */ + public $names; + + /** + * @phpstan-param array{value: string|list} $values + * + * @throws RuntimeException + */ + public function __construct(array $values) + { + if (is_string($values['value'])) { + $values['value'] = [$values['value']]; + } + + if (! is_array($values['value'])) { + throw new RuntimeException(sprintf( + '@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', + json_encode($values['value']) + )); + } + + $this->names = $values['value']; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php new file mode 100644 index 0000000..1690601 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php @@ -0,0 +1,13 @@ + */ + private static $map = [ + 'ALL' => self::TARGET_ALL, + 'CLASS' => self::TARGET_CLASS, + 'METHOD' => self::TARGET_METHOD, + 'PROPERTY' => self::TARGET_PROPERTY, + 'FUNCTION' => self::TARGET_FUNCTION, + 'ANNOTATION' => self::TARGET_ANNOTATION, + ]; + + /** @phpstan-var list */ + public $value; + + /** + * Targets as bitmask. + * + * @var int + */ + public $targets; + + /** + * Literal target declaration. + * + * @var string + */ + public $literal; + + /** + * @phpstan-param array{value?: string|list} $values + * + * @throws InvalidArgumentException + */ + public function __construct(array $values) + { + if (! isset($values['value'])) { + $values['value'] = null; + } + + if (is_string($values['value'])) { + $values['value'] = [$values['value']]; + } + + if (! is_array($values['value'])) { + throw new InvalidArgumentException( + sprintf( + '@Target expects either a string value, or an array of strings, "%s" given.', + is_object($values['value']) ? get_class($values['value']) : gettype($values['value']) + ) + ); + } + + $bitmask = 0; + foreach ($values['value'] as $literal) { + if (! isset(self::$map[$literal])) { + throw new InvalidArgumentException( + sprintf( + 'Invalid Target "%s". Available targets: [%s]', + $literal, + implode(', ', array_keys(self::$map)) + ) + ); + } + + $bitmask |= self::$map[$literal]; + } + + $this->targets = $bitmask; + $this->value = $values['value']; + $this->literal = implode(', ', $this->value); + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php new file mode 100644 index 0000000..dcdfe4d --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php @@ -0,0 +1,167 @@ + $available + * + * @return AnnotationException + */ + public static function enumeratorError($attributeName, $annotationName, $context, $available, $given) + { + return new self(sprintf( + '[Enum Error] Attribute "%s" of @%s declared on %s accepts only [%s], but got %s.', + $attributeName, + $annotationName, + $context, + implode(', ', $available), + is_object($given) ? get_class($given) : $given + )); + } + + /** @return AnnotationException */ + public static function optimizerPlusSaveComments() + { + return new self( + 'You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1.' + ); + } + + /** @return AnnotationException */ + public static function optimizerPlusLoadComments() + { + return new self( + 'You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1.' + ); + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php new file mode 100644 index 0000000..1f538ee --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php @@ -0,0 +1,389 @@ + + */ + private static $globalImports = [ + 'ignoreannotation' => Annotation\IgnoreAnnotation::class, + ]; + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names are case sensitive. + * + * @var array + */ + private static $globalIgnoredNames = ImplicitlyIgnoredAnnotationNames::LIST; + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names are case sensitive. + * + * @var array + */ + private static $globalIgnoredNamespaces = []; + + /** + * Add a new annotation to the globally ignored annotation names with regard to exception handling. + * + * @param string $name + */ + public static function addGlobalIgnoredName($name) + { + self::$globalIgnoredNames[$name] = true; + } + + /** + * Add a new annotation to the globally ignored annotation namespaces with regard to exception handling. + * + * @param string $namespace + */ + public static function addGlobalIgnoredNamespace($namespace) + { + self::$globalIgnoredNamespaces[$namespace] = true; + } + + /** + * Annotations parser. + * + * @var DocParser + */ + private $parser; + + /** + * Annotations parser used to collect parsing metadata. + * + * @var DocParser + */ + private $preParser; + + /** + * PHP parser used to collect imports. + * + * @var PhpParser + */ + private $phpParser; + + /** + * In-memory cache mechanism to store imported annotations per class. + * + * @psalm-var array<'class'|'function', array>> + */ + private $imports = []; + + /** + * In-memory cache mechanism to store ignored annotations per class. + * + * @psalm-var array<'class'|'function', array>> + */ + private $ignoredAnnotationNames = []; + + /** + * Initializes a new AnnotationReader. + * + * @throws AnnotationException + */ + public function __construct(?DocParser $parser = null) + { + if ( + extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.save_comments') === '0' || + ini_get('opcache.save_comments') === '0') + ) { + throw AnnotationException::optimizerPlusSaveComments(); + } + + if (extension_loaded('Zend OPcache') && ini_get('opcache.save_comments') === 0) { + throw AnnotationException::optimizerPlusSaveComments(); + } + + // Make sure that the IgnoreAnnotation annotation is loaded + class_exists(IgnoreAnnotation::class); + + $this->parser = $parser ?: new DocParser(); + + $this->preParser = new DocParser(); + + $this->preParser->setImports(self::$globalImports); + $this->preParser->setIgnoreNotImportedAnnotations(true); + $this->preParser->setIgnoredAnnotationNames(self::$globalIgnoredNames); + + $this->phpParser = new PhpParser(); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + $this->parser->setTarget(Target::TARGET_CLASS); + $this->parser->setImports($this->getImports($class)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName()); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + $annotations = $this->getClassAnnotations($class); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $context = 'property ' . $class->getName() . '::$' . $property->getName(); + + $this->parser->setTarget(Target::TARGET_PROPERTY); + $this->parser->setImports($this->getPropertyImports($property)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($property->getDocComment(), $context); + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + $annotations = $this->getPropertyAnnotations($property); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $context = 'method ' . $class->getName() . '::' . $method->getName() . '()'; + + $this->parser->setTarget(Target::TARGET_METHOD); + $this->parser->setImports($this->getMethodImports($method)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($method->getDocComment(), $context); + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + $annotations = $this->getMethodAnnotations($method); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Gets the annotations applied to a function. + * + * @phpstan-return list An array of Annotations. + */ + public function getFunctionAnnotations(ReflectionFunction $function): array + { + $context = 'function ' . $function->getName(); + + $this->parser->setTarget(Target::TARGET_FUNCTION); + $this->parser->setImports($this->getImports($function)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($function)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($function->getDocComment(), $context); + } + + /** + * Gets a function annotation. + * + * @return object|null The Annotation or NULL, if the requested annotation does not exist. + */ + public function getFunctionAnnotation(ReflectionFunction $function, string $annotationName) + { + $annotations = $this->getFunctionAnnotations($function); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Returns the ignored annotations for the given class or function. + * + * @param ReflectionClass|ReflectionFunction $reflection + * + * @return array + */ + private function getIgnoredAnnotationNames($reflection): array + { + $type = $reflection instanceof ReflectionClass ? 'class' : 'function'; + $name = $reflection->getName(); + + if (isset($this->ignoredAnnotationNames[$type][$name])) { + return $this->ignoredAnnotationNames[$type][$name]; + } + + $this->collectParsingMetadata($reflection); + + return $this->ignoredAnnotationNames[$type][$name]; + } + + /** + * Retrieves imports for a class or a function. + * + * @param ReflectionClass|ReflectionFunction $reflection + * + * @return array + */ + private function getImports($reflection): array + { + $type = $reflection instanceof ReflectionClass ? 'class' : 'function'; + $name = $reflection->getName(); + + if (isset($this->imports[$type][$name])) { + return $this->imports[$type][$name]; + } + + $this->collectParsingMetadata($reflection); + + return $this->imports[$type][$name]; + } + + /** + * Retrieves imports for methods. + * + * @return array + */ + private function getMethodImports(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $classImports = $this->getImports($class); + + $traitImports = []; + + foreach ($class->getTraits() as $trait) { + if ( + ! $trait->hasMethod($method->getName()) + || $trait->getFileName() !== $method->getFileName() + ) { + continue; + } + + $traitImports = array_merge($traitImports, $this->phpParser->parseUseStatements($trait)); + } + + return array_merge($classImports, $traitImports); + } + + /** + * Retrieves imports for properties. + * + * @return array + */ + private function getPropertyImports(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $classImports = $this->getImports($class); + + $traitImports = []; + + foreach ($class->getTraits() as $trait) { + if (! $trait->hasProperty($property->getName())) { + continue; + } + + $traitImports = array_merge($traitImports, $this->phpParser->parseUseStatements($trait)); + } + + return array_merge($classImports, $traitImports); + } + + /** + * Collects parsing metadata for a given class or function. + * + * @param ReflectionClass|ReflectionFunction $reflection + */ + private function collectParsingMetadata($reflection): void + { + $type = $reflection instanceof ReflectionClass ? 'class' : 'function'; + $name = $reflection->getName(); + + $ignoredAnnotationNames = self::$globalIgnoredNames; + $annotations = $this->preParser->parse($reflection->getDocComment(), $type . ' ' . $name); + + foreach ($annotations as $annotation) { + if (! ($annotation instanceof IgnoreAnnotation)) { + continue; + } + + foreach ($annotation->names as $annot) { + $ignoredAnnotationNames[$annot] = true; + } + } + + $this->imports[$type][$name] = array_merge( + self::$globalImports, + $this->phpParser->parseUseStatements($reflection), + [ + '__NAMESPACE__' => $reflection->getNamespaceName(), + 'self' => $name, + ] + ); + + $this->ignoredAnnotationNames[$type][$name] = $ignoredAnnotationNames; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php new file mode 100644 index 0000000..259d497 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php @@ -0,0 +1,190 @@ +|null $dirs + */ + public static function registerAutoloadNamespace(string $namespace, $dirs = null): void + { + self::$autoloadNamespaces[$namespace] = $dirs; + } + + /** + * Registers multiple namespaces. + * + * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. + * + * @deprecated This method is deprecated and will be removed in + * doctrine/annotations 2.0. Annotations will be autoloaded in 2.0. + * + * @param string[][]|string[]|null[] $namespaces indexed by namespace name + */ + public static function registerAutoloadNamespaces(array $namespaces): void + { + self::$autoloadNamespaces = array_merge(self::$autoloadNamespaces, $namespaces); + } + + /** + * Registers an autoloading callable for annotations, much like spl_autoload_register(). + * + * NOTE: These class loaders HAVE to be silent when a class was not found! + * IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class. + * + * @deprecated This method is deprecated and will be removed in + * doctrine/annotations 2.0. Annotations will be autoloaded in 2.0. + */ + public static function registerLoader(callable $callable): void + { + // Reset our static cache now that we have a new loader to work with + self::$failedToAutoload = []; + self::$loaders[] = $callable; + } + + /** + * Registers an autoloading callable for annotations, if it is not already registered + * + * @deprecated This method is deprecated and will be removed in + * doctrine/annotations 2.0. Annotations will be autoloaded in 2.0. + */ + public static function registerUniqueLoader(callable $callable): void + { + if (in_array($callable, self::$loaders, true)) { + return; + } + + self::registerLoader($callable); + } + + /** + * Autoloads an annotation class silently. + */ + public static function loadAnnotationClass(string $class): bool + { + if (class_exists($class, false)) { + return true; + } + + if (array_key_exists($class, self::$failedToAutoload)) { + return false; + } + + foreach (self::$autoloadNamespaces as $namespace => $dirs) { + if (strpos($class, $namespace) !== 0) { + continue; + } + + $file = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; + + if ($dirs === null) { + $path = stream_resolve_include_path($file); + if ($path) { + require $path; + + return true; + } + } else { + foreach ((array) $dirs as $dir) { + if (is_file($dir . DIRECTORY_SEPARATOR . $file)) { + require $dir . DIRECTORY_SEPARATOR . $file; + + return true; + } + } + } + } + + foreach (self::$loaders as $loader) { + if ($loader($class) === true) { + return true; + } + } + + if ( + self::$loaders === [] && + self::$autoloadNamespaces === [] && + self::$registerFileUsed === false && + class_exists($class) + ) { + return true; + } + + self::$failedToAutoload[$class] = null; + + return false; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php new file mode 100644 index 0000000..85dbefa --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php @@ -0,0 +1,266 @@ +> */ + private $loadedAnnotations = []; + + /** @var int[] */ + private $loadedFilemtimes = []; + + /** @param bool $debug */ + public function __construct(Reader $reader, Cache $cache, $debug = false) + { + $this->delegate = $reader; + $this->cache = $cache; + $this->debug = (bool) $debug; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + $cacheKey = $class->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + $annots = $this->fetchFromCache($cacheKey, $class); + if ($annots === false) { + $annots = $this->delegate->getClassAnnotations($class); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + foreach ($this->getClassAnnotations($class) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $cacheKey = $class->getName() . '$' . $property->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + $annots = $this->fetchFromCache($cacheKey, $class); + if ($annots === false) { + $annots = $this->delegate->getPropertyAnnotations($property); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + foreach ($this->getPropertyAnnotations($property) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $cacheKey = $class->getName() . '#' . $method->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + $annots = $this->fetchFromCache($cacheKey, $class); + if ($annots === false) { + $annots = $this->delegate->getMethodAnnotations($method); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + foreach ($this->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * Clears loaded annotations. + * + * @return void + */ + public function clearLoadedAnnotations() + { + $this->loadedAnnotations = []; + $this->loadedFilemtimes = []; + } + + /** + * Fetches a value from the cache. + * + * @param string $cacheKey The cache key. + * + * @return mixed The cached value or false when the value is not in cache. + */ + private function fetchFromCache($cacheKey, ReflectionClass $class) + { + $data = $this->cache->fetch($cacheKey); + if ($data !== false) { + if (! $this->debug || $this->isCacheFresh($cacheKey, $class)) { + return $data; + } + } + + return false; + } + + /** + * Saves a value to the cache. + * + * @param string $cacheKey The cache key. + * @param mixed $value The value. + * + * @return void + */ + private function saveToCache($cacheKey, $value) + { + $this->cache->save($cacheKey, $value); + if (! $this->debug) { + return; + } + + $this->cache->save('[C]' . $cacheKey, time()); + } + + /** + * Checks if the cache is fresh. + * + * @param string $cacheKey + * + * @return bool + */ + private function isCacheFresh($cacheKey, ReflectionClass $class) + { + $lastModification = $this->getLastModification($class); + if ($lastModification === 0) { + return true; + } + + return $this->cache->fetch('[C]' . $cacheKey) >= $lastModification; + } + + /** + * Returns the time the class was last modified, testing traits and parents + */ + private function getLastModification(ReflectionClass $class): int + { + $filename = $class->getFileName(); + + if (isset($this->loadedFilemtimes[$filename])) { + return $this->loadedFilemtimes[$filename]; + } + + $parent = $class->getParentClass(); + + $lastModification = max(array_merge( + [$filename ? filemtime($filename) : 0], + array_map(function (ReflectionClass $reflectionTrait): int { + return $this->getTraitLastModificationTime($reflectionTrait); + }, $class->getTraits()), + array_map(function (ReflectionClass $class): int { + return $this->getLastModification($class); + }, $class->getInterfaces()), + $parent ? [$this->getLastModification($parent)] : [] + )); + + assert($lastModification !== false); + + return $this->loadedFilemtimes[$filename] = $lastModification; + } + + private function getTraitLastModificationTime(ReflectionClass $reflectionTrait): int + { + $fileName = $reflectionTrait->getFileName(); + + if (isset($this->loadedFilemtimes[$fileName])) { + return $this->loadedFilemtimes[$fileName]; + } + + $lastModificationTime = max(array_merge( + [$fileName ? filemtime($fileName) : 0], + array_map(function (ReflectionClass $reflectionTrait): int { + return $this->getTraitLastModificationTime($reflectionTrait); + }, $reflectionTrait->getTraits()) + )); + + assert($lastModificationTime !== false); + + return $this->loadedFilemtimes[$fileName] = $lastModificationTime; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php new file mode 100644 index 0000000..dbba525 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php @@ -0,0 +1,143 @@ + + */ +final class DocLexer extends AbstractLexer +{ + public const T_NONE = 1; + public const T_INTEGER = 2; + public const T_STRING = 3; + public const T_FLOAT = 4; + + // All tokens that are also identifiers should be >= 100 + public const T_IDENTIFIER = 100; + public const T_AT = 101; + public const T_CLOSE_CURLY_BRACES = 102; + public const T_CLOSE_PARENTHESIS = 103; + public const T_COMMA = 104; + public const T_EQUALS = 105; + public const T_FALSE = 106; + public const T_NAMESPACE_SEPARATOR = 107; + public const T_OPEN_CURLY_BRACES = 108; + public const T_OPEN_PARENTHESIS = 109; + public const T_TRUE = 110; + public const T_NULL = 111; + public const T_COLON = 112; + public const T_MINUS = 113; + + /** @var array */ + protected $noCase = [ + '@' => self::T_AT, + ',' => self::T_COMMA, + '(' => self::T_OPEN_PARENTHESIS, + ')' => self::T_CLOSE_PARENTHESIS, + '{' => self::T_OPEN_CURLY_BRACES, + '}' => self::T_CLOSE_CURLY_BRACES, + '=' => self::T_EQUALS, + ':' => self::T_COLON, + '-' => self::T_MINUS, + '\\' => self::T_NAMESPACE_SEPARATOR, + ]; + + /** @var array */ + protected $withCase = [ + 'true' => self::T_TRUE, + 'false' => self::T_FALSE, + 'null' => self::T_NULL, + ]; + + /** + * Whether the next token starts immediately, or if there were + * non-captured symbols before that + */ + public function nextTokenIsAdjacent(): bool + { + return $this->token === null + || ($this->lookahead !== null + && ($this->lookahead['position'] - $this->token['position']) === strlen($this->token['value'])); + } + + /** + * {@inheritdoc} + */ + protected function getCatchablePatterns() + { + return [ + '[a-z_\\\][a-z0-9_\:\\\]*[a-z_][a-z0-9_]*', + '(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?', + '"(?:""|[^"])*+"', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNonCatchablePatterns() + { + return ['\s+', '\*+', '(.)']; + } + + /** + * {@inheritdoc} + */ + protected function getType(&$value) + { + $type = self::T_NONE; + + if ($value[0] === '"') { + $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2)); + + return self::T_STRING; + } + + if (isset($this->noCase[$value])) { + return $this->noCase[$value]; + } + + if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) { + return self::T_IDENTIFIER; + } + + $lowerValue = strtolower($value); + + if (isset($this->withCase[$lowerValue])) { + return $this->withCase[$lowerValue]; + } + + // Checking numeric value + if (is_numeric($value)) { + return strpos($value, '.') !== false || stripos($value, 'e') !== false + ? self::T_FLOAT : self::T_INTEGER; + } + + return $type; + } + + /** @return array{value: int|string, type:self::T_*|null, position:int} */ + public function peek(): ?array + { + $token = parent::peek(); + + if ($token === null) { + return null; + } + + return (array) $token; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php new file mode 100644 index 0000000..5ec150d --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php @@ -0,0 +1,1506 @@ + + */ + private static $classIdentifiers = [ + DocLexer::T_IDENTIFIER, + DocLexer::T_TRUE, + DocLexer::T_FALSE, + DocLexer::T_NULL, + ]; + + /** + * The lexer. + * + * @var DocLexer + */ + private $lexer; + + /** + * Current target context. + * + * @var int + */ + private $target; + + /** + * Doc parser used to collect annotation target. + * + * @var DocParser + */ + private static $metadataParser; + + /** + * Flag to control if the current annotation is nested or not. + * + * @var bool + */ + private $isNestedAnnotation = false; + + /** + * Hashmap containing all use-statements that are to be used when parsing + * the given doc block. + * + * @var array + */ + private $imports = []; + + /** + * This hashmap is used internally to cache results of class_exists() + * look-ups. + * + * @var array + */ + private $classExists = []; + + /** + * Whether annotations that have not been imported should be ignored. + * + * @var bool + */ + private $ignoreNotImportedAnnotations = false; + + /** + * An array of default namespaces if operating in simple mode. + * + * @var string[] + */ + private $namespaces = []; + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names must be the raw names as used in the class, not the fully qualified + * + * @var bool[] indexed by annotation name + */ + private $ignoredAnnotationNames = []; + + /** + * A list with annotations in namespaced format + * that are not causing exceptions when not resolved to an annotation class. + * + * @var bool[] indexed by namespace name + */ + private $ignoredAnnotationNamespaces = []; + + /** @var string */ + private $context = ''; + + /** + * Hash-map for caching annotation metadata. + * + * @var array + */ + private static $annotationMetadata = [ + Annotation\Target::class => [ + 'is_annotation' => true, + 'has_constructor' => true, + 'has_named_argument_constructor' => false, + 'properties' => [], + 'targets_literal' => 'ANNOTATION_CLASS', + 'targets' => Target::TARGET_CLASS, + 'default_property' => 'value', + 'attribute_types' => [ + 'value' => [ + 'required' => false, + 'type' => 'array', + 'array_type' => 'string', + 'value' => 'array', + ], + ], + ], + Annotation\Attribute::class => [ + 'is_annotation' => true, + 'has_constructor' => false, + 'has_named_argument_constructor' => false, + 'targets_literal' => 'ANNOTATION_ANNOTATION', + 'targets' => Target::TARGET_ANNOTATION, + 'default_property' => 'name', + 'properties' => [ + 'name' => 'name', + 'type' => 'type', + 'required' => 'required', + ], + 'attribute_types' => [ + 'value' => [ + 'required' => true, + 'type' => 'string', + 'value' => 'string', + ], + 'type' => [ + 'required' => true, + 'type' => 'string', + 'value' => 'string', + ], + 'required' => [ + 'required' => false, + 'type' => 'boolean', + 'value' => 'boolean', + ], + ], + ], + Annotation\Attributes::class => [ + 'is_annotation' => true, + 'has_constructor' => false, + 'has_named_argument_constructor' => false, + 'targets_literal' => 'ANNOTATION_CLASS', + 'targets' => Target::TARGET_CLASS, + 'default_property' => 'value', + 'properties' => ['value' => 'value'], + 'attribute_types' => [ + 'value' => [ + 'type' => 'array', + 'required' => true, + 'array_type' => Annotation\Attribute::class, + 'value' => 'array<' . Annotation\Attribute::class . '>', + ], + ], + ], + Annotation\Enum::class => [ + 'is_annotation' => true, + 'has_constructor' => true, + 'has_named_argument_constructor' => false, + 'targets_literal' => 'ANNOTATION_PROPERTY', + 'targets' => Target::TARGET_PROPERTY, + 'default_property' => 'value', + 'properties' => ['value' => 'value'], + 'attribute_types' => [ + 'value' => [ + 'type' => 'array', + 'required' => true, + ], + 'literal' => [ + 'type' => 'array', + 'required' => false, + ], + ], + ], + Annotation\NamedArgumentConstructor::class => [ + 'is_annotation' => true, + 'has_constructor' => false, + 'has_named_argument_constructor' => false, + 'targets_literal' => 'ANNOTATION_CLASS', + 'targets' => Target::TARGET_CLASS, + 'default_property' => null, + 'properties' => [], + 'attribute_types' => [], + ], + ]; + + /** + * Hash-map for handle types declaration. + * + * @var array + */ + private static $typeMap = [ + 'float' => 'double', + 'bool' => 'boolean', + // allow uppercase Boolean in honor of George Boole + 'Boolean' => 'boolean', + 'int' => 'integer', + ]; + + /** + * Constructs a new DocParser. + */ + public function __construct() + { + $this->lexer = new DocLexer(); + } + + /** + * Sets the annotation names that are ignored during the parsing process. + * + * The names are supposed to be the raw names as used in the class, not the + * fully qualified class names. + * + * @param bool[] $names indexed by annotation name + * + * @return void + */ + public function setIgnoredAnnotationNames(array $names) + { + $this->ignoredAnnotationNames = $names; + } + + /** + * Sets the annotation namespaces that are ignored during the parsing process. + * + * @param bool[] $ignoredAnnotationNamespaces indexed by annotation namespace name + * + * @return void + */ + public function setIgnoredAnnotationNamespaces($ignoredAnnotationNamespaces) + { + $this->ignoredAnnotationNamespaces = $ignoredAnnotationNamespaces; + } + + /** + * Sets ignore on not-imported annotations. + * + * @param bool $bool + * + * @return void + */ + public function setIgnoreNotImportedAnnotations($bool) + { + $this->ignoreNotImportedAnnotations = (bool) $bool; + } + + /** + * Sets the default namespaces. + * + * @param string $namespace + * + * @return void + * + * @throws RuntimeException + */ + public function addNamespace($namespace) + { + if ($this->imports) { + throw new RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); + } + + $this->namespaces[] = $namespace; + } + + /** + * Sets the imports. + * + * @param array $imports + * + * @return void + * + * @throws RuntimeException + */ + public function setImports(array $imports) + { + if ($this->namespaces) { + throw new RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); + } + + $this->imports = $imports; + } + + /** + * Sets current target context as bitmask. + * + * @param int $target + * + * @return void + */ + public function setTarget($target) + { + $this->target = $target; + } + + /** + * Parses the given docblock string for annotations. + * + * @param string $input The docblock string to parse. + * @param string $context The parsing context. + * + * @phpstan-return list Array of annotations. If no annotations are found, an empty array is returned. + * + * @throws AnnotationException + * @throws ReflectionException + */ + public function parse($input, $context = '') + { + $pos = $this->findInitialTokenPosition($input); + if ($pos === null) { + return []; + } + + $this->context = $context; + + $this->lexer->setInput(trim(substr($input, $pos), '* /')); + $this->lexer->moveNext(); + + return $this->Annotations(); + } + + /** + * Finds the first valid annotation + * + * @param string $input The docblock string to parse + */ + private function findInitialTokenPosition($input): ?int + { + $pos = 0; + + // search for first valid annotation + while (($pos = strpos($input, '@', $pos)) !== false) { + $preceding = substr($input, $pos - 1, 1); + + // if the @ is preceded by a space, a tab or * it is valid + if ($pos === 0 || $preceding === ' ' || $preceding === '*' || $preceding === "\t") { + return $pos; + } + + $pos++; + } + + return null; + } + + /** + * Attempts to match the given token with the current lookahead token. + * If they match, updates the lookahead token; otherwise raises a syntax error. + * + * @param int $token Type of token. + * + * @return bool True if tokens match; false otherwise. + * + * @throws AnnotationException + */ + private function match(int $token): bool + { + if (! $this->lexer->isNextToken($token)) { + throw $this->syntaxError($this->lexer->getLiteral($token)); + } + + return $this->lexer->moveNext(); + } + + /** + * Attempts to match the current lookahead token with any of the given tokens. + * + * If any of them matches, this method updates the lookahead token; otherwise + * a syntax error is raised. + * + * @phpstan-param list $tokens + * + * @throws AnnotationException + */ + private function matchAny(array $tokens): bool + { + if (! $this->lexer->isNextTokenAny($tokens)) { + throw $this->syntaxError(implode(' or ', array_map([$this->lexer, 'getLiteral'], $tokens))); + } + + return $this->lexer->moveNext(); + } + + /** + * Generates a new syntax error. + * + * @param string $expected Expected string. + * @param mixed[]|null $token Optional token. + */ + private function syntaxError(string $expected, ?array $token = null): AnnotationException + { + if ($token === null) { + $token = $this->lexer->lookahead; + } + + $message = sprintf('Expected %s, got ', $expected); + $message .= $this->lexer->lookahead === null + ? 'end of string' + : sprintf("'%s' at position %s", $token['value'], $token['position']); + + if (strlen($this->context)) { + $message .= ' in ' . $this->context; + } + + $message .= '.'; + + return AnnotationException::syntaxError($message); + } + + /** + * Attempts to check if a class exists or not. This never goes through the PHP autoloading mechanism + * but uses the {@link AnnotationRegistry} to load classes. + * + * @param class-string $fqcn + */ + private function classExists(string $fqcn): bool + { + if (isset($this->classExists[$fqcn])) { + return $this->classExists[$fqcn]; + } + + // first check if the class already exists, maybe loaded through another AnnotationReader + if (class_exists($fqcn, false)) { + return $this->classExists[$fqcn] = true; + } + + // final check, does this class exist? + return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn); + } + + /** + * Collects parsing metadata for a given annotation class + * + * @param class-string $name The annotation name + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function collectAnnotationMetadata(string $name): void + { + if (self::$metadataParser === null) { + self::$metadataParser = new self(); + + self::$metadataParser->setIgnoreNotImportedAnnotations(true); + self::$metadataParser->setIgnoredAnnotationNames($this->ignoredAnnotationNames); + self::$metadataParser->setImports([ + 'enum' => Enum::class, + 'target' => Target::class, + 'attribute' => Attribute::class, + 'attributes' => Attributes::class, + 'namedargumentconstructor' => NamedArgumentConstructor::class, + ]); + + // Make sure that annotations from metadata are loaded + class_exists(Enum::class); + class_exists(Target::class); + class_exists(Attribute::class); + class_exists(Attributes::class); + class_exists(NamedArgumentConstructor::class); + } + + $class = new ReflectionClass($name); + $docComment = $class->getDocComment(); + + // Sets default values for annotation metadata + $constructor = $class->getConstructor(); + $metadata = [ + 'default_property' => null, + 'has_constructor' => $constructor !== null && $constructor->getNumberOfParameters() > 0, + 'constructor_args' => [], + 'properties' => [], + 'property_types' => [], + 'attribute_types' => [], + 'targets_literal' => null, + 'targets' => Target::TARGET_ALL, + 'is_annotation' => strpos($docComment, '@Annotation') !== false, + ]; + + $metadata['has_named_argument_constructor'] = $metadata['has_constructor'] + && $class->implementsInterface(NamedArgumentConstructorAnnotation::class); + + // verify that the class is really meant to be an annotation + if ($metadata['is_annotation']) { + self::$metadataParser->setTarget(Target::TARGET_CLASS); + + foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) { + if ($annotation instanceof Target) { + $metadata['targets'] = $annotation->targets; + $metadata['targets_literal'] = $annotation->literal; + + continue; + } + + if ($annotation instanceof NamedArgumentConstructor) { + $metadata['has_named_argument_constructor'] = $metadata['has_constructor']; + if ($metadata['has_named_argument_constructor']) { + // choose the first argument as the default property + $metadata['default_property'] = $constructor->getParameters()[0]->getName(); + } + } + + if (! ($annotation instanceof Attributes)) { + continue; + } + + foreach ($annotation->value as $attribute) { + $this->collectAttributeTypeMetadata($metadata, $attribute); + } + } + + // if not has a constructor will inject values into public properties + if ($metadata['has_constructor'] === false) { + // collect all public properties + foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $property) { + $metadata['properties'][$property->name] = $property->name; + + $propertyComment = $property->getDocComment(); + if ($propertyComment === false) { + continue; + } + + $attribute = new Attribute(); + + $attribute->required = (strpos($propertyComment, '@Required') !== false); + $attribute->name = $property->name; + $attribute->type = (strpos($propertyComment, '@var') !== false && + preg_match('/@var\s+([^\s]+)/', $propertyComment, $matches)) + ? $matches[1] + : 'mixed'; + + $this->collectAttributeTypeMetadata($metadata, $attribute); + + // checks if the property has @Enum + if (strpos($propertyComment, '@Enum') === false) { + continue; + } + + $context = 'property ' . $class->name . '::$' . $property->name; + + self::$metadataParser->setTarget(Target::TARGET_PROPERTY); + + foreach (self::$metadataParser->parse($propertyComment, $context) as $annotation) { + if (! $annotation instanceof Enum) { + continue; + } + + $metadata['enum'][$property->name]['value'] = $annotation->value; + $metadata['enum'][$property->name]['literal'] = (! empty($annotation->literal)) + ? $annotation->literal + : $annotation->value; + } + } + + // choose the first property as default property + $metadata['default_property'] = reset($metadata['properties']); + } elseif ($metadata['has_named_argument_constructor']) { + foreach ($constructor->getParameters() as $parameter) { + if ($parameter->isVariadic()) { + break; + } + + $metadata['constructor_args'][$parameter->getName()] = [ + 'position' => $parameter->getPosition(), + 'default' => $parameter->isOptional() ? $parameter->getDefaultValue() : null, + ]; + } + } + } + + self::$annotationMetadata[$name] = $metadata; + } + + /** + * Collects parsing metadata for a given attribute. + * + * @param mixed[] $metadata + */ + private function collectAttributeTypeMetadata(array &$metadata, Attribute $attribute): void + { + // handle internal type declaration + $type = self::$typeMap[$attribute->type] ?? $attribute->type; + + // handle the case if the property type is mixed + if ($type === 'mixed') { + return; + } + + // Evaluate type + $pos = strpos($type, '<'); + if ($pos !== false) { + // Checks if the property has array + $arrayType = substr($type, $pos + 1, -1); + $type = 'array'; + + if (isset(self::$typeMap[$arrayType])) { + $arrayType = self::$typeMap[$arrayType]; + } + + $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; + } else { + // Checks if the property has type[] + $pos = strrpos($type, '['); + if ($pos !== false) { + $arrayType = substr($type, 0, $pos); + $type = 'array'; + + if (isset(self::$typeMap[$arrayType])) { + $arrayType = self::$typeMap[$arrayType]; + } + + $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; + } + } + + $metadata['attribute_types'][$attribute->name]['type'] = $type; + $metadata['attribute_types'][$attribute->name]['value'] = $attribute->type; + $metadata['attribute_types'][$attribute->name]['required'] = $attribute->required; + } + + /** + * Annotations ::= Annotation {[ "*" ]* [Annotation]}* + * + * @phpstan-return list + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function Annotations(): array + { + $annotations = []; + + while ($this->lexer->lookahead !== null) { + if ($this->lexer->lookahead['type'] !== DocLexer::T_AT) { + $this->lexer->moveNext(); + continue; + } + + // make sure the @ is preceded by non-catchable pattern + if ( + $this->lexer->token !== null && + $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen( + $this->lexer->token['value'] + ) + ) { + $this->lexer->moveNext(); + continue; + } + + // make sure the @ is followed by either a namespace separator, or + // an identifier token + $peek = $this->lexer->glimpse(); + if ( + ($peek === null) + || ($peek['type'] !== DocLexer::T_NAMESPACE_SEPARATOR && ! in_array( + $peek['type'], + self::$classIdentifiers, + true + )) + || $peek['position'] !== $this->lexer->lookahead['position'] + 1 + ) { + $this->lexer->moveNext(); + continue; + } + + $this->isNestedAnnotation = false; + $annot = $this->Annotation(); + if ($annot === false) { + continue; + } + + $annotations[] = $annot; + } + + return $annotations; + } + + /** + * Annotation ::= "@" AnnotationName MethodCall + * AnnotationName ::= QualifiedName | SimpleName + * QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName + * NameSpacePart ::= identifier | null | false | true + * SimpleName ::= identifier | null | false | true + * + * @return object|false False if it is not a valid annotation. + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function Annotation() + { + $this->match(DocLexer::T_AT); + + // check if we have an annotation + $name = $this->Identifier(); + + if ( + $this->lexer->isNextToken(DocLexer::T_MINUS) + && $this->lexer->nextTokenIsAdjacent() + ) { + // Annotations with dashes, such as "@foo-" or "@foo-bar", are to be discarded + return false; + } + + // only process names which are not fully qualified, yet + // fully qualified names must start with a \ + $originalName = $name; + + if ($name[0] !== '\\') { + $pos = strpos($name, '\\'); + $alias = ($pos === false) ? $name : substr($name, 0, $pos); + $found = false; + $loweredAlias = strtolower($alias); + + if ($this->namespaces) { + foreach ($this->namespaces as $namespace) { + if ($this->classExists($namespace . '\\' . $name)) { + $name = $namespace . '\\' . $name; + $found = true; + break; + } + } + } elseif (isset($this->imports[$loweredAlias])) { + $namespace = ltrim($this->imports[$loweredAlias], '\\'); + $name = ($pos !== false) + ? $namespace . substr($name, $pos) + : $namespace; + $found = $this->classExists($name); + } elseif ( + ! isset($this->ignoredAnnotationNames[$name]) + && isset($this->imports['__NAMESPACE__']) + && $this->classExists($this->imports['__NAMESPACE__'] . '\\' . $name) + ) { + $name = $this->imports['__NAMESPACE__'] . '\\' . $name; + $found = true; + } elseif (! isset($this->ignoredAnnotationNames[$name]) && $this->classExists($name)) { + $found = true; + } + + if (! $found) { + if ($this->isIgnoredAnnotation($name)) { + return false; + } + + throw AnnotationException::semanticalError(sprintf( + <<<'EXCEPTION' +The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation? +EXCEPTION + , + $name, + $this->context + )); + } + } + + $name = ltrim($name, '\\'); + + if (! $this->classExists($name)) { + throw AnnotationException::semanticalError(sprintf( + 'The annotation "@%s" in %s does not exist, or could not be auto-loaded.', + $name, + $this->context + )); + } + + // at this point, $name contains the fully qualified class name of the + // annotation, and it is also guaranteed that this class exists, and + // that it is loaded + + // collects the metadata annotation only if there is not yet + if (! isset(self::$annotationMetadata[$name])) { + $this->collectAnnotationMetadata($name); + } + + // verify that the class is really meant to be an annotation and not just any ordinary class + if (self::$annotationMetadata[$name]['is_annotation'] === false) { + if ($this->isIgnoredAnnotation($originalName) || $this->isIgnoredAnnotation($name)) { + return false; + } + + throw AnnotationException::semanticalError(sprintf( + <<<'EXCEPTION' +The class "%s" is not annotated with @Annotation. +Are you sure this class can be used as annotation? +If so, then you need to add @Annotation to the _class_ doc comment of "%s". +If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s. +EXCEPTION + , + $name, + $name, + $originalName, + $this->context + )); + } + + //if target is nested annotation + $target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target; + + // Next will be nested + $this->isNestedAnnotation = true; + + //if annotation does not support current target + if ((self::$annotationMetadata[$name]['targets'] & $target) === 0 && $target) { + throw AnnotationException::semanticalError( + sprintf( + <<<'EXCEPTION' +Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s. +EXCEPTION + , + $originalName, + $this->context, + self::$annotationMetadata[$name]['targets_literal'] + ) + ); + } + + $arguments = $this->MethodCall(); + $values = $this->resolvePositionalValues($arguments, $name); + + if (isset(self::$annotationMetadata[$name]['enum'])) { + // checks all declared attributes + foreach (self::$annotationMetadata[$name]['enum'] as $property => $enum) { + // checks if the attribute is a valid enumerator + if (isset($values[$property]) && ! in_array($values[$property], $enum['value'])) { + throw AnnotationException::enumeratorError( + $property, + $name, + $this->context, + $enum['literal'], + $values[$property] + ); + } + } + } + + // checks all declared attributes + foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) { + if ( + $property === self::$annotationMetadata[$name]['default_property'] + && ! isset($values[$property]) && isset($values['value']) + ) { + $property = 'value'; + } + + // handle a not given attribute or null value + if (! isset($values[$property])) { + if ($type['required']) { + throw AnnotationException::requiredError( + $property, + $originalName, + $this->context, + 'a(n) ' . $type['value'] + ); + } + + continue; + } + + if ($type['type'] === 'array') { + // handle the case of a single value + if (! is_array($values[$property])) { + $values[$property] = [$values[$property]]; + } + + // checks if the attribute has array type declaration, such as "array" + if (isset($type['array_type'])) { + foreach ($values[$property] as $item) { + if (gettype($item) !== $type['array_type'] && ! $item instanceof $type['array_type']) { + throw AnnotationException::attributeTypeError( + $property, + $originalName, + $this->context, + 'either a(n) ' . $type['array_type'] . ', or an array of ' . $type['array_type'] . 's', + $item + ); + } + } + } + } elseif (gettype($values[$property]) !== $type['type'] && ! $values[$property] instanceof $type['type']) { + throw AnnotationException::attributeTypeError( + $property, + $originalName, + $this->context, + 'a(n) ' . $type['value'], + $values[$property] + ); + } + } + + if (self::$annotationMetadata[$name]['has_named_argument_constructor']) { + if (PHP_VERSION_ID >= 80000) { + foreach ($values as $property => $value) { + if (! isset(self::$annotationMetadata[$name]['constructor_args'][$property])) { + throw AnnotationException::creationError(sprintf( + <<<'EXCEPTION' +The annotation @%s declared on %s does not have a property named "%s" +that can be set through its named arguments constructor. +Available named arguments: %s +EXCEPTION + , + $originalName, + $this->context, + $property, + implode(', ', array_keys(self::$annotationMetadata[$name]['constructor_args'])) + )); + } + } + + return $this->instantiateAnnotiation($originalName, $this->context, $name, $values); + } + + $positionalValues = []; + foreach (self::$annotationMetadata[$name]['constructor_args'] as $property => $parameter) { + $positionalValues[$parameter['position']] = $parameter['default']; + } + + foreach ($values as $property => $value) { + if (! isset(self::$annotationMetadata[$name]['constructor_args'][$property])) { + throw AnnotationException::creationError(sprintf( + <<<'EXCEPTION' +The annotation @%s declared on %s does not have a property named "%s" +that can be set through its named arguments constructor. +Available named arguments: %s +EXCEPTION + , + $originalName, + $this->context, + $property, + implode(', ', array_keys(self::$annotationMetadata[$name]['constructor_args'])) + )); + } + + $positionalValues[self::$annotationMetadata[$name]['constructor_args'][$property]['position']] = $value; + } + + return $this->instantiateAnnotiation($originalName, $this->context, $name, $positionalValues); + } + + // check if the annotation expects values via the constructor, + // or directly injected into public properties + if (self::$annotationMetadata[$name]['has_constructor'] === true) { + return $this->instantiateAnnotiation($originalName, $this->context, $name, [$values]); + } + + $instance = $this->instantiateAnnotiation($originalName, $this->context, $name, []); + + foreach ($values as $property => $value) { + if (! isset(self::$annotationMetadata[$name]['properties'][$property])) { + if ($property !== 'value') { + throw AnnotationException::creationError(sprintf( + <<<'EXCEPTION' +The annotation @%s declared on %s does not have a property named "%s". +Available properties: %s +EXCEPTION + , + $originalName, + $this->context, + $property, + implode(', ', self::$annotationMetadata[$name]['properties']) + )); + } + + // handle the case if the property has no annotations + $property = self::$annotationMetadata[$name]['default_property']; + if (! $property) { + throw AnnotationException::creationError(sprintf( + 'The annotation @%s declared on %s does not accept any values, but got %s.', + $originalName, + $this->context, + json_encode($values) + )); + } + } + + $instance->{$property} = $value; + } + + return $instance; + } + + /** + * MethodCall ::= ["(" [Values] ")"] + * + * @return mixed[] + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function MethodCall(): array + { + $values = []; + + if (! $this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) { + return $values; + } + + $this->match(DocLexer::T_OPEN_PARENTHESIS); + + if (! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { + $values = $this->Values(); + } + + $this->match(DocLexer::T_CLOSE_PARENTHESIS); + + return $values; + } + + /** + * Values ::= Array | Value {"," Value}* [","] + * + * @return mixed[] + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function Values(): array + { + $values = [$this->Value()]; + + while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { + $this->match(DocLexer::T_COMMA); + + if ($this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { + break; + } + + $token = $this->lexer->lookahead; + $value = $this->Value(); + + $values[] = $value; + } + + $namedArguments = []; + $positionalArguments = []; + foreach ($values as $k => $value) { + if (is_object($value) && $value instanceof stdClass) { + $namedArguments[$value->name] = $value->value; + } else { + $positionalArguments[$k] = $value; + } + } + + return ['named_arguments' => $namedArguments, 'positional_arguments' => $positionalArguments]; + } + + /** + * Constant ::= integer | string | float | boolean + * + * @return mixed + * + * @throws AnnotationException + */ + private function Constant() + { + $identifier = $this->Identifier(); + + if (! defined($identifier) && strpos($identifier, '::') !== false && $identifier[0] !== '\\') { + [$className, $const] = explode('::', $identifier); + + $pos = strpos($className, '\\'); + $alias = ($pos === false) ? $className : substr($className, 0, $pos); + $found = false; + $loweredAlias = strtolower($alias); + + switch (true) { + case ! empty($this->namespaces): + foreach ($this->namespaces as $ns) { + if (class_exists($ns . '\\' . $className) || interface_exists($ns . '\\' . $className)) { + $className = $ns . '\\' . $className; + $found = true; + break; + } + } + + break; + + case isset($this->imports[$loweredAlias]): + $found = true; + $className = ($pos !== false) + ? $this->imports[$loweredAlias] . substr($className, $pos) + : $this->imports[$loweredAlias]; + break; + + default: + if (isset($this->imports['__NAMESPACE__'])) { + $ns = $this->imports['__NAMESPACE__']; + + if (class_exists($ns . '\\' . $className) || interface_exists($ns . '\\' . $className)) { + $className = $ns . '\\' . $className; + $found = true; + } + } + + break; + } + + if ($found) { + $identifier = $className . '::' . $const; + } + } + + /** + * Checks if identifier ends with ::class and remove the leading backslash if it exists. + */ + if ( + $this->identifierEndsWithClassConstant($identifier) && + ! $this->identifierStartsWithBackslash($identifier) + ) { + return substr($identifier, 0, $this->getClassConstantPositionInIdentifier($identifier)); + } + + if ($this->identifierEndsWithClassConstant($identifier) && $this->identifierStartsWithBackslash($identifier)) { + return substr($identifier, 1, $this->getClassConstantPositionInIdentifier($identifier) - 1); + } + + if (! defined($identifier)) { + throw AnnotationException::semanticalErrorConstants($identifier, $this->context); + } + + return constant($identifier); + } + + private function identifierStartsWithBackslash(string $identifier): bool + { + return $identifier[0] === '\\'; + } + + private function identifierEndsWithClassConstant(string $identifier): bool + { + return $this->getClassConstantPositionInIdentifier($identifier) === strlen($identifier) - strlen('::class'); + } + + /** @return int|false */ + private function getClassConstantPositionInIdentifier(string $identifier) + { + return stripos($identifier, '::class'); + } + + /** + * Identifier ::= string + * + * @throws AnnotationException + */ + private function Identifier(): string + { + // check if we have an annotation + if (! $this->lexer->isNextTokenAny(self::$classIdentifiers)) { + throw $this->syntaxError('namespace separator or identifier'); + } + + $this->lexer->moveNext(); + + $className = $this->lexer->token['value']; + + while ( + $this->lexer->lookahead !== null && + $this->lexer->lookahead['position'] === ($this->lexer->token['position'] + + strlen($this->lexer->token['value'])) && + $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR) + ) { + $this->match(DocLexer::T_NAMESPACE_SEPARATOR); + $this->matchAny(self::$classIdentifiers); + + $className .= '\\' . $this->lexer->token['value']; + } + + return $className; + } + + /** + * Value ::= PlainValue | FieldAssignment + * + * @return mixed + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function Value() + { + $peek = $this->lexer->glimpse(); + + if ($peek['type'] === DocLexer::T_EQUALS) { + return $this->FieldAssignment(); + } + + return $this->PlainValue(); + } + + /** + * PlainValue ::= integer | string | float | boolean | Array | Annotation + * + * @return mixed + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function PlainValue() + { + if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) { + return $this->Arrayx(); + } + + if ($this->lexer->isNextToken(DocLexer::T_AT)) { + return $this->Annotation(); + } + + if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { + return $this->Constant(); + } + + switch ($this->lexer->lookahead['type']) { + case DocLexer::T_STRING: + $this->match(DocLexer::T_STRING); + + return $this->lexer->token['value']; + + case DocLexer::T_INTEGER: + $this->match(DocLexer::T_INTEGER); + + return (int) $this->lexer->token['value']; + + case DocLexer::T_FLOAT: + $this->match(DocLexer::T_FLOAT); + + return (float) $this->lexer->token['value']; + + case DocLexer::T_TRUE: + $this->match(DocLexer::T_TRUE); + + return true; + + case DocLexer::T_FALSE: + $this->match(DocLexer::T_FALSE); + + return false; + + case DocLexer::T_NULL: + $this->match(DocLexer::T_NULL); + + return null; + + default: + throw $this->syntaxError('PlainValue'); + } + } + + /** + * FieldAssignment ::= FieldName "=" PlainValue + * FieldName ::= identifier + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function FieldAssignment(): stdClass + { + $this->match(DocLexer::T_IDENTIFIER); + $fieldName = $this->lexer->token['value']; + + $this->match(DocLexer::T_EQUALS); + + $item = new stdClass(); + $item->name = $fieldName; + $item->value = $this->PlainValue(); + + return $item; + } + + /** + * Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}" + * + * @return mixed[] + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function Arrayx(): array + { + $array = $values = []; + + $this->match(DocLexer::T_OPEN_CURLY_BRACES); + + // If the array is empty, stop parsing and return. + if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { + $this->match(DocLexer::T_CLOSE_CURLY_BRACES); + + return $array; + } + + $values[] = $this->ArrayEntry(); + + while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { + $this->match(DocLexer::T_COMMA); + + // optional trailing comma + if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { + break; + } + + $values[] = $this->ArrayEntry(); + } + + $this->match(DocLexer::T_CLOSE_CURLY_BRACES); + + foreach ($values as $value) { + [$key, $val] = $value; + + if ($key !== null) { + $array[$key] = $val; + } else { + $array[] = $val; + } + } + + return $array; + } + + /** + * ArrayEntry ::= Value | KeyValuePair + * KeyValuePair ::= Key ("=" | ":") PlainValue | Constant + * Key ::= string | integer | Constant + * + * @phpstan-return array{mixed, mixed} + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function ArrayEntry(): array + { + $peek = $this->lexer->glimpse(); + + if ( + $peek['type'] === DocLexer::T_EQUALS + || $peek['type'] === DocLexer::T_COLON + ) { + if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { + $key = $this->Constant(); + } else { + $this->matchAny([DocLexer::T_INTEGER, DocLexer::T_STRING]); + $key = $this->lexer->token['value']; + } + + $this->matchAny([DocLexer::T_EQUALS, DocLexer::T_COLON]); + + return [$key, $this->PlainValue()]; + } + + return [null, $this->Value()]; + } + + /** + * Checks whether the given $name matches any ignored annotation name or namespace + */ + private function isIgnoredAnnotation(string $name): bool + { + if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) { + return true; + } + + foreach (array_keys($this->ignoredAnnotationNamespaces) as $ignoredAnnotationNamespace) { + $ignoredAnnotationNamespace = rtrim($ignoredAnnotationNamespace, '\\') . '\\'; + + if (stripos(rtrim($name, '\\') . '\\', $ignoredAnnotationNamespace) === 0) { + return true; + } + } + + return false; + } + + /** + * Resolve positional arguments (without name) to named ones + * + * @param array $arguments + * + * @return array + */ + private function resolvePositionalValues(array $arguments, string $name): array + { + $positionalArguments = $arguments['positional_arguments'] ?? []; + $values = $arguments['named_arguments'] ?? []; + + if ( + self::$annotationMetadata[$name]['has_named_argument_constructor'] + && self::$annotationMetadata[$name]['default_property'] !== null + ) { + // We must ensure that we don't have positional arguments after named ones + $positions = array_keys($positionalArguments); + $lastPosition = null; + foreach ($positions as $position) { + if ( + ($lastPosition === null && $position !== 0) || + ($lastPosition !== null && $position !== $lastPosition + 1) + ) { + throw $this->syntaxError('Positional arguments after named arguments is not allowed'); + } + + $lastPosition = $position; + } + + foreach (self::$annotationMetadata[$name]['constructor_args'] as $property => $parameter) { + $position = $parameter['position']; + if (isset($values[$property]) || ! isset($positionalArguments[$position])) { + continue; + } + + $values[$property] = $positionalArguments[$position]; + } + } else { + if (count($positionalArguments) > 0 && ! isset($values['value'])) { + if (count($positionalArguments) === 1) { + $value = array_pop($positionalArguments); + } else { + $value = array_values($positionalArguments); + } + + $values['value'] = $value; + } + } + + return $values; + } + + /** + * Try to instantiate the annotation and catch and process any exceptions related to failure + * + * @param class-string $name + * @param array $arguments + * + * @return object + * + * @throws AnnotationException + */ + private function instantiateAnnotiation(string $originalName, string $context, string $name, array $arguments) + { + try { + return new $name(...$arguments); + } catch (Throwable $exception) { + throw AnnotationException::creationError( + sprintf( + 'An error occurred while instantiating the annotation @%s declared on %s: "%s".', + $originalName, + $context, + $exception->getMessage() + ), + $exception + ); + } + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php new file mode 100644 index 0000000..6c6c22c --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php @@ -0,0 +1,315 @@ +> */ + private $loadedAnnotations = []; + + /** @var array */ + private $classNameHashes = []; + + /** @var int */ + private $umask; + + /** + * @param string $cacheDir + * @param bool $debug + * @param int $umask + * + * @throws InvalidArgumentException + */ + public function __construct(Reader $reader, $cacheDir, $debug = false, $umask = 0002) + { + if (! is_int($umask)) { + throw new InvalidArgumentException(sprintf( + 'The parameter umask must be an integer, was: %s', + gettype($umask) + )); + } + + $this->reader = $reader; + $this->umask = $umask; + + if (! is_dir($cacheDir) && ! @mkdir($cacheDir, 0777 & (~$this->umask), true)) { + throw new InvalidArgumentException(sprintf( + 'The directory "%s" does not exist and could not be created.', + $cacheDir + )); + } + + $this->dir = rtrim($cacheDir, '\\/'); + $this->debug = $debug; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + if (! isset($this->classNameHashes[$class->name])) { + $this->classNameHashes[$class->name] = sha1($class->name); + } + + $key = $this->classNameHashes[$class->name]; + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir . '/' . strtr($key, '\\', '-') . '.cache.php'; + if (! is_file($path)) { + $annot = $this->reader->getClassAnnotations($class); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + $filename = $class->getFilename(); + if ( + $this->debug + && $filename !== false + && filemtime($path) < filemtime($filename) + ) { + @unlink($path); + + $annot = $this->reader->getClassAnnotations($class); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + if (! isset($this->classNameHashes[$class->name])) { + $this->classNameHashes[$class->name] = sha1($class->name); + } + + $key = $this->classNameHashes[$class->name] . '$' . $property->getName(); + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir . '/' . strtr($key, '\\', '-') . '.cache.php'; + if (! is_file($path)) { + $annot = $this->reader->getPropertyAnnotations($property); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + $filename = $class->getFilename(); + if ( + $this->debug + && $filename !== false + && filemtime($path) < filemtime($filename) + ) { + @unlink($path); + + $annot = $this->reader->getPropertyAnnotations($property); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + if (! isset($this->classNameHashes[$class->name])) { + $this->classNameHashes[$class->name] = sha1($class->name); + } + + $key = $this->classNameHashes[$class->name] . '#' . $method->getName(); + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir . '/' . strtr($key, '\\', '-') . '.cache.php'; + if (! is_file($path)) { + $annot = $this->reader->getMethodAnnotations($method); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + $filename = $class->getFilename(); + if ( + $this->debug + && $filename !== false + && filemtime($path) < filemtime($filename) + ) { + @unlink($path); + + $annot = $this->reader->getMethodAnnotations($method); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * Saves the cache file. + * + * @param string $path + * @param mixed $data + * + * @return void + */ + private function saveCacheFile($path, $data) + { + if (! is_writable($this->dir)) { + throw new InvalidArgumentException(sprintf( + <<<'EXCEPTION' +The directory "%s" is not writable. Both the webserver and the console user need access. +You can manage access rights for multiple users with "chmod +a". +If your system does not support this, check out the acl package., +EXCEPTION + , + $this->dir + )); + } + + $tempfile = tempnam($this->dir, uniqid('', true)); + + if ($tempfile === false) { + throw new RuntimeException(sprintf('Unable to create tempfile in directory: %s', $this->dir)); + } + + @chmod($tempfile, 0666 & (~$this->umask)); + + $written = file_put_contents( + $tempfile, + 'umask)); + + if (rename($tempfile, $path) === false) { + @unlink($tempfile); + + throw new RuntimeException(sprintf('Unable to rename %s to %s', $tempfile, $path)); + } + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + $annotations = $this->getClassAnnotations($class); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + $annotations = $this->getMethodAnnotations($method); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + $annotations = $this->getPropertyAnnotations($property); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Clears loaded annotations. + * + * @return void + */ + public function clearLoadedAnnotations() + { + $this->loadedAnnotations = []; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php new file mode 100644 index 0000000..ab27f8a --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php @@ -0,0 +1,178 @@ + true, + 'Attribute' => true, + 'Attributes' => true, + /* Can we enable this? 'Enum' => true, */ + 'Required' => true, + 'Target' => true, + 'NamedArgumentConstructor' => true, + ]; + + private const WidelyUsedNonStandard = [ + 'fix' => true, + 'fixme' => true, + 'override' => true, + ]; + + private const PhpDocumentor1 = [ + 'abstract' => true, + 'access' => true, + 'code' => true, + 'deprec' => true, + 'endcode' => true, + 'exception' => true, + 'final' => true, + 'ingroup' => true, + 'inheritdoc' => true, + 'inheritDoc' => true, + 'magic' => true, + 'name' => true, + 'private' => true, + 'static' => true, + 'staticvar' => true, + 'staticVar' => true, + 'toc' => true, + 'tutorial' => true, + 'throw' => true, + ]; + + private const PhpDocumentor2 = [ + 'api' => true, + 'author' => true, + 'category' => true, + 'copyright' => true, + 'deprecated' => true, + 'example' => true, + 'filesource' => true, + 'global' => true, + 'ignore' => true, + /* Can we enable this? 'index' => true, */ + 'internal' => true, + 'license' => true, + 'link' => true, + 'method' => true, + 'package' => true, + 'param' => true, + 'property' => true, + 'property-read' => true, + 'property-write' => true, + 'return' => true, + 'see' => true, + 'since' => true, + 'source' => true, + 'subpackage' => true, + 'throws' => true, + 'todo' => true, + 'TODO' => true, + 'usedby' => true, + 'uses' => true, + 'var' => true, + 'version' => true, + ]; + + private const PHPUnit = [ + 'author' => true, + 'after' => true, + 'afterClass' => true, + 'backupGlobals' => true, + 'backupStaticAttributes' => true, + 'before' => true, + 'beforeClass' => true, + 'codeCoverageIgnore' => true, + 'codeCoverageIgnoreStart' => true, + 'codeCoverageIgnoreEnd' => true, + 'covers' => true, + 'coversDefaultClass' => true, + 'coversNothing' => true, + 'dataProvider' => true, + 'depends' => true, + 'doesNotPerformAssertions' => true, + 'expectedException' => true, + 'expectedExceptionCode' => true, + 'expectedExceptionMessage' => true, + 'expectedExceptionMessageRegExp' => true, + 'group' => true, + 'large' => true, + 'medium' => true, + 'preserveGlobalState' => true, + 'requires' => true, + 'runTestsInSeparateProcesses' => true, + 'runInSeparateProcess' => true, + 'small' => true, + 'test' => true, + 'testdox' => true, + 'testWith' => true, + 'ticket' => true, + 'uses' => true, + ]; + + private const PhpCheckStyle = ['SuppressWarnings' => true]; + + private const PhpStorm = ['noinspection' => true]; + + private const PEAR = ['package_version' => true]; + + private const PlainUML = [ + 'startuml' => true, + 'enduml' => true, + ]; + + private const Symfony = ['experimental' => true]; + + private const PhpCodeSniffer = [ + 'codingStandardsIgnoreStart' => true, + 'codingStandardsIgnoreEnd' => true, + ]; + + private const SlevomatCodingStandard = ['phpcsSuppress' => true]; + + private const Phan = ['suppress' => true]; + + private const Rector = ['noRector' => true]; + + private const StaticAnalysis = [ + // PHPStan, Psalm + 'extends' => true, + 'implements' => true, + 'readonly' => true, + 'template' => true, + 'use' => true, + + // Psalm + 'pure' => true, + 'immutable' => true, + ]; + + public const LIST = self::Reserved + + self::WidelyUsedNonStandard + + self::PhpDocumentor1 + + self::PhpDocumentor2 + + self::PHPUnit + + self::PhpCheckStyle + + self::PhpStorm + + self::PEAR + + self::PlainUML + + self::Symfony + + self::SlevomatCodingStandard + + self::PhpCodeSniffer + + self::Phan + + self::Rector + + self::StaticAnalysis; + + private function __construct() + { + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php new file mode 100644 index 0000000..62dcf74 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php @@ -0,0 +1,100 @@ +delegate = $reader; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + $annotations = []; + foreach ($this->delegate->getClassAnnotations($class) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + return $this->delegate->getClassAnnotation($class, $annotationName); + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $annotations = []; + foreach ($this->delegate->getMethodAnnotations($method) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + return $this->delegate->getMethodAnnotation($method, $annotationName); + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $annotations = []; + foreach ($this->delegate->getPropertyAnnotations($property) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + return $this->delegate->getPropertyAnnotation($property, $annotationName); + } + + /** + * Proxies all methods to the delegate. + * + * @param string $method + * @param mixed[] $args + * + * @return mixed + */ + public function __call($method, $args) + { + return call_user_func_array([$this->delegate, $method], $args); + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/NamedArgumentConstructorAnnotation.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/NamedArgumentConstructorAnnotation.php new file mode 100644 index 0000000..8af224c --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/NamedArgumentConstructorAnnotation.php @@ -0,0 +1,14 @@ +ReflectionClass object. + * + * @return array A list with use statements in the form (Alias => FQN). + */ + public function parseClass(ReflectionClass $class) + { + return $this->parseUseStatements($class); + } + + /** + * Parse a class or function for use statements. + * + * @param ReflectionClass|ReflectionFunction $reflection + * + * @psalm-return array a list with use statements in the form (Alias => FQN). + */ + public function parseUseStatements($reflection): array + { + if (method_exists($reflection, 'getUseStatements')) { + return $reflection->getUseStatements(); + } + + $filename = $reflection->getFileName(); + + if ($filename === false) { + return []; + } + + $content = $this->getFileContent($filename, $reflection->getStartLine()); + + if ($content === null) { + return []; + } + + $namespace = preg_quote($reflection->getNamespaceName()); + $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content); + $tokenizer = new TokenParser('parseUseStatements($reflection->getNamespaceName()); + } + + /** + * Gets the content of the file right up to the given line number. + * + * @param string $filename The name of the file to load. + * @param int $lineNumber The number of lines to read from file. + * + * @return string|null The content of the file or null if the file does not exist. + */ + private function getFileContent($filename, $lineNumber) + { + if (! is_file($filename)) { + return null; + } + + $content = ''; + $lineCnt = 0; + $file = new SplFileObject($filename); + while (! $file->eof()) { + if ($lineCnt++ === $lineNumber) { + break; + } + + $content .= $file->fgets(); + } + + return $content; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php new file mode 100644 index 0000000..a7099d5 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php @@ -0,0 +1,232 @@ +> */ + private $loadedAnnotations = []; + + /** @var int[] */ + private $loadedFilemtimes = []; + + public function __construct(Reader $reader, CacheItemPoolInterface $cache, bool $debug = false) + { + $this->delegate = $reader; + $this->cache = $cache; + $this->debug = (bool) $debug; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + $cacheKey = $class->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + $annots = $this->fetchFromCache($cacheKey, $class, 'getClassAnnotations', $class); + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + foreach ($this->getClassAnnotations($class) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $cacheKey = $class->getName() . '$' . $property->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + $annots = $this->fetchFromCache($cacheKey, $class, 'getPropertyAnnotations', $property); + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + foreach ($this->getPropertyAnnotations($property) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $cacheKey = $class->getName() . '#' . $method->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + $annots = $this->fetchFromCache($cacheKey, $class, 'getMethodAnnotations', $method); + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + foreach ($this->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + public function clearLoadedAnnotations(): void + { + $this->loadedAnnotations = []; + $this->loadedFilemtimes = []; + } + + /** @return mixed[] */ + private function fetchFromCache( + string $cacheKey, + ReflectionClass $class, + string $method, + Reflector $reflector + ): array { + $cacheKey = rawurlencode($cacheKey); + + $item = $this->cache->getItem($cacheKey); + if (($this->debug && ! $this->refresh($cacheKey, $class)) || ! $item->isHit()) { + $this->cache->save($item->set($this->delegate->{$method}($reflector))); + } + + return $item->get(); + } + + /** + * Used in debug mode to check if the cache is fresh. + * + * @return bool Returns true if the cache was fresh, or false if the class + * being read was modified since writing to the cache. + */ + private function refresh(string $cacheKey, ReflectionClass $class): bool + { + $lastModification = $this->getLastModification($class); + if ($lastModification === 0) { + return true; + } + + $item = $this->cache->getItem('[C]' . $cacheKey); + if ($item->isHit() && $item->get() >= $lastModification) { + return true; + } + + $this->cache->save($item->set(time())); + + return false; + } + + /** + * Returns the time the class was last modified, testing traits and parents + */ + private function getLastModification(ReflectionClass $class): int + { + $filename = $class->getFileName(); + + if (isset($this->loadedFilemtimes[$filename])) { + return $this->loadedFilemtimes[$filename]; + } + + $parent = $class->getParentClass(); + + $lastModification = max(array_merge( + [$filename ? filemtime($filename) : 0], + array_map(function (ReflectionClass $reflectionTrait): int { + return $this->getTraitLastModificationTime($reflectionTrait); + }, $class->getTraits()), + array_map(function (ReflectionClass $class): int { + return $this->getLastModification($class); + }, $class->getInterfaces()), + $parent ? [$this->getLastModification($parent)] : [] + )); + + assert($lastModification !== false); + + return $this->loadedFilemtimes[$filename] = $lastModification; + } + + private function getTraitLastModificationTime(ReflectionClass $reflectionTrait): int + { + $fileName = $reflectionTrait->getFileName(); + + if (isset($this->loadedFilemtimes[$fileName])) { + return $this->loadedFilemtimes[$fileName]; + } + + $lastModificationTime = max(array_merge( + [$fileName ? filemtime($fileName) : 0], + array_map(function (ReflectionClass $reflectionTrait): int { + return $this->getTraitLastModificationTime($reflectionTrait); + }, $reflectionTrait->getTraits()) + )); + + assert($lastModificationTime !== false); + + return $this->loadedFilemtimes[$fileName] = $lastModificationTime; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php new file mode 100644 index 0000000..0663ffd --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php @@ -0,0 +1,80 @@ + An array of Annotations. + */ + public function getClassAnnotations(ReflectionClass $class); + + /** + * Gets a class annotation. + * + * @param ReflectionClass $class The ReflectionClass of the class from which + * the class annotations should be read. + * @param class-string $annotationName The name of the annotation. + * + * @return T|null The Annotation or NULL, if the requested annotation does not exist. + * + * @template T + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName); + + /** + * Gets the annotations applied to a method. + * + * @param ReflectionMethod $method The ReflectionMethod of the method from which + * the annotations should be read. + * + * @return array An array of Annotations. + */ + public function getMethodAnnotations(ReflectionMethod $method); + + /** + * Gets a method annotation. + * + * @param ReflectionMethod $method The ReflectionMethod to read the annotations from. + * @param class-string $annotationName The name of the annotation. + * + * @return T|null The Annotation or NULL, if the requested annotation does not exist. + * + * @template T + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName); + + /** + * Gets the annotations applied to a property. + * + * @param ReflectionProperty $property The ReflectionProperty of the property + * from which the annotations should be read. + * + * @return array An array of Annotations. + */ + public function getPropertyAnnotations(ReflectionProperty $property); + + /** + * Gets a property annotation. + * + * @param ReflectionProperty $property The ReflectionProperty to read the annotations from. + * @param class-string $annotationName The name of the annotation. + * + * @return T|null The Annotation or NULL, if the requested annotation does not exist. + * + * @template T + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName); +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php new file mode 100644 index 0000000..8a78c11 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php @@ -0,0 +1,114 @@ +parser = new DocParser(); + $this->parser->setIgnoreNotImportedAnnotations(true); + } + + /** + * Adds a namespace in which we will look for annotations. + * + * @param string $namespace + * + * @return void + */ + public function addNamespace($namespace) + { + $this->parser->addNamespace($namespace); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName()); + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + return $this->parser->parse( + $method->getDocComment(), + 'method ' . $method->getDeclaringClass()->name . '::' . $method->getName() . '()' + ); + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + return $this->parser->parse( + $property->getDocComment(), + 'property ' . $property->getDeclaringClass()->name . '::$' . $property->getName() + ); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + foreach ($this->getClassAnnotations($class) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + foreach ($this->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + foreach ($this->getPropertyAnnotations($property) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php new file mode 100644 index 0000000..69259fc --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php @@ -0,0 +1,206 @@ + + */ + private $tokens; + + /** + * The number of tokens. + * + * @var int + */ + private $numTokens; + + /** + * The current array pointer. + * + * @var int + */ + private $pointer = 0; + + /** @param string $contents */ + public function __construct($contents) + { + $this->tokens = token_get_all($contents); + + // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it + // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored + // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a + // docblock. If the first thing in the file is a class without a doc block this would cause calls to + // getDocBlock() on said class to return our long lost doc_comment. Argh. + // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least + // it's harmless to us. + token_get_all("numTokens = count($this->tokens); + } + + /** + * Gets the next non whitespace and non comment token. + * + * @param bool $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped. + * If FALSE then only whitespace and normal comments are skipped. + * + * @return mixed[]|string|null The token if exists, null otherwise. + */ + public function next($docCommentIsComment = true) + { + for ($i = $this->pointer; $i < $this->numTokens; $i++) { + $this->pointer++; + if ( + $this->tokens[$i][0] === T_WHITESPACE || + $this->tokens[$i][0] === T_COMMENT || + ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT) + ) { + continue; + } + + return $this->tokens[$i]; + } + + return null; + } + + /** + * Parses a single use statement. + * + * @return array A list with all found class names for a use statement. + */ + public function parseUseStatement() + { + $groupRoot = ''; + $class = ''; + $alias = ''; + $statements = []; + $explicitAlias = false; + while (($token = $this->next())) { + if (! $explicitAlias && $token[0] === T_STRING) { + $class .= $token[1]; + $alias = $token[1]; + } elseif ($explicitAlias && $token[0] === T_STRING) { + $alias = $token[1]; + } elseif ( + PHP_VERSION_ID >= 80000 && + ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED) + ) { + $class .= $token[1]; + + $classSplit = explode('\\', $token[1]); + $alias = $classSplit[count($classSplit) - 1]; + } elseif ($token[0] === T_NS_SEPARATOR) { + $class .= '\\'; + $alias = ''; + } elseif ($token[0] === T_AS) { + $explicitAlias = true; + $alias = ''; + } elseif ($token === ',') { + $statements[strtolower($alias)] = $groupRoot . $class; + $class = ''; + $alias = ''; + $explicitAlias = false; + } elseif ($token === ';') { + $statements[strtolower($alias)] = $groupRoot . $class; + break; + } elseif ($token === '{') { + $groupRoot = $class; + $class = ''; + } elseif ($token === '}') { + continue; + } else { + break; + } + } + + return $statements; + } + + /** + * Gets all use statements. + * + * @param string $namespaceName The namespace name of the reflected class. + * + * @return array A list with all found use statements. + */ + public function parseUseStatements($namespaceName) + { + $statements = []; + while (($token = $this->next())) { + if ($token[0] === T_USE) { + $statements = array_merge($statements, $this->parseUseStatement()); + continue; + } + + if ($token[0] !== T_NAMESPACE || $this->parseNamespace() !== $namespaceName) { + continue; + } + + // Get fresh array for new namespace. This is to prevent the parser to collect the use statements + // for a previous namespace with the same name. This is the case if a namespace is defined twice + // or if a namespace with the same name is commented out. + $statements = []; + } + + return $statements; + } + + /** + * Gets the namespace. + * + * @return string The found namespace. + */ + public function parseNamespace() + { + $name = ''; + while ( + ($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR || ( + PHP_VERSION_ID >= 80000 && + ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED) + )) + ) { + $name .= $token[1]; + } + + return $name; + } + + /** + * Gets the class name. + * + * @return string The found class name. + */ + public function parseClass() + { + // Namespaces and class names are tokenized the same: T_STRINGs + // separated by T_NS_SEPARATOR so we can use one function to provide + // both. + return $this->parseNamespace(); + } +} diff --git a/vendor/doctrine/annotations/psalm.xml b/vendor/doctrine/annotations/psalm.xml new file mode 100644 index 0000000..e6af389 --- /dev/null +++ b/vendor/doctrine/annotations/psalm.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/vendor/doctrine/deprecations/LICENSE b/vendor/doctrine/deprecations/LICENSE new file mode 100644 index 0000000..156905c --- /dev/null +++ b/vendor/doctrine/deprecations/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020-2021 Doctrine Project + +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/vendor/doctrine/deprecations/README.md b/vendor/doctrine/deprecations/README.md new file mode 100644 index 0000000..93caf83 --- /dev/null +++ b/vendor/doctrine/deprecations/README.md @@ -0,0 +1,157 @@ +# Doctrine Deprecations + +A small (side-effect free by default) layer on top of +`trigger_error(E_USER_DEPRECATED)` or PSR-3 logging. + +- no side-effects by default, making it a perfect fit for libraries that don't know how the error handler works they operate under +- options to avoid having to rely on error handlers global state by using PSR-3 logging +- deduplicate deprecation messages to avoid excessive triggering and reduce overhead + +We recommend to collect Deprecations using a PSR logger instead of relying on +the global error handler. + +## Usage from consumer perspective: + +Enable Doctrine deprecations to be sent to a PSR3 logger: + +```php +\Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger); +``` + +Enable Doctrine deprecations to be sent as `@trigger_error($message, E_USER_DEPRECATED)` +messages by setting the `DOCTRINE_DEPRECATIONS` environment variable to `trigger`. +Alternatively, call: + +```php +\Doctrine\Deprecations\Deprecation::enableWithTriggerError(); +``` + +If you only want to enable deprecation tracking, without logging or calling `trigger_error` +then set the `DOCTRINE_DEPRECATIONS` environment variable to `track`. +Alternatively, call: + +```php +\Doctrine\Deprecations\Deprecation::enableTrackingDeprecations(); +``` + +Tracking is enabled with all three modes and provides access to all triggered +deprecations and their individual count: + +```php +$deprecations = \Doctrine\Deprecations\Deprecation::getTriggeredDeprecations(); + +foreach ($deprecations as $identifier => $count) { + echo $identifier . " was triggered " . $count . " times\n"; +} +``` + +### Suppressing Specific Deprecations + +Disable triggering about specific deprecations: + +```php +\Doctrine\Deprecations\Deprecation::ignoreDeprecations("https://link/to/deprecations-description-identifier"); +``` + +Disable all deprecations from a package + +```php +\Doctrine\Deprecations\Deprecation::ignorePackage("doctrine/orm"); +``` + +### Other Operations + +When used within PHPUnit or other tools that could collect multiple instances of the same deprecations +the deduplication can be disabled: + +```php +\Doctrine\Deprecations\Deprecation::withoutDeduplication(); +``` + +Disable deprecation tracking again: + +```php +\Doctrine\Deprecations\Deprecation::disable(); +``` + +## Usage from a library/producer perspective: + +When you want to unconditionally trigger a deprecation even when called +from the library itself then the `trigger` method is the way to go: + +```php +\Doctrine\Deprecations\Deprecation::trigger( + "doctrine/orm", + "https://link/to/deprecations-description", + "message" +); +``` + +If variable arguments are provided at the end, they are used with `sprintf` on +the message. + +```php +\Doctrine\Deprecations\Deprecation::trigger( + "doctrine/orm", + "https://github.com/doctrine/orm/issue/1234", + "message %s %d", + "foo", + 1234 +); +``` + +When you want to trigger a deprecation only when it is called by a function +outside of the current package, but not trigger when the package itself is the cause, +then use: + +```php +\Doctrine\Deprecations\Deprecation::triggerIfCalledFromOutside( + "doctrine/orm", + "https://link/to/deprecations-description", + "message" +); +``` + +Based on the issue link each deprecation message is only triggered once per +request. + +A limited stacktrace is included in the deprecation message to find the +offending location. + +Note: A producer/library should never call `Deprecation::enableWith` methods +and leave the decision how to handle deprecations to application and +frameworks. + +## Usage in PHPUnit tests + +There is a `VerifyDeprecations` trait that you can use to make assertions on +the occurrence of deprecations within a test. + +```php +use Doctrine\Deprecations\PHPUnit\VerifyDeprecations; + +class MyTest extends TestCase +{ + use VerifyDeprecations; + + public function testSomethingDeprecation() + { + $this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234'); + + triggerTheCodeWithDeprecation(); + } + + public function testSomethingDeprecationFixed() + { + $this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234'); + + triggerTheCodeWithoutDeprecation(); + } +} +``` + +## What is a deprecation identifier? + +An identifier for deprecations is just a link to any resource, most often a +Github Issue or Pull Request explaining the deprecation and potentially its +alternative. diff --git a/vendor/doctrine/deprecations/composer.json b/vendor/doctrine/deprecations/composer.json new file mode 100644 index 0000000..f8319f9 --- /dev/null +++ b/vendor/doctrine/deprecations/composer.json @@ -0,0 +1,38 @@ +{ + "name": "doctrine/deprecations", + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "license": "MIT", + "type": "library", + "homepage": "https://www.doctrine-project.org/", + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "autoload-dev": { + "psr-4": { + "DeprecationTests\\": "test_fixtures/src", + "Doctrine\\Foo\\": "test_fixtures/vendor/doctrine/foo" + } + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} diff --git a/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php b/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php new file mode 100644 index 0000000..07cb43b --- /dev/null +++ b/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php @@ -0,0 +1,312 @@ +|null */ + private static $type; + + /** @var LoggerInterface|null */ + private static $logger; + + /** @var array */ + private static $ignoredPackages = []; + + /** @var array */ + private static $triggeredDeprecations = []; + + /** @var array */ + private static $ignoredLinks = []; + + /** @var bool */ + private static $deduplication = true; + + /** + * Trigger a deprecation for the given package and identfier. + * + * The link should point to a Github issue or Wiki entry detailing the + * deprecation. It is additionally used to de-duplicate the trigger of the + * same deprecation during a request. + * + * @param float|int|string $args + */ + public static function trigger(string $package, string $link, string $message, ...$args): void + { + $type = self::$type ?? self::getTypeFromEnv(); + + if ($type === self::TYPE_NONE) { + return; + } + + if (isset(self::$ignoredLinks[$link])) { + return; + } + + if (array_key_exists($link, self::$triggeredDeprecations)) { + self::$triggeredDeprecations[$link]++; + } else { + self::$triggeredDeprecations[$link] = 1; + } + + if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) { + return; + } + + if (isset(self::$ignoredPackages[$package])) { + return; + } + + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); + + $message = sprintf($message, ...$args); + + self::delegateTriggerToBackend($message, $backtrace, $link, $package); + } + + /** + * Trigger a deprecation for the given package and identifier when called from outside. + * + * "Outside" means we assume that $package is currently installed as a + * dependency and the caller is not a file in that package. When $package + * is installed as a root package then deprecations triggered from the + * tests folder are also considered "outside". + * + * This deprecation method assumes that you are using Composer to install + * the dependency and are using the default /vendor/ folder and not a + * Composer plugin to change the install location. The assumption is also + * that $package is the exact composer packge name. + * + * Compared to {@link trigger()} this method causes some overhead when + * deprecation tracking is enabled even during deduplication, because it + * needs to call {@link debug_backtrace()} + * + * @param float|int|string $args + */ + public static function triggerIfCalledFromOutside(string $package, string $link, string $message, ...$args): void + { + $type = self::$type ?? self::getTypeFromEnv(); + + if ($type === self::TYPE_NONE) { + return; + } + + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); + + // first check that the caller is not from a tests folder, in which case we always let deprecations pass + if (isset($backtrace[1]['file'], $backtrace[0]['file']) && strpos($backtrace[1]['file'], DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR) === false) { + $path = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package . DIRECTORY_SEPARATOR; + + if (strpos($backtrace[0]['file'], $path) === false) { + return; + } + + if (strpos($backtrace[1]['file'], $path) !== false) { + return; + } + } + + if (isset(self::$ignoredLinks[$link])) { + return; + } + + if (array_key_exists($link, self::$triggeredDeprecations)) { + self::$triggeredDeprecations[$link]++; + } else { + self::$triggeredDeprecations[$link] = 1; + } + + if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) { + return; + } + + if (isset(self::$ignoredPackages[$package])) { + return; + } + + $message = sprintf($message, ...$args); + + self::delegateTriggerToBackend($message, $backtrace, $link, $package); + } + + /** + * @param list $backtrace + */ + private static function delegateTriggerToBackend(string $message, array $backtrace, string $link, string $package): void + { + $type = self::$type ?? self::getTypeFromEnv(); + + if (($type & self::TYPE_PSR_LOGGER) > 0) { + $context = [ + 'file' => $backtrace[0]['file'] ?? null, + 'line' => $backtrace[0]['line'] ?? null, + 'package' => $package, + 'link' => $link, + ]; + + assert(self::$logger !== null); + + self::$logger->notice($message, $context); + } + + if (! (($type & self::TYPE_TRIGGER_ERROR) > 0)) { + return; + } + + $message .= sprintf( + ' (%s:%d called by %s:%d, %s, package %s)', + self::basename($backtrace[0]['file'] ?? 'native code'), + $backtrace[0]['line'] ?? 0, + self::basename($backtrace[1]['file'] ?? 'native code'), + $backtrace[1]['line'] ?? 0, + $link, + $package + ); + + @trigger_error($message, E_USER_DEPRECATED); + } + + /** + * A non-local-aware version of PHPs basename function. + */ + private static function basename(string $filename): string + { + $pos = strrpos($filename, DIRECTORY_SEPARATOR); + + if ($pos === false) { + return $filename; + } + + return substr($filename, $pos + 1); + } + + public static function enableTrackingDeprecations(): void + { + self::$type = self::$type ?? 0; + self::$type |= self::TYPE_TRACK_DEPRECATIONS; + } + + public static function enableWithTriggerError(): void + { + self::$type = self::$type ?? 0; + self::$type |= self::TYPE_TRIGGER_ERROR; + } + + public static function enableWithPsrLogger(LoggerInterface $logger): void + { + self::$type = self::$type ?? 0; + self::$type |= self::TYPE_PSR_LOGGER; + self::$logger = $logger; + } + + public static function withoutDeduplication(): void + { + self::$deduplication = false; + } + + public static function disable(): void + { + self::$type = self::TYPE_NONE; + self::$logger = null; + self::$deduplication = true; + self::$ignoredLinks = []; + + foreach (self::$triggeredDeprecations as $link => $count) { + self::$triggeredDeprecations[$link] = 0; + } + } + + public static function ignorePackage(string $packageName): void + { + self::$ignoredPackages[$packageName] = true; + } + + public static function ignoreDeprecations(string ...$links): void + { + foreach ($links as $link) { + self::$ignoredLinks[$link] = true; + } + } + + public static function getUniqueTriggeredDeprecationsCount(): int + { + return array_reduce(self::$triggeredDeprecations, static function (int $carry, int $count) { + return $carry + $count; + }, 0); + } + + /** + * Returns each triggered deprecation link identifier and the amount of occurrences. + * + * @return array + */ + public static function getTriggeredDeprecations(): array + { + return self::$triggeredDeprecations; + } + + /** + * @return int-mask-of + */ + private static function getTypeFromEnv(): int + { + switch ($_SERVER['DOCTRINE_DEPRECATIONS'] ?? $_ENV['DOCTRINE_DEPRECATIONS'] ?? null) { + case 'trigger': + self::$type = self::TYPE_TRIGGER_ERROR; + break; + + case 'track': + self::$type = self::TYPE_TRACK_DEPRECATIONS; + break; + + default: + self::$type = self::TYPE_NONE; + break; + } + + return self::$type; + } +} diff --git a/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php b/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php new file mode 100644 index 0000000..4c3366a --- /dev/null +++ b/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php @@ -0,0 +1,66 @@ + */ + private $doctrineDeprecationsExpectations = []; + + /** @var array */ + private $doctrineNoDeprecationsExpectations = []; + + public function expectDeprecationWithIdentifier(string $identifier): void + { + $this->doctrineDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; + } + + public function expectNoDeprecationWithIdentifier(string $identifier): void + { + $this->doctrineNoDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; + } + + /** + * @before + */ + public function enableDeprecationTracking(): void + { + Deprecation::enableTrackingDeprecations(); + } + + /** + * @after + */ + public function verifyDeprecationsAreTriggered(): void + { + foreach ($this->doctrineDeprecationsExpectations as $identifier => $expectation) { + $actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; + + $this->assertTrue( + $actualCount > $expectation, + sprintf( + "Expected deprecation with identifier '%s' was not triggered by code executed in test.", + $identifier + ) + ); + } + + foreach ($this->doctrineNoDeprecationsExpectations as $identifier => $expectation) { + $actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0; + + $this->assertTrue( + $actualCount === $expectation, + sprintf( + "Expected deprecation with identifier '%s' was triggered by code executed in test, but expected not to.", + $identifier + ) + ); + } + } +} diff --git a/vendor/doctrine/deprecations/phpcs.xml b/vendor/doctrine/deprecations/phpcs.xml new file mode 100644 index 0000000..f115e43 --- /dev/null +++ b/vendor/doctrine/deprecations/phpcs.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + lib + tests + + + + + + diff --git a/vendor/doctrine/deprecations/phpstan.neon b/vendor/doctrine/deprecations/phpstan.neon new file mode 100644 index 0000000..4ee286b --- /dev/null +++ b/vendor/doctrine/deprecations/phpstan.neon @@ -0,0 +1,9 @@ +parameters: + level: 6 + paths: + - lib + - tests + +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon diff --git a/vendor/doctrine/deprecations/psalm.xml b/vendor/doctrine/deprecations/psalm.xml new file mode 100644 index 0000000..ad76e32 --- /dev/null +++ b/vendor/doctrine/deprecations/psalm.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/doctrine/instantiator/.doctrine-project.json b/vendor/doctrine/instantiator/.doctrine-project.json new file mode 100644 index 0000000..24ae36e --- /dev/null +++ b/vendor/doctrine/instantiator/.doctrine-project.json @@ -0,0 +1,47 @@ +{ + "active": true, + "name": "Instantiator", + "slug": "instantiator", + "docsSlug": "doctrine-instantiator", + "codePath": "/src", + "versions": [ + { + "name": "1.5", + "branchName": "1.5.x", + "slug": "latest", + "upcoming": true + }, + { + "name": "1.4", + "branchName": "1.4.x", + "slug": "1.4", + "aliases": [ + "current", + "stable" + ], + "maintained": true, + "current": true + }, + { + "name": "1.3", + "branchName": "1.3.x", + "slug": "1.3", + "maintained": false + }, + { + "name": "1.2", + "branchName": "1.2.x", + "slug": "1.2" + }, + { + "name": "1.1", + "branchName": "1.1.x", + "slug": "1.1" + }, + { + "name": "1.0", + "branchName": "1.0.x", + "slug": "1.0" + } + ] +} diff --git a/vendor/doctrine/instantiator/CONTRIBUTING.md b/vendor/doctrine/instantiator/CONTRIBUTING.md index 75b84b2..c1a2c42 100644 --- a/vendor/doctrine/instantiator/CONTRIBUTING.md +++ b/vendor/doctrine/instantiator/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing - * Coding standard for the project is [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) + * Follow the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard) * The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php) * Any contribution must provide tests for additional introduced conditions * Any un-confirmed issue needs a failing test case before being accepted diff --git a/vendor/doctrine/instantiator/README.md b/vendor/doctrine/instantiator/README.md index b66064b..1fa9567 100644 --- a/vendor/doctrine/instantiator/README.md +++ b/vendor/doctrine/instantiator/README.md @@ -3,10 +3,8 @@ This library provides a way of avoiding usage of constructors when instantiating PHP classes. [![Build Status](https://travis-ci.org/doctrine/instantiator.svg?branch=master)](https://travis-ci.org/doctrine/instantiator) -[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master) +[![Code Coverage](https://codecov.io/gh/doctrine/instantiator/branch/master/graph/badge.svg)](https://codecov.io/gh/doctrine/instantiator/branch/master) [![Dependency Status](https://www.versioneye.com/package/php--doctrine--instantiator/badge.svg)](https://www.versioneye.com/package/php--doctrine--instantiator) -[![HHVM Status](http://hhvm.h4cc.de/badge/doctrine/instantiator.png)](http://hhvm.h4cc.de/package/doctrine/instantiator) [![Latest Stable Version](https://poser.pugx.org/doctrine/instantiator/v/stable.png)](https://packagist.org/packages/doctrine/instantiator) [![Latest Unstable Version](https://poser.pugx.org/doctrine/instantiator/v/unstable.png)](https://packagist.org/packages/doctrine/instantiator) @@ -16,7 +14,7 @@ This library provides a way of avoiding usage of constructors when instantiating The suggested installation method is via [composer](https://getcomposer.org/): ```sh -php composer.phar require "doctrine/instantiator:~1.0.3" +composer require doctrine/instantiator ``` ## Usage diff --git a/vendor/doctrine/instantiator/composer.json b/vendor/doctrine/instantiator/composer.json index 403ee8e..fab8172 100644 --- a/vendor/doctrine/instantiator/composer.json +++ b/vendor/doctrine/instantiator/composer.json @@ -3,7 +3,7 @@ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", "type": "library", "license": "MIT", - "homepage": "https://github.com/doctrine/instantiator", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ "instantiate", "constructor" @@ -12,18 +12,21 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "homepage": "https://ocramius.github.io/" } ], "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "require-dev": { "ext-phar": "*", "ext-pdo": "*", - "phpunit/phpunit": "^6.2.3", - "squizlabs/php_codesniffer": "^3.0.2", - "athletic/athletic": "~0.1.8" + "doctrine/coding-standard": "^9 || ^11", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" }, "autoload": { "psr-4": { @@ -37,9 +40,9 @@ "DoctrineTest\\InstantiatorTestAsset\\": "tests" } }, - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true } } } diff --git a/vendor/doctrine/instantiator/docs/en/index.rst b/vendor/doctrine/instantiator/docs/en/index.rst new file mode 100644 index 0000000..0c85da0 --- /dev/null +++ b/vendor/doctrine/instantiator/docs/en/index.rst @@ -0,0 +1,68 @@ +Introduction +============ + +This library provides a way of avoiding usage of constructors when instantiating PHP classes. + +Installation +============ + +The suggested installation method is via `composer`_: + +.. code-block:: console + + $ composer require doctrine/instantiator + +Usage +===== + +The instantiator is able to create new instances of any class without +using the constructor or any API of the class itself: + +.. code-block:: php + + instantiate(User::class); + +Contributing +============ + +- Follow the `Doctrine Coding Standard`_ +- The project will follow strict `object calisthenics`_ +- Any contribution must provide tests for additional introduced + conditions +- Any un-confirmed issue needs a failing test case before being + accepted +- Pull requests must be sent from a new hotfix/feature branch, not from + ``master``. + +Testing +======= + +The PHPUnit version to be used is the one installed as a dev- dependency +via composer: + +.. code-block:: console + + $ ./vendor/bin/phpunit + +Accepted coverage for new contributions is 80%. Any contribution not +satisfying this requirement won’t be merged. + +Credits +======= + +This library was migrated from `ocramius/instantiator`_, which has been +donated to the doctrine organization, and which is now deprecated in +favour of this package. + +.. _composer: https://getcomposer.org/ +.. _CONTRIBUTING.md: CONTRIBUTING.md +.. _ocramius/instantiator: https://github.com/Ocramius/Instantiator +.. _Doctrine Coding Standard: https://github.com/doctrine/coding-standard +.. _object calisthenics: http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php diff --git a/vendor/doctrine/instantiator/docs/en/sidebar.rst b/vendor/doctrine/instantiator/docs/en/sidebar.rst new file mode 100644 index 0000000..0c36479 --- /dev/null +++ b/vendor/doctrine/instantiator/docs/en/sidebar.rst @@ -0,0 +1,4 @@ +.. toctree:: + :depth: 3 + + index diff --git a/vendor/doctrine/instantiator/psalm.xml b/vendor/doctrine/instantiator/psalm.xml new file mode 100644 index 0000000..e9b622b --- /dev/null +++ b/vendor/doctrine/instantiator/psalm.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php index 3065375..e6a5195 100644 --- a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php @@ -1,29 +1,12 @@ . - */ namespace Doctrine\Instantiator\Exception; +use Throwable; + /** * Base exception marker interface for the instantiator component - * - * @author Marco Pivetta */ -interface ExceptionInterface +interface ExceptionInterface extends Throwable { } diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php index cb57aa8..33de31c 100644 --- a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php @@ -1,52 +1,50 @@ . - */ namespace Doctrine\Instantiator\Exception; use InvalidArgumentException as BaseInvalidArgumentException; use ReflectionClass; +use function interface_exists; +use function sprintf; +use function trait_exists; + /** * Exception for invalid arguments provided to the instantiator - * - * @author Marco Pivetta */ class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface { - public static function fromNonExistingClass(string $className) : self + public static function fromNonExistingClass(string $className): self { if (interface_exists($className)) { - return new self(sprintf('The provided type "%s" is an interface, and can not be instantiated', $className)); + return new self(sprintf('The provided type "%s" is an interface, and cannot be instantiated', $className)); } - if (PHP_VERSION_ID >= 50400 && trait_exists($className)) { - return new self(sprintf('The provided type "%s" is a trait, and can not be instantiated', $className)); + if (trait_exists($className)) { + return new self(sprintf('The provided type "%s" is a trait, and cannot be instantiated', $className)); } return new self(sprintf('The provided class "%s" does not exist', $className)); } - public static function fromAbstractClass(ReflectionClass $reflectionClass) : self + /** + * @phpstan-param ReflectionClass $reflectionClass + * + * @template T of object + */ + public static function fromAbstractClass(ReflectionClass $reflectionClass): self { return new self(sprintf( - 'The provided class "%s" is abstract, and can not be instantiated', + 'The provided class "%s" is abstract, and cannot be instantiated', $reflectionClass->getName() )); } + + public static function fromEnum(string $className): self + { + return new self(sprintf( + 'The provided class "%s" is an enum, and cannot be instantiated', + $className + )); + } } diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php index 2b704b9..4e55ac5 100644 --- a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php @@ -1,21 +1,4 @@ . - */ namespace Doctrine\Instantiator\Exception; @@ -23,17 +6,22 @@ use ReflectionClass; use UnexpectedValueException as BaseUnexpectedValueException; +use function sprintf; + /** * Exception for given parameters causing invalid/unexpected state on instantiation - * - * @author Marco Pivetta */ class UnexpectedValueException extends BaseUnexpectedValueException implements ExceptionInterface { + /** + * @phpstan-param ReflectionClass $reflectionClass + * + * @template T of object + */ public static function fromSerializationTriggeredException( ReflectionClass $reflectionClass, Exception $exception - ) : self { + ): self { return new self( sprintf( 'An exception was raised while trying to instantiate an instance of "%s" via un-serialization', @@ -44,13 +32,18 @@ public static function fromSerializationTriggeredException( ); } + /** + * @phpstan-param ReflectionClass $reflectionClass + * + * @template T of object + */ public static function fromUncleanUnSerialization( ReflectionClass $reflectionClass, string $errorString, int $errorCode, string $errorFile, int $errorLine - ) : self { + ): self { return new self( sprintf( 'Could not produce an instance of "%s" via un-serialization, since an error was triggered ' diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php index 69fe65d..10067a0 100644 --- a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php @@ -1,61 +1,73 @@ . - */ namespace Doctrine\Instantiator; +use ArrayIterator; +use Doctrine\Instantiator\Exception\ExceptionInterface; use Doctrine\Instantiator\Exception\InvalidArgumentException; use Doctrine\Instantiator\Exception\UnexpectedValueException; use Exception; use ReflectionClass; +use ReflectionException; +use Serializable; + +use function class_exists; +use function enum_exists; +use function is_subclass_of; +use function restore_error_handler; +use function set_error_handler; +use function sprintf; +use function strlen; +use function unserialize; + +use const PHP_VERSION_ID; -/** - * {@inheritDoc} - * - * @author Marco Pivetta - */ final class Instantiator implements InstantiatorInterface { /** * Markers used internally by PHP to define whether {@see \unserialize} should invoke * the method {@see \Serializable::unserialize()} when dealing with classes implementing * the {@see \Serializable} interface. + * + * @deprecated This constant will be private in 2.0 */ - const SERIALIZATION_FORMAT_USE_UNSERIALIZER = 'C'; - const SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O'; + public const SERIALIZATION_FORMAT_USE_UNSERIALIZER = 'C'; + + /** @deprecated This constant will be private in 2.0 */ + public const SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O'; /** - * @var \callable[] used to instantiate specific classes, indexed by class name + * Used to instantiate specific classes, indexed by class name. + * + * @var callable[] */ private static $cachedInstantiators = []; /** - * @var object[] of objects that can directly be cloned, indexed by class name + * Array of objects that can directly be cloned, indexed by class name. + * + * @var object[] */ private static $cachedCloneables = []; /** - * {@inheritDoc} + * @param string $className + * @phpstan-param class-string $className + * + * @return object + * @phpstan-return T + * + * @throws ExceptionInterface + * + * @template T of object */ public function instantiate($className) { if (isset(self::$cachedCloneables[$className])) { - return clone self::$cachedCloneables[$className]; + /** @phpstan-var T */ + $cachedCloneable = self::$cachedCloneables[$className]; + + return clone $cachedCloneable; } if (isset(self::$cachedInstantiators[$className])) { @@ -70,7 +82,12 @@ public function instantiate($className) /** * Builds the requested object and caches it in static properties for performance * + * @phpstan-param class-string $className + * * @return object + * @phpstan-return T + * + * @template T of object */ private function buildAndCacheFromFactory(string $className) { @@ -88,11 +105,17 @@ private function buildAndCacheFromFactory(string $className) * Builds a callable capable of instantiating the given $className without * invoking its constructor. * + * @phpstan-param class-string $className + * + * @phpstan-return callable(): T + * * @throws InvalidArgumentException * @throws UnexpectedValueException - * @throws \ReflectionException + * @throws ReflectionException + * + * @template T of object */ - private function buildFactory(string $className) : callable + private function buildFactory(string $className): callable { $reflectionClass = $this->getReflectionClass($className); @@ -102,32 +125,38 @@ private function buildFactory(string $className) : callable $serializedString = sprintf( '%s:%d:"%s":0:{}', - self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER, + is_subclass_of($className, Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER, strlen($className), $className ); $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString); - return function () use ($serializedString) { + return static function () use ($serializedString) { return unserialize($serializedString); }; } /** - * @param string $className + * @phpstan-param class-string $className * - * @return ReflectionClass + * @phpstan-return ReflectionClass * * @throws InvalidArgumentException - * @throws \ReflectionException + * @throws ReflectionException + * + * @template T of object */ - private function getReflectionClass($className) : ReflectionClass + private function getReflectionClass(string $className): ReflectionClass { if (! class_exists($className)) { throw InvalidArgumentException::fromNonExistingClass($className); } + if (PHP_VERSION_ID >= 80100 && enum_exists($className, false)) { + throw InvalidArgumentException::fromEnum($className); + } + $reflection = new ReflectionClass($className); if ($reflection->isAbstract()) { @@ -138,16 +167,15 @@ private function getReflectionClass($className) : ReflectionClass } /** - * @param ReflectionClass $reflectionClass - * @param string $serializedString + * @phpstan-param ReflectionClass $reflectionClass * * @throws UnexpectedValueException * - * @return void + * @template T of object */ - private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, $serializedString) : void + private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString): void { - set_error_handler(function ($code, $message, $file, $line) use ($reflectionClass, & $error) : void { + set_error_handler(static function (int $code, string $message, string $file, int $line) use ($reflectionClass, &$error): bool { $error = UnexpectedValueException::fromUncleanUnSerialization( $reflectionClass, $message, @@ -155,11 +183,15 @@ private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionCl $file, $line ); - }); - $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString); + return true; + }); - restore_error_handler(); + try { + $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString); + } finally { + restore_error_handler(); + } if ($error) { throw $error; @@ -167,39 +199,47 @@ private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionCl } /** - * @param ReflectionClass $reflectionClass - * @param string $serializedString + * @phpstan-param ReflectionClass $reflectionClass * * @throws UnexpectedValueException * - * @return void + * @template T of object */ - private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, $serializedString) : void + private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString): void { try { unserialize($serializedString); } catch (Exception $exception) { - restore_error_handler(); - throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception); } } - private function isInstantiableViaReflection(ReflectionClass $reflectionClass) : bool + /** + * @phpstan-param ReflectionClass $reflectionClass + * + * @template T of object + */ + private function isInstantiableViaReflection(ReflectionClass $reflectionClass): bool { return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal()); } /** * Verifies whether the given class is to be considered internal + * + * @phpstan-param ReflectionClass $reflectionClass + * + * @template T of object */ - private function hasInternalAncestors(ReflectionClass $reflectionClass) : bool + private function hasInternalAncestors(ReflectionClass $reflectionClass): bool { do { if ($reflectionClass->isInternal()) { return true; } - } while ($reflectionClass = $reflectionClass->getParentClass()); + + $reflectionClass = $reflectionClass->getParentClass(); + } while ($reflectionClass); return false; } @@ -208,9 +248,15 @@ private function hasInternalAncestors(ReflectionClass $reflectionClass) : bool * Checks if a class is cloneable * * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects. + * + * @phpstan-param ReflectionClass $reflectionClass + * + * @template T of object */ - private function isSafeToClone(ReflectionClass $reflection) : bool + private function isSafeToClone(ReflectionClass $reflectionClass): bool { - return $reflection->isCloneable() && ! $reflection->hasMethod('__clone'); + return $reflectionClass->isCloneable() + && ! $reflectionClass->hasMethod('__clone') + && ! $reflectionClass->isSubclassOf(ArrayIterator::class); } } diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php index b665bea..10508b5 100644 --- a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php @@ -1,37 +1,24 @@ . - */ namespace Doctrine\Instantiator; +use Doctrine\Instantiator\Exception\ExceptionInterface; + /** * Instantiator provides utility methods to build objects without invoking their constructors - * - * @author Marco Pivetta */ interface InstantiatorInterface { /** * @param string $className + * @phpstan-param class-string $className * * @return object + * @phpstan-return T + * + * @throws ExceptionInterface * - * @throws \Doctrine\Instantiator\Exception\ExceptionInterface + * @template T of object */ public function instantiate($className); } diff --git a/vendor/doctrine/lexer/LICENSE b/vendor/doctrine/lexer/LICENSE new file mode 100644 index 0000000..e8fdec4 --- /dev/null +++ b/vendor/doctrine/lexer/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2018 Doctrine Project + +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/vendor/doctrine/lexer/README.md b/vendor/doctrine/lexer/README.md new file mode 100644 index 0000000..784f2a2 --- /dev/null +++ b/vendor/doctrine/lexer/README.md @@ -0,0 +1,9 @@ +# Doctrine Lexer + +[![Build Status](https://github.com/doctrine/lexer/workflows/Continuous%20Integration/badge.svg)](https://github.com/doctrine/lexer/actions) + +Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers. + +This lexer is used in Doctrine Annotations and in Doctrine ORM (DQL). + +https://www.doctrine-project.org/projects/lexer.html diff --git a/vendor/doctrine/lexer/UPGRADE.md b/vendor/doctrine/lexer/UPGRADE.md new file mode 100644 index 0000000..42b85b3 --- /dev/null +++ b/vendor/doctrine/lexer/UPGRADE.md @@ -0,0 +1,14 @@ +Note about upgrading: Doctrine uses static and runtime mechanisms to raise +awareness about deprecated code. + +- Use of `@deprecated` docblock that is detected by IDEs (like PHPStorm) or + Static Analysis tools (like Psalm, phpstan) +- Use of our low-overhead runtime deprecation API, details: + https://github.com/doctrine/deprecations/ + +# Upgrade to 2.0.0 + +`AbstractLexer::glimpse()` and `AbstractLexer::peek()` now return +instances of `Doctrine\Common\Lexer\Token`, which is an array-like class +Using it as an array is deprecated in favor of using properties of that class. +Using `count()` on it is deprecated with no replacement. diff --git a/vendor/doctrine/lexer/composer.json b/vendor/doctrine/lexer/composer.json new file mode 100644 index 0000000..be3013c --- /dev/null +++ b/vendor/doctrine/lexer/composer.json @@ -0,0 +1,56 @@ +{ + "name": "doctrine/lexer", + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "license": "MIT", + "type": "library", + "keywords": [ + "php", + "parser", + "lexer", + "annotations", + "docblock" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "require": { + "php": "^7.1 || ^8.0", + "doctrine/deprecations": "^1.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Tests\\Common\\Lexer\\": "tests" + } + }, + "config": { + "allow-plugins": { + "composer/package-versions-deprecated": true, + "dealerdirect/phpcodesniffer-composer-installer": true + }, + "sort-packages": true + } +} diff --git a/vendor/doctrine/lexer/src/AbstractLexer.php b/vendor/doctrine/lexer/src/AbstractLexer.php new file mode 100644 index 0000000..eed4c51 --- /dev/null +++ b/vendor/doctrine/lexer/src/AbstractLexer.php @@ -0,0 +1,346 @@ +> + */ + private $tokens = []; + + /** + * Current lexer position in input string. + * + * @var int + */ + private $position = 0; + + /** + * Current peek of current lexer position. + * + * @var int + */ + private $peek = 0; + + /** + * The next token in the input. + * + * @var mixed[]|null + * @psalm-var Token|null + */ + public $lookahead; + + /** + * The last matched/seen token. + * + * @var mixed[]|null + * @psalm-var Token|null + */ + public $token; + + /** + * Composed regex for input parsing. + * + * @var string|null + */ + private $regex; + + /** + * Sets the input data to be tokenized. + * + * The Lexer is immediately reset and the new input tokenized. + * Any unprocessed tokens from any previous input are lost. + * + * @param string $input The input to be tokenized. + * + * @return void + */ + public function setInput($input) + { + $this->input = $input; + $this->tokens = []; + + $this->reset(); + $this->scan($input); + } + + /** + * Resets the lexer. + * + * @return void + */ + public function reset() + { + $this->lookahead = null; + $this->token = null; + $this->peek = 0; + $this->position = 0; + } + + /** + * Resets the peek pointer to 0. + * + * @return void + */ + public function resetPeek() + { + $this->peek = 0; + } + + /** + * Resets the lexer position on the input to the given position. + * + * @param int $position Position to place the lexical scanner. + * + * @return void + */ + public function resetPosition($position = 0) + { + $this->position = $position; + } + + /** + * Retrieve the original lexer's input until a given position. + * + * @param int $position + * + * @return string + */ + public function getInputUntilPosition($position) + { + return substr($this->input, 0, $position); + } + + /** + * Checks whether a given token matches the current lookahead. + * + * @param T $type + * + * @return bool + * + * @psalm-assert-if-true !=null $this->lookahead + */ + public function isNextToken($type) + { + return $this->lookahead !== null && $this->lookahead->isA($type); + } + + /** + * Checks whether any of the given tokens matches the current lookahead. + * + * @param list $types + * + * @return bool + * + * @psalm-assert-if-true !=null $this->lookahead + */ + public function isNextTokenAny(array $types) + { + return $this->lookahead !== null && $this->lookahead->isA(...$types); + } + + /** + * Moves to the next token in the input string. + * + * @return bool + * + * @psalm-assert-if-true !null $this->lookahead + */ + public function moveNext() + { + $this->peek = 0; + $this->token = $this->lookahead; + $this->lookahead = isset($this->tokens[$this->position]) + ? $this->tokens[$this->position++] : null; + + return $this->lookahead !== null; + } + + /** + * Tells the lexer to skip input tokens until it sees a token with the given value. + * + * @param T $type The token type to skip until. + * + * @return void + */ + public function skipUntil($type) + { + while ($this->lookahead !== null && ! $this->lookahead->isA($type)) { + $this->moveNext(); + } + } + + /** + * Checks if given value is identical to the given token. + * + * @param string $value + * @param int|string $token + * + * @return bool + */ + public function isA($value, $token) + { + return $this->getType($value) === $token; + } + + /** + * Moves the lookahead token forward. + * + * @return mixed[]|null The next token or NULL if there are no more tokens ahead. + * @psalm-return Token|null + */ + public function peek() + { + if (isset($this->tokens[$this->position + $this->peek])) { + return $this->tokens[$this->position + $this->peek++]; + } + + return null; + } + + /** + * Peeks at the next token, returns it and immediately resets the peek. + * + * @return mixed[]|null The next token or NULL if there are no more tokens ahead. + * @psalm-return Token|null + */ + public function glimpse() + { + $peek = $this->peek(); + $this->peek = 0; + + return $peek; + } + + /** + * Scans the input string for tokens. + * + * @param string $input A query string. + * + * @return void + */ + protected function scan($input) + { + if (! isset($this->regex)) { + $this->regex = sprintf( + '/(%s)|%s/%s', + implode(')|(', $this->getCatchablePatterns()), + implode('|', $this->getNonCatchablePatterns()), + $this->getModifiers() + ); + } + + $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; + $matches = preg_split($this->regex, $input, -1, $flags); + + if ($matches === false) { + // Work around https://bugs.php.net/78122 + $matches = [[$input, 0]]; + } + + foreach ($matches as $match) { + // Must remain before 'value' assignment since it can change content + $firstMatch = $match[0]; + $type = $this->getType($firstMatch); + + $this->tokens[] = new Token( + $firstMatch, + $type, + $match[1] + ); + } + } + + /** + * Gets the literal for a given token. + * + * @param T $token + * + * @return int|string + */ + public function getLiteral($token) + { + if ($token instanceof UnitEnum) { + return get_class($token) . '::' . $token->name; + } + + $className = static::class; + + $reflClass = new ReflectionClass($className); + $constants = $reflClass->getConstants(); + + foreach ($constants as $name => $value) { + if ($value === $token) { + return $className . '::' . $name; + } + } + + return $token; + } + + /** + * Regex modifiers + * + * @return string + */ + protected function getModifiers() + { + return 'iu'; + } + + /** + * Lexical catchable patterns. + * + * @return string[] + */ + abstract protected function getCatchablePatterns(); + + /** + * Lexical non-catchable patterns. + * + * @return string[] + */ + abstract protected function getNonCatchablePatterns(); + + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * + * @return T|null + * + * @param-out V $value + */ + abstract protected function getType(&$value); +} diff --git a/vendor/doctrine/lexer/src/Token.php b/vendor/doctrine/lexer/src/Token.php new file mode 100644 index 0000000..4fbbf4e --- /dev/null +++ b/vendor/doctrine/lexer/src/Token.php @@ -0,0 +1,145 @@ + + */ +final class Token implements ArrayAccess +{ + /** + * The string value of the token in the input string + * + * @readonly + * @var V + */ + public $value; + + /** + * The type of the token (identifier, numeric, string, input parameter, none) + * + * @readonly + * @var T|null + */ + public $type; + + /** + * The position of the token in the input string + * + * @readonly + * @var int + */ + public $position; + + /** + * @param V $value + * @param T|null $type + */ + public function __construct($value, $type, int $position) + { + $this->value = $value; + $this->type = $type; + $this->position = $position; + } + + /** @param T ...$types */ + public function isA(...$types): bool + { + return in_array($this->type, $types, true); + } + + /** + * @deprecated Use the value, type or position property instead + * {@inheritDoc} + */ + public function offsetExists($offset): bool + { + Deprecation::trigger( + 'doctrine/lexer', + 'https://github.com/doctrine/lexer/pull/79', + 'Accessing %s properties via ArrayAccess is deprecated, use the value, type or position property instead', + self::class + ); + + return in_array($offset, ['value', 'type', 'position'], true); + } + + /** + * @deprecated Use the value, type or position property instead + * {@inheritDoc} + * + * @param O $offset + * + * @return mixed + * @psalm-return ( + * O is 'value' + * ? V + * : ( + * O is 'type' + * ? T|null + * : ( + * O is 'position' + * ? int + * : mixed + * ) + * ) + * ) + * + * @template O of array-key + */ + #[ReturnTypeWillChange] + public function offsetGet($offset) + { + Deprecation::trigger( + 'doctrine/lexer', + 'https://github.com/doctrine/lexer/pull/79', + 'Accessing %s properties via ArrayAccess is deprecated, use the value, type or position property instead', + self::class + ); + + return $this->$offset; + } + + /** + * @deprecated no replacement planned + * {@inheritDoc} + */ + public function offsetSet($offset, $value): void + { + Deprecation::trigger( + 'doctrine/lexer', + 'https://github.com/doctrine/lexer/pull/79', + 'Setting %s properties via ArrayAccess is deprecated', + self::class + ); + + $this->$offset = $value; + } + + /** + * @deprecated no replacement planned + * {@inheritDoc} + */ + public function offsetUnset($offset): void + { + Deprecation::trigger( + 'doctrine/lexer', + 'https://github.com/doctrine/lexer/pull/79', + 'Setting %s properties via ArrayAccess is deprecated', + self::class + ); + + $this->$offset = null; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/.php_cs b/vendor/friendsofphp/php-cs-fixer/.php_cs deleted file mode 100644 index 53c3b69..0000000 --- a/vendor/friendsofphp/php-cs-fixer/.php_cs +++ /dev/null @@ -1,34 +0,0 @@ - - Dariusz Rumiński - -This source file is subject to the MIT license that is bundled -with this source code in the file LICENSE. -EOF; - -Symfony\CS\Fixer\Contrib\HeaderCommentFixer::setHeader($header); - -return Symfony\CS\Config::create() - // use default SYMFONY_LEVEL and extra fixers: - ->fixers(array( - 'combine_consecutive_unsets', - 'header_comment', - 'long_array_syntax', - 'no_useless_else', - 'no_useless_return', - 'ordered_use', - 'php_unit_construct', - 'php_unit_strict', - 'strict', - 'strict_param', - )) - ->finder( - Symfony\CS\Finder::create() - ->exclude('Symfony/CS/Tests/Fixtures') - ->in(__DIR__) - ) -; diff --git a/vendor/friendsofphp/php-cs-fixer/CHANGELOG.md b/vendor/friendsofphp/php-cs-fixer/CHANGELOG.md index ced9c93..5129158 100644 --- a/vendor/friendsofphp/php-cs-fixer/CHANGELOG.md +++ b/vendor/friendsofphp/php-cs-fixer/CHANGELOG.md @@ -3,6 +3,3181 @@ CHANGELOG for PHP CS Fixer This file contains changelogs for stable releases only. +Changelog for v2.19.3 +--------------------- + +* minor #6060 DX: Add upgrade guide link when next Major is available (keradus) + +Changelog for v2.19.2 +--------------------- + +* bug #5881 SelfUpdateCommand - fix link to UPGRADE docs (keradus) + +Changelog for v2.19.1 +--------------------- + +* bug #5395 PhpdocTagTypeFixer: Do not modify array shapes (localheinz, julienfalque) +* bug #5678 UseArrowFunctionsFixer - fix for return without value (kubawerlos) +* bug #5679 PhpUnitNamespacedFixer - do not try to fix constant usage (kubawerlos) +* bug #5681 RegularCallableCallFixer - fix for function name with escaped slash (kubawerlos) +* bug #5687 FinalInternalClassFixer - fix for annotation with space after "@" (kubawerlos) +* bug #5688 ArrayIndentationFixer - fix for really long arrays (kubawerlos) +* bug #5690 PhpUnitNoExpectationAnnotationFixer - fix "expectedException" annotation with message below (kubawerlos) +* bug #5693 YodaStyleFixer - fix for assignment operators (kubawerlos) +* bug #5697 StrictParamFixer - fix for method definition (kubawerlos) +* bug #5702 CommentToPhpdocFixer - fix for single line comments starting with more than 2 slashes (kubawerlos) +* bug #5703 DateTimeImmutableFixer - fix for method definition (kubawerlos) +* bug #5718 VoidReturnFixer - do not break syntax with magic methods (kubawerlos) +* bug #5727 SingleSpaceAfterConstructFixer - Add support for `namespace` (julienfalque) +* bug #5730 Fix transforming deprecations into exceptions (julienfalque) +* bug #5738 TokensAnalyzer - fix for union types (kubawerlos) +* bug #5741 Fix constant invocation detection cases (kubawerlos) +* bug #5769 Fix priority between `phpdoc_to_property_type` and `no_superfluous_phpdoc_tags` (julienfalque) +* bug #5774 FunctionsAnalyzer::isTheSameClassCall - fix for $this with double colon following (kubawerlos) +* bug #5779 SingleLineThrowFixer - fix for throw in match (kubawerlos) +* bug #5781 ClassDefinition - fix for anonymous class with trailing comma (kubawerlos) +* bug #5783 StaticLambdaFixer - consider parent:: as a possible reference to $this (fancyweb) +* bug #5791 NoBlankLinesAfterPhpdoc - Add T_NAMESPACE in array of forbidden successors (paulbalandan) +* bug #5799 TypeAlternationTransformer - fix for multiple function parameters (kubawerlos) +* bug #5804 NoBreakCommentFixer - fix for "default" in "match" (kubawerlos) +* bug #5805 SingleLineCommentStyleFixer - run after HeaderCommentFixer (kubawerlos) +* bug #5817 NativeFunctionTypeDeclarationCasingFixer - fix for union types (kubawerlos) +* bug #5823 YodaStyleFixer - yield support (SpacePossum) +* minor #4914 Improve PHPDoc types support (julienfalque, keradus) +* minor #5680 DX: benchmark.sh - ensure deps are updated to enable script working across less-similar branches (keradus) +* minor #5689 Calculate code coverage on PHP 8 (kubawerlos) +* minor #5694 DX: fail on risky tests (kubawerlos) +* minor #5695 Utils - save only unique deprecations to avoid memory issues (PetrHeinz) +* minor #5710 [typo] add correct backquotes (PhilETaylor) +* minor #5717 Run migration rules on PHP 8 (kubawerlos, keradus) +* minor #5721 Fix reStructuredText markup (julienfalque) +* minor #5725 Update LICENSE (exussum12) +* minor #5731 CI - Fix checkbashisms installation (julienfalque) +* minor #5740 DX: more type-related docblocks (keradus) +* minor #5746 Config - Improve deprecation message with details (SpacePossum) +* minor #5747 RandomApiMigrationFixer - better docs and better "random_int" support (SpacePossum) +* minor #5748 Updated the link to netbeans plugins page (cyberguroo) +* minor #5750 Test all const are in uppercase (SpacePossum) +* minor #5752 NoNullPropertyInitializationFixer - fix static properties as well (HypeMC) +* minor #5756 Fix rule sets descriptions (kubawerlos) +* minor #5761 Fix links in custom rules documentation (julienfalque) +* minor #5777 DX: update PHPStan (kubawerlos) +* minor #5789 DX: update PHPStan (kubawerlos) +* minor #5808 Update PHPStan to 0.12.92 (kubawerlos) +* minor #5824 Deprecate v2 (keradus) +* minor #5825 DX: update checkbashisms to v2.21.3 (keradus) +* minor #5826 SCA: check both composer files (keradus) +* minor #5827 ClassAttributesSeparationFixer - Add `trait_import` support (SpacePossum) + +Changelog for v2.19.0 +--------------------- + +* feature #4238 TrailingCommaInMultilineFixer - introduction (kubawerlos) +* feature #4592 PhpdocToPropertyTypeFixer - introduction (julienfalque) +* feature #5390 feature #4024 added a `list-files` command (clxmstaab, keradus) +* feature #5635 Add list-sets command (keradus) +* feature #5674 UX: Display deprecations to end-user (keradus) +* minor #5601 Always stop when "PHP_CS_FIXER_FUTURE_MODE" is used (kubawerlos) +* minor #5607 DX: new config filename (keradus) +* minor #5613 DX: UtilsTest - add missing teardown (keradus) +* minor #5631 DX: config deduplication (keradus) +* minor #5633 fix typos (staabm) +* minor #5642 Deprecate parameter of Token::toJson() (keradus) +* minor #5672 DX: do not test deprecated fixer (kubawerlos) + +Changelog for v2.18.7 +--------------------- + +* bug #5593 SingleLineThrowFixer - fix handling anonymous classes (kubawerlos) +* bug #5654 SingleLineThrowFixer - fix for match expression (kubawerlos) +* bug #5660 TypeAlternationTransformer - fix for "array" type in type alternation (kubawerlos) +* bug #5665 NullableTypeDeclarationForDefaultNullValueFixer - fix for nullable with attribute (kubawerlos) +* bug #5670 PhpUnitNamespacedFixer - do not try to fix constant (kubawerlos) +* bug #5671 PhpdocToParamTypeFixer - do not change function call (kubawerlos) +* bug #5673 GroupImportFixer - Fix failing case (julienfalque) +* minor #4591 Refactor conversion of PHPDoc to type declarations (julienfalque, keradus) +* minor #5611 DX: use method expectDeprecation from Symfony Bridge instead of annotation (kubawerlos) +* minor #5658 DX: use constants in tests for Fixer configuration (keradus) +* minor #5661 DX: remove PHPStan exceptions for "tests" from phpstan.neon (kubawerlos) +* minor #5662 Change wording from "merge" to "intersect" (jschaedl) +* minor #5663 DX: do not abuse "inheritdoc" tag (kubawerlos) +* minor #5664 DX: code grooming (keradus) + +Changelog for v2.18.6 +--------------------- + +* bug #5586 Add support for nullsafe object operator ("?->") (kubawerlos) +* bug #5597 Tokens - fix for checking block edges (kubawerlos) +* bug #5604 Custom annotations @type changed into @var (Leprechaunz) +* bug #5606 DoctrineAnnotationBracesFixer false positive (Leprechaunz) +* bug #5610 BracesFixer - fix braces of match expression (Leprechaunz) +* bug #5615 GroupImportFixer severely broken (Leprechaunz) +* bug #5617 ClassAttributesSeparationFixer - fix for using visibility for class elements (kubawerlos) +* bug #5618 GroupImportFixer - fix removal of import type when mixing multiple types (Leprechaunz) +* bug #5622 Exclude Doctrine documents from final fixer (ossinkine) +* bug #5630 PhpdocTypesOrderFixer - handle complex keys (Leprechaunz) +* minor #5554 DX: use tmp file in sys_temp_dir for integration tests (keradus) +* minor #5564 DX: make integration tests matching entries in FixerFactoryTest (kubawerlos) +* minor #5603 DX: DocumentationGenerator - no need to re-configure Differ (keradus) +* minor #5612 DX: use ::class whenever possible (kubawerlos) +* minor #5619 DX: allow XDebugHandler v2 (keradus) +* minor #5623 DX: when displaying app version, don't put extra space if there is no CODENAME available (keradus) +* minor #5626 DX: update PHPStan and way of ignoring flickering PHPStan exception (keradus) +* minor #5629 DX: fix CiIntegrationTest (keradus) +* minor #5636 DX: remove 'create' method in internal classes (keradus) +* minor #5637 DX: do not calculate bitmap via helper anymore (keradus) +* minor #5639 Move fix reports (classes and schemas) (keradus) +* minor #5640 DX: use constants for PHPUnit version (keradus) +* minor #5646 Cleanup YodaStyleFixerTest (kubawerlos) + +Changelog for v2.18.5 +--------------------- + +* bug #5561 NoMixedEchoPrintFixer: fix for conditions without curly brackets (kubawerlos) +* bug #5563 Priority fix: SingleSpaceAfterConstructFixer must run before BracesFixer (kubawerlos) +* bug #5567 Fix order of BracesFixer and ClassDefinitionFixer (Daeroni) +* bug #5596 NullableTypeTransformer - fix for attributes (kubawerlos, jrmajor) +* bug #5598 GroupImportFixer - fix breaking code when fixing root classes (Leprechaunz) +* minor #5571 DX: add test to make sure SingleSpaceAfterConstructFixer runs before FunctionDeclarationFixer (kubawerlos) +* minor #5577 Extend priority test for "class_definition" vs "braces" (kubawerlos) +* minor #5585 DX: make doc examples prettier (kubawerlos) +* minor #5590 Docs: HeaderCommentFixer - document example how to remove header comment (keradus) +* minor #5602 DX: regenerate docs (keradus) + +Changelog for v2.18.4 +--------------------- + +* bug #4085 Priority: AlignMultilineComment should run before every PhpdocFixer (dmvdbrugge) +* bug #5421 PsrAutoloadingFixer - Fix PSR autoloading outside configured directory (kelunik, keradus) +* bug #5464 NativeFunctionInvocationFixer - PHP 8 attributes (HypeMC, keradus) +* bug #5548 NullableTypeDeclarationForDefaultNullValueFixer - fix handling promoted properties (jrmajor, keradus) +* bug #5550 TypeAlternationTransformer - fix for typed static properties (kubawerlos) +* bug #5551 ClassAttributesSeparationFixer - fix for properties with type alternation (kubawerlos, keradus) +* bug #5552 DX: test relation between function_declaration and method_argument_space (keradus) +* minor #5540 DX: RuleSet - convert null handling to soft-warning (keradus) +* minor #5545 DX: update checkbashisms (keradus) + +Changelog for v2.18.3 +--------------------- + +* bug #5484 NullableTypeDeclarationForDefaultNullValueFixer - handle mixed pseudotype (keradus) +* minor #5470 Disable CI fail-fast (mvorisek) +* minor #5491 Support php8 static return type for NoSuperfluousPhpdocTagsFixer (tigitz) +* minor #5494 BinaryOperatorSpacesFixer - extend examples (keradus) +* minor #5499 DX: add TODOs for PHP requirements cleanup (keradus) +* minor #5500 DX: Test that Transformers are adding only CustomTokens that they define and nothing else (keradus) +* minor #5507 Fix quoting in exception message (gquemener) +* minor #5514 DX: PHP 7.0 integration test - solve TODO for random_api_migration usage (keradus) +* minor #5515 DX: do not override getConfigurationDefinition (keradus) +* minor #5516 DX: AbstractDoctrineAnnotationFixer - no need for import aliases (keradus) +* minor #5518 DX: minor typing and validation fixes (keradus) +* minor #5522 Token - add handling json_encode crash (keradus) +* minor #5523 DX: EregToPregFixer - fix sorting (keradus) +* minor #5528 DX: code cleanup (keradus) + +Changelog for v2.18.2 +--------------------- + +* bug #5466 Fix runtime check of PHP version (keradus) +* minor #4250 POC Tokens::insertSlices (keradus) + +Changelog for v2.18.1 +--------------------- + +* bug #5447 switch_case_semicolon_to_colon should skip match/default statements (derrabus) +* bug #5453 SingleSpaceAfterConstructFixer - better handling of closing parenthesis and brace (keradus) +* bug #5454 NullableTypeDeclarationForDefaultNullValueFixer - support property promotion via constructor (keradus) +* bug #5455 PhpdocToCommentFixer - add support for attributes (keradus) +* bug #5462 NullableTypeDeclarationForDefaultNullValueFixer - support union types (keradus) +* minor #5444 Fix PHP version number in PHP54MigrationSet description (jdreesen, keradus) +* minor #5445 DX: update usage of old TraversableContains in tests (keradus) +* minor #5456 DX: Fix CiIntegrationTest (keradus) +* minor #5457 CI: fix params order (keradus) +* minor #5458 CI: fix migration workflow (keradus) +* minor #5459 DX: cleanup PHP Migration rulesets (keradus) + +Changelog for v2.18.0 +--------------------- + +* feature #4943 Add PSR12 ruleset (julienfalque, keradus) +* feature #5426 Update Symfony ruleset (keradus) +* feature #5428 Add/Change PHP.MigrationSet to update array/list syntax to short one (keradus) +* minor #5441 Allow execution under PHP 8 (keradus) + +Changelog for v2.17.5 +--------------------- + +* bug #5447 switch_case_semicolon_to_colon should skip match/default statements (derrabus) +* bug #5453 SingleSpaceAfterConstructFixer - better handling of closing parenthesis and brace (keradus) +* bug #5454 NullableTypeDeclarationForDefaultNullValueFixer - support property promotion via constructor (keradus) +* bug #5455 PhpdocToCommentFixer - add support for attributes (keradus) +* bug #5462 NullableTypeDeclarationForDefaultNullValueFixer - support union types (keradus) +* minor #5445 DX: update usage of old TraversableContains in tests (keradus) +* minor #5456 DX: Fix CiIntegrationTest (keradus) +* minor #5457 CI: fix params order (keradus) +* minor #5459 DX: cleanup PHP Migration rulesets (keradus) + +Changelog for v2.17.4 +--------------------- + +* bug #5379 PhpUnitMethodCasingFixer - Do not modify class name (localheinz) +* bug #5404 NullableTypeTransformer - constructor property promotion support (Wirone) +* bug #5433 PhpUnitTestCaseStaticMethodCallsFixer - fix for abstract static method (kubawerlos) +* minor #5234 DX: Add Docker dev setup (julienfalque, keradus) +* minor #5391 PhpdocOrderByValueFixer - Add additional annotations to sort (localheinz) +* minor #5392 PhpdocScalarFixer - Fix description (localheinz) +* minor #5397 NoExtraBlankLinesFixer - PHP8 throw support (SpacePossum) +* minor #5399 Add PHP8 integration test (keradus) +* minor #5405 TypeAlternationTransformer - add support for PHP8 (SpacePossum) +* minor #5406 SingleSpaceAfterConstructFixer - Attributes, comments and PHPDoc support (SpacePossum) +* minor #5407 TokensAnalyzer::getClassyElements - return trait imports (SpacePossum) +* minor #5410 minors (SpacePossum) +* minor #5411 bump year in LICENSE file (SpacePossum) +* minor #5414 TypeAlternationTransformer - T_FN support (SpacePossum) +* minor #5415 Forbid execution under PHP 8.0.0 (keradus) +* minor #5416 Drop Travis CI (keradus) +* minor #5419 CI: separate SCA checks to dedicated jobs (keradus) +* minor #5420 DX: unblock PHPUnit 9.5 (keradus) +* minor #5423 DX: PHPUnit - disable verbose by default (keradus) +* minor #5425 Cleanup 3.0 todos (keradus) +* minor #5427 Plan changing defaults for array_syntax and list_syntax in 3.0 release (keradus) +* minor #5429 DX: Drop speedtrap PHPUnit listener (keradus) +* minor #5432 Don't allow unserializing classes with a destructor (jderusse) +* minor #5435 DX: PHPUnit - groom configuration of time limits (keradus) +* minor #5439 VisibilityRequiredFixer - support type alternation for properties (keradus) +* minor #5442 DX: FunctionsAnalyzerTest - add missing 7.0 requirement (keradus) + +Changelog for v2.17.3 +--------------------- + +* bug #5384 PsrAutoloadingFixer - do not remove directory structure from the Class name (kubawerlos, keradus) +* bug #5385 SingleLineCommentStyleFixer- run before NoUselessReturnFixer (kubawerlos) +* bug #5387 SingleSpaceAfterConstructFixer - do not touch multi line implements (SpacePossum) +* minor #5329 DX: collect coverage with Github Actions (kubawerlos) +* minor #5380 PhpdocOrderByValueFixer - Allow sorting of throws annotations by value (localheinz, keradus) +* minor #5383 DX: fail PHPUnit tests on warning (kubawerlos) +* minor #5386 DX: remove incorrect priority relations (kubawerlos) + +Changelog for v2.17.2 +--------------------- + +* bug #5345 CleanNamespaceFixer - preserve traling comments (SpacePossum) +* bug #5348 PsrAutoloadingFixer - fix for class without namespace (kubawerlos) +* bug #5362 SingleSpaceAfterConstructFixer: Do not adjust whitespace before multiple multi-line extends (localheinz, SpacePossum) +* minor #5314 Enable testing with PHPUnit 9.x (sanmai) +* minor #5319 Clean ups (SpacePossum) +* minor #5338 clean ups (SpacePossum) +* minor #5339 NoEmptyStatementFixer - fix more cases (SpacePossum) +* minor #5340 NamedArgumentTransformer - Introduction (SpacePossum) +* minor #5344 Update docs: do not use deprecated create method (SpacePossum) +* minor #5353 Fix typo in issue template (stof) +* minor #5355 OrderedTraitsFixer - mark as risky (SpacePossum) +* minor #5356 RuleSet description fixes (SpacePossum) +* minor #5359 Add application version to "fix" out put when verbosity flag is set (SpacePossum) +* minor #5360 DX: clean up detectIndent methods (kubawerlos) +* minor #5363 Added missing self return type to ConfigInterface::registerCustomFixers() (vudaltsov) +* minor #5366 PhpUnitDedicateAssertInternalTypeFixer - recover target option (keradus) +* minor #5368 DX: PHPUnit 9 compatibility for 2.17 (keradus) +* minor #5370 DX: update PHPUnit usage to use external Prophecy trait and solve warning (keradus) +* minor #5371 Update documentation about PHP_CS_FIXER_IGNORE_ENV (SanderSander, keradus) +* minor #5373 DX: MagicMethodCasingFixerTest - fix test case description (keradus) +* minor #5374 DX: PhpUnitDedicateAssertInternalTypeFixer - add code sample for non-default config (keradus) + +Changelog for v2.17.1 +--------------------- + +* bug #5325 NoBreakCommentFixer - better throw handling (SpacePossum) +* bug #5327 StaticLambdaFixer - fix for arrow function used in class with $this (kubawerlos, SpacePossum) +* bug #5332 Fix file missing for php8 (jderusse) +* bug #5333 Fix file missing for php8 (jderusse) +* minor #5328 Fixed deprecation message version (GrahamCampbell) +* minor #5330 DX: cleanup Github Actions configs (kubawerlos) + +Changelog for v2.17.0 +--------------------- + +* bug #4752 SimpleLambdaCallFixer - bug fixes (SpacePossum) +* bug #4794 TernaryToElvisOperatorFixer - fix open tag with echo (SpacePossum) +* bug #5084 Fix for variables within string interpolation in lambda_not_used_import (GrahamCampbell) +* bug #5094 SwitchContinueToBreakFixer - do not support alternative syntax (SpacePossum) +* feature #2619 PSR-5 @inheritDoc support (julienfalque) +* feature #3253 Add SimplifiedIfReturnFixer (Slamdunk, SpacePossum) +* feature #4005 GroupImportFixer - introduction (greeflas) +* feature #4012 BracesFixer - add "allow_single_line_anonymous_class_with_empty_body" option (kubawerlos) +* feature #4021 OperatorLinebreakFixer - Introduction (kubawerlos, SpacePossum) +* feature #4259 PsrAutoloadingFixer - introduction (kubawerlos) +* feature #4375 extend ruleset "@PHP73Migration" (gharlan) +* feature #4435 SingleSpaceAfterConstructFixer - Introduction (localheinz) +* feature #4493 Add echo_tag_syntax rule (mlocati, kubawerlos) +* feature #4544 SimpleLambdaCallFixer - introduction (keradus) +* feature #4569 PhpdocOrderByValueFixer - Introduction (localheinz) +* feature #4590 SwitchContinueToBreakFixer - Introduction (SpacePossum) +* feature #4679 NativeConstantInvocationFixer - add "strict" flag (kubawerlos) +* feature #4701 OrderedTraitsFixer - introduction (julienfalque) +* feature #4704 LambdaNotUsedImportFixer - introduction (SpacePossum) +* feature #4740 NoAliasLanguageConstructCallFixer - introduction (SpacePossum) +* feature #4741 TernaryToElvisOperatorFixer - introduction (SpacePossum) +* feature #4778 UseArrowFunctionsFixer - introduction (gharlan) +* feature #4790 ArrayPushFixer - introduction (SpacePossum) +* feature #4800 NoUnneededFinalMethodFixer - Add "private_methods" option (SpacePossum) +* feature #4831 BlankLineBeforeStatementFixer - add yield from (SpacePossum) +* feature #4832 NoUnneededControlParenthesesFixer - add yield from (SpacePossum) +* feature #4863 NoTrailingWhitespaceInStringFixer - introduction (gharlan) +* feature #4875 ClassAttributesSeparationFixer - add option for no new lines between properties (adri, ruudk) +* feature #4880 HeredocIndentationFixer - config option for indentation level (gharlan) +* feature #4908 PhpUnitExpectationFixer - update for Phpunit 8.4 (ktomk) +* feature #4942 OrderedClassElementsFixer - added support for abstract method sorting (carlalexander, SpacePossum) +* feature #4947 NativeConstantInvocation - Add "PHP_INT_SIZE" to SF rule set (kubawerlos) +* feature #4953 Add support for custom differ (paulhenri-l, SpacePossum) +* feature #5264 CleanNamespaceFixer - Introduction (SpacePossum) +* feature #5280 NoUselessSprintfFixer - Introduction (SpacePossum) +* minor #4634 Make all options snake_case (kubawerlos) +* minor #4667 PhpUnitOrderedCoversFixer - stop using deprecated fixer (keradus) +* minor #4673 FinalStaticAccessFixer - deprecate (julienfalque) +* minor #4762 Rename simple_lambda_call to regular_callable_call (julienfalque) +* minor #4782 Update RuleSets (SpacePossum) +* minor #4802 Master cleanup (SpacePossum) +* minor #4828 Deprecate Config::create() (DocFX) +* minor #4872 Update RuleSet SF and PHP-CS-Fixer with new config for `no_extra_blan… (SpacePossum) +* minor #4900 Move "no_trailing_whitespace_in_string" to SF ruleset. (SpacePossum) +* minor #4903 Docs: extend regular_callable_call rule docs (keradus, SpacePossum) +* minor #4910 Add use_arrow_functions rule to PHP74Migration:risky set (keradus) +* minor #5025 PhpUnitDedicateAssertInternalTypeFixer - deprecate "target" option (kubawerlos) +* minor #5037 FinalInternalClassFixer- Rename option (SpacePossum) +* minor #5093 LambdaNotUsedImportFixer - add heredoc test (SpacePossum) +* minor #5163 Fix CS (SpacePossum) +* minor #5169 PHP8 care package master (SpacePossum) +* minor #5186 Fix tests (SpacePossum) +* minor #5192 GotoLabelAnalyzer - introduction (SpacePossum) +* minor #5230 Fix: Reference (localheinz) +* minor #5240 PHP8 - Allow trailing comma in parameter list support (SpacePossum) +* minor #5244 Fix 2.17 build (keradus) +* minor #5251 PHP8 - match support (SpacePossum) +* minor #5252 Update RuleSets (SpacePossum) +* minor #5278 PHP8 constructor property promotion support (SpacePossum) +* minor #5284 PHP8 - Attribute support (SpacePossum) +* minor #5323 NoUselessSprintfFixer - Fix test on PHP5.6 (SpacePossum) +* minor #5326 DX: relax composer requirements to not block installation under PHP v8, support for PHP v8 is not yet ready (keradus) + + +Changelog for v2.16.10 +---------------------- + +* minor #5314 Enable testing with PHPUnit 9.x (sanmai) +* minor #5338 clean ups (SpacePossum) +* minor #5339 NoEmptyStatementFixer - fix more cases (SpacePossum) +* minor #5340 NamedArgumentTransformer - Introduction (SpacePossum) +* minor #5344 Update docs: do not use deprecated create method (SpacePossum) +* minor #5356 RuleSet description fixes (SpacePossum) +* minor #5360 DX: clean up detectIndent methods (kubawerlos) +* minor #5370 DX: update PHPUnit usage to use external Prophecy trait and solve warning (keradus) +* minor #5373 DX: MagicMethodCasingFixerTest - fix test case description (keradus) +* minor #5374 DX: PhpUnitDedicateAssertInternalTypeFixer - add code sample for non-default config (keradus) + +Changelog for v2.16.9 +--------------------- + +* bug #5095 Annotation - fix for Windows line endings (SpacePossum) +* bug #5221 NoSuperfluousPhpdocTagsFixer - fix for single line PHPDoc (kubawerlos) +* bug #5225 TernaryOperatorSpacesFixer - fix for alternative control structures (kubawerlos) +* bug #5235 ArrayIndentationFixer - fix for nested arrays (kubawerlos) +* bug #5248 NoBreakCommentFixer - fix throw detect (SpacePossum) +* bug #5250 SwitchAnalyzer - fix for semicolon after case/default (kubawerlos) +* bug #5253 IO - fix cache info message (SpacePossum) +* bug #5273 Fix PHPDoc line span fixer when property has array typehint (ossinkine) +* bug #5274 TernaryToNullCoalescingFixer - concat precedence fix (SpacePossum) +* feature #5216 Add RuleSets to docs (SpacePossum) +* minor #5226 Applied CS fixes from 2.17-dev (GrahamCampbell) +* minor #5229 Fixed incorrect phpdoc (GrahamCampbell) +* minor #5231 CS: unify styling with younger branches (keradus) +* minor #5232 PHP8 - throw expression support (SpacePossum) +* minor #5233 DX: simplify check_file_permissions.sh (kubawerlos) +* minor #5236 Improve handling of unavailable code samples (julienfalque, keradus) +* minor #5239 PHP8 - Allow trailing comma in parameter list support (SpacePossum) +* minor #5254 PHP8 - mixed type support (SpacePossum) +* minor #5255 Tests: do not skip documentation test (keradus) +* minor #5256 Docs: phpdoc_to_return_type - add new example in docs (keradus) +* minor #5261 Do not update Composer twice (sanmai) +* minor #5263 PHP8 support (SpacePossum) +* minor #5266 PhpUnitTestCaseStaticMethodCallsFixer - PHPUnit 9.x support (sanmai) +* minor #5267 Improve InstallViaComposerTest (sanmai) +* minor #5268 Add GitHub Workflows CI, including testing on PHP 8 and on macOS/Windows/Ubuntu (sanmai) +* minor #5269 Prep work to migrate to PHPUnit 9.x (sanmai, keradus) +* minor #5275 remove not supported verbose options (SpacePossum) +* minor #5276 PHP8 - add NoUnreachableDefaultArgumentValueFixer to risky set (SpacePossum) +* minor #5277 PHP8 - Constructor Property Promotion support (SpacePossum) +* minor #5292 Disable blank issue template and expose community chat (keradus) +* minor #5293 Add documentation to "yoda_style" sniff to convert Yoda style to non-Yoda style (Luc45) +* minor #5295 Run static code analysis off GitHub Actions (sanmai) +* minor #5298 Add yamllint workflow, validates .yaml files (sanmai) +* minor #5302 SingleLineCommentStyleFixer - do not fix possible attributes (PHP8) (SpacePossum) +* minor #5303 Drop CircleCI and AppVeyor (keradus) +* minor #5304 DX: rename TravisTest, as we no longer test only Travis there (keradus) +* minor #5305 Groom GitHub CI and move some checks from TravisCI to GitHub CI (keradus) +* minor #5308 Only run yamllint when a YAML file is changed (julienfalque, keradus) +* minor #5309 CICD: create yamllint config file (keradus) +* minor #5311 OrderedClassElementsFixer - PHPUnit Bridge support (ktomk) +* minor #5316 PHP8 - Attribute support (SpacePossum) +* minor #5321 DX: little code grooming (keradus) + +Changelog for v2.16.8 +--------------------- + +* bug #5325 NoBreakCommentFixer - better throw handling (SpacePossum) +* bug #5327 StaticLambdaFixer - fix for arrow function used in class with $this (kubawerlos, SpacePossum) +* bug #5333 Fix file missing for php8 (jderusse) +* minor #5328 Fixed deprecation message version (GrahamCampbell) +* minor #5330 DX: cleanup Github Actions configs (kubawerlos) + +Changelog for v2.16.5 +--------------------- + +* bug #4378 PhpUnitNoExpectationAnnotationFixer - annotation in single line doc comment (kubawerlos) +* bug #4936 HeaderCommentFixer - Fix unexpected removal of regular comments (julienfalque) +* bug #5006 PhpdocToParamTypeFixer - fix for breaking PHP syntax for type having reserved name (kubawerlos) +* bug #5016 NoSuperfluousPhpdocTagsFixer - fix for @return with @inheritDoc in description (kubawerlos) +* bug #5017 PhpdocTrimConsecutiveBlankLineSeparationFixer - must run after AlignMultilineCommentFixer (kubawerlos) +* bug #5032 SingleLineAfterImportsFixer - fix for line after import (and before another import) already added using CRLF (kubawerlos) +* bug #5033 VoidReturnFixer - must run after NoSuperfluousPhpdocTagsFixer (kubawerlos) +* bug #5038 HelpCommandTest - toString nested array (SpacePossum) +* bug #5040 LinebreakAfterOpeningTagFixer - do not change code if linebreak already present (kubawerlos) +* bug #5044 StandardizeIncrementFixer - fix handling static properties (kubawerlos) +* bug #5045 BacktickToShellExecFixer - add priority relation to NativeFunctionInvocationFixer and SingleQuoteFixer (kubawerlos) +* bug #5054 PhpdocTypesFixer - fix for multidimensional array (kubawerlos) +* bug #5065 TernaryOperatorSpacesFixer - fix for discovering ":" correctly (kubawerlos) +* bug #5068 Fixed php-cs-fixer crashes on input file syntax error (GrahamCampbell) +* bug #5087 NoAlternativeSyntaxFixer - add support for switch and declare (SpacePossum) +* bug #5092 PhpdocToParamTypeFixer - remove not used option (SpacePossum) +* bug #5105 ClassKeywordRemoveFixer - fix for fully qualified class (kubawerlos) +* bug #5113 TernaryOperatorSpacesFixer - handle goto labels (SpacePossum) +* bug #5124 Fix TernaryToNullCoalescingFixer when dealing with object properties (HypeMC) +* bug #5137 DoctrineAnnotationSpacesFixer - fix for typed properties (kubawerlos) +* bug #5180 Always lint test cases with the stricter process linter (GrahamCampbell) +* bug #5190 PhpUnit*Fixers - Only fix in unit test class scope (SpacePossum) +* bug #5195 YodaStyle - statements in braces should be treated as variables in strict … (SpacePossum) +* bug #5220 NoUnneededFinalMethodFixer - do not fix private constructors (SpacePossum) +* feature #3475 Rework documentation (julienfalque, SpacePossum) +* feature #5166 PHP8 (SpacePossum) +* minor #4878 ArrayIndentationFixer - refactor (julienfalque) +* minor #5031 CI: skip_cleanup: true (keradus) +* minor #5035 PhpdocToParamTypeFixer - Rename attribute (SpacePossum) +* minor #5048 Allow composer/semver ^2.0 and ^3.0 (thomasvargiu) +* minor #5050 DX: moving integration test for braces, indentation_type and no_break_comment into right place (kubawerlos) +* minor #5051 DX: move all tests from AutoReview\FixerTest to Test\AbstractFixerTestCase (kubawerlos) +* minor #5053 DX: cleanup FunctionTypehintSpaceFixer (kubawerlos) +* minor #5056 DX: add missing priority test for indentation_type and phpdoc_indent (kubawerlos) +* minor #5077 DX: add missing priority test between NoUnsetCastFixer and BinaryOperatorSpacesFixer (kubawerlos) +* minor #5083 Update composer.json to prevent issue #5030 (mvorisek) +* minor #5088 NoBreakCommentFixer - NoUselessElseFixer - priority test (SpacePossum) +* minor #5100 Fixed invalid PHP 5.6 syntax (GrahamCampbell) +* minor #5106 Symfony's finder already ignores vcs and dot files by default (GrahamCampbell) +* minor #5112 DX: check file permissions (kubawerlos, SpacePossum) +* minor #5122 Show runtime PHP version (kubawerlos) +* minor #5132 Do not allow assignments in if statements (SpacePossum) +* minor #5133 RuleSetTest - Early return for boolean and detect more defaults (SpacePossum) +* minor #5139 revert some unneeded exclusions (SpacePossum) +* minor #5148 Upgrade Xcode (kubawerlos) +* minor #5149 NoUnsetOnPropertyFixer - risky description tweaks (SpacePossum) +* minor #5161 minors (SpacePossum) +* minor #5170 Fix test on PHP8 (SpacePossum) +* minor #5172 Remove accidentally inserted newlines (GrahamCampbell) +* minor #5173 Fix PHP8 RuleSet inherit (SpacePossum) +* minor #5174 Corrected linting error messages (GrahamCampbell) +* minor #5177 PHP8 (SpacePossum) +* minor #5178 Fix tests (SpacePossum) +* minor #5184 [FinalStaticAccessFixer] Handle new static() in final class (localheinz) +* minor #5188 DX: Update sibling debs to version supporting PHP8/PHPUnit9 (keradus) +* minor #5189 Create temporary linting file in system temp dir (keradus) +* minor #5191 MethodArgumentSpaceFixer - support use/import of anonymous functions. (undefinedor) +* minor #5193 DX: add AbstractPhpUnitFixer (kubawerlos) +* minor #5204 DX: cleanup NullableTypeTransformerTest (kubawerlos) +* minor #5207 Add © for logo (keradus) +* minor #5208 DX: cleanup php-cs-fixer entry file (keradus) +* minor #5210 CICD - temporarily disable problematic test (keradus) +* minor #5211 CICD: fix file permissions (keradus) +* minor #5213 DX: move report schemas to dedicated dir (keradus) +* minor #5214 CICD: fix file permissions (keradus) +* minor #5215 CICD: update checkbashisms (keradus) +* minor #5217 CICD: use Composer v2 and drop hirak/prestissimo plugin (keradus) +* minor #5218 DX: .gitignore - add .phpunit.result.cache (keradus) +* minor #5222 Upgrade Xcode (kubawerlos) +* minor #5223 Docs: regenerate docs on 2.16 line (keradus) + +Changelog for v2.16.4 +--------------------- + +* bug #3893 Fix handling /** and */ on the same line as the first and/or last annotation (dmvdbrugge) +* bug #4919 PhpUnitTestAnnotationFixer - fix function starting with "test" and having lowercase letter after (kubawerlos) +* bug #4929 YodaStyleFixer - handling equals empty array (kubawerlos) +* bug #4934 YodaStyleFixer - fix for conditions weird are (kubawerlos) +* bug #4958 OrderedImportsFixer - fix for trailing comma in group (kubawerlos) +* bug #4959 BlankLineBeforeStatementFixer - handle comment case (SpacePossum) +* bug #4962 MethodArgumentSpaceFixer - must run after MethodChainingIndentationFixer (kubawerlos) +* bug #4963 PhpdocToReturnTypeFixer - fix for breaking PHP syntax for type having reserved name (kubawerlos, Slamdunk) +* bug #4978 ArrayIndentationFixer - must run after MethodArgumentSpaceFixer (kubawerlos) +* bug #4994 FinalInternalClassFixer - must run before ProtectedToPrivateFixer (kubawerlos) +* bug #4996 NoEmptyCommentFixer - handle multiline comments (kubawerlos) +* bug #4999 BlankLineBeforeStatementFixer - better comment handling (SpacePossum) +* bug #5009 NoEmptyCommentFixer - better handle comments sequence (kubawerlos) +* bug #5010 SimplifiedNullReturnFixer - must run before VoidReturnFixer (kubawerlos) +* bug #5011 SingleClassElementPerStatementFixer - must run before ClassAttributesSeparationFixer (kubawerlos) +* bug #5012 StrictParamFixer - must run before NativeFunctionInvocationFixer (kubawerlos) +* bug #5014 PhpdocToParamTypeFixer - fix for void as param (kubawerlos) +* bug #5018 PhpdocScalarFixer - fix for comment with Windows line endings (kubawerlos) +* bug #5029 SingleLineAfterImportsFixer - fix for line after import already added using CRLF (kubawerlos) +* minor #4904 Increase PHPStan level to 8 with strict rules (julienfalque) +* minor #4920 Enhancement: Use DocBlock itself to make it multi-line (localheinz) +* minor #4930 DX: ensure PhpUnitNamespacedFixer handles all classes (kubawerlos) +* minor #4931 DX: add test to ensure each target version in PhpUnitTargetVersion has its set in RuleSet (kubawerlos) +* minor #4932 DX: Travis CI config - fix warnings and infos (kubawerlos) +* minor #4940 Reject empty path (julienfalque) +* minor #4944 Fix grammar (julienfalque) +* minor #4946 Allow "const" option on PHP <7.1 (julienfalque) +* minor #4948 Added describe command to readme (david, 8ctopus) +* minor #4949 Fixed build readme on Windows fails if using Git Bash (Mintty) (8ctopus) +* minor #4954 Config - Trim path (julienfalque) +* minor #4957 DX: Check trailing spaces in project files only (ktomk) +* minor #4961 Assert all project source files are monolithic. (SpacePossum) +* minor #4964 Fix PHPStan baseline (julienfalque) +* minor #4965 Fix PHPStan baseline (julienfalque) +* minor #4973 DX: test "isRisky" method in fixer tests, not as auto review (kubawerlos) +* minor #4974 Minor: Fix typo (ktomk) +* minor #4975 Revert PHPStan level to 5 (julienfalque) +* minor #4976 Add instructions for PHPStan (julienfalque) +* minor #4980 Introduce new issue templates (julienfalque) +* minor #4981 Prevent error in CTTest::testConstants (for PHP8) (guilliamxavier) +* minor #4982 Remove PHIVE (kubawerlos) +* minor #4985 Fix tests with Symfony 5.1 (julienfalque) +* minor #4987 PhpdocAnnotationWithoutDotFixer - handle unicode characters using mb_* (SpacePossum) +* minor #5008 Enhancement: Social justification applied (gbyrka-fingo) +* minor #5023 Fix issue templates (kubawerlos) +* minor #5024 DX: add missing non-default code samples (kubawerlos) + +Changelog for v2.16.3 +--------------------- + +* bug #4915 Fix handling property PHPDocs with unsupported type (julienfalque) +* minor #4916 Fix AppVeyor build (julienfalque) +* minor #4917 CircleCI - Bump xcode to 11.4 (GrahamCampbell) +* minor #4918 DX: do not fix ".phpt" files by default (kubawerlos) + +Changelog for v2.16.2 +--------------------- + +* bug #3820 Braces - (re)indenting comment issues (SpacePossum) +* bug #3911 PhpdocVarWithoutNameFixer - fix for properties only (dmvdbrugge) +* bug #4601 ClassKeywordRemoveFixer - Fix for namespace (yassine-ah, kubawerlos) +* bug #4630 FullyQualifiedStrictTypesFixer - Ignore partial class names which look like FQCNs (localheinz, SpacePossum) +* bug #4661 ExplicitStringVariableFixer - variables pair if one is already explicit (kubawerlos) +* bug #4675 NonPrintableCharacterFixer - fix for backslash and quotes when changing to escape sequences (kubawerlos) +* bug #4678 TokensAnalyzer::isConstantInvocation - fix for importing multiple classes with single "use" (kubawerlos) +* bug #4682 Fix handling array type declaration in properties (julienfalque) +* bug #4685 Improve Symfony 5 compatibility (keradus) +* bug #4688 TokensAnalyzer::isConstantInvocation - Fix detection for fully qualified return type (julienfalque) +* bug #4689 DeclareStrictTypesFixer - fix for "strict_types" set to "0" (kubawerlos) +* bug #4690 PhpdocVarAnnotationCorrectOrderFixer - fix for multiline `@var` without type (kubawerlos) +* bug #4710 SingleTraitInsertPerStatement - fix formatting for multiline "use" (kubawerlos) +* bug #4711 Ensure that files from "tests" directory in release are autoloaded (kubawerlos) +* bug #4749 TokensAnalyze::isUnaryPredecessorOperator fix for CT::T_ARRAY_INDEX_C… (SpacePossum) +* bug #4759 Add more priority cases (SpacePossum) +* bug #4761 NoSuperfluousElseifFixer - handle single line (SpacePossum) +* bug #4783 NoSuperfluousPhpdocTagsFixer - fix for really big PHPDoc (kubawerlos, mvorisek) +* bug #4787 NoUnneededFinalMethodFixer - Mark as risky (SpacePossum) +* bug #4795 OrderedClassElementsFixer - Fix (SpacePossum) +* bug #4801 GlobalNamespaceImportFixer - fix docblock handling (gharlan) +* bug #4804 TokensAnalyzer::isUnarySuccessorOperator fix for array curly braces (SpacePossum) +* bug #4807 IncrementStyleFixer - handle after ")" (SpacePossum) +* bug #4808 Modernize types casting fixer array curly (SpacePossum) +* bug #4809 Fix "braces" and "method_argument_space" priority (julienfalque) +* bug #4813 BracesFixer - fix invalid code generation on alternative syntax (SpacePossum) +* bug #4822 fix 2 bugs in phpdoc_line_span (lmichelin) +* bug #4823 ReturnAssignmentFixer - repeat fix (SpacePossum) +* bug #4824 NoUnusedImportsFixer - SingleLineAfterImportsFixer - fix priority (SpacePossum) +* bug #4825 GlobalNamespaceImportFixer - do not import global into global (SpacePossum) +* bug #4829 YodaStyleFixer - fix precedence for T_MOD_EQUAL and T_COALESCE_EQUAL (SpacePossum) +* bug #4830 TernaryToNullCoalescingFixer - handle yield from (SpacePossum) +* bug #4835 Remove duplicate "function_to_constant" from RuleSet (SpacePossum) +* bug #4840 LineEndingFixer - T_CLOSE_TAG support, StringLineEndingFixer - T_INLI… (SpacePossum) +* bug #4846 FunctionsAnalyzer - better isGlobalFunctionCall detection (SpacePossum) +* bug #4852 Priority issues (SpacePossum) +* bug #4870 HeaderCommentFixer - do not remove class docs (gharlan) +* bug #4871 NoExtraBlankLinesFixer - handle cases on same line (SpacePossum) +* bug #4895 Fix conflict between header_comment and declare_strict_types (BackEndTea, julienfalque) +* bug #4911 PhpdocSeparationFixer - fix regression with lack of next line (keradus) +* feature #4742 FunctionToConstantFixer - get_class($this) support (SpacePossum) +* minor #4377 CommentsAnalyzer - fix for declare before header comment (kubawerlos) +* minor #4636 DX: do not check for PHPDBG when collecting coverage (kubawerlos) +* minor #4644 Docs: add info about "-vv..." (voku) +* minor #4691 Run Travis CI on stable PHP 7.4 (kubawerlos) +* minor #4693 Increase Travis CI Git clone depth (julienfalque) +* minor #4699 LineEndingFixer - handle "\r\r\n" (kubawerlos) +* minor #4703 NoSuperfluousPhpdocTagsFixer,PhpdocAddMissingParamAnnotationFixer - p… (SpacePossum) +* minor #4707 Fix typos (TysonAndre) +* minor #4712 NoBlankLinesAfterPhpdocFixer — Do not strip newline between docblock and use statements (mollierobbert) +* minor #4715 Enhancement: Install ergebnis/composer-normalize via Phive (localheinz) +* minor #4722 Fix Circle CI build (julienfalque) +* minor #4724 DX: Simplify installing PCOV (kubawerlos) +* minor #4736 NoUnusedImportsFixer - do not match variable name as import (SpacePossum) +* minor #4746 NoSuperfluousPhpdocTagsFixer - Remove for typed properties (PHP 7.4) (ruudk) +* minor #4753 Do not apply any text/.git filters to fixtures (mvorisek) +* minor #4757 Test $expected is used before $input (SpacePossum) +* minor #4758 Autoreview the PHPDoc of *Fixer::getPriority based on the priority map (SpacePossum) +* minor #4765 Add test on some return types (SpacePossum) +* minor #4766 Remove false test skip (SpacePossum) +* minor #4767 Remove useless priority comments (kubawerlos) +* minor #4769 DX: add missing priority tests (kubawerlos) +* minor #4772 NoUnneededFinalMethodFixer - update description (kubawerlos) +* minor #4774 DX: simplify Utils::camelCaseToUnderscore (kubawerlos) +* minor #4781 NoUnneededCurlyBracesFixer - handle namespaces (SpacePossum) +* minor #4784 Travis CI - Use multiple keyservers (ktomk) +* minor #4785 Improve static analysis (enumag) +* minor #4788 Configurable fixers code sample (SpacePossum) +* minor #4791 Increase PHPStan level to 3 (julienfalque) +* minor #4797 clean ups (SpacePossum) +* minor #4803 FinalClassFixer - Doctrine\ORM\Mapping as ORM alias should not be required (localheinz) +* minor #4839 2.15 - clean ups (SpacePossum) +* minor #4842 ReturnAssignmentFixer - Support more cases (julienfalque) +* minor #4843 NoSuperfluousPhpdocTagsFixer - fix typo in option description (OndraM) +* minor #4844 Same requirements for descriptions (SpacePossum) +* minor #4849 Increase PHPStan level to 5 (julienfalque) +* minor #4850 Fix phpstan (SpacePossum) +* minor #4857 Fixed the unit tests (GrahamCampbell) +* minor #4865 Use latest xcode image (GrahamCampbell) +* minor #4892 CombineNestedDirnameFixer - Add space after comma (julienfalque) +* minor #4894 DX: PhpdocToParamTypeFixer - improve typing (keradus) +* minor #4898 FixerTest - yield the data in AutoReview (Nyholm) +* minor #4899 Fix exception message format for fabbot.io (SpacePossum) +* minor #4905 Support composer v2 installed.json files (GrahamCampbell) +* minor #4906 CI: use Composer stable release for AppVeyor (kubawerlos) +* minor #4909 DX: HeaderCommentFixer - use non-aliased version of option name in code (keradus) +* minor #4912 CI: Fix AppVeyor integration (keradus) + +Changelog for v2.16.1 +--------------------- + +* bug #4476 FunctionsAnalyzer - add "isTheSameClassCall" for correct verifying of function calls (kubawerlos) +* bug #4605 PhpdocToParamTypeFixer - cover more cases (keradus, julienfalque) +* bug #4626 FinalPublicMethodForAbstractClassFixer - Do not attempt to mark abstract public methods as final (localheinz) +* bug #4632 NullableTypeDeclarationForDefaultNullValueFixer - fix for not lowercase "null" (kubawerlos) +* bug #4638 Ensure compatibility with PHP 7.4 (julienfalque) +* bug #4641 Add typed properties test to VisibilityRequiredFixerTest (GawainLynch, julienfalque) +* bug #4654 ArrayIndentationFixer - Fix array indentation for multiline values (julienfalque) +* bug #4660 TokensAnalyzer::isConstantInvocation - fix for extending multiple interfaces (kubawerlos) +* bug #4668 TokensAnalyzer::isConstantInvocation - fix for interface method return type (kubawerlos) +* minor #4608 Allow Symfony 5 components (l-vo) +* minor #4622 Disallow PHP 7.4 failures on Travis CI (julienfalque) +* minor #4623 README - Mark up as code (localheinz) +* minor #4637 PHP 7.4 integration test (GawainLynch, julienfalque) +* minor #4643 DX: Update .gitattributes and move ci-integration.sh to root of the project (kubawerlos, keradus) +* minor #4645 Check PHP extensions on runtime (kubawerlos) +* minor #4655 Improve docs - README (mvorisek) +* minor #4662 DX: generate headers in README.rst (kubawerlos) +* minor #4669 Enable execution under PHP 7.4 (keradus) +* minor #4670 TravisTest - rewrite tests to allow last supported by tool PHP version to be snapshot (keradus) +* minor #4671 TravisTest - rewrite tests to allow last supported by tool PHP version to be snapshot (keradus) + +Changelog for v2.16.0 +--------------------- + +* feature #3810 PhpdocLineSpanFixer - Introduction (BackEndTea) +* feature #3928 Add FinalPublicMethodForAbstractClassFixer (Slamdunk) +* feature #4000 FinalStaticAccessFixer - Introduction (ntzm) +* feature #4275 Issue #4274: Let lowercase_constants directive to be configurable. (drupol) +* feature #4355 GlobalNamespaceImportFixer - Introduction (gharlan) +* feature #4358 SelfStaticAccessorFixer - Introduction (SpacePossum) +* feature #4385 CommentToPhpdocFixer - allow to ignore tags (kubawerlos) +* feature #4401 Add NullableTypeDeclarationForDefaultNullValueFixer (HypeMC) +* feature #4452 Add SingleLineThrowFixer (kubawerlos) +* feature #4500 NoSuperfluousPhpdocTags - Add remove_inheritdoc option (julienfalque) +* feature #4505 NoSuperfluousPhpdocTagsFixer - allow params that aren't on the signature (azjezz) +* feature #4531 PhpdocAlignFixer - add "property-read" and "property-write" to allowed tags (kubawerlos) +* feature #4583 Phpdoc to param type fixer rebase (jg-development) +* minor #4033 Raise deprecation warnings on usage of deprecated aliases (ntzm) +* minor #4423 DX: update branch alias (keradus) +* minor #4537 SelfStaticAccessor - extend itests (keradus) +* minor #4607 Configure no_superfluous_phpdoc_tags for Symfony (keradus) +* minor #4618 DX: fix usage of deprecated options (0x450x6c) +* minor #4619 Fix PHP 7.3 strict mode warnings (keradus) +* minor #4621 Add single_line_throw to Symfony ruleset (keradus) + +Changelog for v2.15.10 +---------------------- + +* bug #5095 Annotation - fix for Windows line endings (SpacePossum) +* bug #5221 NoSuperfluousPhpdocTagsFixer - fix for single line PHPDoc (kubawerlos) +* bug #5225 TernaryOperatorSpacesFixer - fix for alternative control structures (kubawerlos) +* bug #5235 ArrayIndentationFixer - fix for nested arrays (kubawerlos) +* bug #5248 NoBreakCommentFixer - fix throw detect (SpacePossum) +* bug #5250 SwitchAnalyzer - fix for semicolon after case/default (kubawerlos) +* bug #5253 IO - fix cache info message (SpacePossum) +* bug #5274 TernaryToNullCoalescingFixer - concat precedence fix (SpacePossum) +* feature #5216 Add RuleSets to docs (SpacePossum) +* minor #5226 Applied CS fixes from 2.17-dev (GrahamCampbell) +* minor #5229 Fixed incorrect phpdoc (GrahamCampbell) +* minor #5231 CS: unify styling with younger branches (keradus) +* minor #5232 PHP8 - throw expression support (SpacePossum) +* minor #5233 DX: simplify check_file_permissions.sh (kubawerlos) +* minor #5236 Improve handling of unavailable code samples (julienfalque, keradus) +* minor #5239 PHP8 - Allow trailing comma in parameter list support (SpacePossum) +* minor #5254 PHP8 - mixed type support (SpacePossum) +* minor #5255 Tests: do not skip documentation test (keradus) +* minor #5261 Do not update Composer twice (sanmai) +* minor #5263 PHP8 support (SpacePossum) +* minor #5266 PhpUnitTestCaseStaticMethodCallsFixer - PHPUnit 9.x support (sanmai) +* minor #5267 Improve InstallViaComposerTest (sanmai) +* minor #5276 PHP8 - add NoUnreachableDefaultArgumentValueFixer to risky set (SpacePossum) + +Changelog for v2.15.9 +--------------------- + +* bug #4378 PhpUnitNoExpectationAnnotationFixer - annotation in single line doc comment (kubawerlos) +* bug #4936 HeaderCommentFixer - Fix unexpected removal of regular comments (julienfalque) +* bug #5017 PhpdocTrimConsecutiveBlankLineSeparationFixer - must run after AlignMultilineCommentFixer (kubawerlos) +* bug #5033 VoidReturnFixer - must run after NoSuperfluousPhpdocTagsFixer (kubawerlos) +* bug #5038 HelpCommandTest - toString nested array (SpacePossum) +* bug #5040 LinebreakAfterOpeningTagFixer - do not change code if linebreak already present (kubawerlos) +* bug #5044 StandardizeIncrementFixer - fix handling static properties (kubawerlos) +* bug #5045 BacktickToShellExecFixer - add priority relation to NativeFunctionInvocationFixer and SingleQuoteFixer (kubawerlos) +* bug #5054 PhpdocTypesFixer - fix for multidimensional array (kubawerlos) +* bug #5065 TernaryOperatorSpacesFixer - fix for discovering ":" correctly (kubawerlos) +* bug #5068 Fixed php-cs-fixer crashes on input file syntax error (GrahamCampbell) +* bug #5087 NoAlternativeSyntaxFixer - add support for switch and declare (SpacePossum) +* bug #5105 ClassKeywordRemoveFixer - fix for fully qualified class (kubawerlos) +* bug #5113 TernaryOperatorSpacesFixer - handle goto labels (SpacePossum) +* bug #5124 Fix TernaryToNullCoalescingFixer when dealing with object properties (HypeMC) +* bug #5137 DoctrineAnnotationSpacesFixer - fix for typed properties (kubawerlos) +* bug #5180 Always lint test cases with the stricter process linter (GrahamCampbell) +* bug #5190 PhpUnit*Fixers - Only fix in unit test class scope (SpacePossum) +* bug #5195 YodaStyle - statements in braces should be treated as variables in strict … (SpacePossum) +* bug #5220 NoUnneededFinalMethodFixer - do not fix private constructors (SpacePossum) +* feature #3475 Rework documentation (julienfalque, SpacePossum) +* feature #5166 PHP8 (SpacePossum) +* minor #4878 ArrayIndentationFixer - refactor (julienfalque) +* minor #5031 CI: skip_cleanup: true (keradus) +* minor #5048 Allow composer/semver ^2.0 and ^3.0 (thomasvargiu) +* minor #5050 DX: moving integration test for braces, indentation_type and no_break_comment into right place (kubawerlos) +* minor #5051 DX: move all tests from AutoReview\FixerTest to Test\AbstractFixerTestCase (kubawerlos) +* minor #5053 DX: cleanup FunctionTypehintSpaceFixer (kubawerlos) +* minor #5056 DX: add missing priority test for indentation_type and phpdoc_indent (kubawerlos) +* minor #5077 DX: add missing priority test between NoUnsetCastFixer and BinaryOperatorSpacesFixer (kubawerlos) +* minor #5083 Update composer.json to prevent issue #5030 (mvorisek) +* minor #5088 NoBreakCommentFixer - NoUselessElseFixer - priority test (SpacePossum) +* minor #5100 Fixed invalid PHP 5.6 syntax (GrahamCampbell) +* minor #5106 Symfony's finder already ignores vcs and dot files by default (GrahamCampbell) +* minor #5112 DX: check file permissions (kubawerlos, SpacePossum) +* minor #5122 Show runtime PHP version (kubawerlos) +* minor #5132 Do not allow assignments in if statements (SpacePossum) +* minor #5133 RuleSetTest - Early return for boolean and detect more defaults (SpacePossum) +* minor #5139 revert some unneeded exclusions (SpacePossum) +* minor #5148 Upgrade Xcode (kubawerlos) +* minor #5149 NoUnsetOnPropertyFixer - risky description tweaks (SpacePossum) +* minor #5161 minors (SpacePossum) +* minor #5172 Remove accidentally inserted newlines (GrahamCampbell) +* minor #5173 Fix PHP8 RuleSet inherit (SpacePossum) +* minor #5174 Corrected linting error messages (GrahamCampbell) +* minor #5177 PHP8 (SpacePossum) +* minor #5188 DX: Update sibling debs to version supporting PHP8/PHPUnit9 (keradus) +* minor #5189 Create temporary linting file in system temp dir (keradus) +* minor #5191 MethodArgumentSpaceFixer - support use/import of anonymous functions. (undefinedor) +* minor #5193 DX: add AbstractPhpUnitFixer (kubawerlos) +* minor #5204 DX: cleanup NullableTypeTransformerTest (kubawerlos) +* minor #5207 Add © for logo (keradus) +* minor #5208 DX: cleanup php-cs-fixer entry file (keradus) +* minor #5210 CICD - temporarily disable problematic test (keradus) +* minor #5211 CICD: fix file permissions (keradus) +* minor #5213 DX: move report schemas to dedicated dir (keradus) +* minor #5214 CICD: fix file permissions (keradus) +* minor #5215 CICD: update checkbashisms (keradus) +* minor #5217 CICD: use Composer v2 and drop hirak/prestissimo plugin (keradus) +* minor #5218 DX: .gitignore - add .phpunit.result.cache (keradus) +* minor #5222 Upgrade Xcode (kubawerlos) + +Changelog for v2.15.8 +--------------------- + +* bug #3893 Fix handling /** and */ on the same line as the first and/or last annotation (dmvdbrugge) +* bug #4919 PhpUnitTestAnnotationFixer - fix function starting with "test" and having lowercase letter after (kubawerlos) +* bug #4929 YodaStyleFixer - handling equals empty array (kubawerlos) +* bug #4934 YodaStyleFixer - fix for conditions weird are (kubawerlos) +* bug #4958 OrderedImportsFixer - fix for trailing comma in group (kubawerlos) +* bug #4959 BlankLineBeforeStatementFixer - handle comment case (SpacePossum) +* bug #4962 MethodArgumentSpaceFixer - must run after MethodChainingIndentationFixer (kubawerlos) +* bug #4963 PhpdocToReturnTypeFixer - fix for breaking PHP syntax for type having reserved name (kubawerlos, Slamdunk) +* bug #4978 ArrayIndentationFixer - must run after MethodArgumentSpaceFixer (kubawerlos) +* bug #4994 FinalInternalClassFixer - must run before ProtectedToPrivateFixer (kubawerlos) +* bug #4996 NoEmptyCommentFixer - handle multiline comments (kubawerlos) +* bug #4999 BlankLineBeforeStatementFixer - better comment handling (SpacePossum) +* bug #5009 NoEmptyCommentFixer - better handle comments sequence (kubawerlos) +* bug #5010 SimplifiedNullReturnFixer - must run before VoidReturnFixer (kubawerlos) +* bug #5011 SingleClassElementPerStatementFixer - must run before ClassAttributesSeparationFixer (kubawerlos) +* bug #5012 StrictParamFixer - must run before NativeFunctionInvocationFixer (kubawerlos) +* bug #5029 SingleLineAfterImportsFixer - fix for line after import already added using CRLF (kubawerlos) +* minor #4904 Increase PHPStan level to 8 with strict rules (julienfalque) +* minor #4930 DX: ensure PhpUnitNamespacedFixer handles all classes (kubawerlos) +* minor #4931 DX: add test to ensure each target version in PhpUnitTargetVersion has its set in RuleSet (kubawerlos) +* minor #4932 DX: Travis CI config - fix warnings and infos (kubawerlos) +* minor #4940 Reject empty path (julienfalque) +* minor #4944 Fix grammar (julienfalque) +* minor #4946 Allow "const" option on PHP <7.1 (julienfalque) +* minor #4948 Added describe command to readme (david, 8ctopus) +* minor #4949 Fixed build readme on Windows fails if using Git Bash (Mintty) (8ctopus) +* minor #4954 Config - Trim path (julienfalque) +* minor #4957 DX: Check trailing spaces in project files only (ktomk) +* minor #4961 Assert all project source files are monolithic. (SpacePossum) +* minor #4964 Fix PHPStan baseline (julienfalque) +* minor #4973 DX: test "isRisky" method in fixer tests, not as auto review (kubawerlos) +* minor #4974 Minor: Fix typo (ktomk) +* minor #4975 Revert PHPStan level to 5 (julienfalque) +* minor #4976 Add instructions for PHPStan (julienfalque) +* minor #4980 Introduce new issue templates (julienfalque) +* minor #4981 Prevent error in CTTest::testConstants (for PHP8) (guilliamxavier) +* minor #4982 Remove PHIVE (kubawerlos) +* minor #4985 Fix tests with Symfony 5.1 (julienfalque) +* minor #4987 PhpdocAnnotationWithoutDotFixer - handle unicode characters using mb_* (SpacePossum) +* minor #5008 Enhancement: Social justification applied (gbyrka-fingo) +* minor #5023 Fix issue templates (kubawerlos) +* minor #5024 DX: add missing non-default code samples (kubawerlos) + +Changelog for v2.15.7 +--------------------- + +* bug #4915 Fix handling property PHPDocs with unsupported type (julienfalque) +* minor #4916 Fix AppVeyor build (julienfalque) +* minor #4917 CircleCI - Bump xcode to 11.4 (GrahamCampbell) +* minor #4918 DX: do not fix ".phpt" files by default (kubawerlos) + +Changelog for v2.15.6 +--------------------- + +* bug #3820 Braces - (re)indenting comment issues (SpacePossum) +* bug #3911 PhpdocVarWithoutNameFixer - fix for properties only (dmvdbrugge) +* bug #4601 ClassKeywordRemoveFixer - Fix for namespace (yassine-ah, kubawerlos) +* bug #4630 FullyQualifiedStrictTypesFixer - Ignore partial class names which look like FQCNs (localheinz, SpacePossum) +* bug #4661 ExplicitStringVariableFixer - variables pair if one is already explicit (kubawerlos) +* bug #4675 NonPrintableCharacterFixer - fix for backslash and quotes when changing to escape sequences (kubawerlos) +* bug #4678 TokensAnalyzer::isConstantInvocation - fix for importing multiple classes with single "use" (kubawerlos) +* bug #4682 Fix handling array type declaration in properties (julienfalque) +* bug #4685 Improve Symfony 5 compatibility (keradus) +* bug #4688 TokensAnalyzer::isConstantInvocation - Fix detection for fully qualified return type (julienfalque) +* bug #4689 DeclareStrictTypesFixer - fix for "strict_types" set to "0" (kubawerlos) +* bug #4690 PhpdocVarAnnotationCorrectOrderFixer - fix for multiline `@var` without type (kubawerlos) +* bug #4710 SingleTraitInsertPerStatement - fix formatting for multiline "use" (kubawerlos) +* bug #4711 Ensure that files from "tests" directory in release are autoloaded (kubawerlos) +* bug #4749 TokensAnalyze::isUnaryPredecessorOperator fix for CT::T_ARRAY_INDEX_C… (SpacePossum) +* bug #4759 Add more priority cases (SpacePossum) +* bug #4761 NoSuperfluousElseifFixer - handle single line (SpacePossum) +* bug #4783 NoSuperfluousPhpdocTagsFixer - fix for really big PHPDoc (kubawerlos, mvorisek) +* bug #4787 NoUnneededFinalMethodFixer - Mark as risky (SpacePossum) +* bug #4795 OrderedClassElementsFixer - Fix (SpacePossum) +* bug #4804 TokensAnalyzer::isUnarySuccessorOperator fix for array curly braces (SpacePossum) +* bug #4807 IncrementStyleFixer - handle after ")" (SpacePossum) +* bug #4808 Modernize types casting fixer array curly (SpacePossum) +* bug #4809 Fix "braces" and "method_argument_space" priority (julienfalque) +* bug #4813 BracesFixer - fix invalid code generation on alternative syntax (SpacePossum) +* bug #4823 ReturnAssignmentFixer - repeat fix (SpacePossum) +* bug #4824 NoUnusedImportsFixer - SingleLineAfterImportsFixer - fix priority (SpacePossum) +* bug #4829 YodaStyleFixer - fix precedence for T_MOD_EQUAL and T_COALESCE_EQUAL (SpacePossum) +* bug #4830 TernaryToNullCoalescingFixer - handle yield from (SpacePossum) +* bug #4835 Remove duplicate "function_to_constant" from RuleSet (SpacePossum) +* bug #4840 LineEndingFixer - T_CLOSE_TAG support, StringLineEndingFixer - T_INLI… (SpacePossum) +* bug #4846 FunctionsAnalyzer - better isGlobalFunctionCall detection (SpacePossum) +* bug #4852 Priority issues (SpacePossum) +* bug #4870 HeaderCommentFixer - do not remove class docs (gharlan) +* bug #4871 NoExtraBlankLinesFixer - handle cases on same line (SpacePossum) +* bug #4895 Fix conflict between header_comment and declare_strict_types (BackEndTea, julienfalque) +* bug #4911 PhpdocSeparationFixer - fix regression with lack of next line (keradus) +* feature #4742 FunctionToConstantFixer - get_class($this) support (SpacePossum) +* minor #4377 CommentsAnalyzer - fix for declare before header comment (kubawerlos) +* minor #4636 DX: do not check for PHPDBG when collecting coverage (kubawerlos) +* minor #4644 Docs: add info about "-vv..." (voku) +* minor #4691 Run Travis CI on stable PHP 7.4 (kubawerlos) +* minor #4693 Increase Travis CI Git clone depth (julienfalque) +* minor #4699 LineEndingFixer - handle "\r\r\n" (kubawerlos) +* minor #4703 NoSuperfluousPhpdocTagsFixer,PhpdocAddMissingParamAnnotationFixer - p… (SpacePossum) +* minor #4707 Fix typos (TysonAndre) +* minor #4712 NoBlankLinesAfterPhpdocFixer — Do not strip newline between docblock and use statements (mollierobbert) +* minor #4715 Enhancement: Install ergebnis/composer-normalize via Phive (localheinz) +* minor #4722 Fix Circle CI build (julienfalque) +* minor #4724 DX: Simplify installing PCOV (kubawerlos) +* minor #4736 NoUnusedImportsFixer - do not match variable name as import (SpacePossum) +* minor #4746 NoSuperfluousPhpdocTagsFixer - Remove for typed properties (PHP 7.4) (ruudk) +* minor #4753 Do not apply any text/.git filters to fixtures (mvorisek) +* minor #4757 Test $expected is used before $input (SpacePossum) +* minor #4758 Autoreview the PHPDoc of *Fixer::getPriority based on the priority map (SpacePossum) +* minor #4765 Add test on some return types (SpacePossum) +* minor #4766 Remove false test skip (SpacePossum) +* minor #4767 Remove useless priority comments (kubawerlos) +* minor #4769 DX: add missing priority tests (kubawerlos) +* minor #4772 NoUnneededFinalMethodFixer - update description (kubawerlos) +* minor #4774 DX: simplify Utils::camelCaseToUnderscore (kubawerlos) +* minor #4781 NoUnneededCurlyBracesFixer - handle namespaces (SpacePossum) +* minor #4784 Travis CI - Use multiple keyservers (ktomk) +* minor #4785 Improve static analysis (enumag) +* minor #4788 Configurable fixers code sample (SpacePossum) +* minor #4791 Increase PHPStan level to 3 (julienfalque) +* minor #4797 clean ups (SpacePossum) +* minor #4803 FinalClassFixer - Doctrine\ORM\Mapping as ORM alias should not be required (localheinz) +* minor #4839 2.15 - clean ups (SpacePossum) +* minor #4842 ReturnAssignmentFixer - Support more cases (julienfalque) +* minor #4844 Same requirements for descriptions (SpacePossum) +* minor #4849 Increase PHPStan level to 5 (julienfalque) +* minor #4857 Fixed the unit tests (GrahamCampbell) +* minor #4865 Use latest xcode image (GrahamCampbell) +* minor #4892 CombineNestedDirnameFixer - Add space after comma (julienfalque) +* minor #4898 FixerTest - yield the data in AutoReview (Nyholm) +* minor #4899 Fix exception message format for fabbot.io (SpacePossum) +* minor #4905 Support composer v2 installed.json files (GrahamCampbell) +* minor #4906 CI: use Composer stable release for AppVeyor (kubawerlos) +* minor #4909 DX: HeaderCommentFixer - use non-aliased version of option name in code (keradus) +* minor #4912 CI: Fix AppVeyor integration (keradus) + +Changelog for v2.15.5 +--------------------- + +* bug #4476 FunctionsAnalyzer - add "isTheSameClassCall" for correct verifying of function calls (kubawerlos) +* bug #4641 Add typed properties test to VisibilityRequiredFixerTest (GawainLynch, julienfalque) +* bug #4654 ArrayIndentationFixer - Fix array indentation for multiline values (julienfalque) +* bug #4660 TokensAnalyzer::isConstantInvocation - fix for extending multiple interfaces (kubawerlos) +* bug #4668 TokensAnalyzer::isConstantInvocation - fix for interface method return type (kubawerlos) +* minor #4608 Allow Symfony 5 components (l-vo) +* minor #4622 Disallow PHP 7.4 failures on Travis CI (julienfalque) +* minor #4637 PHP 7.4 integration test (GawainLynch, julienfalque) +* minor #4643 DX: Update .gitattributes and move ci-integration.sh to root of the project (kubawerlos, keradus) +* minor #4645 Check PHP extensions on runtime (kubawerlos) +* minor #4655 Improve docs - README (mvorisek) +* minor #4662 DX: generate headers in README.rst (kubawerlos) +* minor #4669 Enable execution under PHP 7.4 (keradus) +* minor #4671 TravisTest - rewrite tests to allow last supported by tool PHP version to be snapshot (keradus) + +Changelog for v2.15.4 +--------------------- + +* bug #4183 IndentationTypeFixer - fix handling 2 spaces indent (kubawerlos) +* bug #4406 NoSuperfluousElseifFixer - fix invalid escape sequence in character class (remicollet, SpacePossum) +* bug #4416 NoUnusedImports - Fix imports detected as used in namespaces (julienfalque, SpacePossum) +* bug #4518 PhpUnitNoExpectationAnnotationFixer - fix handling expect empty exception message (ktomk) +* bug #4548 HeredocIndentationFixer - remove whitespace in empty lines (gharlan) +* bug #4556 ClassKeywordRemoveFixer - fix for self,static and parent keywords (kubawerlos) +* bug #4572 TokensAnalyzer - handle nested anonymous classes (SpacePossum) +* bug #4573 CombineConsecutiveIssetsFixer - fix stop based on precedence (SpacePossum) +* bug #4577 Fix command exit code on lint error after fixing fix. (SpacePossum) +* bug #4581 FunctionsAnalyzer: fix for comment in type (kubawerlos) +* bug #4586 BracesFixer - handle dynamic static method call (SpacePossum) +* bug #4594 Braces - fix both single line comment styles (SpacePossum) +* bug #4609 PhpdocTypesOrderFixer - Prevent unexpected default value change (laurent35240) +* minor #4458 Add PHPStan (julienfalque) +* minor #4479 IncludeFixer - remove braces when the statement is wrapped in block (kubawerlos) +* minor #4490 Allow running if installed as project specific (ticktackk) +* minor #4517 Verify PCRE pattern before use (ktomk) +* minor #4521 Remove superfluous leading backslash, closes 4520 (ktomk) +* minor #4532 DX: ensure data providers are used (kubawerlos) +* minor #4534 Redo PHP7.4 - Add "str_split" => "mb_str_split" mapping (keradus, Slamdunk) +* minor #4536 DX: use PHIVE for dev tools (keradus) +* minor #4538 Docs: update Cookbook (keradus) +* minor #4541 Enhancement: Use default name property to configure command names (localheinz) +* minor #4546 DX: removing unnecessary variable initialization (kubawerlos) +* minor #4549 DX: use ::class whenever possible (keradus, kubawerlos) +* minor #4550 DX: travis_retry for dev-tools install (ktomk, keradus) +* minor #4559 Allow 7.4snapshot to fail due to a bug on it (kubawerlos) +* minor #4563 GitlabReporter - fix report output (mjanser) +* minor #4564 Move readme-update command to Section 3 (iwasherefirst2) +* minor #4566 Update symfony ruleset (gharlan) +* minor #4570 Command::execute() should always return an integer (derrabus) +* minor #4580 Add suport for true/false return type hints. (SpacePossum) +* minor #4584 Increase PHPStan level to 1 (julienfalque) +* minor #4585 Fix deprecation notices (julienfalque) +* minor #4587 Output details - Explain why a file was skipped (SpacePossum) +* minor #4588 Fix STDIN test when path is one level deep (julienfalque) +* minor #4589 PhpdocToReturnType - Add support for Foo[][] (SpacePossum) +* minor #4593 Ensure compatibility with PHP 7.4 typed properties (julienfalque) +* minor #4595 Import cannot be used after `::` so can be removed (SpacePossum) +* minor #4596 Ensure compatibility with PHP 7.4 numeric literal separator (julienfalque) +* minor #4597 Fix PHP 7.4 deprecation notices (julienfalque) +* minor #4600 Ensure compatibility with PHP 7.4 arrow functions (julienfalque) +* minor #4602 Ensure compatibility with PHP 7.4 spread operator in array expression (julienfalque) +* minor #4603 Ensure compatibility with PHP 7.4 null coalescing assignment operator (julienfalque) +* minor #4606 Configure no_superfluous_phpdoc_tags for Symfony (keradus) +* minor #4610 Travis CI - Update known files list (julienfalque) +* minor #4615 Remove workaround for dev-tools install reg. Phive (ktomk) + +Changelog for v2.15.3 +--------------------- + +* bug #4533 Revert PHP7.4 - Add "str_split" => "mb_str_split" mapping (keradus) +* minor #4264 DX: AutoReview - ensure Travis handle all needed PHP versions (keradus) +* minor #4524 MethodArgumentSpaceFixerTest - make explicit configuration to prevent fail on configuration change (keradus) + +Changelog for v2.15.2 +--------------------- + +* bug #4132 BlankLineAfterNamespaceFixer - do not remove indent, handle comments (kubawerlos) +* bug #4384 MethodArgumentSpaceFixer - fix for on_multiline:ensure_fully_multiline with trailing comma in function call (kubawerlos) +* bug #4404 FileLintingIterator - fix current value on end/invalid (SpacePossum) +* bug #4421 FunctionTypehintSpaceFixer - Ensure single space between type declaration and parameter (localheinz) +* bug #4436 MethodArgumentSpaceFixer - handle misplaced ) (keradus) +* bug #4439 NoLeadingImportSlashFixer - Add space if needed (SpacePossum) +* bug #4440 SimpleToComplexStringVariableFixer - Fix $ bug (dmvdbrugge) +* bug #4453 Fix preg_match error on 7.4snapshot (kubawerlos) +* bug #4461 IsNullFixer - fix null coalescing operator handling (linniksa) +* bug #4467 ToolInfo - fix access to reference without checking existence (black-silence) +* bug #4472 Fix non-static closure unbinding this on PHP 7.4 (kelunik) +* minor #3726 Use Box 3 to build the PHAR (theofidry, keradus) +* minor #4412 PHP 7.4 - Tests for support (SpacePossum) +* minor #4431 DX: test that default config is not passed in RuleSet (kubawerlos) +* minor #4433 DX: test to ensure @PHPUnitMigration rule sets are correctly defined (kubawerlos) +* minor #4445 DX: static call of markTestSkippedOrFail (kubawerlos) +* minor #4463 Add apostrophe to possessive "team's" (ChandlerSwift) +* minor #4471 ReadmeCommandTest - use CommandTester (kubawerlos) +* minor #4477 DX: control names of public methods in test's classes (kubawerlos) +* minor #4483 NewWithBracesFixer - Fix object operator and curly brace open cases (SpacePossum) +* minor #4484 fix typos in README (Sven Ludwig) +* minor #4494 DX: Fix shell script syntax in order to fix Travis builds (drupol) +* minor #4516 DX: Lock binary SCA tools versions (keradus) + +Changelog for v2.15.1 +--------------------- + +* bug #4418 PhpUnitNamespacedFixer - properly translate classes which do not follow translation pattern (ktomk) +* bug #4419 PhpUnitTestCaseStaticMethodCallsFixer - skip anonymous classes and lambda (SpacePossum) +* bug #4420 MethodArgumentSpaceFixer - PHP7.3 trailing commas in function calls (SpacePossum) +* minor #4345 Travis: PHP 7.4 isn't allowed to fail anymore (Slamdunk) +* minor #4403 LowercaseStaticReferenceFixer - Fix invalid PHP version in example (HypeMC) +* minor #4424 DX: cleanup of composer.json - no need for branch-alias (keradus) +* minor #4425 DX: assertions are static, adjust custom assertions (keradus) +* minor #4426 DX: handle deprecations of symfony/event-dispatcher:4.3 (keradus) +* minor #4427 DX: stop using reserved T_FN in code samples (keradus) +* minor #4428 DX: update dev-tools (keradus) +* minor #4429 DX: MethodArgumentSpaceFixerTest - fix hidden merge conflict (keradus) + +Changelog for v2.15.0 +--------------------- + +* feature #3927 Add FinalClassFixer (Slamdunk) +* feature #3939 Add PhpUnitSizeClassFixer (Jefersson Nathan) +* feature #3942 SimpleToComplexStringVariableFixer - Introduction (dmvdbrugge, SpacePossum) +* feature #4113 OrderedInterfacesFixer - Introduction (dmvdbrugge) +* feature #4121 SingleTraitInsertPerStatementFixer - Introduction (SpacePossum) +* feature #4126 NativeFunctionTypeDeclarationCasingFixer - Introduction (SpacePossum) +* feature #4167 PhpUnitMockShortWillReturnFixer - Introduction (michadam-pearson) +* feature #4191 [7.3] NoWhitespaceBeforeCommaInArrayFixer - fix comma after heredoc-end (gharlan) +* feature #4288 Add Gitlab Reporter (hco) +* feature #4328 Add PhpUnitDedicateAssertInternalTypeFixer (Slamdunk) +* feature #4341 [7.3] TrailingCommaInMultilineArrayFixer - fix comma after heredoc-end (gharlan) +* feature #4342 [7.3] MethodArgumentSpaceFixer - fix comma after heredoc-end (gharlan) +* minor #4112 NoSuperfluousPhpdocTagsFixer - Add missing code sample, groom tests (keradus, SpacePossum) +* minor #4360 Add gitlab as output format in the README/help doc. (SpacePossum) +* minor #4386 Add PhpUnitMockShortWillReturnFixer to @Symfony:risky rule set (kubawerlos) +* minor #4398 New ruleset "@PHP73Migration" (gharlan) +* minor #4399 Fix 2.15 line (keradus) + +Changelog for v2.14.6 +--------------------- + +* bug #4533 Revert PHP7.4 - Add "str_split" => "mb_str_split" mapping (keradus) +* minor #4264 DX: AutoReview - ensure Travis handle all needed PHP versions (keradus) +* minor #4524 MethodArgumentSpaceFixerTest - make explicit configuration to prevent fail on configuration change (keradus) + +Changelog for v2.14.5 +--------------------- + +* bug #4132 BlankLineAfterNamespaceFixer - do not remove indent, handle comments (kubawerlos) +* bug #4384 MethodArgumentSpaceFixer - fix for on_multiline:ensure_fully_multiline with trailing comma in function call (kubawerlos) +* bug #4404 FileLintingIterator - fix current value on end/invalid (SpacePossum) +* bug #4421 FunctionTypehintSpaceFixer - Ensure single space between type declaration and parameter (localheinz) +* bug #4436 MethodArgumentSpaceFixer - handle misplaced ) (keradus) +* bug #4439 NoLeadingImportSlashFixer - Add space if needed (SpacePossum) +* bug #4453 Fix preg_match error on 7.4snapshot (kubawerlos) +* bug #4461 IsNullFixer - fix null coalescing operator handling (linniksa) +* bug #4467 ToolInfo - fix access to reference without checking existence (black-silence) +* bug #4472 Fix non-static closure unbinding this on PHP 7.4 (kelunik) +* minor #3726 Use Box 3 to build the PHAR (theofidry, keradus) +* minor #4412 PHP 7.4 - Tests for support (SpacePossum) +* minor #4431 DX: test that default config is not passed in RuleSet (kubawerlos) +* minor #4433 DX: test to ensure @PHPUnitMigration rule sets are correctly defined (kubawerlos) +* minor #4445 DX: static call of markTestSkippedOrFail (kubawerlos) +* minor #4463 Add apostrophe to possessive "team's" (ChandlerSwift) +* minor #4471 ReadmeCommandTest - use CommandTester (kubawerlos) +* minor #4477 DX: control names of public methods in test's classes (kubawerlos) +* minor #4483 NewWithBracesFixer - Fix object operator and curly brace open cases (SpacePossum) +* minor #4484 fix typos in README (Sven Ludwig) +* minor #4494 DX: Fix shell script syntax in order to fix Travis builds (drupol) +* minor #4516 DX: Lock binary SCA tools versions (keradus) + +Changelog for v2.14.4 +--------------------- + +* bug #4418 PhpUnitNamespacedFixer - properly translate classes which do not follow translation pattern (ktomk) +* bug #4419 PhpUnitTestCaseStaticMethodCallsFixer - skip anonymous classes and lambda (SpacePossum) +* bug #4420 MethodArgumentSpaceFixer - PHP7.3 trailing commas in function calls (SpacePossum) +* minor #4345 Travis: PHP 7.4 isn't allowed to fail anymore (Slamdunk) +* minor #4403 LowercaseStaticReferenceFixer - Fix invalid PHP version in example (HypeMC) +* minor #4425 DX: assertions are static, adjust custom assertions (keradus) +* minor #4426 DX: handle deprecations of symfony/event-dispatcher:4.3 (keradus) +* minor #4427 DX: stop using reserved T_FN in code samples (keradus) +* minor #4428 DX: update dev-tools (keradus) + +Changelog for v2.14.3 +--------------------- + +* bug #4298 NoTrailingWhitespaceInCommentFixer - fix for non-Unix line separators (kubawerlos) +* bug #4303 FullyQualifiedStrictTypesFixer - Fix the short type detection when a question mark (nullable) is prefixing it. (drupol) +* bug #4313 SelfAccessorFixer - fix for part qualified class name (kubawerlos, SpacePossum) +* bug #4314 PhpUnitTestCaseStaticMethodCallsFixer - fix for having property with name as method to update (kubawerlos, SpacePossum) +* bug #4316 NoUnsetCastFixer - Test for higher-precedence operators (SpacePossum) +* bug #4327 TokensAnalyzer - add concat operator to list of binary operators (SpacePossum) +* bug #4335 Cache - add indent and line ending to cache signature (dmvdbrugge) +* bug #4344 VoidReturnFixer - handle yield from (SpacePossum) +* bug #4346 BracesFixer - Do not pull close tag onto same line as a comment (SpacePossum) +* bug #4350 StrictParamFixer - Don't detect functions in use statements (bolmstedt) +* bug #4357 Fix short list syntax detection. (SpacePossum) +* bug #4365 Fix output escaping of diff for text format when line is not changed (SpacePossum) +* bug #4370 PhpUnitConstructFixer - Fix handle different casing (SpacePossum) +* bug #4379 ExplicitStringVariableFixer - add test case for variable as an array key (kubawerlos, Slamdunk) +* feature #4337 PhpUnitTestCaseStaticMethodCallsFixer - prepare for PHPUnit 8 (kubawerlos) +* minor #3799 DX: php_unit_test_case_static_method_calls - use default config (keradus) +* minor #4103 NoExtraBlankLinesFixer - fix candidate detection (SpacePossum) +* minor #4245 LineEndingFixer - BracesFixer - Priority (dmvdbrugge) +* minor #4325 Use lowercase mikey179/vfsStream in composer.json (lolli42) +* minor #4336 Collect coverage with PCOV (kubawerlos) +* minor #4338 Fix wording (kmvan, kubawerlos) +* minor #4339 Change BracesFixer to avoid indenting PHP inline braces (alecgeatches) +* minor #4340 Travis: build against 7.4snapshot instead of nightly (Slamdunk) +* minor #4351 code grooming (SpacePossum) +* minor #4353 Add more priority tests (SpacePossum) +* minor #4364 DX: MethodChainingIndentationFixer - remove unneccesary loop (Sijun Zhu) +* minor #4366 Unset the auxillary variable $a (GrahamCampbell) +* minor #4368 Fixed TypeShortNameResolverTest::testResolver (GrahamCampbell) +* minor #4380 PHP7.4 - Add "str_split" => "mb_str_split" mapping. (SpacePossum) +* minor #4381 PHP7.4 - Add support for magic methods (un)serialize. (SpacePossum) +* minor #4393 DX: add missing explicit return types (kubawerlos) + +Changelog for v2.14.2 +--------------------- + +* minor #4306 DX: Drop HHVM conflict on Composer level to help Composer with HHVM compatibility, we still prevent HHVM on runtime (keradus) + +Changelog for v2.14.1 +--------------------- + +* bug #4240 ModernizeTypesCastingFixer - fix for operators with higher precedence (kubawerlos) +* bug #4254 PhpUnitDedicateAssertFixer - fix for count with additional operations (kubawerlos) +* bug #4260 Psr0Fixer and Psr4Fixer - fix for multiple classes in file with anonymous class (kubawerlos) +* bug #4262 FixCommand - fix help (keradus) +* bug #4276 MethodChainingIndentationFixer, ArrayIndentationFixer - Fix priority issue (dmvdbrugge) +* bug #4280 MethodArgumentSpaceFixer - Fix method argument alignment (Billz95) +* bug #4286 IncrementStyleFixer - fix for static statement (kubawerlos) +* bug #4291 ArrayIndentationFixer - Fix indentation after trailing spaces (julienfalque, keradus) +* bug #4292 NoSuperfluousPhpdocTagsFixer - Make null only type not considered superfluous (julienfalque) +* minor #4204 DX: Tokens - do not unregister/register found tokens when collection is not changing (kubawerlos) +* minor #4235 DX: more specific @param types (kubawerlos) +* minor #4263 DX: AppVeyor - bump PHP version (keradus) +* minor #4293 Add official support for PHP 7.3 (keradus) +* minor #4295 DX: MethodArgumentSpaceFixerTest - fix edge case for handling different line ending when only expected code is provided (keradus) +* minor #4296 DX: cleanup testing with fixer config (keradus) +* minor #4299 NativeFunctionInvocationFixer - add array_key_exists (deguif, keradus) +* minor #4300 DX: cleanup testing with fixer config (keradus) + +Changelog for v2.14.0 +--------------------- + +* bug #4220 NativeFunctionInvocationFixer - namespaced strict to remove backslash (kubawerlos) +* feature #3881 Add PhpdocVarAnnotationCorrectOrderFixer (kubawerlos) +* feature #3915 Add HeredocIndentationFixer (gharlan) +* feature #4002 NoSuperfluousPhpdocTagsFixer - Allow `mixed` in superfluous PHPDoc by configuration (MortalFlesh) +* feature #4030 Add get_required_files and user_error aliases (ntzm) +* feature #4043 NativeFunctionInvocationFixer - add option to remove redundant backslashes (kubawerlos) +* feature #4102 Add NoUnsetCastFixer (SpacePossum) +* minor #4025 Add phpdoc_types_order rule to Symfony's ruleset (carusogabriel) +* minor #4213 [7.3] PHP7.3 integration tests (SpacePossum) +* minor #4233 Add official support for PHP 7.3 (keradus) + +Changelog for v2.13.3 +--------------------- + +* bug #4216 Psr4Fixer - fix for multiple classy elements in file (keradus, kubawerlos) +* bug #4217 Psr0Fixer - class with anonymous class (kubawerlos) +* bug #4219 NativeFunctionCasingFixer - handle T_RETURN_REF (kubawerlos) +* bug #4224 FunctionToConstantFixer - handle T_RETURN_REF (SpacePossum) +* bug #4229 IsNullFixer - fix parenthesis not closed (guilliamxavier) +* minor #4193 [7.3] CombineNestedDirnameFixer - support PHP 7.3 (kubawerlos) +* minor #4198 [7.3] PowToExponentiationFixer - adding to PHP7.3 integration test (kubawerlos) +* minor #4199 [7.3] MethodChainingIndentationFixer - add tests for PHP 7.3 (kubawerlos) +* minor #4200 [7.3] ModernizeTypesCastingFixer - support PHP 7.3 (kubawerlos) +* minor #4201 [7.3] MultilineWhitespaceBeforeSemicolonsFixer - add tests for PHP 7.3 (kubawerlos) +* minor #4202 [7.3] ErrorSuppressionFixer - support PHP 7.3 (kubawerlos) +* minor #4205 DX: PhpdocAlignFixer - refactor to use DocBlock (kubawerlos) +* minor #4206 DX: enable multiline_whitespace_before_semicolons (keradus) +* minor #4207 [7.3] RandomApiMigrationFixerTest - tests for 7.3 (SpacePossum) +* minor #4208 [7.3] NativeFunctionCasingFixerTest - tests for 7.3 (SpacePossum) +* minor #4209 [7.3] PhpUnitStrictFixerTest - tests for 7.3 (SpacePossum) +* minor #4210 [7.3] PhpUnitConstructFixer - add test for PHP 7.3 (kubawerlos) +* minor #4211 [7.3] PhpUnitDedicateAssertFixer - support PHP 7.3 (kubawerlos) +* minor #4214 [7.3] NoUnsetOnPropertyFixerTest - tests for 7.3 (SpacePossum) +* minor #4222 [7.3] PhpUnitExpectationFixer - support PHP 7.3 (kubawerlos) +* minor #4223 [7.3] PhpUnitMockFixer - add tests for PHP 7.3 (kubawerlos) +* minor #4230 [7.3] IsNullFixer - fix trailing comma (guilliamxavier) +* minor #4232 DX: remove Utils::splitLines (kubawerlos) +* minor #4234 [7.3] Test that "LITERAL instanceof X" is valid (guilliamxavier) + +Changelog for v2.13.2 +--------------------- + +* bug #3968 SelfAccessorFixer - support FQCN (kubawerlos) +* bug #3974 Psr4Fixer - class with anonymous class (kubawerlos) +* bug #3987 Run HeaderCommentFixer after NoBlankLinesAfterPhpdocFixer (StanAngeloff) +* bug #4009 TypeAlternationTransformer - Fix pipes in function call with constants being classified incorrectly (ntzm, SpacePossum) +* bug #4022 NoUnsetOnPropertyFixer - refactor and bugfixes (kubawerlos) +* bug #4036 ExplicitStringVariableFixer - fixes for backticks and for 2 variables next to each other (kubawerlos, Slamdunk) +* bug #4038 CommentToPhpdocFixer - handling nested PHPDoc (kubawerlos) +* bug #4064 Ignore invalid mode strings, add option to remove the "b" flag. (SpacePossum) +* bug #4071 DX: do not insert Token when calling removeLeadingWhitespace/removeTrailingWhitespace from Tokens (kubawerlos) +* bug #4073 IsNullFixer - fix function detection (kubawerlos) +* bug #4074 FileFilterIterator - do not filter out files that need fixing (SpacePossum) +* bug #4076 EregToPregFixer - fix function detection (kubawerlos) +* bug #4084 MethodChainingIndentation - fix priority with Braces (dmvdbrugge) +* bug #4099 HeaderCommentFixer - throw exception on invalid header configuration (SpacePossum) +* bug #4100 PhpdocAddMissingParamAnnotationFixer - Handle variable number of arguments and pass by reference cases (SpacePossum) +* bug #4101 ReturnAssignmentFixer - do not touch invalid code (SpacePossum) +* bug #4104 Change transformers order, fixing untransformed T_USE (dmvdbrugge) +* bug #4107 Preg::split - fix for non-UTF8 subject (ostrolucky, kubawerlos) +* bug #4109 NoBlankLines*: fix removing lines consisting only of spaces (kubawerlos, keradus) +* bug #4114 VisibilityRequiredFixer - don't remove comments (kubawerlos) +* bug #4116 OrderedImportsFixer - fix sorting without any grouping (SpacePossum) +* bug #4119 PhpUnitNoExpectationAnnotationFixer - fix extracting content from annotation (kubawerlos) +* bug #4127 LowercaseConstantsFixer - Fix case with properties using constants as their name (srathbone) +* bug #4134 [7.3] SquareBraceTransformer - nested array destructuring not handled correctly (SpacePossum) +* bug #4153 PhpUnitFqcnAnnotationFixer - handle only PhpUnit classes (kubawerlos) +* bug #4169 DirConstantFixer - Fixes for PHP7.3 syntax (SpacePossum) +* bug #4181 MultilineCommentOpeningClosingFixer - fix handling empty comment (kubawerlos) +* bug #4186 Tokens - fix removal of leading/trailing whitespace with empty token in collection (kubawerlos) +* minor #3436 Add a handful of integration tests (BackEndTea) +* minor #3774 PhpUnitTestClassRequiresCoversFixer - Remove unneeded loop and use phpunit indicator class (BackEndTea, SpacePossum) +* minor #3778 DX: Throw an exception if FileReader::read fails (ntzm) +* minor #3916 New ruleset "@PhpCsFixer" (gharlan) +* minor #4007 Fixes cookbook for fixers (greeflas) +* minor #4031 Correct FixerOptionBuilder::getOption return type (ntzm) +* minor #4046 Token - Added fast isset() path to token->equals() (staabm) +* minor #4047 Token - inline $other->getPrototype() to speedup equals() (staabm, keradus) +* minor #4048 Tokens - inlined extractTokenKind() call on the hot path (staabm) +* minor #4069 DX: Add dev-tools directory to gitattributes as export-ignore (alexmanno) +* minor #4070 Docs: Add link to a VS Code extension in readme (jakebathman) +* minor #4077 DX: cleanup - NoAliasFunctionsFixer - use FunctionsAnalyzer (kubawerlos) +* minor #4088 Add Travis test with strict types (kubawerlos) +* minor #4091 Adjust misleading sentence in CONTRIBUTING.md (ostrolucky) +* minor #4092 UseTransformer - simplify/optimize (SpacePossum) +* minor #4095 DX: Use ::class (keradus) +* minor #4096 DX: fixing typo (kubawerlos) +* minor #4097 DX: namespace casing (kubawerlos) +* minor #4110 Enhancement: Update localheinz/composer-normalize (localheinz) +* minor #4115 Changes for upcoming Travis' infra migration (sergeyklay) +* minor #4122 DX: AppVeyor - Update Composer download link (SpacePossum) +* minor #4128 DX: cleanup - AbstractFunctionReferenceFixer - use FunctionsAnalyzer (SpacePossum, kubawerlos) +* minor #4129 Fix: Symfony 4.2 deprecations (kubawerlos) +* minor #4139 DX: Fix CircleCI (kubawerlos) +* minor #4142 [7.3] NoAliasFunctionsFixer - mbregex_encoding' => 'mb_regex_encoding (SpacePossum) +* minor #4143 PhpUnitTestCaseStaticMethodCallsFixer - Add PHPUnit 7.5 new assertions (Slamdunk) +* minor #4149 [7.3] ArgumentsAnalyzer - PHP7.3 support (SpacePossum) +* minor #4161 DX: CI - show packages installed via Composer (keradus) +* minor #4162 DX: Drop symfony/lts (keradus) +* minor #4166 DX: do not use AbstractFunctionReferenceFixer when no need to (kubawerlos) +* minor #4168 DX: FopenFlagsFixer - remove useless proxy method (SpacePossum) +* minor #4171 Fix CircleCI cache (kubawerlos) +* minor #4173 [7.3] PowToExponentiationFixer - add support for PHP7.3 (SpacePossum) +* minor #4175 Fixing typo (kubawerlos) +* minor #4177 CI: Check that tag is matching version of PHP CS Fixer during deployment (keradus) +* minor #4180 Fixing typo (kubawerlos) +* minor #4182 DX: update php-cs-fixer file style (kubawerlos) +* minor #4185 [7.3] ImplodeCallFixer - add tests for PHP7.3 (kubawerlos) +* minor #4187 [7.3] IsNullFixer - support PHP 7.3 (kubawerlos) +* minor #4188 DX: cleanup (keradus) +* minor #4189 Travis - add PHP 7.3 job (keradus) +* minor #4190 Travis CI - fix config (kubawerlos) +* minor #4192 [7.3] MagicMethodCasingFixer - add tests for PHP 7.3 (kubawerlos) +* minor #4194 [7.3] NativeFunctionInvocationFixer - add tests for PHP 7.3 (kubawerlos) +* minor #4195 [7.3] SetTypeToCastFixer - support PHP 7.3 (kubawerlos) +* minor #4196 Update website (keradus) +* minor #4197 [7.3] StrictParamFixer - support PHP 7.3 (kubawerlos) + +Changelog for v2.13.1 +--------------------- + +* bug #3977 NoSuperfluousPhpdocTagsFixer - Fix handling of description with variable (julienfalque) +* bug #4027 PhpdocAnnotationWithoutDotFixer - add failing cases (keradus) +* bug #4028 PhpdocNoEmptyReturnFixer - handle single line PHPDoc (kubawerlos) +* bug #4034 PhpUnitTestCaseIndicator - handle anonymous class (kubawerlos) +* bug #4037 NativeFunctionInvocationFixer - fix function detection (kubawerlos) +* feature #4019 PhpdocTypesFixer - allow for configuration (keradus) +* minor #3980 Clarifies allow-risky usage (josephzidell) +* minor #4016 Bump console component due to it's bug (keradus) +* minor #4023 Enhancement: Update localheinz/composer-normalize (localheinz) +* minor #4049 use parent::offset*() methods when moving items around in insertAt() (staabm) + +Changelog for v2.13.0 +--------------------- + +* feature #3739 Add MagicMethodCasingFixer (SpacePossum) +* feature #3812 Add FopenFlagOrderFixer & FopenFlagsFixer (SpacePossum) +* feature #3826 Add CombineNestedDirnameFixer (gharlan) +* feature #3833 BinaryOperatorSpacesFixer - Add "no space" fix strategy (SpacePossum) +* feature #3841 NoAliasFunctionsFixer - add opt in option for ext-mbstring aliasses (SpacePossum) +* feature #3876 NativeConstantInvocationFixer - add the scope option (stof, keradus) +* feature #3886 Add PhpUnitMethodCasingFixer (Slamdunk) +* feature #3907 Add ImplodeCallFixer (kubawerlos) +* feature #3914 NoUnreachableDefaultArgumentValueFixer - remove `null` for nullable typehints (gharlan, keradus) +* minor #3813 PhpUnitDedicateAssertFixer - fix "sizeOf" same as "count". (SpacePossum) +* minor #3873 Add the native_function_invocation fixer in the Symfony:risky ruleset (stof) +* minor #3979 DX: enable php_unit_method_casing (keradus) + +Changelog for v2.12.12 +---------------------- + +* bug #4533 Revert PHP7.4 - Add "str_split" => "mb_str_split" mapping (keradus) +* minor #4264 DX: AutoReview - ensure Travis handle all needed PHP versions (keradus) +* minor #4524 MethodArgumentSpaceFixerTest - make explicit configuration to prevent fail on configuration change (keradus) + +Changelog for v2.12.11 +---------------------- + +* bug #4132 BlankLineAfterNamespaceFixer - do not remove indent, handle comments (kubawerlos) +* bug #4384 MethodArgumentSpaceFixer - fix for on_multiline:ensure_fully_multiline with trailing comma in function call (kubawerlos) +* bug #4404 FileLintingIterator - fix current value on end/invalid (SpacePossum) +* bug #4421 FunctionTypehintSpaceFixer - Ensure single space between type declaration and parameter (localheinz) +* bug #4436 MethodArgumentSpaceFixer - handle misplaced ) (keradus) +* bug #4439 NoLeadingImportSlashFixer - Add space if needed (SpacePossum) +* bug #4453 Fix preg_match error on 7.4snapshot (kubawerlos) +* bug #4461 IsNullFixer - fix null coalescing operator handling (linniksa) +* bug #4467 ToolInfo - fix access to reference without checking existence (black-silence) +* bug #4472 Fix non-static closure unbinding this on PHP 7.4 (kelunik) +* minor #3726 Use Box 3 to build the PHAR (theofidry, keradus) +* minor #4412 PHP 7.4 - Tests for support (SpacePossum) +* minor #4431 DX: test that default config is not passed in RuleSet (kubawerlos) +* minor #4433 DX: test to ensure @PHPUnitMigration rule sets are correctly defined (kubawerlos) +* minor #4445 DX: static call of markTestSkippedOrFail (kubawerlos) +* minor #4463 Add apostrophe to possessive "team's" (ChandlerSwift) +* minor #4471 ReadmeCommandTest - use CommandTester (kubawerlos) +* minor #4477 DX: control names of public methods in test's classes (kubawerlos) +* minor #4483 NewWithBracesFixer - Fix object operator and curly brace open cases (SpacePossum) +* minor #4484 fix typos in README (Sven Ludwig) +* minor #4494 DX: Fix shell script syntax in order to fix Travis builds (drupol) +* minor #4516 DX: Lock binary SCA tools versions (keradus) + +Changelog for v2.12.10 +---------------------- + +* bug #4418 PhpUnitNamespacedFixer - properly translate classes which do not follow translation pattern (ktomk) +* bug #4419 PhpUnitTestCaseStaticMethodCallsFixer - skip anonymous classes and lambda (SpacePossum) +* bug #4420 MethodArgumentSpaceFixer - PHP7.3 trailing commas in function calls (SpacePossum) +* minor #4345 Travis: PHP 7.4 isn't allowed to fail anymore (Slamdunk) +* minor #4403 LowercaseStaticReferenceFixer - Fix invalid PHP version in example (HypeMC) +* minor #4425 DX: assertions are static, adjust custom assertions (keradus) +* minor #4426 DX: handle deprecations of symfony/event-dispatcher:4.3 (keradus) +* minor #4427 DX: stop using reserved T_FN in code samples (keradus) + +Changelog for v2.12.9 +--------------------- + +* bug #4298 NoTrailingWhitespaceInCommentFixer - fix for non-Unix line separators (kubawerlos) +* bug #4303 FullyQualifiedStrictTypesFixer - Fix the short type detection when a question mark (nullable) is prefixing it. (drupol) +* bug #4313 SelfAccessorFixer - fix for part qualified class name (kubawerlos, SpacePossum) +* bug #4314 PhpUnitTestCaseStaticMethodCallsFixer - fix for having property with name as method to update (kubawerlos, SpacePossum) +* bug #4327 TokensAnalyzer - add concat operator to list of binary operators (SpacePossum) +* bug #4335 Cache - add indent and line ending to cache signature (dmvdbrugge) +* bug #4344 VoidReturnFixer - handle yield from (SpacePossum) +* bug #4346 BracesFixer - Do not pull close tag onto same line as a comment (SpacePossum) +* bug #4350 StrictParamFixer - Don't detect functions in use statements (bolmstedt) +* bug #4357 Fix short list syntax detection. (SpacePossum) +* bug #4365 Fix output escaping of diff for text format when line is not changed (SpacePossum) +* bug #4370 PhpUnitConstructFixer - Fix handle different casing (SpacePossum) +* bug #4379 ExplicitStringVariableFixer - add test case for variable as an array key (kubawerlos, Slamdunk) +* feature #4337 PhpUnitTestCaseStaticMethodCallsFixer - prepare for PHPUnit 8 (kubawerlos) +* minor #3799 DX: php_unit_test_case_static_method_calls - use default config (keradus) +* minor #4103 NoExtraBlankLinesFixer - fix candidate detection (SpacePossum) +* minor #4245 LineEndingFixer - BracesFixer - Priority (dmvdbrugge) +* minor #4325 Use lowercase mikey179/vfsStream in composer.json (lolli42) +* minor #4336 Collect coverage with PCOV (kubawerlos) +* minor #4338 Fix wording (kmvan, kubawerlos) +* minor #4339 Change BracesFixer to avoid indenting PHP inline braces (alecgeatches) +* minor #4340 Travis: build against 7.4snapshot instead of nightly (Slamdunk) +* minor #4351 code grooming (SpacePossum) +* minor #4353 Add more priority tests (SpacePossum) +* minor #4364 DX: MethodChainingIndentationFixer - remove unneccesary loop (Sijun Zhu) +* minor #4366 Unset the auxillary variable $a (GrahamCampbell) +* minor #4368 Fixed TypeShortNameResolverTest::testResolver (GrahamCampbell) +* minor #4380 PHP7.4 - Add "str_split" => "mb_str_split" mapping. (SpacePossum) +* minor #4393 DX: add missing explicit return types (kubawerlos) + +Changelog for v2.12.8 +--------------------- + +* minor #4306 DX: Drop HHVM conflict on Composer level to help Composer with HHVM compatibility, we still prevent HHVM on runtime (keradus) + +Changelog for v2.12.7 +--------------------- + +* bug #4240 ModernizeTypesCastingFixer - fix for operators with higher precedence (kubawerlos) +* bug #4254 PhpUnitDedicateAssertFixer - fix for count with additional operations (kubawerlos) +* bug #4260 Psr0Fixer and Psr4Fixer - fix for multiple classes in file with anonymous class (kubawerlos) +* bug #4262 FixCommand - fix help (keradus) +* bug #4276 MethodChainingIndentationFixer, ArrayIndentationFixer - Fix priority issue (dmvdbrugge) +* bug #4280 MethodArgumentSpaceFixer - Fix method argument alignment (Billz95) +* bug #4286 IncrementStyleFixer - fix for static statement (kubawerlos) +* bug #4291 ArrayIndentationFixer - Fix indentation after trailing spaces (julienfalque, keradus) +* bug #4292 NoSuperfluousPhpdocTagsFixer - Make null only type not considered superfluous (julienfalque) +* minor #4204 DX: Tokens - do not unregister/register found tokens when collection is not changing (kubawerlos) +* minor #4235 DX: more specific @param types (kubawerlos) +* minor #4263 DX: AppVeyor - bump PHP version (keradus) +* minor #4293 Add official support for PHP 7.3 (keradus) +* minor #4295 DX: MethodArgumentSpaceFixerTest - fix edge case for handling different line ending when only expected code is provided (keradus) +* minor #4296 DX: cleanup testing with fixer config (keradus) +* minor #4299 NativeFunctionInvocationFixer - add array_key_exists (deguif, keradus) + +Changelog for v2.12.6 +--------------------- + +* bug #4216 Psr4Fixer - fix for multiple classy elements in file (keradus, kubawerlos) +* bug #4217 Psr0Fixer - class with anonymous class (kubawerlos) +* bug #4219 NativeFunctionCasingFixer - handle T_RETURN_REF (kubawerlos) +* bug #4224 FunctionToConstantFixer - handle T_RETURN_REF (SpacePossum) +* bug #4229 IsNullFixer - fix parenthesis not closed (guilliamxavier) +* minor #4198 [7.3] PowToExponentiationFixer - adding to PHP7.3 integration test (kubawerlos) +* minor #4199 [7.3] MethodChainingIndentationFixer - add tests for PHP 7.3 (kubawerlos) +* minor #4200 [7.3] ModernizeTypesCastingFixer - support PHP 7.3 (kubawerlos) +* minor #4201 [7.3] MultilineWhitespaceBeforeSemicolonsFixer - add tests for PHP 7.3 (kubawerlos) +* minor #4202 [7.3] ErrorSuppressionFixer - support PHP 7.3 (kubawerlos) +* minor #4205 DX: PhpdocAlignFixer - refactor to use DocBlock (kubawerlos) +* minor #4206 DX: enable multiline_whitespace_before_semicolons (keradus) +* minor #4207 [7.3] RandomApiMigrationFixerTest - tests for 7.3 (SpacePossum) +* minor #4208 [7.3] NativeFunctionCasingFixerTest - tests for 7.3 (SpacePossum) +* minor #4209 [7.3] PhpUnitStrictFixerTest - tests for 7.3 (SpacePossum) +* minor #4210 [7.3] PhpUnitConstructFixer - add test for PHP 7.3 (kubawerlos) +* minor #4211 [7.3] PhpUnitDedicateAssertFixer - support PHP 7.3 (kubawerlos) +* minor #4214 [7.3] NoUnsetOnPropertyFixerTest - tests for 7.3 (SpacePossum) +* minor #4222 [7.3] PhpUnitExpectationFixer - support PHP 7.3 (kubawerlos) +* minor #4223 [7.3] PhpUnitMockFixer - add tests for PHP 7.3 (kubawerlos) +* minor #4230 [7.3] IsNullFixer - fix trailing comma (guilliamxavier) +* minor #4232 DX: remove Utils::splitLines (kubawerlos) +* minor #4234 [7.3] Test that "LITERAL instanceof X" is valid (guilliamxavier) + +Changelog for v2.12.5 +--------------------- + +* bug #3968 SelfAccessorFixer - support FQCN (kubawerlos) +* bug #3974 Psr4Fixer - class with anonymous class (kubawerlos) +* bug #3987 Run HeaderCommentFixer after NoBlankLinesAfterPhpdocFixer (StanAngeloff) +* bug #4009 TypeAlternationTransformer - Fix pipes in function call with constants being classified incorrectly (ntzm, SpacePossum) +* bug #4022 NoUnsetOnPropertyFixer - refactor and bugfixes (kubawerlos) +* bug #4036 ExplicitStringVariableFixer - fixes for backticks and for 2 variables next to each other (kubawerlos, Slamdunk) +* bug #4038 CommentToPhpdocFixer - handling nested PHPDoc (kubawerlos) +* bug #4071 DX: do not insert Token when calling removeLeadingWhitespace/removeTrailingWhitespace from Tokens (kubawerlos) +* bug #4073 IsNullFixer - fix function detection (kubawerlos) +* bug #4074 FileFilterIterator - do not filter out files that need fixing (SpacePossum) +* bug #4076 EregToPregFixer - fix function detection (kubawerlos) +* bug #4084 MethodChainingIndentation - fix priority with Braces (dmvdbrugge) +* bug #4099 HeaderCommentFixer - throw exception on invalid header configuration (SpacePossum) +* bug #4100 PhpdocAddMissingParamAnnotationFixer - Handle variable number of arguments and pass by reference cases (SpacePossum) +* bug #4101 ReturnAssignmentFixer - do not touch invalid code (SpacePossum) +* bug #4104 Change transformers order, fixing untransformed T_USE (dmvdbrugge) +* bug #4107 Preg::split - fix for non-UTF8 subject (ostrolucky, kubawerlos) +* bug #4109 NoBlankLines*: fix removing lines consisting only of spaces (kubawerlos, keradus) +* bug #4114 VisibilityRequiredFixer - don't remove comments (kubawerlos) +* bug #4116 OrderedImportsFixer - fix sorting without any grouping (SpacePossum) +* bug #4119 PhpUnitNoExpectationAnnotationFixer - fix extracting content from annotation (kubawerlos) +* bug #4127 LowercaseConstantsFixer - Fix case with properties using constants as their name (srathbone) +* bug #4134 [7.3] SquareBraceTransformer - nested array destructuring not handled correctly (SpacePossum) +* bug #4153 PhpUnitFqcnAnnotationFixer - handle only PhpUnit classes (kubawerlos) +* bug #4169 DirConstantFixer - Fixes for PHP7.3 syntax (SpacePossum) +* bug #4181 MultilineCommentOpeningClosingFixer - fix handling empty comment (kubawerlos) +* bug #4186 Tokens - fix removal of leading/trailing whitespace with empty token in collection (kubawerlos) +* minor #3436 Add a handful of integration tests (BackEndTea) +* minor #3774 PhpUnitTestClassRequiresCoversFixer - Remove unneeded loop and use phpunit indicator class (BackEndTea, SpacePossum) +* minor #3778 DX: Throw an exception if FileReader::read fails (ntzm) +* minor #3916 New ruleset "@PhpCsFixer" (gharlan) +* minor #4007 Fixes cookbook for fixers (greeflas) +* minor #4031 Correct FixerOptionBuilder::getOption return type (ntzm) +* minor #4046 Token - Added fast isset() path to token->equals() (staabm) +* minor #4047 Token - inline $other->getPrototype() to speedup equals() (staabm, keradus) +* minor #4048 Tokens - inlined extractTokenKind() call on the hot path (staabm) +* minor #4069 DX: Add dev-tools directory to gitattributes as export-ignore (alexmanno) +* minor #4070 Docs: Add link to a VS Code extension in readme (jakebathman) +* minor #4077 DX: cleanup - NoAliasFunctionsFixer - use FunctionsAnalyzer (kubawerlos) +* minor #4088 Add Travis test with strict types (kubawerlos) +* minor #4091 Adjust misleading sentence in CONTRIBUTING.md (ostrolucky) +* minor #4092 UseTransformer - simplify/optimize (SpacePossum) +* minor #4095 DX: Use ::class (keradus) +* minor #4097 DX: namespace casing (kubawerlos) +* minor #4110 Enhancement: Update localheinz/composer-normalize (localheinz) +* minor #4115 Changes for upcoming Travis' infra migration (sergeyklay) +* minor #4122 DX: AppVeyor - Update Composer download link (SpacePossum) +* minor #4128 DX: cleanup - AbstractFunctionReferenceFixer - use FunctionsAnalyzer (SpacePossum, kubawerlos) +* minor #4129 Fix: Symfony 4.2 deprecations (kubawerlos) +* minor #4139 DX: Fix CircleCI (kubawerlos) +* minor #4143 PhpUnitTestCaseStaticMethodCallsFixer - Add PHPUnit 7.5 new assertions (Slamdunk) +* minor #4149 [7.3] ArgumentsAnalyzer - PHP7.3 support (SpacePossum) +* minor #4161 DX: CI - show packages installed via Composer (keradus) +* minor #4162 DX: Drop symfony/lts (keradus) +* minor #4166 DX: do not use AbstractFunctionReferenceFixer when no need to (kubawerlos) +* minor #4171 Fix CircleCI cache (kubawerlos) +* minor #4173 [7.3] PowToExponentiationFixer - add support for PHP7.3 (SpacePossum) +* minor #4175 Fixing typo (kubawerlos) +* minor #4177 CI: Check that tag is matching version of PHP CS Fixer during deployment (keradus) +* minor #4182 DX: update php-cs-fixer file style (kubawerlos) +* minor #4187 [7.3] IsNullFixer - support PHP 7.3 (kubawerlos) +* minor #4188 DX: cleanup (keradus) +* minor #4189 Travis - add PHP 7.3 job (keradus) +* minor #4190 Travis CI - fix config (kubawerlos) +* minor #4194 [7.3] NativeFunctionInvocationFixer - add tests for PHP 7.3 (kubawerlos) +* minor #4195 [7.3] SetTypeToCastFixer - support PHP 7.3 (kubawerlos) +* minor #4196 Update website (keradus) +* minor #4197 [7.3] StrictParamFixer - support PHP 7.3 (kubawerlos) + +Changelog for v2.12.4 +--------------------- + +* bug #3977 NoSuperfluousPhpdocTagsFixer - Fix handling of description with variable (julienfalque) +* bug #4027 PhpdocAnnotationWithoutDotFixer - add failing cases (keradus) +* bug #4028 PhpdocNoEmptyReturnFixer - handle single line PHPDoc (kubawerlos) +* bug #4034 PhpUnitTestCaseIndicator - handle anonymous class (kubawerlos) +* bug #4037 NativeFunctionInvocationFixer - fix function detection (kubawerlos) +* feature #4019 PhpdocTypesFixer - allow for configuration (keradus) +* minor #3980 Clarifies allow-risky usage (josephzidell) +* minor #4016 Bump console component due to it's bug (keradus) +* minor #4023 Enhancement: Update localheinz/composer-normalize (localheinz) +* minor #4049 use parent::offset*() methods when moving items around in insertAt() (staabm) + +Changelog for v2.12.3 +--------------------- + +* bug #3867 PhpdocAnnotationWithoutDotFixer - Handle trailing whitespaces (kubawerlos) +* bug #3884 NoSuperfluousPhpdocTagsFixer - handle null in every position (dmvdbrugge, julienfalque) +* bug #3885 AlignMultilineCommentFixer - ArrayIndentationFixer - Priority (dmvdbrugge) +* bug #3887 ArrayIndentFixer - Don't indent empty lines (dmvdbrugge) +* bug #3888 NoExtraBlankLinesFixer - remove blank lines after open tag (kubawerlos) +* bug #3890 StrictParamFixer - make it case-insensitive (kubawerlos) +* bug #3895 FunctionsAnalyzer - false positive for constant and function definition (kubawerlos) +* bug #3908 StrictParamFixer - fix edge case (kubawerlos) +* bug #3910 FunctionsAnalyzer - fix isGlobalFunctionCall (gharlan) +* bug #3912 FullyQualifiedStrictTypesFixer - NoSuperfluousPhpdocTagsFixer - adjust priority (dmvdbrugge) +* bug #3913 TokensAnalyzer - fix isConstantInvocation (gharlan, keradus) +* bug #3921 TypeAnalysis - Fix iterable not being detected as a reserved type (ntzm) +* bug #3924 FullyQualifiedStrictTypesFixer - space bug (dmvdbrugge) +* bug #3937 LowercaseStaticReferenceFixer - Fix "Parent" word in namespace (kubawerlos) +* bug #3944 ExplicitStringVariableFixer - fix array handling (gharlan) +* bug #3951 NoSuperfluousPhpdocTagsFixer - do not call strtolower with null (SpacePossum) +* bug #3954 NoSuperfluousPhpdocTagsFixer - Index invalid or out of range (kubawerlos) +* bug #3957 NoTrailingWhitespaceFixer - trim space after opening tag (kubawerlos) +* minor #3798 DX: enable native_function_invocation (keradus) +* minor #3882 PhpdocAnnotationWithoutDotFixer - Handle empty line in comment (kubawerlos) +* minor #3889 DX: Cleanup - remove unused variables (kubawerlos, SpacePossum) +* minor #3891 PhpdocNoEmptyReturnFixer - account for null[] (dmvdbrugge) +* minor #3892 PhpdocNoEmptyReturnFixer - fix docs (keradus) +* minor #3897 DX: FunctionsAnalyzer - simplifying return expression (kubawerlos) +* minor #3903 DX: cleanup - remove special treatment for PHP <5.6 (kubawerlos) +* minor #3905 DX: Upgrade composer-require-checker to stable version (keradus) +* minor #3919 Simplify single uses of Token::isGivenKind (ntzm) +* minor #3920 Docs: Fix typo (ntzm) +* minor #3940 DX: fix phpdoc parameter type (malukenho) +* minor #3948 DX: cleanup - remove redundant @param annotations (kubawerlos) +* minor #3950 Circle CI v2 yml (siad007) +* minor #3952 DX: AbstractFixerTestCase - drop testing method already provided by trait (keradus) +* minor #3973 Bump xdebug-handler (keradus) + +Changelog for v2.12.2 +--------------------- + +* bug #3823 NativeConstantInvocationFixer - better constant detection (gharlan, SpacePossum, keradus) +* bug #3832 "yield from" as keyword (SpacePossum) +* bug #3835 Fix priority between PHPDoc return type fixers (julienfalque, keradus) +* bug #3839 MethodArgumentSpaceFixer - add empty line incorrectly (SpacePossum) +* bug #3866 SpaceAfterSemicolonFixer - loop over all tokens (SpacePossum) +* minor #3817 Update integrations tests (SpacePossum) +* minor #3829 Fix typos in changelog (mnabialek) +* minor #3848 Add install/update instructions for PHIVE to the README (SpacePossum) +* minor #3877 NamespacesAnalyzer - Optimize performance (stof) +* minor #3878 NativeFunctionInvocationFixer - use the NamespacesAnalyzer to remove duplicated code (stof) + +Changelog for v2.12.1 +--------------------- + +* bug #3808 LowercaseStaticReferenceFixer - Fix constants handling (kubawerlos, keradus) +* bug #3815 NoSuperfluousPhpdocTagsFixer - support array/callable type hints (gharlan) +* minor #3824 DX: Support PHPUnit 7.2 (keradus) +* minor #3825 UX: Provide full diff for code samples (keradus) + +Changelog for v2.12.0 +--------------------- + +* feature #2577 Add LogicalOperatorsFixer (hkdobrev, keradus) +* feature #3060 Add ErrorSuppressionFixer (kubawerlos) +* feature #3127 Add NativeConstantInvocationFixer (Slamdunk, keradus) +* feature #3223 NativeFunctionInvocationFixer - add namespace scope and include sets (SpacePossum) +* feature #3453 PhpdocAlignFixer - add align option (robert.ahmerov) +* feature #3476 Add PhpUnitTestCaseStaticMethodCallsFixer (Slamdunk, keradus) +* feature #3524 MethodArgumentSpaceFixer - Add ensure_single_line option (julienfalque, keradus) +* feature #3534 MultilineWhitespaceBeforeSemicolonsFixer - support static calls (ntzm) +* feature #3585 Add ReturnAssignmentFixer (SpacePossum, keradus) +* feature #3640 Add PhpdocToReturnTypeFixer (Slamdunk, keradus) +* feature #3691 Add PhpdocTrimAfterDescriptionFixer (nobuf, keradus) +* feature #3698 YodaStyleFixer - Add always_move_variable option (julienfalque, SpacePossum) +* feature #3709 Add SetTypeToCastFixer (SpacePossum) +* feature #3724 BlankLineBeforeStatementFixer - Add case and default as options (dmvdbrugge) +* feature #3734 Add NoSuperfluousPhpdocTagsFixer (julienfalque) +* feature #3735 Add LowercaseStaticReferenceFixer (kubawerlos, SpacePossum) +* feature #3737 Add NoUnsetOnPropertyFixer (BackEndTea, SpacePossum) +* feature #3745 Add PhpUnitInternalClassFixer (BackEndTea, SpacePossum, keradus) +* feature #3766 Add NoBinaryStringFixer (ntzm, SpacePossum, keradus) +* feature #3780 ShortScalarCastFixer - Change binary cast to string cast as well (ntzm) +* feature #3785 PhpUnitDedicateAssertFixer - fix to assertCount too (SpacePossum) +* feature #3802 Convert PhpdocTrimAfterDescriptionFixer into PhpdocTrimConsecutiveBlankLineSeparationFixer (keradus) +* minor #3738 ReturnAssignmentFixer description update (kubawerlos) +* minor #3761 Application: when run with FUTURE_MODE, error_reporting(-1) is done in entry file instead (keradus) +* minor #3772 DX: use PhpUnitTestCaseIndicator->isPhpUnitClass to discover PHPUnit classes (keradus) +* minor #3783 CI: Split COLLECT_COVERAGE job (keradus) +* minor #3789 DX: ProjectCodeTest.testThatDataProvidersAreCorrectlyNamed - performance optimization (keradus) +* minor #3791 DX: Fix collecting code coverage (keradus) +* minor #3792 DX: Upgrade DX deps (keradus) +* minor #3797 DX: ProjectCodeTest - shall not depends on xdebug/phpdbg anymore (keradus, SpacePossum) +* minor #3800 Symfony:risky ruleset: include set_type_to_cast rule (keradus) +* minor #3801 NativeFunctionInvocationFixer - fix buggy config validation (keradus, SpacePossum) + +Changelog for v2.11.2 +--------------------- + +* bug #3233 PhpdocAlignFixer - Fix linebreak inconsistency (SpacePossum, keradus) +* bug #3445 Rewrite NoUnusedImportsFixer (kubawerlos, julienfalque) +* bug #3528 MethodChainingIndentationFixer - nested params bugfix (Slamdunk) +* bug #3547 MultilineWhitespaceBeforeSemicolonsFixer - chained call for a return fix (egircys, keradus) +* bug #3597 DeclareStrictTypesFixer - fix bug of removing line (kubawerlos, keradus) +* bug #3605 DoctrineAnnotationIndentationFixer - Fix indentation with mixed lines (julienfalque) +* bug #3606 PhpdocToCommentFixer - allow multiple ( (SpacePossum) +* bug #3614 Refactor PhpdocToCommentFixer - extract checking to CommentsAnalyzer (kubawerlos) +* bug #3668 Rewrite NoUnusedImportsFixer (kubawerlos, julienfalque) +* bug #3670 PhpdocTypesOrderFixer - Fix ordering of nested generics (julienfalque) +* bug #3671 ArrayIndentationFixer - Fix indentation in HTML (julienfalque) +* bug #3673 PhpdocScalarFixer - Add "types" option (julienfalque, keradus) +* bug #3674 YodaStyleFixer - Fix variable detection for multidimensional arrays (julienfalque, SpacePossum) +* bug #3684 PhpUnitStrictFixer - Do not fix if not correct # of arguments are used (SpacePossum) +* bug #3708 EspaceImplicitBackslashesFixer - Fix escaping multiple backslashes (julienfalque) +* bug #3715 SingleImportPerStatementFixer - Fix handling whitespace before opening brace (julienfalque) +* bug #3731 PhpdocIndentFixer - crash fix (SpacePossum) +* bug #3755 YodaStyleFixer - handle space between var name and index (SpacePossum) +* bug #3765 Fix binary-prefixed double-quoted strings to single quotes (ntzm) +* bug #3770 Handle binary flags in heredoc_to_nowdoc (ntzm) +* bug #3776 ExplicitStringVariableFixer - handle binary strings (ntzm) +* bug #3777 EscapeImplicitBackslashesFixer - handle binary strings (ntzm) +* bug #3790 ProcessLinter - don't execute external process without timeout! It can freeze! (keradus) +* minor #3188 AppVeyor - add PHP 7.x (keradus, julienfalque) +* minor #3451 Update findPHPUnit functions (BackEndTea, SpacePossum, keradus) +* minor #3548 Make shell scripts POSIX-compatible (EvgenyOrekhov, keradus) +* minor #3568 New Autoreview: Correct option casing (ntzm) +* minor #3578 Add interface for deprecated options (julienfalque, keradus) +* minor #3590 Use XdebugHandler to avoid perormance penalty (AJenbo, keradus) +* minor #3607 PhpdocVarWithoutNameFixer - update sample with @ type (SpacePossum) +* minor #3617 Tests stability patches (Tom Klingenberg, keradus) +* minor #3622 Docs: Update descriptions (localheinz) +* minor #3627 Fix tests execution under phpdbg (keradus) +* minor #3629 ProjectFixerConfigurationTest - test rules are sorted (SpacePossum) +* minor #3639 DX: use benefits of symfony/force-lowest (keradus) +* minor #3641 Update check_trailing_spaces script with upstream (keradus) +* minor #3646 Extract SameStringsConstraint and XmlMatchesXsdConstraint (keradus) +* minor #3647 DX: Add CachingLinter for tests (keradus) +* minor #3649 Update check_trailing_spaces script with upstream (keradus) +* minor #3652 CiIntegrationTest - run tests with POSIX sh, not Bash (keradus) +* minor #3656 DX: Clean ups (SpacePossum) +* minor #3657 update phpunitgoodpractices/traits (SpacePossum, keradus) +* minor #3658 DX: Clean ups (SpacePossum) +* minor #3660 Fix do not rely on order of fixing in CiIntegrationTest (kubawerlos) +* minor #3661 Fix: covers annotation for NoAlternativeSyntaxFixerTest (kubawerlos) +* minor #3662 DX: Add Smoke/InstallViaComposerTest (keradus) +* minor #3663 DX: During deployment, run all smoke tests and don't allow to skip phar-related ones (keradus) +* minor #3665 CircleCI fix (kubawerlos) +* minor #3666 Use "set -eu" in shell scripts (EvgenyOrekhov) +* minor #3669 Document possible values for subset options (julienfalque, keradus) +* minor #3672 Remove SameStringsConstraint and XmlMatchesXsdConstraint (keradus) +* minor #3676 RunnerTest - workaround for failing Symfony v2.8.37 (kubawerlos) +* minor #3680 DX: Tokens - removeLeadingWhitespace and removeTrailingWhitespace must act in same way (SpacePossum) +* minor #3686 README.rst - Format all code-like strings in fixer descriptions (ntzm, keradus) +* minor #3692 DX: Optimize tests (julienfalque) +* minor #3700 README.rst - Format all code-like strings in fixer description (ntzm) +* minor #3701 Use correct casing for "PHPDoc" (ntzm) +* minor #3703 DX: InstallViaComposerTest - groom naming (keradus) +* minor #3704 DX: Tokens - fix naming (keradus) +* minor #3706 Update homebrew installation instructions (ntzm) +* minor #3713 Use HTTPS whenever possible (fabpot) +* minor #3723 Extend tests coverage (ntzm) +* minor #3733 Disable Composer optimized autoloader by default (julienfalque) +* minor #3748 PhpUnitStrictFixer - extend risky note (jnvsor) +* minor #3749 Make sure PHPUnit is cased correctly in fixers descriptions (kubawerlos) +* minor #3768 Improve deprecation messages (julienfalque, SpacePossum) +* minor #3773 AbstractFixerWithAliasedOptionsTestCase - don't export (keradus) +* minor #3775 Add tests for binary strings in string_line_ending (ntzm) +* minor #3779 Misc fixes (ntzm, keradus) +* minor #3796 DX: StdinTest - do not assume name of folder, into which project was cloned (keradus) +* minor #3803 NoEmptyPhpdocFixer/PhpdocAddMissingParamAnnotationFixer - missing priority test (SpacePossum, keradus) +* minor #3804 Cleanup: remove useless constructor comment (kubawerlos) +* minor #3805 Cleanup: add missing @param type (kubawerlos, keradus) + +Changelog for v2.11.1 +--------------------- + +* bug #3626 ArrayIndentationFixer: priority bug with BinaryOperatorSpacesFixer and MethodChainingIndentationFixer (Slamdunk) +* bug #3632 DateTimeImmutableFixer bug with adding tokens while iterating over them (kubawerlos) +* minor #3478 PhpUnitDedicateAssertFixer: handle static calls (Slamdunk) +* minor #3618 DateTimeImmutableFixer - grooming (keradus) + +Changelog for v2.11.0 +--------------------- + +* feature #3135 Add ArrayIndentationFixer (julienfalque) +* feature #3235 Implement StandardizeIncrementFixer (ntzm, SpacePossum) +* feature #3260 Add DateTimeImmutableFixer (kubawerlos) +* feature #3276 Transform Fully Qualified parameters and return types to short version (veewee, keradus) +* feature #3299 SingleQuoteFixer - fix single quote char (Slamdunk) +* feature #3340 Verbose LintingException after fixing (Slamdunk) +* feature #3423 FunctionToConstantFixer - add fix "get_called_class" option (SpacePossum) +* feature #3434 Add PhpUnitSetUpTearDownVisibilityFixer (BackEndTea, SpacePossum) +* feature #3442 Add CommentToPhpdocFixer (kubawerlos, keradus) +* feature #3448 OrderedClassElementsFixer - added sortAlgorithm option (meridius) +* feature #3454 Add StringLineEndingFixer (iluuu1994, SpacePossum, keradus, julienfalque) +* feature #3477 PhpUnitStrictFixer: handle static calls (Slamdunk) +* feature #3479 PhpUnitConstructFixer: handle static calls (Slamdunk) +* feature #3507 Add PhpUnitOrderedCoversFixer (Slamdunk) +* feature #3545 Add the 'none' sort algorithm to OrderedImportsFixer (EvgenyOrekhov) +* feature #3588 Add NoAlternativeSyntaxFixer (eddmash, keradus) +* minor #3414 DescribeCommand: add fixer class when verbose (Slamdunk) +* minor #3432 ConfigurationDefinitionFixerInterface - fix deprecation notice (keradus) +* minor #3527 Deprecate last param of Tokens::findBlockEnd (ntzm, keradus) +* minor #3539 Update UnifiedDiffOutputBuilder from gecko-packages/gecko-diff-output-builder usage after it was incorporated into sebastian/diff (keradus) +* minor #3549 DescribeCommand - use our Differ wrapper class, not external one directly (keradus) +* minor #3592 Support PHPUnit 7 (keradus) +* minor #3619 Travis - extend additional files list (keradus) + +Changelog for v2.10.5 +--------------------- + +* bug #3344 Fix method chaining indentation in HTML (julienfalque) +* bug #3594 ElseifFixer - Bug with alternative syntax (kubawerlos) +* bug #3600 StrictParamFixer - Fix issue when functions are imported (ntzm, keradus) +* minor #3589 FixerFactoryTest - add missing test (SpacePossum, keradus) +* minor #3610 make phar extension optional (Tom Klingenberg, keradus) +* minor #3612 Travis - allow for hhvm failures (keradus) +* minor #3615 Detect fabbot.io (julienfalque, keradus) +* minor #3616 FixerFactoryTest - Don't rely on autovivification (keradus) +* minor #3621 FixerFactoryTest - apply CS (keradus) + +Changelog for v2.10.4 +--------------------- + +* bug #3446 Add PregWrapper (kubawerlos) +* bug #3464 IncludeFixer - fix incorrect order of fixing (kubawerlos, SpacePossum) +* bug #3496 Bug in Tokens::removeLeadingWhitespace (kubawerlos, SpacePossum, keradus) +* bug #3557 AbstractDoctrineAnnotationFixer: edge case bugfix (Slamdunk) +* bug #3574 GeneralPhpdocAnnotationRemoveFixer - remove PHPDoc if no content is left (SpacePossum) +* minor #3563 DX add missing covers annotations (keradus) +* minor #3564 Use ::class keyword when possible (keradus) +* minor #3565 Use EventDispatcherInterface instead of EventDispatcher when possible (keradus) +* minor #3566 Update PHPUnitGoodPractices\Traits (keradus) +* minor #3572 DX: allow for more phpunit-speedtrap versions to support more PHPUnit versions (keradus) +* minor #3576 Fix Doctrine Annotation test cases merging (julienfalque) +* minor #3577 DoctrineAnnotationArrayAssignmentFixer - Add test case (julienfalque) + +Changelog for v2.10.3 +--------------------- + +* bug #3504 NoBlankLinesAfterPhpdocFixer - allow blank line before declare statement (julienfalque) +* bug #3522 Remove LOCK_EX (SpacePossum) +* bug #3560 SelfAccessorFixer is risky (Slamdunk) +* minor #3435 Add tests for general_phpdoc_annotation_remove (BackEndTea) +* minor #3484 Create Tokens::findBlockStart (ntzm) +* minor #3512 Add missing array typehints (ntzm) +* minor #3513 Making AppVeyor happy (kubawerlos) +* minor #3516 Use null|type instead of ?type in PHPDocs (ntzm) +* minor #3518 FixerFactoryTest - Test each priority test file is listed as test (SpacePossum) +* minor #3519 Fix typo (SpacePossum) +* minor #3520 Fix typos: ran vs. run (SpacePossum) +* minor #3521 Use HTTPS (carusogabriel) +* minor #3526 Remove gecko dependency (SpacePossum, keradus, julienfalque) +* minor #3531 Backport PHPMD to LTS version to ease maintainability (keradus) +* minor #3532 Implement Tokens::findOppositeBlockEdge (ntzm) +* minor #3533 DX: SCA - drop src/Resources exclusion (keradus) +* minor #3538 Don't use third parameter of Tokens::findBlockStart (ntzm) +* minor #3542 Enhancement: Run composer-normalize on Travis CI (localheinz, keradus) +* minor #3550 AutoReview\FixerFactoryTest - fix missing priority test, mark not fully valid test as incomplete (keradus) +* minor #3555 DX: composer.json - drop branch-alias, branch is already following the version (keradus) +* minor #3556 DX: Add AutoReview/ComposerTest (keradus) +* minor #3559 Don't expose new files under Test namespace (keradus) +* minor #3561 PHPUnit5 - add in place missing compat layer for PHPUnit6 (keradus) + +Changelog for v2.10.2 +--------------------- + +* bug #3502 Fix missing file in export (keradus) + +Changelog for v2.10.1 +--------------------- + +* bug #3265 YodaFixer - fix problems of block statements followed by ternary statements (weareoutman, keradus, SpacePossum) +* bug #3367 NoUnusedImportsFixer - fix comment handling (SpacePossum, keradus) +* bug #3438 PhpUnitTestAnnotationFixer: Do not prepend with test if method is test() (localheinz, SpacePossum) +* bug #3455 NoEmptyCommentFixer - comment block detection for line ending different than LF (kubawerlos, SpacePossum) +* bug #3458 SilencedDeprecationErrorFixer - fix edge cases (kubawerlos) +* bug #3466 no_whitespace_in_blank_line and no_blank_lines_after_phpdoc fixers bug (kubawerlos, keradus) +* bug #3472 YodaStyleFixer - do not un-Yoda if right side is assignment (SpacePossum, keradus) +* bug #3492 PhpdocScalarFixer - Add callback pesudo-type to callable type (carusogabriel) +* minor #3354 Added missing types to the PhpdocTypesFixer (GrahamCampbell) +* minor #3406 Fix for escaping in README (kubawerlos) +* minor #3430 Fix integration test (SpacePossum) +* minor #3431 Add missing tests (SpacePossum) +* minor #3440 Add a handful of integration tests (BackEndTea) +* minor #3443 ConfigurableFixerInterface - not deprecated but TODO (SpacePossum) +* minor #3444 IntegrationTest - ensure tests in priority dir are priority tests indeed (keradus) +* minor #3494 Add missing PHPDoc param type (ntzm) +* minor #3495 Swap @var type and element (ntzm) +* minor #3498 NoUnusedImportsFixer - fix deprecation (keradus) + +Changelog for v2.10.0 +--------------------- + +* feature #3290 Add PhpdocOpeningClosingFixer (Slamdunk, keradus) +* feature #3327 Add MultilineWhitespaceBeforeSemicolonsFixer (egircys, keradus) +* feature #3351 PhuUnit: migrate getMock to createPartialMock when arguments count is 2 (Slamdunk) +* feature #3362 Add BacktickToShellExecFixer (Slamdunk) +* minor #3285 PHPUnit - use protective traits (keradus) +* minor #3329 ConfigurationResolver - detect deprecated fixers (keradus, SpacePossum) +* minor #3343 Tokens - improve block end lookup (keradus) +* minor #3360 Adjust Symfony ruleset (keradus) +* minor #3361 no_extra_consecutive_blank_lines - rename to no_extra_blank_lines (with BC layer) (keradus) +* minor #3363 progress-type - name main option value 'dots' (keradus) +* minor #3404 Deprecate "use_yoda_style" in IsNullFixer (kubawerlos, keradus) +* minor #3418 ConfigurableFixerInterface, ConfigurationDefinitionFixerInterface - update deprecations (keradus) +* minor #3419 Dont use deprecated fixer in itest (keradus) + +Changelog for v2.9.3 +-------------------- + +* bug #3502 Fix missing file in export (keradus) + +Changelog for v2.9.2 +-------------------- + +* bug #3265 YodaFixer - fix problems of block statements followed by ternary statements (weareoutman, keradus, SpacePossum) +* bug #3367 NoUnusedImportsFixer - fix comment handling (SpacePossum, keradus) +* bug #3438 PhpUnitTestAnnotationFixer: Do not prepend with test if method is test() (localheinz, SpacePossum) +* bug #3455 NoEmptyCommentFixer - comment block detection for line ending different than LF (kubawerlos, SpacePossum) +* bug #3458 SilencedDeprecationErrorFixer - fix edge cases (kubawerlos) +* bug #3466 no_whitespace_in_blank_line and no_blank_lines_after_phpdoc fixers bug (kubawerlos, keradus) +* bug #3472 YodaStyleFixer - do not un-Yoda if right side is assignment (SpacePossum, keradus) +* minor #3354 Added missing types to the PhpdocTypesFixer (GrahamCampbell) +* minor #3406 Fix for escaping in README (kubawerlos) +* minor #3430 Fix integration test (SpacePossum) +* minor #3431 Add missing tests (SpacePossum) +* minor #3440 Add a handful of integration tests (BackEndTea) +* minor #3444 IntegrationTest - ensure tests in priority dir are priority tests indeed (keradus) +* minor #3494 Add missing PHPDoc param type (ntzm) +* minor #3495 Swap @var type and element (ntzm) +* minor #3498 NoUnusedImportsFixer - fix deprecation (keradus) + +Changelog for v2.9.1 +-------------------- + +* bug #3298 DiffConsoleFormatter - fix output escaping. (SpacePossum) +* bug #3312 PhpUnitTestAnnotationFixer: Only remove prefix if it really is a prefix (localheinz) +* bug #3318 SingleLineCommentStyleFixer - fix closing tag inside comment causes an error (kubawerlos) +* bug #3334 ExplicitStringVariableFixer: handle parsed array and object (Slamdunk) +* bug #3337 BracesFixer: nowdoc bug on template files (Slamdunk) +* bug #3349 Fix stdin handling and add tests for it (keradus) +* bug #3350 PhpUnitNoExpectationAnnotationFixer - fix handling of multiline expectedExceptionMessage annotation (Slamdunk) +* bug #3352 FunctionToConstantFixer - bugfix for get_class with leading backslash (kubawerlos) +* bug #3359 BracesFixer - handle comment for content outside of given block (keradus) +* bug #3371 IsNullFixer must be run before YodaStyleFixer (kubawerlos) +* bug #3373 PhpdocAlignFixer - Fix removing of everything after @ when there is a space after the @ (ntzm) +* bug #3415 FileFilterIterator - input checks and utests (SpacePossum, keradus) +* bug #3420 SingleLineCommentStyleFixer - fix 'strpos() expects parameter 1 to be string, boolean given' (keradus, SpacePossum) +* bug #3428 Fix archive analysing (keradus) +* bug #3429 Fix archive analysing (keradus) +* minor #3137 PHPUnit - use common base class (keradus) +* minor #3311 FinalInternalClassFixer - fix typo (localheinz) +* minor #3328 Remove duplicated space in exceptions (keradus) +* minor #3342 PhpUnitDedicateAssertFixer - Remove unexistent method is_boolean (carusogabriel) +* minor #3345 StdinFileInfo - fix __toString (keradus) +* minor #3346 StdinFileInfo - drop getContents (keradus) +* minor #3347 DX: reapply newest CS (keradus) +* minor #3365 COOKBOOK-FIXERS.md - update to provide definition instead of description (keradus) +* minor #3370 AbstractFixer - FQCN in in exceptions (Slamdunk) +* minor #3372 ProjectCodeTest - fix comment (keradus) +* minor #3393 Method call typos (Slamdunk, keradus) +* minor #3402 Always provide delimiter to `preg_quote` calls (ntzm) +* minor #3403 Remove unused import (ntzm) +* minor #3405 Fix `fopen` mode (ntzm) +* minor #3407 CombineConsecutiveIssetsFixer - Improve description (kubawerlos) +* minor #3408 Improving fixers descriptions (kubawerlos) +* minor #3409 move itests from misc to priority (keradus) +* minor #3411 Better type hinting for AbstractFixerTestCase::$fixer (kubawerlos) +* minor #3412 Convert `strtolower` inside `strpos` to just `stripos` (ntzm) +* minor #3421 DX: Use ::class (keradus) +* minor #3424 AbstractFixerTest: fix expectException arguments (Slamdunk, keradus) +* minor #3425 FixerFactoryTest - test that priority pair fixers have itest (keradus, SpacePossum) +* minor #3427 ConfigurationResolver: fix @return annotation (Slamdunk) + +Changelog for v2.9.0 +-------------------- + +* feature #3063 Method chaining indentation fixer (boliev, julienfalque) +* feature #3076 Add ExplicitStringVariableFixer (Slamdunk, keradus) +* feature #3098 MethodSeparationFixer - add class elements separation options (SpacePossum, keradus) +* feature #3155 Add EscapeImplicitBackslashesFixer (Slamdunk) +* feature #3164 Add ExplicitIndirectVariableFixer (Slamdunk, keradus) +* feature #3183 FinalInternalClassFixer introduction (keradus, SpacePossum) +* feature #3187 StaticLambdaFixer - introduction (SpacePossum, keradus) +* feature #3209 PhpdocAlignFixer - Make @method alignable (ntzm) +* feature #3275 Add PhpUnitTestAnnotationFixer (BackEndTea, keradus) + +Changelog for v2.8.4 +-------------------- + +* bug #3281 SelfAccessorFixer - stop modifying traits (kubawerlos) +* minor #3195 Add self-update command test (julienfalque) +* minor #3287 FileCacheManagerTest - drop duplicated line (keradus) +* minor #3292 PHPUnit - set memory limit (veewee) +* minor #3306 Token - better input validation (keradus) +* minor #3310 Upgrade PHP Coveralls (keradus) + +Changelog for v2.8.3 +-------------------- + +* bug #3173 SimplifiedNullReturnFixer - handle nullable return types (Slamdunk) +* bug #3268 PhpUnitNoExpectationAnnotationFixer - add case with backslashes (keradus, Slamdunk) +* bug #3272 PhpdocTrimFixer - unicode support (SpacePossum) + +Changelog for v2.8.2 +-------------------- + +* bug #3225 PhpdocTrimFixer - Fix handling of lines without leading asterisk (julienfalque) +* bug #3241 NoExtraConsecutiveBlankLinesFixer - do not crash on ^M LF only (SpacePossum) +* bug #3242 PhpUnitNoExpectationAnnotationFixer - fix ' handling (keradus) +* bug #3243 PhpUnitExpectationFixer - don't create ->expectExceptionMessage(null) (keradus) +* bug #3244 PhpUnitNoExpectationAnnotationFixer - expectation extracted from annotation shall be separated from rest of code with one blank line (keradus) +* bug #3259 PhpUnitNamespacedFixer - fix isCandidate to not rely on class declaration (keradus) +* bug #3261 PhpUnitNamespacedFixer - properly fix next usage of already fixed class (keradus) +* bug #3262 ToolInfo - support installation by branch as well (keradus) +* bug #3263 NoBreakCommentFixer - Fix handling comment text with PCRE characters (julienfalque) +* bug #3266 PhpUnitConstructFixer - multiple asserts bug (kubawerlos) +* minor #3239 Improve contributing guide and issue template (julienfalque) +* minor #3246 Make ToolInfo methods non-static (julienfalque) +* minor #3249 PhpUnitNoExpectationAnnotationFixerTest - fix hidden conflict (keradus) +* minor #3250 Travis: fail early, spare resources, save the Earth (Slamdunk, keradus) +* minor #3251 Create Title for config file docs section (IanEdington) +* minor #3254 AutoReview/FixerFactoryTest::testFixersPriority: verbose assertion message (Slamdunk) +* minor #3255 IntegrationTest: output exception stack trace (Slamdunk) +* minor #3257 README.rst - Fixed bullet list formatting (moebrowne) + +Changelog for v2.8.1 +-------------------- + +* bug #3199 TokensAnalyzer - getClassyElements (SpacePossum) +* bug #3208 BracesFixer - Fix for instantiation in control structures (julienfalque, SpacePossum) +* bug #3215 BinaryOperatorSpacesFixer - Fix spaces around multiple exception catching (|) (ntzm) +* bug #3216 AbstractLinesBeforeNamespaceFixer - add min. and max. option, not only single target count (SpacePossum) +* bug #3217 TokenizerLinter - fix lack of linting when code is cached (SpacePossum, keradus) +* minor #3200 Skip slow test when Xdebug is loaded (julienfalque) +* minor #3211 Use udiff format in CI (julienfalque) +* minor #3212 Handle rulesets unknown to fabbot.io (julienfalque) +* minor #3219 Normalise references to GitHub in docs (ntzm) +* minor #3226 Remove unused imports (ntzm) +* minor #3231 Fix typos (ntzm) +* minor #3234 Simplify Cache\Signature::equals (ntzm) +* minor #3237 UnconfigurableFixer - use only LF (keradus) +* minor #3238 AbstractFixerTest - fix @cover annotation (keradus) + +Changelog for v2.8.0 +-------------------- + +* feature #3065 Add IncrementStyleFixer (kubawerlos) +* feature #3119 Feature checkstyle reporter (K-Phoen) +* feature #3162 Add udiff as diff format (SpacePossum, keradus) +* feature #3170 Add CompactNullableTypehintFixer (jfcherng) +* feature #3189 Add PHP_CS_FIXER_FUTURE_MODE env (keradus) +* feature #3201 Add PHPUnit Migration rulesets and fixers (keradus) +* minor #3149 AbstractProxyFixer - Support multiple proxied fixers (julienfalque) +* minor #3160 Add DeprecatedFixerInterface (kubawerlos) +* minor #3185 IndentationTypeFixerTest - clean up (SpacePossum, keradus) +* minor #3198 Cleanup: add test that there is no deprecated fixer in rule set (kubawerlos) + +Changelog for v2.7.5 +-------------------- + +* bug #3225 PhpdocTrimFixer - Fix handling of lines without leading asterisk (julienfalque) +* bug #3241 NoExtraConsecutiveBlankLinesFixer - do not crash on ^M LF only (SpacePossum) +* bug #3262 ToolInfo - support installation by branch as well (keradus) +* bug #3263 NoBreakCommentFixer - Fix handling comment text with PCRE characters (julienfalque) +* bug #3266 PhpUnitConstructFixer - multiple asserts bug (kubawerlos) +* minor #3239 Improve contributing guide and issue template (julienfalque) +* minor #3246 Make ToolInfo methods non-static (julienfalque) +* minor #3250 Travis: fail early, spare resources, save the Earth (Slamdunk, keradus) +* minor #3251 Create Title for config file docs section (IanEdington) +* minor #3254 AutoReview/FixerFactoryTest::testFixersPriority: verbose assertion message (Slamdunk) +* minor #3255 IntegrationTest: output exception stack trace (Slamdunk) + +Changelog for v2.7.4 +-------------------- + +* bug #3199 TokensAnalyzer - getClassyElements (SpacePossum) +* bug #3208 BracesFixer - Fix for instantiation in control structures (julienfalque, SpacePossum) +* bug #3215 BinaryOperatorSpacesFixer - Fix spaces around multiple exception catching (|) (ntzm) +* bug #3216 AbstractLinesBeforeNamespaceFixer - add min. and max. option, not only single target count (SpacePossum) +* bug #3217 TokenizerLinter - fix lack of linting when code is cached (SpacePossum, keradus) +* minor #3200 Skip slow test when Xdebug is loaded (julienfalque) +* minor #3219 Normalise references to GitHub in docs (ntzm) +* minor #3226 Remove unused imports (ntzm) +* minor #3231 Fix typos (ntzm) +* minor #3234 Simplify Cache\Signature::equals (ntzm) +* minor #3237 UnconfigurableFixer - use only LF (keradus) +* minor #3238 AbstractFixerTest - fix @cover annotation (keradus) + +Changelog for v2.7.3 +-------------------- + +* bug #3114 SelfAccessorFixer - Fix type declarations replacement (julienfalque) + +Changelog for v2.7.2 +-------------------- + +* bug #3062 BraceClassInstantiationTransformer - Fix instantiation inside method call braces case (julienfalque, keradus) +* bug #3083 SingleBlankLineBeforeNamespaceFixer - Fix handling namespace right after opening tag (mlocati) +* bug #3109 SwitchCaseSemicolonToColonFixer - Fix bug with nested constructs (SpacePossum) +* bug #3117 Multibyte character in array key makes alignment incorect (kubawerlos) +* bug #3123 Cache - File permissions (SpacePossum) +* bug #3138 NoHomoglyphNamesFixer - fix crash on non-ascii but not mapped either (SpacePossum) +* bug #3172 IndentationTypeFixer - do not touch whitespace that is not indentation (SpacePossum) +* bug #3176 NoMultilineWhitespaceBeforeSemicolonsFixer - SpaceAfterSemicolonFixer - priority fix (SpacePossum) +* bug #3193 TokensAnalyzer::getClassyElements - sort result before returning (SpacePossum) +* bug #3196 SelfUpdateCommand - fix exit status when can't determine newest version (julienfalque) +* minor #3107 ConfigurationResolver - improve error message when rule is not found (SpacePossum) +* minor #3113 Add WordMatcher (keradus) +* minor #3128 README: remove deprecated rule from CLI examples (chteuchteu) +* minor #3133 Unify Reporter tests (keradus) +* minor #3134 Allow Symfony 4 (keradus, garak) +* minor #3136 PHPUnit - call hooks from parent class as well (keradus) +* minor #3141 Unify description of deprecated fixer (kubawerlos) +* minor #3144 PhpUnitDedicateAssertFixer - Sort map and array by function name (localheinz) +* minor #3145 misc - Typo (localheinz) +* minor #3150 Fix CircleCI (julienfalque) +* minor #3151 Update gitattributes to ignore next file (keradus) +* minor #3156 Update php-coveralls (keradus) +* minor #3166 README - add link to new gitter channel. (SpacePossum) +* minor #3174 Update UPGRADE.md (vitek-rostislav) +* minor #3180 Fix usage of static variables (kubawerlos) +* minor #3182 Add support for PHPUnit 6, drop PHPUnit 4 (keradus) +* minor #3184 Code grooming - sort content of arrays (keradus) +* minor #3191 Travis - add nightly build to allow_failures due to Travis issues (keradus) +* minor #3197 DX groom CS (keradus) + +Changelog for v2.7.1 +-------------------- + +* bug #3115 NoUnneededFinalMethodFixer - fix edge case (Slamdunk) + +Changelog for v2.7.0 +-------------------- + +* feature #2573 BinaryOperatorSpaces reworked (SpacePossum, keradus) +* feature #3073 SpaceAfterSemicolonFixer - Add option to remove space in empty for expressions (julienfalque) +* feature #3089 NoAliasFunctionsFixer - add imap aliases (Slamdunk) +* feature #3093 NoUnneededFinalMethodFixer - Remove final keyword from private methods (localheinz, keradus) +* minor #3068 Symfony:risky ruleset - add no_homoglyph_names (keradus) +* minor #3074 [IO] Replace Diff with fork version (SpacePossum) + +Changelog for v2.6.1 +-------------------- + +* bug #3052 Fix false positive warning about paths overridden by provided as command arguments (kubawerlos) +* bug #3053 CombineConsecutiveIssetsFixer - fix priority (SpacePossum) +* bug #3058 IsNullFixer - fix whitespace handling (roukmoute) +* bug #3069 MethodArgumentSpaceFixer - new test case (keradus) +* bug #3072 IsNullFixer - fix non_yoda_style edge case (keradus) +* bug #3088 Drop dedicated Phar stub (keradus) +* bug #3100 NativeFunctionInvocationFixer - Fix test if previous token is already namespace separator (SpacePossum) +* bug #3104 DoctrineAnnotationIndentationFixer - Fix str_repeat() error (julienfalque) +* minor #3038 Support PHP 7.2 (SpacePossum, keradus) +* minor #3064 Fix couple of typos (KKSzymanowski) +* minor #3070 YodaStyleFixer - Clarify configuration parameters (SteveJobzniak) +* minor #3078 ConfigurationResolver - hide context while including config file (keradus) +* minor #3080 Direct function call instead of by string (kubawerlos) +* minor #3085 CiIntegrationTest - skip when no git is available (keradus) +* minor #3087 phar-stub.php - allow PHP 7.2 (keradus) +* minor #3092 .travis.yml - fix matrix for PHP 7.1 (keradus) +* minor #3094 NoUnneededFinalMethodFixer - Add test cases (julienfalque) +* minor #3111 DoctrineAnnotationIndentationFixer - Restore test case (julienfalque) + +Changelog for v2.6.0 +-------------------- + +* bug #3039 YodaStyleFixer - Fix echo case (SpacePossum, keradus) +* feature #2446 Add YodaStyleFixer (SpacePossum) +* feature #2940 Add NoHomoglyphNamesFixer (mcfedr, keradus) +* feature #3012 Add CombineConsecutiveIssetsFixer (SpacePossum) +* minor #3037 Update SF rule set (SpacePossum) + +Changelog for v2.5.1 +-------------------- + +* bug #3002 Bugfix braces (mnabialek) +* bug #3010 Fix handling of Github releases (julienfalque, keradus) +* bug #3015 Fix exception arguments (julienfalque) +* bug #3016 Verify phar file (keradus) +* bug #3021 Risky rules cleanup (kubawerlos) +* bug #3023 RandomApiMigrationFixer - "rand();" to "random_int(0, getrandmax());" fixing (SpacePossum) +* bug #3024 ConfigurationResolver - Handle empty "rules" value (SpacePossum, keradus) +* bug #3031 IndentationTypeFixer - fix handling tabs in indented comments (keradus) +* minor #2999 Notice when paths from config file are overridden by command arguments (julienfalque, keradus) +* minor #3007 Add PHP 7.2 to Travis build matrix (Jean85) +* minor #3009 CiIntegrationTest - run local (SpacePossum) +* minor #3013 Adjust phpunit configuration (localheinz) +* minor #3017 Fix: Risky tests (localheinz) +* minor #3018 Fix: Make sure that data providers are named correctly (localheinz, keradus) +* minor #3032 .php_cs.dist - handling UnexpectedValueException (keradus) +* minor #3033 Use ::class (keradus) +* minor #3034 Follow newest CS (keradus) +* minor #3036 Drop not existing Standalone group from PHPUnit configuration and duplicated internal tags (keradus) +* minor #3042 Update gitter address (keradus) + +Changelog for v2.5.0 +-------------------- + +* feature #2770 DoctrineAnnotationSpaces - split assignments options (julienfalque) +* feature #2843 Add estimating-max progress output type (julienfalque) +* feature #2885 Add NoSuperfluousElseifFixer (julienfalque) +* feature #2929 Add NoUnneededCurlyBracesFixer (SpacePossum) +* feature #2944 FunctionToConstantFixer - handle get_class() -> __CLASS__ as well (SpacePossum) +* feature #2953 BlankLineBeforeStatementFixer - Add more statements (localheinz, keradus) +* feature #2972 Add NoUnneededFinalMethodFixer (Slamdunk, keradus) +* feature #2992 Add Doctrine Annotation ruleset (julienfalque) +* minor #2926 Token::getNameForId (SpacePossum) + +Changelog for v2.4.2 +-------------------- + +* bug #3002 Bugfix braces (mnabialek) +* bug #3010 Fix handling of Github releases (julienfalque, keradus) +* bug #3015 Fix exception arguments (julienfalque) +* bug #3016 Verify phar file (keradus) +* bug #3021 Risky rules cleanup (kubawerlos) +* bug #3023 RandomApiMigrationFixer - "rand();" to "random_int(0, getrandmax());" fixing (SpacePossum) +* bug #3024 ConfigurationResolver - Handle empty "rules" value (SpacePossum, keradus) +* bug #3031 IndentationTypeFixer - fix handling tabs in indented comments (keradus) +* minor #2999 Notice when paths from config file are overridden by command arguments (julienfalque, keradus) +* minor #3007 Add PHP 7.2 to Travis build matrix (Jean85) +* minor #3009 CiIntegrationTest - run local (SpacePossum) +* minor #3013 Adjust phpunit configuration (localheinz) +* minor #3017 Fix: Risky tests (localheinz) +* minor #3018 Fix: Make sure that data providers are named correctly (localheinz, keradus) +* minor #3032 .php_cs.dist - handling UnexpectedValueException (keradus) +* minor #3033 Use ::class (keradus) +* minor #3034 Follow newest CS (keradus) +* minor #3036 Drop not existing Standalone group from PHPUnit configuration and duplicated internal tags (keradus) +* minor #3042 Update gitter address (keradus) + +Changelog for v2.4.1 +-------------------- + +* bug #2925 Improve CI integration suggestion (julienfalque) +* bug #2928 TokensAnalyzer::getClassyElements - Anonymous class support (SpacePossum) +* bug #2931 Psr0Fixer, Psr4Fixer - ignore "new class" syntax (dg, keradus) +* bug #2934 Config - fix handling rule without value (keradus, SpacePossum) +* bug #2939 NoUnusedImportsFixer - Fix extra blank line (julienfalque) +* bug #2941 PHP 7.2 - Group imports with trailing comma support (SpacePossum, julienfalque) +* bug #2954 NoBreakCommentFixer - Disable case sensitivity (julienfalque) +* bug #2959 MethodArgumentSpaceFixer - Skip body of fixed function (greg0ire) +* bug #2984 AlignMultilineCommentFixer - handle uni code (SpacePossum) +* bug #2987 Fix incorrect indentation of comments in `braces` fixer (rob006) +* minor #2924 Add missing Token deprecations (julienfalque) +* minor #2927 WhiteSpaceConfig - update message copy and more strict tests (SpacePossum, keradus) +* minor #2930 Trigger website build (keradus) +* minor #2932 Integrate CircleCI (keradus, aidantwoods) +* minor #2933 ProcessLinterTest - Ensure Windows test only runs on Windows, add a Mac test execution (aidantwoods) +* minor #2935 special handling of fabbot.io service if it's using too old PHP CS Fixer version (keradus) +* minor #2937 Travis: execute 5.3 job on precise (keradus) +* minor #2938 Tests fix configuration of project (SpacePossum, keradus) +* minor #2943 FunctionToConstantFixer - test with diff. arguments than fixable (SpacePossum) +* minor #2945 BlankLineBeforeStatementFixerTest - Fix covered class (julienfalque) +* minor #2946 Detect extra old installations (keradus) +* minor #2947 Test suggested CI integration (keradus) +* minor #2951 AccessibleObject - remove most of usage (keradus) +* minor #2952 BlankLineBeforeStatementFixer - Reference fixer instead of test class (localheinz) +* minor #2955 Travis - stop using old TASK_SCA residue (keradus) +* minor #2968 AssertTokensTrait - don't use AccessibleObject (keradus) +* minor #2969 Shrink down AccessibleObject usage (keradus) +* minor #2982 TrailingCommaInMultilineArrayFixer - simplify isMultilineArray condition (TomasVotruba) +* minor #2989 CiIntegrationTest - fix min supported PHP versions (keradus) + +Changelog for v2.4.0 +-------------------- + +* bug #2880 NoBreakCommentFixer - fix edge case (julienfalque) +* bug #2900 VoidReturnFixer - handle functions containing anonymous functions/classes (bendavies, keradus) +* bug #2902 Fix test classes constructor (julienfalque) +* feature #2384 Add BlankLineBeforeStatementFixer (localheinz, keradus, SpacePossum) +* feature #2440 MethodArgumentSpaceFixer - add ensure_fully_multiline option (greg0ire) +* feature #2649 PhpdocAlignFixer - make fixer configurable (ntzm) +* feature #2664 Add DoctrineAnnotationArrayAssignmentFixer (julienfalque) +* feature #2667 Add NoBreakCommentFixer (julienfalque) +* feature #2684 BracesFixer - new options for braces position after control structures and anonymous constructs (aidantwoods, keradus) +* feature #2701 NoExtraConsecutiveBlankLinesFixer - Add more configuration options related to switch statements (SpacePossum) +* feature #2740 Add VoidReturnFixer (mrmark) +* feature #2765 DoctrineAnnotationIndentationFixer - add option to indent mixed lines (julienfalque) +* feature #2815 NonPrintableCharacterFixer - Add option to replace with escape sequences (julienfalque, keradus) +* feature #2822 Add NoNullPropertyInitializationFixer (ntzm, julienfalque, SpacePossum) +* feature #2825 Add PhpdocTypesOrderFixer (julienfalque, keradus) +* feature #2856 CastSpacesFixer - add space option (kubawerlos, keradus) +* feature #2857 Add AlignMultilineCommentFixer (Slamdunk, keradus) +* feature #2866 Add SingleLineCommentStyleFixer, deprecate HashToSlashCommentFixer (Slamdunk, keradus) +* minor #2773 Travis - use stages (keradus) +* minor #2794 Drop HHVM support (keradus, julienfalque) +* minor #2801 ProjectCodeTest - Fix typo in deprecation message (SpacePossum) +* minor #2818 Token become immutable, performance optimizations (keradus) +* minor #2877 Fix PHPMD report (julienfalque) +* minor #2894 NonPrintableCharacterFixer - fix handling required PHP version on PHPUnit 4.x (keradus) +* minor #2921 InvalidForEnvFixerConfigurationException - fix handling in tests on 2.4 line (keradus) + +Changelog for v2.3.3 +-------------------- + +* bug #2807 NoUselessElseFixer - Fix detection of conditional block (SpacePossum) +* bug #2809 Phar release - fix readme generation (SpacePossum, keradus) +* bug #2827 MethodArgumentSpaceFixer - Always remove trailing spaces (julienfalque) +* bug #2835 SelfAcessorFixer - class property fix (mnabialek) +* bug #2848 PhpdocIndentFixer - fix edge case with inline phpdoc (keradus) +* bug #2849 BracesFixer - Fix indentation issues with comments (julienfalque) +* bug #2851 Tokens - ensureWhitespaceAtIndex (GrahamCampbell, SpacePossum) +* bug #2854 NoLeadingImportSlashFixer - Removing leading slash from import even when in global space (kubawerlos) +* bug #2858 Support generic types (keradus) +* bug #2869 Fix handling required configuration (keradus) +* bug #2881 NoUnusedImportsFixer - Bug when trying to insert empty token (GrahamCampbell, keradus) +* bug #2882 DocBlock\Annotation - Fix parsing of collections with multiple key types (julienfalque) +* bug #2886 NoSpacesInsideParenthesisFixer - Do not remove whitespace if next token is comment (SpacePossum) +* bug #2888 SingleImportPerStatementFixer - Add support for function and const (SpacePossum) +* bug #2901 Add missing files to archive files (keradus) +* bug #2914 HeredocToNowdocFixer - works with CRLF line ending (dg) +* bug #2920 RuleSet - Update deprecated configuration of fixers (SpacePossum, keradus) +* minor #1531 Update docs for few generic types (keradus) +* minor #2793 COOKBOOK-FIXERS.md - update to current version, fix links (keradus) +* minor #2812 ProcessLinter - compatibility with Symfony 3.3 (keradus) +* minor #2816 Tokenizer - better docs and validation (keradus) +* minor #2817 Tokenizer - use future-compatible interface (keradus) +* minor #2819 Fix benchmark (keradus) +* minor #2820 MagicConstantCasingFixer - Remove defined check (SpacePossum) +* minor #2823 Tokenizer - use future-compatible interface (keradus) +* minor #2824 code grooming (keradus) +* minor #2826 Exceptions - provide utests (localheinz) +* minor #2828 Enhancement: Reference phpunit.xsd from phpunit.xml.dist (localheinz) +* minor #2830 Differs - add tests (localheinz) +* minor #2832 Fix: Use all the columns (localheinz) +* minor #2833 Doctrine\Annotation\Token - provide utests (localheinz) +* minor #2839 Use PHP 7.2 polyfill instead of xml one (keradus) +* minor #2842 Move null to first position in PHPDoc types (julienfalque) +* minor #2850 ReadmeCommandTest - Prevent diff output (julienfalque) +* minor #2859 Fixed typo and dead code removal (GrahamCampbell) +* minor #2863 FileSpecificCodeSample - add tests (localheinz) +* minor #2864 WhitespacesAwareFixerInterface clean up (Slamdunk) +* minor #2865 AutoReview\FixerTest - test configuration samples (SpacePossum, keradus) +* minor #2867 VersionSpecification - Fix copy-paste typo (SpacePossum) +* minor #2870 Tokens - ensureWhitespaceAtIndex - Clear tokens before compare. (SpacePossum) +* minor #2874 LineTest - fix typo (keradus) +* minor #2875 HelpCommand - recursive layout fix (SpacePossum) +* minor #2883 DescribeCommand - Show which sample uses the default configuration (SpacePossum) +* minor #2887 Housekeeping - Strict whitespace checks (SpacePossum) +* minor #2895 ProjectCodeTest - check that classes in no-tests exception exist (keradus) +* minor #2896 Move testing related classes from src to tests (keradus) +* minor #2904 Reapply CS (keradus) +* minor #2910 PhpdocAnnotationWithoutDotFixer - Restrict lowercasing (oschwald) +* minor #2913 Tests - tweaks (SpacePossum, keradus) +* minor #2916 FixerFactory - drop return in sortFixers(), never used (TomasVotruba) + +Changelog for v2.3.2 +-------------------- + +* bug #2682 DoctrineAnnotationIndentationFixer - fix handling nested annotations (edhgoose, julienfalque) +* bug #2700 Fix Doctrine Annotation end detection (julienfalque) +* bug #2715 OrderedImportsFixer - handle indented groups (pilgerone) +* bug #2732 HeaderCommentFixer - fix handling blank lines (s7b4) +* bug #2745 Fix Doctrine Annotation newlines (julienfalque) +* bug #2752 FixCommand - fix typo in warning message (mnapoli) +* bug #2757 GeckoPHPUnit is not dev dependency (keradus) +* bug #2759 Update gitattributes (SpacePossum) +* bug #2763 Fix describe command with PSR-0 fixer (julienfalque) +* bug #2768 Tokens::ensureWhitespaceAtIndex - clean up comment check, add check for T_OPEN (SpacePossum) +* bug #2783 Tokens::ensureWhitespaceAtIndex - Fix handling line endings (SpacePossum) +* minor #2304 DX: use PHPMD (keradus) +* minor #2663 Use colors for keywords in commands output (julienfalque, keradus) +* minor #2706 Update README (SpacePossum) +* minor #2714 README.rst - fix wrong value in example (mleko) +* minor #2718 Remove old Symfony exception message expectation (julienfalque) +* minor #2721 Update phpstorm article link to a fresh blog post (valeryan) +* minor #2725 Use method chaining for configuration definitions (julienfalque) +* minor #2727 PHPUnit - use speedtrap (keradus) +* minor #2728 SelfUpdateCommand - verify that it's possible to replace current file (keradus) +* minor #2729 DescribeCommand - add decorated output test (julienfalque) +* minor #2731 BracesFixer - properly pass config in utest dataProvider (keradus) +* minor #2738 Upgrade tests to use new, namespaced PHPUnit TestCase class (keradus) +* minor #2742 Code cleanup (GrahamCampbell, keradus) +* minor #2743 Fixing example and description for GeneralPhpdocAnnotationRemoveFixer (kubawerlos) +* minor #2744 AbstractDoctrineAnnotationFixerTestCase - split fixers test cases (julienfalque) +* minor #2755 Fix compatibility with PHPUnit 5.4.x (keradus) +* minor #2758 Readme - improve CI integration guidelines (keradus) +* minor #2769 Psr0Fixer - remove duplicated example (julienfalque) +* minor #2774 AssertTokens Trait (keradus) +* minor #2775 NoExtraConsecutiveBlankLinesFixer - remove duplicate code sample. (SpacePossum) +* minor #2778 AutoReview - watch that code samples are unique (keradus) +* minor #2787 Add warnings about missing dom ext and require json ext (keradus) +* minor #2792 Use composer-require-checker (keradus) +* minor #2796 Update .gitattributes (SpacePossum) +* minor #2797 Update .gitattributes (SpacePossum) +* minor #2800 PhpdocTypesFixerTest - Fix typo in covers annotation (SpacePossum) + +Changelog for v2.3.1 +-------------------- + +Port of v2.2.3. + +* bug #2724 Revert #2554 Add short diff. output format (keradus) + +Changelog for v2.3.0 +-------------------- + +* feature #2450 Add ListSyntaxFixer (SpacePossum) +* feature #2708 Add PhpUnitTestClassRequiresCoversFixer (keradus) +* minor #2568 Require PHP 5.6+ (keradus) +* minor #2672 Bump symfony/* deps (keradus) + +Changelog for v2.2.20 +--------------------- + +* bug #3233 PhpdocAlignFixer - Fix linebreak inconsistency (SpacePossum, keradus) +* bug #3445 Rewrite NoUnusedImportsFixer (kubawerlos, julienfalque) +* bug #3597 DeclareStrictTypesFixer - fix bug of removing line (kubawerlos, keradus) +* bug #3605 DoctrineAnnotationIndentationFixer - Fix indentation with mixed lines (julienfalque) +* bug #3606 PhpdocToCommentFixer - allow multiple ( (SpacePossum) +* bug #3684 PhpUnitStrictFixer - Do not fix if not correct # of arguments are used (SpacePossum) +* bug #3715 SingleImportPerStatementFixer - Fix handling whitespace before opening brace (julienfalque) +* bug #3731 PhpdocIndentFixer - crash fix (SpacePossum) +* bug #3765 Fix binary-prefixed double-quoted strings to single quotes (ntzm) +* bug #3770 Handle binary flags in heredoc_to_nowdoc (ntzm) +* bug #3790 ProcessLinter - don't execute external process without timeout! It can freeze! (keradus) +* minor #3548 Make shell scripts POSIX-compatible (EvgenyOrekhov, keradus) +* minor #3568 New Autoreview: Correct option casing (ntzm) +* minor #3590 Use XdebugHandler to avoid performance penalty (AJenbo, keradus) +* minor #3607 PhpdocVarWithoutNameFixer - update sample with @ type (SpacePossum) +* minor #3617 Tests stability patches (Tom Klingenberg, keradus) +* minor #3627 Fix tests execution under phpdbg (keradus) +* minor #3629 ProjectFixerConfigurationTest - test rules are sorted (SpacePossum) +* minor #3639 DX: use benefits of symfony/force-lowest (keradus) +* minor #3641 Update check_trailing_spaces script with upstream (keradus) +* minor #3646 Extract SameStringsConstraint and XmlMatchesXsdConstraint (keradus) +* minor #3647 DX: Add CachingLinter for tests (keradus) +* minor #3649 Update check_trailing_spaces script with upstream (keradus) +* minor #3652 CiIntegrationTest - run tests with POSIX sh, not Bash (keradus) +* minor #3656 DX: Clean ups (SpacePossum) +* minor #3660 Fix do not rely on order of fixing in CiIntegrationTest (kubawerlos) +* minor #3662 DX: Add Smoke/InstallViaComposerTest (keradus) +* minor #3663 DX: During deployment, run all smoke tests and don't allow to skip phar-related ones (keradus) +* minor #3665 CircleCI fix (kubawerlos) +* minor #3666 Use "set -eu" in shell scripts (EvgenyOrekhov) +* minor #3669 Document possible values for subset options (julienfalque, keradus) +* minor #3676 RunnerTest - workaround for failing Symfony v2.8.37 (kubawerlos) +* minor #3680 DX: Tokens - removeLeadingWhitespace and removeTrailingWhitespace must act in same way (SpacePossum) +* minor #3686 README.rst - Format all code-like strings in fixer descriptions (ntzm, keradus) +* minor #3692 DX: Optimize tests (julienfalque) +* minor #3701 Use correct casing for "PHPDoc" (ntzm) +* minor #3703 DX: InstallViaComposerTets - groom naming (keradus) +* minor #3704 DX: Tokens - fix naming (keradus) +* minor #3706 Update homebrew installation instructions (ntzm) +* minor #3713 Use HTTPS whenever possible (fabpot) +* minor #3723 Extend tests coverage (ntzm) +* minor #3733 Disable Composer optimized autoloader by default (julienfalque) +* minor #3748 PhpUnitStrictFixer - extend risky note (jnvsor) +* minor #3749 Make sure PHPUnit is cased correctly in fixers descriptions (kubawerlos) +* minor #3773 AbstractFixerWithAliasedOptionsTestCase - don't export (keradus) +* minor #3796 DX: StdinTest - do not assume name of folder, into which project was cloned (keradus) +* minor #3803 NoEmptyPhpdocFixer/PhpdocAddMissingParamAnnotationFixer - missing priority test (SpacePossum, keradus) +* minor #3804 Cleanup: remove useless constructor comment (kubawerlos) + +Changelog for v2.2.19 +--------------------- + +* bug #3594 ElseifFixer - Bug with alternative syntax (kubawerlos) +* bug #3600 StrictParamFixer - Fix issue when functions are imported (ntzm, keradus) +* minor #3589 FixerFactoryTest - add missing test (SpacePossum, keradus) +* minor #3610 make phar extension optional (Tom Klingenberg, keradus) +* minor #3612 Travis - allow for hhvm failures (keradus) +* minor #3615 Detect fabbot.io (julienfalque, keradus) +* minor #3616 FixerFactoryTest - Don't rely on autovivification (keradus) + +Changelog for v2.2.18 +--------------------- + +* bug #3446 Add PregWrapper (kubawerlos) +* bug #3464 IncludeFixer - fix incorrect order of fixing (kubawerlos, SpacePossum) +* bug #3496 Bug in Tokens::removeLeadingWhitespace (kubawerlos, SpacePossum, keradus) +* bug #3557 AbstractDoctrineAnnotationFixer: edge case bugfix (Slamdunk) +* bug #3574 GeneralPhpdocAnnotationRemoveFixer - remove PHPDoc if no content is left (SpacePossum) +* minor #3563 DX add missing covers annotations (keradus) +* minor #3565 Use EventDispatcherInterface instead of EventDispatcher when possible (keradus) +* minor #3572 DX: allow for more phpunit-speedtrap versions to support more PHPUnit versions (keradus) +* minor #3576 Fix Doctrine Annotation test cases merging (julienfalque) + +Changelog for v2.2.17 +--------------------- + +* bug #3504 NoBlankLinesAfterPhpdocFixer - allow blank line before declare statement (julienfalque) +* bug #3522 Remove LOCK_EX (SpacePossum) +* bug #3560 SelfAccessorFixer is risky (Slamdunk) +* minor #3435 Add tests for general_phpdoc_annotation_remove (BackEndTea) +* minor #3484 Create Tokens::findBlockStart (ntzm) +* minor #3512 Add missing array typehints (ntzm) +* minor #3516 Use null|type instead of ?type in PHPDocs (ntzm) +* minor #3518 FixerFactoryTest - Test each priority test file is listed as test (SpacePossum) +* minor #3520 Fix typos: ran vs. run (SpacePossum) +* minor #3521 Use HTTPS (carusogabriel) +* minor #3526 Remove gecko dependency (SpacePossum, keradus, julienfalque) +* minor #3531 Backport PHPMD to LTS version to ease maintainability (keradus) +* minor #3532 Implement Tokens::findOppositeBlockEdge (ntzm) +* minor #3533 DX: SCA - drop src/Resources exclusion (keradus) +* minor #3538 Don't use third parameter of Tokens::findBlockStart (ntzm) +* minor #3542 Enhancement: Run composer-normalize on Travis CI (localheinz, keradus) +* minor #3555 DX: composer.json - drop branch-alias, branch is already following the version (keradus) +* minor #3556 DX: Add AutoReview/ComposerTest (keradus) +* minor #3559 Don't expose new files under Test namespace (keradus) + +Changelog for v2.2.16 +--------------------- + +* bug #3502 Fix missing file in export (keradus) + +Changelog for v2.2.15 +--------------------- + +* bug #3367 NoUnusedImportsFixer - fix comment handling (SpacePossum, keradus) +* bug #3455 NoEmptyCommentFixer - comment block detection for line ending different than LF (kubawerlos, SpacePossum) +* bug #3458 SilencedDeprecationErrorFixer - fix edge cases (kubawerlos) +* bug #3466 no_whitespace_in_blank_line and no_blank_lines_after_phpdoc fixers bug (kubawerlos, keradus) +* minor #3354 Added missing types to the PhpdocTypesFixer (GrahamCampbell) +* minor #3406 Fix for escaping in README (kubawerlos) +* minor #3431 Add missing tests (SpacePossum) +* minor #3440 Add a handful of integration tests (BackEndTea) +* minor #3444 IntegrationTest - ensure tests in priority dir are priority tests indeed (keradus) +* minor #3494 Add missing PHPDoc param type (ntzm) +* minor #3495 Swap @var type and element (ntzm) +* minor #3498 NoUnusedImportsFixer - fix deprecation (keradus) + +Changelog for v2.2.14 +--------------------- + +* bug #3298 DiffConsoleFormatter - fix output escaping. (SpacePossum) +* bug #3337 BracesFixer: nowdoc bug on template files (Slamdunk) +* bug #3349 Fix stdin handling and add tests for it (keradus) +* bug #3359 BracesFixer - handle comment for content outside of given block (keradus) +* bug #3415 FileFilterIterator - input checks and utests (SpacePossum, keradus) +* bug #3429 Fix archive analysing (keradus) +* minor #3137 PHPUnit - use common base class (keradus) +* minor #3342 PhpUnitDedicateAssertFixer - Remove unexistent method is_boolean (carusogabriel) +* minor #3345 StdinFileInfo - fix `__toString` (keradus) +* minor #3346 StdinFileInfo - drop getContents (keradus) +* minor #3347 DX: reapply newest CS (keradus) +* minor #3365 COOKBOOK-FIXERS.md - update to provide definition instead of description (keradus) +* minor #3370 AbstractFixer - FQCN in in exceptions (Slamdunk) +* minor #3372 ProjectCodeTest - fix comment (keradus) +* minor #3402 Always provide delimiter to `preg_quote` calls (ntzm) +* minor #3403 Remove unused import (ntzm) +* minor #3405 Fix `fopen` mode (ntzm) +* minor #3408 Improving fixers descriptions (kubawerlos) +* minor #3409 move itests from misc to priority (keradus) +* minor #3411 Better type hinting for AbstractFixerTestCase::$fixer (kubawerlos) +* minor #3412 Convert `strtolower` inside `strpos` to just `stripos` (ntzm) +* minor #3425 FixerFactoryTest - test that priority pair fixers have itest (keradus, SpacePossum) +* minor #3427 ConfigurationResolver: fix @return annotation (Slamdunk) + +Changelog for v2.2.13 +--------------------- + +* bug #3281 SelfAccessorFixer - stop modifying traits (kubawerlos) +* minor #3195 Add self-update command test (julienfalque) +* minor #3292 PHPUnit - set memory limit (veewee) +* minor #3306 Token - better input validation (keradus) + +Changelog for v2.2.12 +--------------------- + +* bug #3173 SimplifiedNullReturnFixer - handle nullable return types (Slamdunk) +* bug #3272 PhpdocTrimFixer - unicode support (SpacePossum) + +Changelog for v2.2.11 +--------------------- + +* bug #3225 PhpdocTrimFixer - Fix handling of lines without leading asterisk (julienfalque) +* bug #3262 ToolInfo - support installation by branch as well (keradus) +* bug #3266 PhpUnitConstructFixer - multiple asserts bug (kubawerlos) +* minor #3239 Improve contributing guide and issue template (julienfalque) +* minor #3246 Make ToolInfo methods non-static (julienfalque) +* minor #3250 Travis: fail early, spare resources, save the Earth (Slamdunk, keradus) +* minor #3251 Create Title for config file docs section (IanEdington) +* minor #3254 AutoReview/FixerFactoryTest::testFixersPriority: verbose assertion message (Slamdunk) + +Changelog for v2.2.10 +--------------------- + +* bug #3199 TokensAnalyzer - getClassyElements (SpacePossum) +* bug #3208 BracesFixer - Fix for instantiation in control structures (julienfalque, SpacePossum) +* bug #3215 BinaryOperatorSpacesFixer - Fix spaces around multiple exception catching (|) (ntzm) +* bug #3216 AbstractLinesBeforeNamespaceFixer - add min. and max. option, not only single target count (SpacePossum) +* bug #3217 TokenizerLinter - fix lack of linting when code is cached (SpacePossum, keradus) +* minor #3200 Skip slow test when Xdebug is loaded (julienfalque) +* minor #3219 Normalise references to GitHub in docs (ntzm) +* minor #3226 Remove unused imports (ntzm) +* minor #3231 Fix typos (ntzm) +* minor #3234 Simplify Cache\Signature::equals (ntzm) +* minor #3237 UnconfigurableFixer - use only LF (keradus) +* minor #3238 AbstractFixerTest - fix @cover annotation (keradus) + +Changelog for v2.2.9 +-------------------- + +* bug #3062 BraceClassInstantiationTransformer - Fix instantiation inside method call braces case (julienfalque, keradus) +* bug #3083 SingleBlankLineBeforeNamespaceFixer - Fix handling namespace right after opening tag (mlocati) +* bug #3109 SwitchCaseSemicolonToColonFixer - Fix bug with nested constructs (SpacePossum) +* bug #3123 Cache - File permissions (SpacePossum) +* bug #3172 IndentationTypeFixer - do not touch whitespace that is not indentation (SpacePossum) +* bug #3176 NoMultilineWhitespaceBeforeSemicolonsFixer - SpaceAfterSemicolonFixer - priority fix (SpacePossum) +* bug #3193 TokensAnalyzer::getClassyElements - sort result before returning (SpacePossum) +* bug #3196 SelfUpdateCommand - fix exit status when can't determine newest version (julienfalque) +* minor #3107 ConfigurationResolver - improve error message when rule is not found (SpacePossum) +* minor #3113 Add WordMatcher (keradus) +* minor #3133 Unify Reporter tests (keradus) +* minor #3134 Allow Symfony 4 (keradus, garak) +* minor #3136 PHPUnit - call hooks from parent class as well (keradus) +* minor #3145 misc - Typo (localheinz) +* minor #3150 Fix CircleCI (julienfalque) +* minor #3151 Update gitattributes to ignore next file (keradus) +* minor #3156 Update php-coveralls (keradus) +* minor #3166 README - add link to new gitter channel. (SpacePossum) +* minor #3174 Update UPGRADE.md (vitek-rostislav) +* minor #3180 Fix usage of static variables (kubawerlos) +* minor #3184 Code grooming - sort content of arrays (keradus) +* minor #3191 Travis - add nightly build to allow_failures due to Travis issues (keradus) +* minor #3197 DX groom CS (keradus) + +Changelog for v2.2.8 +-------------------- + +* bug #3052 Fix false positive warning about paths overridden by provided as command arguments (kubawerlos) +* bug #3058 IsNullFixer - fix whitespace handling (roukmoute) +* bug #3072 IsNullFixer - fix non_yoda_style edge case (keradus) +* bug #3088 Drop dedicated Phar stub (keradus) +* bug #3100 NativeFunctionInvocationFixer - Fix test if previous token is already namespace separator (SpacePossum) +* bug #3104 DoctrineAnnotationIndentationFixer - Fix str_repeat() error (julienfalque) +* minor #3038 Support PHP 7.2 (SpacePossum, keradus) +* minor #3064 Fix couple of typos (KKSzymanowski) +* minor #3078 ConfigurationResolver - hide context while including config file (keradus) +* minor #3080 Direct function call instead of by string (kubawerlos) +* minor #3085 CiIntegrationTest - skip when no git is available (keradus) +* minor #3087 phar-stub.php - allow PHP 7.2 (keradus) + +Changelog for v2.2.7 +-------------------- + +* bug #3002 Bugfix braces (mnabialek) +* bug #3010 Fix handling of Github releases (julienfalque, keradus) +* bug #3015 Fix exception arguments (julienfalque) +* bug #3016 Verify phar file (keradus) +* bug #3021 Risky rules cleanup (kubawerlos) +* bug #3023 RandomApiMigrationFixer - "rand();" to "random_int(0, getrandmax());" fixing (SpacePossum) +* bug #3024 ConfigurationResolver - Handle empty "rules" value (SpacePossum, keradus) +* bug #3031 IndentationTypeFixer - fix handling tabs in indented comments (keradus) +* minor #2999 Notice when paths from config file are overridden by command arguments (julienfalque, keradus) +* minor #3007 Add PHP 7.2 to Travis build matrix (Jean85) +* minor #3009 CiIntegrationTest - run local (SpacePossum) +* minor #3013 Adjust phpunit configuration (localheinz) +* minor #3017 Fix: Risky tests (localheinz) +* minor #3018 Fix: Make sure that data providers are named correctly (localheinz, keradus) +* minor #3032 .php_cs.dist - handling UnexpectedValueException (keradus) +* minor #3034 Follow newest CS (keradus) +* minor #3036 Drop not existing Standalone group from PHPUnit configuration and duplicated internal tags (keradus) +* minor #3042 Update gitter address (keradus) + +Changelog for v2.2.6 +-------------------- + +* bug #2925 Improve CI integration suggestion (julienfalque) +* bug #2928 TokensAnalyzer::getClassyElements - Anonymous class support (SpacePossum) +* bug #2931 Psr0Fixer, Psr4Fixer - ignore "new class" syntax (dg, keradus) +* bug #2934 Config - fix handling rule without value (keradus, SpacePossum) +* bug #2939 NoUnusedImportsFixer - Fix extra blank line (julienfalque) +* bug #2941 PHP 7.2 - Group imports with trailing comma support (SpacePossum, julienfalque) +* bug #2987 Fix incorrect indentation of comments in `braces` fixer (rob006) +* minor #2927 WhiteSpaceConfig - update message copy and more strict tests (SpacePossum, keradus) +* minor #2930 Trigger website build (keradus) +* minor #2932 Integrate CircleCI (keradus, aidantwoods) +* minor #2933 ProcessLinterTest - Ensure Windows test only runs on Windows, add a Mac test execution (aidantwoods) +* minor #2935 special handling of fabbot.io service if it's using too old PHP CS Fixer version (keradus) +* minor #2937 Travis: execute 5.3 job on precise (keradus) +* minor #2938 Tests fix configuration of project (SpacePossum, keradus) +* minor #2943 FunctionToConstantFixer - test with diff. arguments than fixable (SpacePossum) +* minor #2946 Detect extra old installations (keradus) +* minor #2947 Test suggested CI integration (keradus) +* minor #2951 AccessibleObject - remove most of usage (keradus) +* minor #2969 Shrink down AccessibleObject usage (keradus) +* minor #2982 TrailingCommaInMultilineArrayFixer - simplify isMultilineArray condition (TomasVotruba) + +Changelog for v2.2.5 +-------------------- + +* bug #2807 NoUselessElseFixer - Fix detection of conditional block (SpacePossum) +* bug #2809 Phar release - fix readme generation (SpacePossum, keradus) +* bug #2827 MethodArgumentSpaceFixer - Always remove trailing spaces (julienfalque) +* bug #2835 SelfAcessorFixer - class property fix (mnabialek) +* bug #2848 PhpdocIndentFixer - fix edge case with inline phpdoc (keradus) +* bug #2849 BracesFixer - Fix indentation issues with comments (julienfalque) +* bug #2851 Tokens - ensureWhitespaceAtIndex (GrahamCampbell, SpacePossum) +* bug #2854 NoLeadingImportSlashFixer - Removing leading slash from import even when in global space (kubawerlos) +* bug #2858 Support generic types (keradus) +* bug #2869 Fix handling required configuration (keradus) +* bug #2881 NoUnusedImportsFixer - Bug when trying to insert empty token (GrahamCampbell, keradus) +* bug #2882 DocBlock\Annotation - Fix parsing of collections with multiple key types (julienfalque) +* bug #2886 NoSpacesInsideParenthesisFixer - Do not remove whitespace if next token is comment (SpacePossum) +* bug #2888 SingleImportPerStatementFixer - Add support for function and const (SpacePossum) +* bug #2901 Add missing files to archive files (keradus) +* bug #2914 HeredocToNowdocFixer - works with CRLF line ending (dg) +* bug #2920 RuleSet - Update deprecated configuration of fixers (SpacePossum, keradus) +* minor #1531 Update docs for few generic types (keradus) +* minor #2793 COOKBOOK-FIXERS.md - update to current version, fix links (keradus) +* minor #2812 ProcessLinter - compatibility with Symfony 3.3 (keradus) +* minor #2816 Tokenizer - better docs and validation (keradus) +* minor #2817 Tokenizer - use future-compatible interface (keradus) +* minor #2819 Fix benchmark (keradus) +* minor #2824 code grooming (keradus) +* minor #2826 Exceptions - provide utests (localheinz) +* minor #2828 Enhancement: Reference phpunit.xsd from phpunit.xml.dist (localheinz) +* minor #2830 Differs - add tests (localheinz) +* minor #2832 Fix: Use all the columns (localheinz) +* minor #2833 Doctrine\Annotation\Token - provide utests (localheinz) +* minor #2839 Use PHP 7.2 polyfill instead of xml one (keradus) +* minor #2842 Move null to first position in PHPDoc types (julienfalque) +* minor #2850 ReadmeCommandTest - Prevent diff output (julienfalque) +* minor #2859 Fixed typo and dead code removal (GrahamCampbell) +* minor #2863 FileSpecificCodeSample - add tests (localheinz) +* minor #2864 WhitespacesAwareFixerInterface clean up (Slamdunk) +* minor #2865 AutoReview\FixerTest - test configuration samples (SpacePossum, keradus) +* minor #2867 VersionSpecification - Fix copy-paste typo (SpacePossum) +* minor #2874 LineTest - fix typo (keradus) +* minor #2875 HelpCommand - recursive layout fix (SpacePossum) +* minor #2883 DescribeCommand - Show which sample uses the default configuration (SpacePossum) +* minor #2887 Housekeeping - Strict whitespace checks (SpacePossum) +* minor #2895 ProjectCodeTest - check that classes in no-tests exception exist (keradus) +* minor #2896 Move testing related classes from src to tests (keradus) +* minor #2904 Reapply CS (keradus) +* minor #2910 PhpdocAnnotationWithoutDotFixer - Restrict lowercasing (oschwald) +* minor #2913 Tests - tweaks (SpacePossum, keradus) +* minor #2916 FixerFactory - drop return in sortFixers(), never used (TomasVotruba) + +Changelog for v2.2.4 +-------------------- + +* bug #2682 DoctrineAnnotationIndentationFixer - fix handling nested annotations (edhgoose, julienfalque) +* bug #2700 Fix Doctrine Annotation end detection (julienfalque) +* bug #2715 OrderedImportsFixer - handle indented groups (pilgerone) +* bug #2732 HeaderCommentFixer - fix handling blank lines (s7b4) +* bug #2745 Fix Doctrine Annotation newlines (julienfalque) +* bug #2752 FixCommand - fix typo in warning message (mnapoli) +* bug #2757 GeckoPHPUnit is not dev dependency (keradus) +* bug #2759 Update gitattributes (SpacePossum) +* bug #2763 Fix describe command with PSR-0 fixer (julienfalque) +* bug #2768 Tokens::ensureWhitespaceAtIndex - clean up comment check, add check for T_OPEN (SpacePossum) +* bug #2783 Tokens::ensureWhitespaceAtIndex - Fix handling line endings (SpacePossum) +* minor #2663 Use colors for keywords in commands output (julienfalque, keradus) +* minor #2706 Update README (SpacePossum) +* minor #2714 README.rst - fix wrong value in example (mleko) +* minor #2721 Update phpstorm article link to a fresh blog post (valeryan) +* minor #2727 PHPUnit - use speedtrap (keradus) +* minor #2728 SelfUpdateCommand - verify that it's possible to replace current file (keradus) +* minor #2729 DescribeCommand - add decorated output test (julienfalque) +* minor #2731 BracesFixer - properly pass config in utest dataProvider (keradus) +* minor #2738 Upgrade tests to use new, namespaced PHPUnit TestCase class (keradus) +* minor #2743 Fixing example and description for GeneralPhpdocAnnotationRemoveFixer (kubawerlos) +* minor #2744 AbstractDoctrineAnnotationFixerTestCase - split fixers test cases (julienfalque) +* minor #2755 Fix compatibility with PHPUnit 5.4.x (keradus) +* minor #2758 Readme - improve CI integration guidelines (keradus) +* minor #2769 Psr0Fixer - remove duplicated example (julienfalque) +* minor #2775 NoExtraConsecutiveBlankLinesFixer - remove duplicate code sample. (SpacePossum) +* minor #2778 AutoReview - watch that code samples are unique (keradus) +* minor #2787 Add warnings about missing dom ext and require json ext (keradus) +* minor #2792 Use composer-require-checker (keradus) +* minor #2796 Update .gitattributes (SpacePossum) +* minor #2800 PhpdocTypesFixerTest - Fix typo in covers annotation (SpacePossum) + +Changelog for v2.2.3 +-------------------- + +* bug #2724 Revert #2554 Add short diff. output format (keradus) + +Changelog for v2.2.2 +-------------------- + +Warning, this release breaks BC due to introduction of: +* minor #2554 Add short diff. output format (SpacePossum, keradus) +That PR was reverted in v2.2.3, which should be used instead of v2.2.2. + +* bug #2545 RuleSet - change resolvement (SpacePossum) +* bug #2686 Commands readme and describe - fix rare casing when not displaying some possible options of configuration (keradus) +* bug #2711 FixCommand - fix diff optional value handling (keradus) +* minor #2688 AppVeyor - Remove github oauth (keradus) +* minor #2703 Clean ups - No mixed annotations (SpacePossum) +* minor #2704 Create PHP70Migration:risky ruleset (keradus) +* minor #2707 Deprecate other than "yes" or "no" for input options (SpacePossum) +* minor #2709 code grooming (keradus) +* minor #2710 Travis - run more rules on TASK_SCA (keradus) + +Changelog for v2.2.1 +-------------------- + +* bug #2621 Tokenizer - fix edge cases with empty code, registered found tokens and code hash (SpacePossum, keradus) +* bug #2674 SemicolonAfterInstructionFixer - Fix case where block ends with an opening curly brace (ntzm) +* bug #2675 ProcessOutputTest - update tests to pass on newest Symfony components under Windows (keradus) +* minor #2651 Fix UPGRADE.md table syntax so it works in GitHub (ntzm, keradus) +* minor #2665 Travis - Improve trailing spaces detection (julienfalque) +* minor #2666 TransformersTest - move test to auto-review group (keradus) +* minor #2668 add covers annotation (keradus) +* minor #2669 TokensTest - grooming (SpacePossum) +* minor #2670 AbstractFixer: use applyFix instead of fix (Slamdunk) +* minor #2677 README: Correct progressbar option support (Laurens St�tzel) + +Changelog for v2.2.0 +-------------------- + +* bug #2640 NoExtraConsecutiveBlankLinesFixer - Fix single indent characters not working (ntzm) +* feature #2220 Doctrine annotation fixers (julienfalque) +* feature #2431 MethodArgumentSpaceFixer: allow to retain multiple spaces after comma (Slamdunk) +* feature #2459 BracesFixer - Add option for keeping opening brackets on the same line (jtojnar, SpacePossum) +* feature #2486 Add FunctionToConstantFixer (SpacePossum, keradus) +* feature #2505 FunctionDeclarationFixer - Make space after anonymous function configurable (jtojnar, keradus) +* feature #2509 FullOpeningTagFixer - Ensure opening PHP tag is lowercase (jtojnar) +* feature #2532 FixCommand - add stop-on-violation option (keradus) +* feature #2591 Improve process output (julienfalque) +* feature #2603 Add InvisibleSymbols Fixer (ivan1986, keradus) +* feature #2642 Add MagicConstantCasingFixer (ntzm) +* feature #2657 PhpdocToCommentFixer - Allow phpdoc for language constructs (ceeram, SpacePossum) +* minor #2500 Configuration resolver (julienfalque, SpacePossum, keradus) +* minor #2566 Show more details on errors and exceptions. (SpacePossum, julienfalque) +* minor #2597 HHVM - bump required version to 3.18 (keradus) +* minor #2606 FixCommand - fix missing comment close tag (keradus) +* minor #2623 OrderedClassElementsFixer - remove dead code (SpacePossum) +* minor #2625 Update Symfony and Symfony:risky rulesets (keradus) +* minor #2626 TernaryToNullCoalescingFixer - adjust ruleset membership and description (keradus) +* minor #2635 ProjectCodeTest - watch that all classes have dedicated tests (keradus) +* minor #2647 DescribeCommandTest - remove deprecated code usage (julienfalque) +* minor #2648 Move non-code covering tests to AutoReview subnamespace (keradus) +* minor #2652 NoSpacesAroundOffsetFixerTest - fix deprecation (keradus) +* minor #2656 Code grooming (keradus) +* minor #2659 Travis - speed up preparation for phar building (keradus) +* minor #2660 Fixed typo in suggest for ext-mbstring (pascal-hofmann) +* minor #2661 NonPrintableCharacterFixer - include into Symfony:risky ruleset (keradus) + +Changelog for v2.1.3 +-------------------- + +* bug #2358 Cache - Deal with signature encoding (keradus, GrahamCampbell) +* bug #2475 Add shorthand array destructing support (SpacePossum, keradus) +* bug #2595 NoUnusedImportsFixer - Fix import usage detection with properties (julienfalque) +* bug #2605 PhpdocAddMissingParamAnnotationFixer, PhpdocOrderFixer - fix priority issue (SpacePossum) +* bug #2607 Fixers - better comments handling (SpacePossum) +* bug #2612 BracesFixer - Fix early bracket close for do-while loop inside an if without brackets (felixgomez) +* bug #2614 Ensure that '*Fixer::fix()' won't crash when running on non-candidate collection (keradus) +* bug #2630 HeaderCommentFixer - Fix trailing whitespace not removed after AliasFunctionsFixer (kalessil) +* feature #1275 Added PhpdocInlineTagFixer (SpacePossum, keradus) +* feature #1292 Added MethodSeparationFixer (SpacePossum) +* feature #1383 Introduce rules and sets (keradus) +* feature #1416 Mark fixers as risky (keradus) +* feature #1440 Made AbstractFixerTestCase and AbstractIntegrationTestCase public (keradus) +* feature #1489 Added Psr4Fixer (GrahamCampbell) +* feature #1497 ExtraEmptyLinesFixer - allow to remove empty blank lines after configured tags (SpacePossum) +* feature #1529 Added PhpdocPropertyFixer, refactored Tag and Annotation (GrahamCampbell) +* feature #1628 Added OrderedClassElementsFixer (gharlan) +* feature #1742 path argument is used to create an intersection with existing finder (keradus, gharlan) +* feature #1779 Added GeneralPhpdocAnnotationRemoveFixer, GeneralPhpdocAnnotationRenameFixer (keradus) +* feature #1811 Added NoSpacesInsideOfssetFixer (phansys) +* feature #1819 Added DirConstantFixer, ModernizeTypesCastingFixer, RandomApiMigrationFixer (kalessil, SpacePossum, keradus) +* feature #1825 Added junit format (ekho) +* feature #1862 FixerFactory - Do not allow conflicting fixers (SpacePossum) +* feature #1888 Cache refactoring, better cache handling in dry-run mode (localheinz) +* feature #1889 Added SingleClassElementPerStatementFixer (phansys, SpacePossum) +* feature #1903 FixCommand - allow to pass multiple path argument (keradus) +* feature #1913 Introduce path-mode CLI option (keradus) +* feature #1949 Added DeclareStrictTypesFixer, introduce options for HeaderCommentFixer (Seldaek, SpacePossum, keradus) +* feature #1955 Introduce CT_ARRAY_INDEX_CURLY_BRACE_OPEN and CT_ARRAY_INDEX_CURLY_BRACE_CLOSE (keradus) +* feature #1958 Added NormalizeIndexBraceFixer (keradus) +* feature #2069 Add semicolon after instruction fixer (SpacePossum) +* feature #2089 Add `no_spaces_around_offset` fixer (phansys) +* feature #2179 BinaryOperatorSpacesFixer - add (un)align configuration options (SpacePossum) +* feature #2192 Add PowToExponentiationFixer (SpacePossum, keradus) +* feature #2207 Added ReturnTypeDeclarationFixer (keradus) +* feature #2213 VisibilityRequiredFixer - Add support for class const visibility added in PHP7.1. (SpacePossum) +* feature #2221 Add support for user-defined whitespaces (keradus) +* feature #2244 Config cleanup (keradus, SpacePossum) +* feature #2247 PhpdocAnnotationWithoutDotFixer - support more cases (keradus) +* feature #2289 Add PhpdocAddMissingParamAnnotationFixer (keradus) +* feature #2331 Add DescribeCommand (keradus, SpacePossum) +* feature #2332 New colours of diff on console (keradus) +* feature #829 add support for .php_cs.dist file (keradus) +* feature #998 MethodArgumentSpaceFixer - enhance, now only one space after comma (trilopin, keradus) +* minor #1007 Simplify Transformers (keradus) +* minor #1050 Make Config's setDir() fluent like the rest of methods (gonzaloserrano) +* minor #1062 Added NamespaceOperatorTransformer (gharlan) +* minor #1078 Exit status should be 0 if there are no errors (gharlan) +* minor #1101 CS: fix project itself (localheinz) +* minor #1102 Enhancement: List errors occurred before, during and after fixing (localheinz) +* minor #1105 Token::isStructureAlternativeEnd - remove unused method (keradus) +* minor #1106 readme grooming (SpacePossum, keradus) +* minor #1115 Fixer - simplify flow (keradus) +* minor #1118 Process output refactor (SpacePossum) +* minor #1132 Linter - public methods should be first (keradus) +* minor #1134 Token::isWhitespace - simplify interface (keradus) +* minor #1140 FixerInterface - check if fixer should be applied by isCandidate method (keradus) +* minor #1146 Linter - detect executable (keradus) +* minor #1156 deleted old ConfigurationResolver class (keradus) +* minor #1160 Grammar fix to README (Falkirks) +* minor #1174 DefaultFinder - boost performance by not filtering when files array is empty (keradus) +* minor #1179 Exit with non-zero if invalid files were detected prior to fixing (localheinz) +* minor #1186 Finder - do not search for .xml and .yml files (keradus) +* minor #1206 BracesFixer::getClassyTokens - remove duplicated method (keradus) +* minor #1222 Made fixers final (GrahamCampbell) +* minor #1229 Tokens - Fix PHPDoc (SpacePossum) +* minor #1241 More details on exceptions. (SpacePossum) +* minor #1263 Made internal classes final (GrahamCampbell) +* minor #1272 Readme - Add spaces around PHP-CS-Fixer headers (Soullivaneuh) +* minor #1283 Error - Fixed type phpdoc (GrahamCampbell) +* minor #1284 Token - Fix PHPDoc (SpacePossum) +* minor #1314 Added missing internal annotations (keradus) +* minor #1329 Psr0Fixer - move to contrib level (gharlan) +* minor #1340 Clean ups (SpacePossum) +* minor #1341 Linter - throw exception when write fails (SpacePossum) +* minor #1348 Linter - Prefer error output when throwing a linting exception (GrahamCampbell) +* minor #1350 Add "phpt" as a valid extension (henriquemoody) +* minor #1376 Add time and memory to XML report (junichi11) +* minor #1387 Made all test classes final (keradus) +* minor #1388 Made all tests internal (keradus) +* minor #1390 Added ProjectCodeTest that tests if all classes inside tests are internal and final or abstract (keradus) +* minor #1391 Fixer::getLevelAsString is no longer static (keradus) +* minor #1392 Add report to XML report as the root node (junichi11) +* minor #1394 Stop mixing level from config file and fixers from CLI arg when one of fixers has dash (keradus) +* minor #1426 MethodSeparationFixer - Fix spacing around comments (SpacePossum, keradus) +* minor #1432 Fixer check on factory (Soullivaneuh) +* minor #1434 Add Test\AccessibleObject class (keradus) +* minor #1442 FixerFactory - disallow to register multiple fixers with same name (keradus) +* minor #1477 rename PhpdocShortDescriptionFixer into PhpdocSummaryFixer (keradus) +* minor #1481 Fix running the tests (keradus) +* minor #1482 move AbstractTransformerTestBase class outside Tests dir (keradus) +* minor #1530 Added missing internal annotation (GrahamCampbell) +* minor #1534 Clean ups (SpacePossum) +* minor #1536 Typo fix (fabpot) +* minor #1555 Fixed indentation in composer.json (GrahamCampbell) +* minor #1558 [2.0] Cleanup the tags property in the abstract phpdoc types fixer (GrahamCampbell) +* minor #1567 PrintToEchoFixer - add to symfony rule set (gharlan) +* minor #1607 performance improvement (gharlan) +* minor #1621 Switch to PSR-4 (keradus) +* minor #1631 Configuration exceptions exception cases on master. (SpacePossum) +* minor #1646 Remove non-default Config/Finder classes (keradus) +* minor #1648 Fixer - avoid extra calls to getFileRelativePathname (GrahamCampbell) +* minor #1649 Consider the php version when caching (GrahamCampbell) +* minor #1652 Rename namespace "Symfony\CS" to "PhpCsFixer" (gharlan) +* minor #1666 new Runner, ProcessOutputInterface, DifferInterface and ResultInterface (keradus) +* minor #1674 Config - add addCustomFixers method (PedroTroller) +* minor #1677 Enhance tests (keradus) +* minor #1695 Rename Fixers (keradus) +* minor #1702 Upgrade guide (keradus) +* minor #1707 ExtraEmptyLinesFixer - fix configure docs (keradus) +* minor #1712 NoExtraConsecutiveBlankLinesFixer - Remove blankline after curly brace open (SpacePossum) +* minor #1718 CLI: rename --config-file argument (keradus) +* minor #1722 Renamed not_operators_with_space to not_operator_with_space (GrahamCampbell) +* minor #1728 PhpdocNoSimplifiedNullReturnFixer - rename back to PhpdocNoEmptyReturnFixer (keradus) +* minor #1729 Renamed whitespacy_lines to no_whitespace_in_blank_lines (GrahamCampbell) +* minor #1731 FixCommand - value for config option is required (keradus) +* minor #1732 move fixer classes from level subdirs to thematic subdirs (gharlan, keradus) +* minor #1733 ConfigurationResolver - look for .php_cs file in cwd as well (keradus) +* minor #1737 RuleSet/FixerFactory - sort arrays content (keradus) +* minor #1751 FixerInterface::configure - method should always override configuration, not patch it (keradus) +* minor #1752 Remove unused code (keradus) +* minor #1756 Finder - clean up code (keradus) +* minor #1757 Psr0Fixer - change way of configuring the fixer (keradus) +* minor #1762 Remove ConfigInterface::getDir, ConfigInterface::setDir, Finder::setDir and whole FinderInterface (keradus) +* minor #1764 Remove ConfigAwareInterface (keradus) +* minor #1780 AbstractFixer - throw error on configuring non-configurable Fixer (keradus) +* minor #1782 rename fixers (gharlan) +* minor #1815 NoSpacesInsideParenthesisFixer - simplify implementation (keradus) +* minor #1821 Ensure that PhpUnitDedicateAssertFixer runs after NoAliasFunctionsFixer, clean up NoEmptyCommentFixer (SpacePossum) +* minor #1824 Reporting extracted to separate classes (ekho, keradus, SpacePossum) +* minor #1826 Fixer - remove measuring fixing time per file (keradus) +* minor #1843 FileFilterIterator - add missing import (GrahamCampbell) +* minor #1845 FileCacheManager - Allow linting to determine the cache state too (GrahamCampbell) +* minor #1846 FileFilterIterator - Corrected an iterator typehint (GrahamCampbell) +* minor #1848 DocBlock - Remove some old unused phpdoc tags (GrahamCampbell) +* minor #1856 NoDuplicateSemicolonsFixer - Remove overcomplete fixer (SpacePossum) +* minor #1861 Fix: Ofsset should be Offset (localheinz) +* minor #1867 Print non-report output to stdErr (SpacePossum, keradus) +* minor #1873 Enhancement: Show path to cache file if it exists (localheinz) +* minor #1875 renamed Composer package (fabpot) +* minor #1882 Runner - Handle throwables too (GrahamCampbell) +* minor #1886 PhpdocScalarFixer - Fix lowercase str to string too (GrahamCampbell) +* minor #1940 README.rst - update CI example (keradus) +* minor #1947 SCA, CS, add more tests (SpacePossum, keradus) +* minor #1954 tests - stop using deprecated method (sebastianbergmann) +* minor #1962 TextDiffTest - tests should not produce cache file (keradus) +* minor #1973 Introduce fast PHP7 based linter (keradus) +* minor #1999 Runner - No need to determine relative file name twice (localheinz) +* minor #2002 FileCacheManagerTest - Adjust name of test and variable (localheinz) +* minor #2010 NoExtraConsecutiveBlankLinesFixer - SF rule set, add 'extra' (SpacePossum) +* minor #2013 no_whitespace_in_blank_lines -> no_whitespace_in_blank_line (SpacePossum) +* minor #2024 AbstractFixerTestCase - check if there is no duplicated Token instance inside Tokens collection (keradus) +* minor #2031 COOKBOOK-FIXERS.md - update calling doTest method (keradus) +* minor #2032 code grooming (keradus) +* minor #2068 Code grooming (keradus) +* minor #2073 DeclareStrictTypesFixer - Remove fix CS fix logic from fixer. (SpacePossum) +* minor #2088 TokenizerLintingResult - expose line number of parsing error (keradus) +* minor #2093 Tokens - add block type BLOCK_TYPE_ARRAY_INDEX_CURLY_BRACE (SpacePossum) +* minor #2095 Transformers - add required PHP version (keradus) +* minor #2096 Introduce CT for PHP7 (keradus) +* minor #2119 Create @Symfony:risky ruleset (keradus) +* minor #2163 ClassKeywordRemoveFixerTest - Fix tests (SpacePossum) +* minor #2180 FixCommand - don't refer to renamed rules (keradus) +* minor #2181 Disallow to disable linter (keradus) +* minor #2194 semicolon_after_instruction,no_unneeded_control_parentheses prio issue (SpacePossum) +* minor #2199 make fixers less risky (SpacePossum) +* minor #2206 Add PHP70Migration ruleset (keradus) +* minor #2217 SelfUpdateCommand - Print version of update fixer (SpacePossum) +* minor #2223 update integration test format (keradus) +* minor #2227 Stop polluting global namespace with CT (keradus) +* minor #2237 DX: extend integration tests for PSR2 and Symfony rulesets (keradus) +* minor #2240 Make some objects immutable (keradus) +* minor #2251 ProtectedToPrivateFixer - fix priority, fix comments with new fixer names (SpacePossum) +* minor #2252 ClassDefinitionFixer - Set configuration of the fixer in the RuleSet of SF. (SpacePossum) +* minor #2257 extend Symfony_whitespaces itest (keradus) +* minor #2258 README.rst - indicate configurable rules (keradus) +* minor #2267 RuleSet - validate set (keradus) +* minor #2268 Use strict parameters for PHP functions (keradus) +* minor #2273 fixed typo (fabpot) +* minor #2274 ShortArraySyntaxFixer/LongArraySyntaxFixer - Merge conflicting fixers (SpacePossum) +* minor #2275 Clean ups (SpacePossum) +* minor #2278 Concat*Fixer - unify concat fixers (SpacePossum, keradus) +* minor #2279 Use Prophecy (keradus) +* minor #2284 Code grooming (SpacePossum) +* minor #2285 IntegrationCase is now aware about RuleSet but not Fixers (keradus, SpacePossum) +* minor #2286 Phpdoc*Fixer - unify rename fixers (SpacePossum, keradus) +* minor #2288 FixerInterface::configure(null) reset fixer to use default configuration (keradus) +* minor #2291 Make fixers ready to use directly after creation (keradus) +* minor #2295 Code grooming (keradus) +* minor #2296 ProjectCodeTest - make test part of regular testsuite, not standalone one (keradus) +* minor #2298 ConfigurationResolver - grooming (SpacePossum) +* minor #2300 Simplify rule set (SpacePossum, keradus) +* minor #2306 DeclareStrictTypesFixer - do not move tokens (SpacePossum) +* minor #2312 RuleSet - sort rules (localheinz) +* minor #2313 DX: provide doctyping for tests (keradus) +* minor #2317 Add utests (keradus) +* minor #2318 *TestCase - Reduce visibility of setUp() (localheinz) +* minor #2319 Code grooming (keradus) +* minor #2322 DX: use whitemessy aware assertion (keradus) +* minor #2324 Echo|Print*Fixer - unify printing fixers (SpacePossum, keradus) +* minor #2337 Normalize rule naming (keradus) +* minor #2338 Drop hacks for unsupported HHVM (keradus) +* minor #2339 Add some Fixer descriptions (SpacePossum, keradus) +* minor #2343 PowToExponentiationFixer - allow to run on 5.6.0 as well (keradus) +* minor #767 Add @internal tag (keradus) +* minor #807 Tokens::isMethodNameIsMagic - remove unused method (keradus) +* minor #809 Split Tokens into Tokens and TokensAnalyzer (keradus) +* minor #844 Renamed phpdoc_params to phpdoc_align (GrahamCampbell) +* minor #854 Change default level to PSR2 (keradus) +* minor #873 Config - using cache by default (keradus) +* minor #902 change FixerInterface (keradus) +* minor #911 remove Token::$line (keradus) +* minor #914 All Transformer classes should be named with Transformer as suffix (keradus) +* minor #915 add UseTransformer (keradus) +* minor #916 add ArraySquareBraceTransformer (keradus) +* minor #917 clean up Transformer tests (keradus) +* minor #919 CurlyBraceTransformer - one transformer to handle all curly braces transformations (keradus) +* minor #928 remove Token::getLine (keradus) +* minor #929 add WhitespacyCommentTransformer (keradus) +* minor #937 fix docs/typehinting in few classes (keradus) +* minor #958 FileCacheManager - remove code for BC support (keradus) +* minor #979 Improve Tokens::clearEmptyTokens performance (keradus) +* minor #981 Tokens - code grooming (keradus) +* minor #988 Fixers - no need to search for tokens of given kind in extra loop (keradus) +* minor #989 No need for loop in Token::equals (keradus) + Changelog for v1.13.3 --------------------- @@ -282,7 +3457,7 @@ Changelog for v1.11 * feature #1484 Added ArrayElementNoSpaceBeforeCommaFixer and ArrayElementWhiteSpaceAfterCommaFixer (amarczuk) * feature #1449 PhpUnitConstructFixer - Fix more use cases (SpacePossum) * feature #1382 Added PhpdocTypesFixer (GrahamCampbell) -* feature #1384 Add intergration tests (SpacePossum) +* feature #1384 Add integration tests (SpacePossum) * feature #1349 Added FunctionTypehintSpaceFixer (keradus) * minor #1562 Fix invalid PHP code samples in utests (SpacePossum) * minor #1560 Fixed project name in xdebug warning (gharlan) diff --git a/vendor/friendsofphp/php-cs-fixer/CONTRIBUTING.md b/vendor/friendsofphp/php-cs-fixer/CONTRIBUTING.md index 32a8d8d..a3eb381 100644 --- a/vendor/friendsofphp/php-cs-fixer/CONTRIBUTING.md +++ b/vendor/friendsofphp/php-cs-fixer/CONTRIBUTING.md @@ -1,41 +1,104 @@ -# Contributions are welcome! +# Contributions Are Welcome! -## Quick guide +If you need any help, don't hesitate to ask the community on [Gitter](https://gitter.im/PHP-CS-Fixer/Lobby). - * Fork the repo. - * Checkout the branch you want to make changes on: - * Master if you make changes to the code that are not backward compatible. - * Default branch when adding new features. - * Branch before the default if you are fixing a bug for an existing feature (or the default/master branch if the feature was introduced in that version). - * Install dependencies: `composer install`. - * Create branch, e.g. `feature-foo` or `bugfix-bar`. - * Make changes. - * If you are adding functionality or fixing a bug - add a test! - * Fix project itself: `php php-cs-fixer fix`. - * Regenerate readme: `php php-cs-fixer readme > README.rst`. Do not modify `README.rst` manually! - * Check if tests pass: `phpunit` [(4.x or 5.x)](https://phpunit.de/manual/current/en/installation.html) +## Quick Guide -## Opening a pull request +### Fixer -You can do some things to increase the chance that your pull request is accepted the first time: +A *fixer* is a class that tries to fix one code style issue (a ``Fixer`` class +must implement ``FixerInterface``). - * Submit one pull request per fix or feature. - * If your changes are not up to date - rebase your branch on the parent branch. - * Follow the conventions used in the project. - * Remember about tests and documentation. - * Don't bump version. +### Config -## Making new fixers +A *config* knows about the code style rules and the files and directories that +must be scanned by the tool when run in the directory of your project. It is +useful for projects that follow a well-known directory structures (like for +Symfony projects for instance). -There is a [cookbook](https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/COOKBOOK-FIXERS.md) with basic instructions on how to build a new fixer. Consider reading it +### How-To + +* [Fork](https://help.github.com/articles/fork-a-repo/) the repo. +* [Checkout](https://git-scm.com/docs/git-checkout) the branch you want to make changes on: + * If you are fixing a bug or typo, improving tests or for any small tweak: the lowest branch where the changes can be applied. Once your Pull Request is accepted, the changes will get merged up to highest branches. + * `master` in other cases (new feature, deprecation, or backwards compatibility breaking changes). Note that most of the time, `master` represents the next minor release of PHP CS Fixer, so Pull Requests that break backwards compatibility might be postponed. +* Install dependencies: `composer install`. +* Create a new branch, e.g. `feature-foo` or `bugfix-bar`. +* Make changes. +* If you are adding functionality or fixing a bug - add a test! Prefer adding new test cases over modifying existing ones. +* Make sure there is no wrong file permissions in the repository: `./dev-tools/check_file_permissions.sh`. +* Make sure there is no trailing spaces in the code: `./dev-tools/check_trailing_spaces.sh`. +* Update documentation: `php dev-tools/doc.php`. This requires the highest version of PHP supported by PHP CS Fixer. If it is not installed on your system, you can run it in a Docker container instead: `docker run -it --rm --user="$(id -u):$(id -g)" -w="/app" --volume="$(pwd):/app" php:7.4-cli php dev-tools/doc.php`. +* Install dev tools: `dev-tools/install.sh` +* Run static analysis using PHPStan: `php -d memory_limit=256M dev-tools/vendor/bin/phpstan analyse` +* Check if tests pass: `vendor/bin/phpunit`. +* Fix project itself: `php php-cs-fixer fix`. + +## Working With Docker + +This project provides a Docker setup that allows working on it using any of the supported PHP versions. + +To use it, you first need to install: + + * [Docker](https://docs.docker.com/get-docker/) + * [Docker Compose](https://docs.docker.com/compose/install/) + +Make sure the versions installed support [Compose file format 3.8](https://docs.docker.com/compose/compose-file/). + +Next, copy [`docker-compose.override.yaml.dist`](./docker-compose.override.yaml.dist) to `docker-compose.override.yaml` +and edit it to your needs. The relevant parameters that might require some tweaking have comments to help you. + +You can then build the images: + +```console +$ docker-compose build --parallel +``` + +Now you can run commands needed to work on the project. For example, say you want to run PHPUnit tests on PHP 7.4: + +```console +$ docker-compose run php-7.4 vendor/bin/phpunit +``` + +Sometimes it can be more convenient to have a shell inside the container: + +```console +$ docker-compose run php-7.4 sh +/app $ vendor/bin/phpunit +``` + +The images come with an [`xdebug` script](github.com/julienfalque/xdebug/) that allows running any PHP command with +Xdebug enabled to help debug problems. + +```console +docker-compose run php-7.4 xdebug vendor/bin/phpunit +``` + +If you're using PhpStorm, you need to create a [server](https://www.jetbrains.com/help/phpstorm/servers.html) with a +name that matches the `PHP_IDE_CONFIG` environment variable defined in the Docker Compose configuration files, which is +`php-cs-fixer` by default. + +All images use port 9003 for debug connections. + +## Opening a [Pull Request](https://help.github.com/articles/about-pull-requests/) + +You can do some things to increase the chance that your Pull Request is accepted the first time: + +* Submit one Pull Request per fix or feature. +* If your changes are not up to date, [rebase](https://git-scm.com/docs/git-rebase) your branch onto the parent branch. +* Follow the conventions used in the project. +* Remember about tests and documentation. +* Don't bump version. + +## Making New Fixers + +There is a [cookbook](doc/cookbook_fixers.rst) with basic instructions on how to build a new fixer. Consider reading it before opening a PR. -## Project's standards +## Project's Standards - * [PSR-1: Basic Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md) - * [PSR-2: Coding Style Guide](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) - * [PSR-4: Autoloading Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md) - * [PSR-5: PHPDoc (draft)](https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md) - * [Symfony Coding Standards](http://symfony.com/doc/current/contributing/code/standards.html) - * [Symfony Documentation Standards](http://symfony.com/doc/current/contributing/documentation/standards.html) - * Keep the order of class elements: static properties, instance properties, constructor (or setUp for PHPUnit), destructor (or tearDown for PHPUnit), static methods, instance methods, magic static methods, magic instance methods. +* [PSR-1: Basic Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md) +* [PSR-2: Coding Style Guide](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) +* [PSR-4: Autoloading Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md) +* [PSR-5: PHPDoc (draft)](https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md) +* [Symfony Coding Standards](https://symfony.com/doc/current/contributing/code/standards.html) diff --git a/vendor/friendsofphp/php-cs-fixer/COOKBOOK-FIXERS.md b/vendor/friendsofphp/php-cs-fixer/COOKBOOK-FIXERS.md deleted file mode 100644 index 7a897c9..0000000 --- a/vendor/friendsofphp/php-cs-fixer/COOKBOOK-FIXERS.md +++ /dev/null @@ -1,489 +0,0 @@ -Cookbook - Making a new Fixer for PHP CS Fixer -============================================== - -You want to make a new fixer to PHP CS Fixer and do not know how to -start. Follow this document and you will be able to do it. - -## Background - -In order to be able to create a new fixer, you need some background. -PHP CS Fixer is a transcompiler which takes valid PHP code and pretty -print valid PHP code. It does all transformations in multiple passes, -a.k.a., multi-pass compiler. - -Therefore, a new fixer is meant to be ideally -[idempotent](http://en.wikipedia.org/wiki/Idempotence#Computer_science_meaning), -or at least atomic in its actions. More on this later. - -All contributions go through a code review process. Do not feel -discouraged - it is meant only to give more people more chance to -contribute, and to detect bugs ([Linus' -Law](http://en.wikipedia.org/wiki/Linus%27s_Law)). - -If possible, try to get acquainted with the public interface for the -[Tokens class](Symfony/CS/Tokenizer/Tokens.php) -and [Token class](Symfony/CS/Tokenizer/Token.php) -classes. - -## Assumptions - -* You are familiar with Test Driven Development. -* Forked FriendsOfPHP/PHP-CS-Fixer into your own Github Account. -* Cloned your forked repository locally. -* Installed the dependencies of PHP CS Fixer using [Composer](https://getcomposer.org/). -* You have read [`CONTRIBUTING.md`](CONTRIBUTING.md). - -## Step by step - -For this step-by-step, we are going to create a simple fixer that -removes all comments of the code that are preceded by ';' (semicolon). - -We are calling it `remove_comments` (code name), or, -`RemoveCommentsFixer` (class name). - -### Step 1 - Creating files - -Create a new file in -`PHP-CS-Fixer/Symfony/CS/Fixer/Contrib/RemoveCommentsFixer.php`. -Put this content inside: -```php - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Your name - */ -final class RemoveCommentsFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - // Add the fixing logic of the fixer here. - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - // Return a short description of the Fixer, it will be used in the README.rst. - } -} -``` - -Note how the class and file name match. Also keep in mind that all -fixers must implement `FixerInterface`. In this case, the fixer is -inheriting from `AbstractFixer`, which fulfills the interface with some -default behavior. - -Now let us create the test file at -`Symfony/CS/Tests/Fixer/Contrib/RemoveCommentsFixerTest.php` . Put this -content inside: - -```php - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tests\Fixer\Contrib; - -use Symfony\CS\Tests\Fixer\AbstractFixerTestBase; - -/** - * @author Your name - * - * @internal - */ -final class RemoveCommentsFixerTest extends AbstractFixerTestBase -{ - /** - * @dataProvider provideFixCases - */ - public function testFix($expected, $input = null) - { - $this->makeTest($expected, $input); - } - - public function provideFixCases() - { - return array(); - } -} -``` - -The files are created, one thing is still missing though: we need to -update the README.md. Fortunately, PHP CS Fixer can help you here. -Execute the following command in your command shell: - -`$ php php-cs-fixer readme > README.rst` - -### Step 2 - Using tests to define fixers behavior - -Now that the files are created, you can start writing test to define the -behavior of the fixer. You have to do it in two ways: first, ensuring -the fixer changes what it should be changing; second, ensuring that -fixer does not change what is not supposed to change. Thus: - -#### Keeping things as they are: -`Symfony/CS/Tests/Fixer/Contrib/RemoveCommentsFixerTest.php`@provideFixCases: -```php - ... - public function provideFixCases() - { - return array( - array(' - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tests\Fixer\Contrib; - -use Symfony\CS\Tests\Fixer\AbstractFixerTestBase; - -/** - * @author Your name - * - * @internal - */ -final class RemoveCommentsFixerTest extends AbstractFixerTestBase -{ - /** - * @dataProvider provideFixCases - */ - public function testFix($expected, $input = null) - { - $this->makeTest($expected, $input); - } - - public function provideFixCases() - { - return array( - array( - 'generateCode(); - } -} -``` - -Run `$ phpunit Symfony/CS/Tests/Fixer/Contrib/RemoveCommentsFixerTest.php`. -You are going to see that the tests fails. - -### Break -Now we have pretty much a cradle to work with. A file with a failing -test, and the fixer, that for now does not do anything. - -How do fixers work? In the PHP CS Fixer, they work by iterating through -pieces of codes (each being a Token), and inspecting what exists before -and after that bit and making a decision, usually: - - * Adding code. - * Modifying code. - * Deleting code. - * Ignoring code. - -In our case, we want to find all comments, and foreach (pun intended) -one of them check if they are preceded by a semicolon symbol. - -Now you need to do some reading, because all these symbols obey a list -defined by the PHP compiler. It is the ["List of Parser -Tokens"](http://php.net/manual/en/tokens.php). - -Internally, PHP CS Fixer transforms some of PHP native tokens into custom -tokens through the use of [Transfomers](Symfony/CS/Tokenizer/Transformer), -they aim to help you reason about the changes you may want to do in the -fixers. - -So we can get to move forward, humor me in believing that comments have -one symbol name: `T_COMMENT`. - -### Step 3 - Implement your solution - continuation. - -We do not want all symbols to be analysed. Only `T_COMMENT`. So let us -iterate the token(s) we are interested in. -`Symfony/CS/Fixer/Contrib/RemoveCommentsFixer.php`: -```php -final class RemoveCommentsFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $foundComments = $tokens->findGivenKind(T_COMMENT); - foreach($foundComments as $index => $token){ - - } - - return $tokens->generateCode(); - } -} -``` - -OK, now for each `T_COMMENT`, all we need to do is check if the previous -token is a semicolon. -`Symfony/CS/Fixer/Contrib/RemoveCommentsFixer.php`: -```php -final class RemoveCommentsFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $foundComments = $tokens->findGivenKind(T_COMMENT); - foreach($foundComments as $index => $token){ - $prevTokenIndex = $tokens->getPrevMeaningfulToken($index); - $prevToken = $tokens[$prevTokenIndex]; - - if($prevToken->equals(';')){ - $token->clear(); - } - } - - return $tokens->generateCode(); - } -} -``` - -So the fixer in the end looks like this: -```php - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - * - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Your name - */ -final class RemoveCommentsFixer extends AbstractFixer { - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) { - $tokens = Tokens::fromCode($content); - - $foundComments = $tokens->findGivenKind(T_COMMENT); - foreach ($foundComments as $index => $token) { - $prevTokenIndex = $tokens->getPrevMeaningfulToken($index); - $prevToken = $tokens[$prevTokenIndex]; - - if ($prevToken->equals(';')) { - $token->clear(); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() { - return 'Removes all comments of the code that are preceded by ";" (semicolon).';// Trailing dot is important. We thrive to use English grammar properly. - } -} -``` - -### Step 4 - Format, Commit, PR. - -Note that so far, we have not coded adhering to PSR-1/2. This is done on -purpose. For every commit you make, you must use PHP CS Fixer to fix -itself. Thus, on the command line call: - -`$ php php-cs-fixer fix` - -This will fix all the coding style mistakes. - -After the final CS fix, you are ready to commit. Do it. - -Now, go to Github and open a Pull Request. - - -### Step 5 - Peer review: it is all about code and community building. - -Congratulations, you have made your first fixer. Be proud. Your work -will be reviewed carefully by PHP CS Fixer community. - -The review usually flows like this: - -1. People will check your code for common mistakes and logical -caveats. Usually, the person building a fixer is blind about some -behavior mistakes of fixers. Expect to write few more tests to cater for -the reviews. -2. People will discuss the relevance of your fixer. If it is -something that goes along with Symfony style standards, or PSR-1/PSR-2 -standards, they will ask you to move from Symfony/CS/Fixers/Contrib to -Symfony/CS/Fixers/{Symfony, PSR2, etc}. -3. People will also discuss whether your fixer is idempotent or not. -If they understand that your fixer must always run before or after a -certain fixer, they will ask you to override a method named -`getPriority()`. Do not be afraid of asking the reviewer for help on how -to do it. -4. People may ask you to rebase your code to unify commits or to get -rid of merge commits. -5. Go to 1 until no actions are needed anymore. - -Your fixer will be incorporated in the next release. - -# Congratulations! You have done it. - - - -## Q&A - -#### Why is not my PR merged yet? - -PHP CS Fixer is used by many people, that expect it to be stable. So -sometimes, few PR are delayed a bit so to avoid cluttering at @dev -channel on composer. - -Other possibility is that reviewers are giving time to other members of -PHP CS Fixer community to partake on the review debates of your fixer. - -In any case, we care a lot about what you do and we want to see it being -part of the application as soon as possible. - -#### May I use short arrays (`$a = []`)? - -No. Short arrays were introduced in PHP 5.4 and PHP CS Fixer still -supports PHP 5.3.6. - -#### Why are you steering me to create my fixer at CONTRIB_LEVEL ? - -CONTRIB_LEVEL is the most lax level - and it is far more likely to have -your fixer accepted at CONTRIB_LEVEL and later changed to SYMFOMY_LEVEL -or PSR2_LEVEL; than the other way around. - -If you make your contribution directly at PSR2_LEVEL, eventually the -relevance debate will take place and your fixer might be pushed to -CONTRIB_LEVEL. - -#### Why am I asked to use `getPrevMeaningfulToken()` instead of `getPrevNonWhitespace()`? - -The main difference is that `getPrevNonWhitespace()` ignores only -whitespaces (`T_WHITESPACE`), while `getPrevMeaningfulToken()` ignores -whitespaces and comments. And usually that is what you want. For -example: - -```php -$a->/*comment*/func(); -``` - -If you are inspecting `func()`, and you want to check whether this is -part of an object, if you use `getPrevNonWhitespace()` you are going to -get `/*comment*/`, which might belie your test. On the other hand, if -you use `getPrevMeaningfulToken()`, no matter if you have got a comment -or a whitespace, the returned token will always be `->`. diff --git a/vendor/friendsofphp/php-cs-fixer/LICENSE b/vendor/friendsofphp/php-cs-fixer/LICENSE index ed5ba0a..40c3bc3 100644 --- a/vendor/friendsofphp/php-cs-fixer/LICENSE +++ b/vendor/friendsofphp/php-cs-fixer/LICENSE @@ -1,5 +1,4 @@ -Copyright (c) 2012-2016 Fabien Potencier - Dariusz Rumiński +Copyright (c) 2012-2021 Fabien Potencier, Dariusz Rumiński Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/friendsofphp/php-cs-fixer/README.md b/vendor/friendsofphp/php-cs-fixer/README.md new file mode 100644 index 0000000..ea45c0c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/README.md @@ -0,0 +1,75 @@ +

+ + PHP CS Fixer logo + +

+ +PHP Coding Standards Fixer +========================== + +The PHP Coding Standards Fixer (PHP CS Fixer) tool fixes your code to follow standards; +whether you want to follow PHP coding standards as defined in the PSR-1, PSR-2, etc., +or other community driven ones like the Symfony one. +You can **also** define your (team's) style through configuration. + +It can modernize your code (like converting the ``pow`` function to the ``**`` operator on PHP 5.6) +and (micro) optimize it. + +If you are already using a linter to identify coding standards problems in your +code, you know that fixing them by hand is tedious, especially on large +projects. This tool does not only detect them, but also fixes them for you. + +## Documentation + +### Installation + +The recommended way to install PHP CS Fixer is to use [Composer](https://getcomposer.org/download/) +in a dedicated `composer.json` file in your project, for example in the +`tools/php-cs-fixer` directory: + +```console +$ mkdir --parents tools/php-cs-fixer +$ composer require --working-dir=tools/php-cs-fixer friendsofphp/php-cs-fixer +``` + +For more details and other installation methods, see +[installation instructions](./doc/installation.rst). + +### Usage + +Assuming you installed PHP CS Fixer as instructed above, you can run the +following command to fix the files PHP files in the `src` directory: + +```console +$ tools/php-cs-fixer/vendor/bin/php-cs-fixer fix src +``` + +See [usage](./doc/usage.rst), list of [built-in rules](./doc/rules/index.rst), list of [rule sets](./doc/ruleSets/index.rst) +and [configuration file](./doc/config.rst) documentation for more details. + +If you need to apply code styles that are not supported by the tool, you can +[create custom rules](./doc/custom_rules.rst). + +## Editor Integration + +Dedicated plugins exist for: + +* [Atom](https://github.com/Glavin001/atom-beautify) +* [NetBeans](https://plugins.netbeans.apache.org/catalogue/?id=36) +* [PhpStorm](https://medium.com/@valeryan/how-to-configure-phpstorm-to-use-php-cs-fixer-1844991e521f) +* [Sublime Text](https://github.com/benmatselby/sublime-phpcs) +* [Vim](https://github.com/stephpy/vim-php-cs-fixer) +* [VS Code](https://github.com/junstyle/vscode-php-cs-fixer) + +## Community + +The PHP CS Fixer is maintained on GitHub at https://github.com/FriendsOfPHP/PHP-CS-Fixer. +Bug reports and ideas about new features are welcome there. + +You can reach us at https://gitter.im/PHP-CS-Fixer/Lobby about the project, +configuration, possible improvements, ideas and questions, please visit us! + +## Contribute + +The tool comes with quite a few built-in fixers, but everyone is more than +welcome to [contribute](CONTRIBUTING.md) more of them. diff --git a/vendor/friendsofphp/php-cs-fixer/README.rst b/vendor/friendsofphp/php-cs-fixer/README.rst deleted file mode 100644 index b42b3d6..0000000 --- a/vendor/friendsofphp/php-cs-fixer/README.rst +++ /dev/null @@ -1,753 +0,0 @@ -PHP Coding Standards Fixer -========================== - -The PHP Coding Standards Fixer tool fixes *most* issues in your code when you -want to follow the PHP coding standards as defined in the PSR-1 and PSR-2 -documents and many more. - -If you are already using a linter to identify coding standards problems in your -code, you know that fixing them by hand is tedious, especially on large -projects. This tool does not only detect them, but also fixes them for you. - -Requirements ------------- - -PHP needs to be a minimum version of PHP 5.3.6. - -Installation ------------- - -Locally -~~~~~~~ - -Download the `php-cs-fixer.phar`_ file and store it somewhere on your computer. - -Globally (manual) -~~~~~~~~~~~~~~~~~ - -You can run these commands to easily access ``php-cs-fixer`` from anywhere on -your system: - -.. code-block:: bash - - $ wget https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v1.13.3/php-cs-fixer.phar -O php-cs-fixer - -or with curl: - -.. code-block:: bash - - $ curl -L https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v1.13.3/php-cs-fixer.phar -o php-cs-fixer - -then: - -.. code-block:: bash - - $ sudo chmod a+x php-cs-fixer - $ sudo mv php-cs-fixer /usr/local/bin/php-cs-fixer - -Then, just run ``php-cs-fixer``. - -Globally (Composer) -~~~~~~~~~~~~~~~~~~~ - -To install PHP CS Fixer, install Composer and issue the following command: - -.. code-block:: bash - - $ ./composer.phar global require friendsofphp/php-cs-fixer - -Please be aware that before v1.12 package name was different: - -.. code-block:: bash - - $ ./composer.phar global require fabpot/php-cs-fixer - -Then make sure you have ``~/.composer/vendor/bin`` in your ``PATH`` and -you're good to go: - -.. code-block:: bash - - $ export PATH="$PATH:$HOME/.composer/vendor/bin" - -Globally (homebrew) -~~~~~~~~~~~~~~~~~~~ - -PHP-CS-Fixer is part of the homebrew-php project. Follow the installation -instructions at https://github.com/homebrew/homebrew-php if you don't -already have it. - -.. code-block:: bash - - $ brew install homebrew/php/php-cs-fixer - -Update ------- - -Locally -~~~~~~~ - -The ``self-update`` command tries to update ``php-cs-fixer`` itself: - -.. code-block:: bash - - $ php php-cs-fixer.phar self-update - -Globally (manual) -~~~~~~~~~~~~~~~~~ - -You can update ``php-cs-fixer`` through this command: - -.. code-block:: bash - - $ sudo php-cs-fixer self-update - -Globally (Composer) -~~~~~~~~~~~~~~~~~~~ - -You can update ``php-cs-fixer`` through this command: - -.. code-block:: bash - - $ ./composer.phar global update friendsofphp/php-cs-fixer - -Globally (homebrew) -~~~~~~~~~~~~~~~~~~~ - -You can update ``php-cs-fixer`` through this command: - -.. code-block:: bash - - $ brew upgrade php-cs-fixer - -Usage ------ - -The ``fix`` command tries to fix as much coding standards -problems as possible on a given file or files in a given directory and its subdirectories: - -.. code-block:: bash - - $ php php-cs-fixer.phar fix /path/to/dir - $ php php-cs-fixer.phar fix /path/to/file - -The ``--format`` option for the output format. Supported formats are ``txt`` (default one), ``json`` and ``xml``. - -The ``--verbose`` option will show the applied fixers. When using the ``txt`` format it will also displays progress notifications. - -The ``--level`` option limits the fixers to apply on the -project: - -.. code-block:: bash - - $ php php-cs-fixer.phar fix /path/to/project --level=psr0 - $ php php-cs-fixer.phar fix /path/to/project --level=psr1 - $ php php-cs-fixer.phar fix /path/to/project --level=psr2 - $ php php-cs-fixer.phar fix /path/to/project --level=symfony - -By default, all PSR-2 fixers and some additional ones are run. The "contrib -level" fixers cannot be enabled via this option; you should instead set them -manually by their name via the ``--fixers`` option. - -The ``--fixers`` option lets you choose the exact fixers to -apply (the fixer names must be separated by a comma): - -.. code-block:: bash - - $ php php-cs-fixer.phar fix /path/to/dir --fixers=linefeed,short_tag,indentation - -You can also blacklist the fixers you don't want by placing a dash in front of the fixer name, if this is more convenient, -using ``-name_of_fixer``: - -.. code-block:: bash - - $ php php-cs-fixer.phar fix /path/to/dir --fixers=-short_tag,-indentation - -When using combination with exact and blacklist fixers, apply exact fixers along with above blacklisted result: - -.. code-block:: bash - - $ php php-cs-fixer.phar fix /path/to/dir --fixers=linefeed,-short_tag - -A combination of ``--dry-run`` and ``--diff`` will -display summary of proposed fixes, leaving your files unchanged. - -The command can also read from standard input, in which case it won't -automatically fix anything: - -.. code-block:: bash - - $ cat foo.php | php php-cs-fixer.phar fix --diff - - -Choose from the list of available fixers: - -* **psr0** [PSR-0] - Classes must be in a path that matches their namespace, be at least one - namespace deep, and the class name should match the file name. - -* **encoding** [PSR-1] - PHP code MUST use only UTF-8 without BOM (remove BOM). - -* **short_tag** [PSR-1] - PHP code must use the long tags or the short-echo tags; - it must not use the other tag variations. - -* **braces** [PSR-2] - The body of each structure MUST be enclosed by braces. Braces should be - properly placed. Body of braces should be properly indented. - -* **class_definition** [PSR-2] - Whitespace around the key words of a class, trait or interfaces - definition should be one space. - -* **elseif** [PSR-2] - The keyword elseif should be used instead of else if so that all control - keywords looks like single words. - -* **eof_ending** [PSR-2] - A file must always end with a single empty line feed. - -* **function_call_space** [PSR-2] - When making a method or function call, there MUST NOT be a space between - the method or function name and the opening parenthesis. - -* **function_declaration** [PSR-2] - Spaces should be properly placed in a function declaration. - -* **indentation** [PSR-2] - Code MUST use an indent of 4 spaces, and MUST NOT use tabs for - indenting. - -* **line_after_namespace** [PSR-2] - There MUST be one blank line after the namespace declaration. - -* **linefeed** [PSR-2] - All PHP files must use the Unix LF (linefeed) line ending. - -* **lowercase_constants** [PSR-2] - The PHP constants true, false, and null MUST be in lower case. - -* **lowercase_keywords** [PSR-2] - PHP keywords MUST be in lower case. - -* **method_argument_space** [PSR-2] - In method arguments and method call, there MUST NOT be a space before - each comma and there MUST be one space after each comma. - -* **multiple_use** [PSR-2] - There MUST be one use keyword per declaration. - -* **no_trailing_whitespace_in_comment** [PSR-2] - There MUST be no trailing spaces inside comments and phpdocs. - -* **parenthesis** [PSR-2] - There MUST NOT be a space after the opening parenthesis. There MUST NOT - be a space before the closing parenthesis. - -* **php_closing_tag** [PSR-2] - The closing ?> tag MUST be omitted from files containing only PHP. - -* **single_line_after_imports** [PSR-2] - Each namespace use MUST go on its own line and there MUST be one blank - line after the use statements block. - -* **switch_case_semicolon_to_colon** [PSR-2] - A case should be followed by a colon and not a semicolon. - -* **switch_case_space** [PSR-2] - Removes extra spaces between colon and case value. - -* **trailing_spaces** [PSR-2] - Remove trailing whitespace at the end of non-blank lines. - -* **visibility** [PSR-2] - Visibility MUST be declared on all properties and methods; abstract and - final MUST be declared before the visibility; static MUST be declared - after the visibility. - -* **array_element_no_space_before_comma** [symfony] - In array declaration, there MUST NOT be a whitespace before each comma. - -* **array_element_white_space_after_comma** [symfony] - In array declaration, there MUST be a whitespace after each comma. - -* **blankline_after_open_tag** [symfony] - Ensure there is no code on the same line as the PHP open tag and it is - followed by a blankline. - -* **concat_without_spaces** [symfony] - Concatenation should be used without spaces. - -* **declare_equal_normalize** [symfony] - Equal sign in declare statement should not be surrounded by spaces. - -* **double_arrow_multiline_whitespaces** [symfony] - Operator => should not be surrounded by multi-line whitespaces. - -* **duplicate_semicolon** [symfony] - Remove duplicated semicolons. - -* **extra_empty_lines** [symfony] - Removes extra empty lines. - -* **function_typehint_space** [symfony] - Add missing space between function's argument and its typehint. - -* **hash_to_slash_comment** [symfony] - Single line comments should use double slashes (//) and not hash (#). - -* **heredoc_to_nowdoc** [symfony] - Convert heredoc to nowdoc if possible. - -* **include** [symfony] - Include/Require and file path should be divided with a single space. - File path should not be placed under brackets. - -* **join_function** [symfony] - Implode function should be used instead of join function. - -* **list_commas** [symfony] - Remove trailing commas in list function calls. - -* **lowercase_cast** [symfony] - Cast should be written in lower case. - -* **method_argument_default_value** [symfony] - In method arguments there must not be arguments with default values - before non-default ones. - -* **multiline_array_trailing_comma** [symfony] - PHP multi-line arrays should have a trailing comma. - -* **namespace_no_leading_whitespace** [symfony] - The namespace declaration line shouldn't contain leading whitespace. - -* **native_function_casing** [symfony] - Function defined by PHP should be called using the correct casing. - -* **new_with_braces** [symfony] - All instances created with new keyword must be followed by braces. - -* **no_blank_lines_after_class_opening** [symfony] - There should be no empty lines after class opening brace. - -* **no_empty_comment** [symfony] - There should not be an empty comments. - -* **no_empty_lines_after_phpdocs** [symfony] - There should not be blank lines between docblock and the documented - element. - -* **no_empty_phpdoc** [symfony] - There should not be empty PHPDoc blocks. - -* **no_empty_statement** [symfony] - Remove useless semicolon statements. - -* **object_operator** [symfony] - There should not be space before or after object T_OBJECT_OPERATOR. - -* **operators_spaces** [symfony] - Binary operators should be surrounded by at least one space. - -* **php_unit_fqcn_annotation** [symfony] - PHPUnit annotations should be a FQCNs including a root namespace. - -* **phpdoc_annotation_without_dot** [symfony] - Phpdocs annotation descriptions should not end with a full stop. - -* **phpdoc_indent** [symfony] - Docblocks should have the same indentation as the documented subject. - -* **phpdoc_inline_tag** [symfony] - Fix phpdoc inline tags, make inheritdoc always inline. - -* **phpdoc_no_access** [symfony] - @access annotations should be omitted from phpdocs. - -* **phpdoc_no_empty_return** [symfony] - @return void and @return null annotations should be omitted from - phpdocs. - -* **phpdoc_no_package** [symfony] - @package and @subpackage annotations should be omitted from phpdocs. - -* **phpdoc_params** [symfony] - All items of the @param, @throws, @return, @var, and @type phpdoc tags - must be aligned vertically. - -* **phpdoc_scalar** [symfony] - Scalar types should always be written in the same form. "int", not - "integer"; "bool", not "boolean"; "float", not "real" or "double". - -* **phpdoc_separation** [symfony] - Annotations in phpdocs should be grouped together so that annotations of - the same type immediately follow each other, and annotations of a - different type are separated by a single blank line. - -* **phpdoc_short_description** [symfony] - Phpdocs short descriptions should end in either a full stop, exclamation - mark, or question mark. - -* **phpdoc_single_line_var_spacing** [symfony] - Single line @var PHPDoc should have proper spacing. - -* **phpdoc_to_comment** [symfony] - Docblocks should only be used on structural elements. - -* **phpdoc_trim** [symfony] - Phpdocs should start and end with content, excluding the very first and - last line of the docblocks. - -* **phpdoc_type_to_var** [symfony] - @type should always be written as @var. - -* **phpdoc_types** [symfony] - The correct case must be used for standard PHP types in phpdoc. - -* **phpdoc_var_without_name** [symfony] - @var and @type annotations should not contain the variable name. - -* **pre_increment** [symfony] - Pre incrementation/decrementation should be used if possible. - -* **print_to_echo** [symfony] - Converts print language construct to echo if possible. - -* **remove_leading_slash_use** [symfony] - Remove leading slashes in use clauses. - -* **remove_lines_between_uses** [symfony] - Removes line breaks between use statements. - -* **return** [symfony] - An empty line feed should precede a return statement. - -* **self_accessor** [symfony] - Inside a classy element "self" should be preferred to the class name - itself. - -* **short_bool_cast** [symfony] - Short cast bool using double exclamation mark should not be used. - -* **short_scalar_cast** [symfony] - Cast "(boolean)" and "(integer)" should be written as "(bool)" and - "(int)". "(double)" and "(real)" as "(float)". - -* **single_array_no_trailing_comma** [symfony] - PHP single-line arrays should not have trailing comma. - -* **single_blank_line_before_namespace** [symfony] - There should be exactly one blank line before a namespace declaration. - -* **single_quote** [symfony] - Convert double quotes to single quotes for simple strings. - -* **spaces_after_semicolon** [symfony] - Fix whitespace after a semicolon. - -* **spaces_before_semicolon** [symfony] - Single-line whitespace before closing semicolon are prohibited. - -* **spaces_cast** [symfony] - A single space should be between cast and variable. - -* **standardize_not_equal** [symfony] - Replace all <> with !=. - -* **ternary_spaces** [symfony] - Standardize spaces around ternary operator. - -* **trim_array_spaces** [symfony] - Arrays should be formatted like function/method arguments, without - leading or trailing single line space. - -* **unalign_double_arrow** [symfony] - Unalign double arrow symbols. - -* **unalign_equals** [symfony] - Unalign equals symbols. - -* **unary_operators_spaces** [symfony] - Unary operators should be placed adjacent to their operands. - -* **unneeded_control_parentheses** [symfony] - Removes unneeded parentheses around control statements. - -* **unused_use** [symfony] - Unused use statements must be removed. - -* **whitespacy_lines** [symfony] - Remove trailing whitespace at the end of blank lines. - -* **align_double_arrow** [contrib] - Align double arrow symbols in consecutive lines. - -* **align_equals** [contrib] - Align equals symbols in consecutive lines. - -* **class_keyword_remove** [contrib] - Converts ::class keywords to FQCN strings. - -* **combine_consecutive_unsets** [contrib] - Calling unset on multiple items should be done in one call. - -* **concat_with_spaces** [contrib] - Concatenation should be used with at least one whitespace around. - -* **echo_to_print** [contrib] - Converts echo language construct to print if possible. - -* **empty_return** [contrib] - A return statement wishing to return nothing should be simply "return". - Warning! This could change code behavior. - -* **ereg_to_preg** [contrib] - Replace deprecated ereg regular expression functions with preg. Warning! - This could change code behavior. - -* **header_comment** [contrib] - Add, replace or remove header comment. - -* **logical_not_operators_with_spaces** [contrib] - Logical NOT operators (!) should have leading and trailing whitespaces. - -* **logical_not_operators_with_successor_space** [contrib] - Logical NOT operators (!) should have one trailing whitespace. - -* **long_array_syntax** [contrib] - Arrays should use the long syntax. - -* **mb_str_functions** [contrib] - Replace non multibyte-safe functions with corresponding mb function. - Warning! This could change code behavior. - -* **multiline_spaces_before_semicolon** [contrib] - Multi-line whitespace before closing semicolon are prohibited. - -* **newline_after_open_tag** [contrib] - Ensure there is no code on the same line as the PHP open tag. - -* **no_blank_lines_before_namespace** [contrib] - There should be no blank lines before a namespace declaration. - -* **no_useless_else** [contrib] - There should not be useless else cases. - -* **no_useless_return** [contrib] - There should not be an empty return statement at the end of a function. - -* **ordered_use** [contrib] - Ordering use statements. - -* **php4_constructor** [contrib] - Convert PHP4-style constructors to __construct. Warning! This could - change code behavior. - -* **php_unit_construct** [contrib] - PHPUnit assertion method calls like "->assertSame(true, $foo)" should be - written with dedicated method like "->assertTrue($foo)". Warning! This - could change code behavior. - -* **php_unit_dedicate_assert** [contrib] - PHPUnit assertions like "assertInternalType", "assertFileExists", should - be used over "assertTrue". Warning! This could change code behavior. - -* **php_unit_strict** [contrib] - PHPUnit methods like "assertSame" should be used instead of - "assertEquals". Warning! This could change code behavior. - -* **phpdoc_order** [contrib] - Annotations in phpdocs should be ordered so that param annotations come - first, then throws annotations, then return annotations. - -* **phpdoc_var_to_type** [contrib] - @var should always be written as @type. - -* **protected_to_private** [contrib] - Converts protected variables and methods to private where possible. - -* **short_array_syntax** [contrib] - PHP arrays should use the PHP 5.4 short-syntax. - -* **short_echo_tag** [contrib] - Replace short-echo exclude('somedir') - ->notPath('src/Symfony/Component/Translation/Tests/fixtures/resources.php') - ->in(__DIR__) - ; - - return Symfony\CS\Config::create() - ->fixers(array('strict_param', 'short_array_syntax')) - ->finder($finder) - ; - -**NOTE**: ``exclude`` will work only for directories, so if you need to exclude file, try ``notPath``. - -See `Symfony\\Finder `_ -online documentation for other `Finder` methods. - -If you want complete control over which fixers you use, you may use the empty level and -then specify all fixers to be used: - -.. code-block:: php - - in(__DIR__) - ; - - return Symfony\CS\Config::create() - ->level(Symfony\CS\FixerInterface::NONE_LEVEL) - ->fixers(array('trailing_spaces', 'encoding')) - ->finder($finder) - ; - -You may also use a blacklist for the Fixers instead of the above shown whitelist approach. -The following example shows how to use all ``symfony`` Fixers but the ``psr0`` fixer. -Note the additional ``-`` in front of the Fixer name. - -.. code-block:: php - - exclude('somedir') - ->in(__DIR__) - ; - - return Symfony\CS\Config::create() - ->fixers(array('-psr0')) - ->finder($finder) - ; - -The ``symfony`` level is set by default, you can also change the default level: - -.. code-block:: php - - level(Symfony\CS\FixerInterface::PSR2_LEVEL) - ; - -In combination with these config and command line options, you can choose various usage. - -For example, default level is ``symfony``, but if you also don't want to use -the ``psr0`` fixer, you can specify the ``--fixers="-psr0"`` option. - -But if you use the ``--fixers`` option with only exact fixers, -only those exact fixers are enabled whether or not level is set. - -With the ``--config-file`` option you can specify the path to the -``.php_cs`` file. - -Caching -------- - -You can enable caching by returning a custom config with caching enabled. This will -speed up further runs. - -.. code-block:: php - - setUsingCache(true) - ; - -Exit codes ----------- -* 0 OK. -* 1 Changes made (or dry-run was used and files need changes) or PHP/HHVM minimal requirement to run the Fixer not match. -* 16 Configuration error of the application. -* 32 Configuration error of a Fixer. - -(applies to exit codes of the `fix` command only) - -Helpers -------- - -Dedicated plugins exist for: - -* `Atom`_ -* `NetBeans`_ -* `PhpStorm`_ -* `Sublime Text`_ -* `Vim`_ - -Contribute ----------- - -The tool comes with quite a few built-in fixers and finders, but everyone is -more than welcome to `contribute`_ more of them. - -Fixers -~~~~~~ - -A *fixer* is a class that tries to fix one CS issue (a ``Fixer`` class must -implement ``FixerInterface``). - -Configs -~~~~~~~ - -A *config* knows about the CS level and the files and directories that must be -scanned by the tool when run in the directory of your project. It is useful for -projects that follow a well-known directory structures (like for Symfony -projects for instance). - -.. _php-cs-fixer.phar: https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v1.13.3/php-cs-fixer.phar -.. _Atom: https://github.com/Glavin001/atom-beautify -.. _NetBeans: http://plugins.netbeans.org/plugin/49042/php-cs-fixer -.. _PhpStorm: http://tzfrs.de/2015/01/automatically-format-code-to-match-psr-standards-with-phpstorm -.. _Sublime Text: https://github.com/benmatselby/sublime-phpcs -.. _Vim: https://github.com/stephpy/vim-php-cs-fixer -.. _contribute: https://github.com/FriendsOfPhp/php-cs-fixer/blob/master/CONTRIBUTING.md diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractAnnotationRemovalFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractAnnotationRemovalFixer.php deleted file mode 100644 index f3d51a6..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractAnnotationRemovalFixer.php +++ /dev/null @@ -1,61 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -abstract class AbstractAnnotationRemovalFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function getPriority() - { - // must be run before the PhpdocSeparationFixer, PhpdocOrderFixer, - // PhpdocTrimFixer and PhpdocNoEmptyReturnFixer. - return 10; - } - - /** - * Make sure the expected number of new lines prefix a namespace. - * - * @param Tokens $tokens - * @param string[] $type - */ - protected function removeAnnotations(Tokens $tokens, array $type) - { - foreach ($tokens as $token) { - if (!$token->isGivenKind(T_DOC_COMMENT)) { - continue; - } - - $doc = new DocBlock($token->getContent()); - $annotations = $doc->getAnnotationsOfType($type); - - // nothing to do if there are no annotations - if (empty($annotations)) { - continue; - } - - foreach ($annotations as $annotation) { - $annotation->remove(); - } - - $token->setContent($doc->getContent()); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractFixer.php deleted file mode 100644 index 3edb46a..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractFixer.php +++ /dev/null @@ -1,68 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -/** - * @author Dariusz Rumiński - */ -abstract class AbstractFixer implements FixerInterface -{ - /** - * {@inheritdoc} - */ - public function getLevel() - { - static $map = array( - 'PSR0' => FixerInterface::PSR0_LEVEL, - 'PSR1' => FixerInterface::PSR1_LEVEL, - 'PSR2' => FixerInterface::PSR2_LEVEL, - 'Symfony' => FixerInterface::SYMFONY_LEVEL, - 'Contrib' => FixerInterface::CONTRIB_LEVEL, - ); - - $level = current(explode('\\', substr(get_called_class(), strlen(__NAMESPACE__.'\\Fixer\\')))); - - if (!isset($map[$level])) { - throw new \LogicException('Can not determine Fixer level'); - } - - return $map[$level]; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - $nameParts = explode('\\', get_called_class()); - $name = substr(end($nameParts), 0, -strlen('Fixer')); - - return Utils::camelCaseToUnderscore($name); - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - return 0; - } - - /** - * {@inheritdoc} - */ - public function supports(\SplFileInfo $file) - { - return true; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractLinesBeforeNamespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractLinesBeforeNamespaceFixer.php deleted file mode 100644 index bdd9571..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractLinesBeforeNamespaceFixer.php +++ /dev/null @@ -1,51 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -use Symfony\CS\Tokenizer\Tokens; - -/** - * This abstract fixer is responsible for ensuring that a certain number of - * lines prefix a namespace declaration. - * - * @author Graham Campbell - */ -abstract class AbstractLinesBeforeNamespaceFixer extends AbstractFixer -{ - /** - * Make sure the expected number of new lines prefix a namespace. - * - * @param Tokens $tokens - * @param int $index - * @param int $expected - */ - protected function fixLinesBeforeNamespace(Tokens $tokens, $index, $expected) - { - // if we've got a isGivenKind(T_OPEN_TAG)) { - $expected -= substr_count($opening->getContent(), "\n"); - } - } - - $previous = $tokens[$index - 1]; - if ($previous->isWhitespace()) { - $content = $previous->getContent(); - if (substr_count($content, "\n") !== $expected) { - $previous->setContent(str_repeat("\n", $expected)); - } - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config.php deleted file mode 100644 index 59385d9..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config.php +++ /dev/null @@ -1,188 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -use Symfony\CS\Finder\DefaultFinder; - -/** - * @author Fabien Potencier - * @author Katsuhiro Ogawa - */ -class Config implements ConfigInterface -{ - protected $name; - protected $description; - protected $finder; - protected $level; - protected $fixers; - protected $dir; - protected $customFixers; - protected $usingCache = false; - protected $usingLinter = true; - protected $hideProgress = false; - - public function __construct($name = 'default', $description = 'A default configuration') - { - $this->name = $name; - $this->description = $description; - $this->level = FixerInterface::SYMFONY_LEVEL; - $this->fixers = array(); - $this->finder = new DefaultFinder(); - $this->customFixers = array(); - } - - public static function create() - { - return new static(); - } - - public function setDir($dir) - { - @trigger_error( - sprintf( - 'The "%s" method is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Configure finder instead.', - __METHOD__ - ), - E_USER_DEPRECATED - ); - - $this->dir = $dir; - } - - public function setUsingCache($usingCache) - { - $this->usingCache = $usingCache; - - return $this; - } - - public function setUsingLinter($usingLinter) - { - $this->usingLinter = $usingLinter; - - return $this; - } - - public function getDir() - { - @trigger_error( - sprintf( - 'The "%s" method is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use finder instead.', - __METHOD__ - ), - E_USER_DEPRECATED - ); - - return $this->dir; - } - - public function finder(\Traversable $finder) - { - $this->finder = $finder; - - return $this; - } - - public function getFinder() - { - if ($this->finder instanceof FinderInterface && $this->dir !== null) { - $this->finder->setDir($this->dir); - } - - return $this->finder; - } - - public function level($level) - { - $this->level = $level; - - return $this; - } - - public function getLevel() - { - return $this->level; - } - - public function fixers($fixers) - { - $this->fixers = $fixers; - - return $this; - } - - public function getFixers() - { - return $this->fixers; - } - - public function getName() - { - return $this->name; - } - - public function getDescription() - { - return $this->description; - } - - public function getHideProgress() - { - return $this->hideProgress; - } - - public function addCustomFixer(FixerInterface $fixer) - { - $this->customFixers[] = $fixer; - - return $this; - } - - public function addCustomFixers($fixers) - { - if (false === is_array($fixers) && false === $fixers instanceof \Traversable) { - throw new \InvalidArgumentException(sprintf( - 'Argument must be an array or a Traversable, got "%s".', - is_object($fixers) ? get_class($fixers) : gettype($fixers) - )); - } - - foreach ($fixers as $fixer) { - $this->addCustomFixer($fixer); - } - - return $this; - } - - public function getCustomFixers() - { - return $this->customFixers; - } - - public function hideProgress($hideProgress) - { - $this->hideProgress = $hideProgress; - - return $this; - } - - public function usingCache() - { - return $this->usingCache; - } - - public function usingLinter() - { - return $this->usingLinter; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/Config.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/Config.php deleted file mode 100644 index f158c21..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/Config.php +++ /dev/null @@ -1,38 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Config; - -use Symfony\CS\Config as BaseConfig; - -/** - * @author Fabien Potencier - * @author Katsuhiro Ogawa - * - * @deprecated - */ -class Config extends BaseConfig -{ - public function __construct() - { - @trigger_error( - sprintf( - 'The "%s" class is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "%s" instead.', - __CLASS__, - 'Symfony\CS\Config' - ), - E_USER_DEPRECATED - ); - - parent::__construct(); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/MagentoConfig.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/MagentoConfig.php deleted file mode 100644 index 0b9073b..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/MagentoConfig.php +++ /dev/null @@ -1,49 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Config; - -use Symfony\CS\Finder\MagentoFinder; - -/** - * @author Myke Hines - * - * @deprecated - */ -class MagentoConfig extends Config -{ - public function __construct() - { - @trigger_error( - sprintf( - 'The "%s" class is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "%s" instead.', - __CLASS__, - 'Symfony\CS\Config' - ), - E_USER_DEPRECATED - ); - - parent::__construct(); - - $this->finder = new MagentoFinder(); - } - - public function getName() - { - return 'magento'; - } - - public function getDescription() - { - return 'The configuration for a Magento application'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/Symfony23Config.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/Symfony23Config.php deleted file mode 100644 index 573f067..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Config/Symfony23Config.php +++ /dev/null @@ -1,49 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Config; - -use Symfony\CS\Finder\Symfony23Finder; - -/** - * @author Fabien Potencier - * - * @deprecated - */ -class Symfony23Config extends Config -{ - public function __construct() - { - @trigger_error( - sprintf( - 'The "%s" class is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "%s" instead.', - __CLASS__, - 'Symfony\CS\Config' - ), - E_USER_DEPRECATED - ); - - parent::__construct(); - - $this->finder = new Symfony23Finder(); - } - - public function getName() - { - return 'sf23'; - } - - public function getDescription() - { - return 'The configuration for the Symfony 2.3+ branch'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigInterface.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigInterface.php deleted file mode 100644 index c4844cb..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigInterface.php +++ /dev/null @@ -1,86 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -/** - * @author Fabien Potencier - */ -interface ConfigInterface -{ - /** - * Returns the name of the configuration. - * - * The name must be all lowercase and without any spaces. - * - * @return string The name of the configuration - */ - public function getName(); - - /** - * Returns the description of the configuration. - * - * A short one-line description for the configuration. - * - * @return string The description of the configuration - */ - public function getDescription(); - - /** - * Returns an iterator of files to scan. - * - * @return \Traversable A \Traversable instance that returns \SplFileInfo instances - */ - public function getFinder(); - - /** - * Returns the level to run. - * - * @return int A level - */ - public function getLevel(); - - /** - * Returns the fixers to run. - * - * @return array A list of fixer names - */ - public function getFixers(); - - /** - * Sets the root directory of the project. - * - * @param string $dir The project root directory - */ - public function setDir($dir); - - /** - * Returns the root directory of the project. - * - * @return string The project root directory - */ - public function getDir(); - - /** - * Adds an instance of a custom fixer. - * - * @param FixerInterface $fixer - */ - public function addCustomFixer(FixerInterface $fixer); - - /** - * Returns the custom fixers to use. - * - * @return FixerInterface[] - */ - public function getCustomFixers(); -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationException/InvalidConfigurationException.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationException/InvalidConfigurationException.php deleted file mode 100644 index 23b9f21..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationException/InvalidConfigurationException.php +++ /dev/null @@ -1,34 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\ConfigurationException; - -use Symfony\CS\Console\Command\FixCommand; - -/** - * Exceptions of this type are thrown on misconfiguration of the Fixer. - * - * @author SpacePossum - * - * @internal - */ -class InvalidConfigurationException extends \InvalidArgumentException -{ - /** - * @param string $message - * @param int|null $code - */ - public function __construct($message, $code = null) - { - parent::__construct($message, null === $code ? FixCommand::EXIT_STATUS_FLAG_HAS_INVALID_CONFIG : $code); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationException/InvalidFixerConfigurationException.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationException/InvalidFixerConfigurationException.php deleted file mode 100644 index 75fc787..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationException/InvalidFixerConfigurationException.php +++ /dev/null @@ -1,34 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\ConfigurationException; - -use Symfony\CS\Console\Command\FixCommand; - -/** - * Exception thrown by Fixers on misconfiguration. - * - * @author SpacePossum - * - * @internal - */ -class InvalidFixerConfigurationException extends InvalidConfigurationException -{ - /** - * @param string $fixerName - * @param string $message - */ - public function __construct($fixerName, $message) - { - parent::__construct(sprintf('[%s] %s', $fixerName, $message), FixCommand::EXIT_STATUS_FLAG_HAS_INVALID_FIXER_CONFIG); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationResolver.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationResolver.php deleted file mode 100644 index 8e7983d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigurationResolver.php +++ /dev/null @@ -1,239 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -use Symfony\CS\ConfigurationException\InvalidConfigurationException; - -/** - * The resolver that resolves configuration to use by command line options and config. - * - * @author Fabien Potencier - * @author Katsuhiro Ogawa - * @author Dariusz Rumiński - */ -class ConfigurationResolver -{ - /** - * @var FixerInterface[] - */ - protected $allFixers; - - /** - * @var ConfigInterface - */ - protected $config; - - /** - * @var FixerInterface[] - */ - protected $fixers = array(); - - /** - * @var array - */ - protected $options = array( - 'fixers' => null, - 'level' => null, - 'progress' => null, - ); - - /** - * @var string - */ - private $format; - - public function setAllFixers(array $allFixers) - { - $this->allFixers = $allFixers; - - return $this; - } - - public function setConfig(ConfigInterface $config) - { - $this->config = $config; - - return $this; - } - - public function setOption($name, $value) - { - $this->options[$name] = $value; - - return $this; - } - - public function setOptions(array $options) - { - foreach ($options as $name => $value) { - $this->setOption($name, $value); - } - - return $this; - } - - /** - * Resolves fixers. - * - * @return ConfigurationResolver - */ - public function resolve() - { - $this->resolveByLevel(); - $this->resolveByNames(); - $this->resolveFormat(); - - return $this; - } - - /** - * Returns fixers. - * - * @return FixerInterface[] An array of FixerInterface - */ - public function getFixers() - { - return $this->fixers; - } - - /** - * Returns output format. - * - * @return string - */ - public function getFormat() - { - return $this->format; - } - - public function getProgress() - { - // TODO: following condition should be removed on 2.0 line - // and method should be added to ConfigInterface - if (!method_exists($this->config, 'getHideProgress')) { - return $this->options['progress']; - } - - return $this->options['progress'] && !$this->config->getHideProgress(); - } - - protected function resolveByLevel() - { - $level = $this->parseLevel(); - - if (null === $level) { - return; - } - - $fixers = array(); - - foreach ($this->allFixers as $fixer) { - if ($fixer->getLevel() === ($fixer->getLevel() & $level)) { - $fixers[] = $fixer; - } - } - - $this->fixers = $fixers; - } - - protected function resolveByNames() - { - $names = $this->parseFixers(); - - if (null === $names) { - return; - } - - $addNames = array(); - $removeNames = array(); - foreach ($names as $name) { - if (0 === strpos($name, '-')) { - $removeNames[ltrim($name, '-')] = true; - } else { - $addNames[$name] = true; - } - } - - foreach ($this->fixers as $key => $fixer) { - if (isset($removeNames[$fixer->getName()])) { - unset($this->fixers[$key]); - } - } - - foreach ($this->allFixers as $fixer) { - if (isset($addNames[$fixer->getName()]) && !in_array($fixer, $this->fixers, true)) { - $this->fixers[] = $fixer; - } - } - } - - protected function resolveFormat() - { - if (array_key_exists('format', $this->options)) { - $format = $this->options['format']; - } elseif (method_exists($this->config, 'getFormat')) { - $format = $this->config->getFormat(); - } else { - $format = 'txt'; // default - } - - static $formats = array('txt', 'xml', 'json'); - if (!in_array($format, $formats, true)) { - throw new InvalidConfigurationException(sprintf('The format "%s" is not defined, supported are %s.', $format, implode(', ', $formats))); - } - - $this->format = $format; - } - - protected function parseLevel() - { - static $levelMap = array( - 'none' => FixerInterface::NONE_LEVEL, - 'psr0' => FixerInterface::PSR0_LEVEL, - 'psr1' => FixerInterface::PSR1_LEVEL, - 'psr2' => FixerInterface::PSR2_LEVEL, - 'symfony' => FixerInterface::SYMFONY_LEVEL, - ); - - $levelOption = $this->options['level']; - - if (null !== $levelOption) { - if (!isset($levelMap[$levelOption])) { - throw new InvalidConfigurationException(sprintf('The level "%s" is not defined.', $levelOption)); - } - - return $levelMap[$levelOption]; - } - - if (null === $this->options['fixers']) { - return $this->config->getLevel(); - } - - foreach ($this->parseFixers() as $fixer) { - if (0 === strpos($fixer, '-')) { - return $this->config->getLevel(); - } - } - } - - protected function parseFixers() - { - if (null !== $this->options['fixers']) { - return array_map('trim', explode(',', $this->options['fixers'])); - } - - if (null === $this->options['level']) { - return $this->config->getFixers(); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Application.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Application.php deleted file mode 100644 index 30c082e..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Application.php +++ /dev/null @@ -1,81 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Console; - -use Symfony\Component\Console\Application as BaseApplication; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\CS\Console\Command\FixCommand; -use Symfony\CS\Console\Command\ReadmeCommand; -use Symfony\CS\Console\Command\SelfUpdateCommand; -use Symfony\CS\Fixer; - -/** - * @author Fabien Potencier - */ -class Application extends BaseApplication -{ - /** - * Constructor. - */ - public function __construct() - { - error_reporting(-1); - - parent::__construct('PHP CS Fixer', Fixer::VERSION); - - $this->add(new FixCommand()); - $this->add(new ReadmeCommand()); - $this->add(new SelfUpdateCommand()); - } - - public function getLongVersion() - { - $version = parent::getLongVersion().' by Fabien Potencier and Dariusz Ruminski'; - $commit = '@git-commit@'; - - if ('@'.'git-commit@' !== $commit) { - $version .= ' ('.substr($commit, 0, 7).')'; - } - - return $version; - } - - /** - * {@inheritdoc} - */ - public function doRun(InputInterface $input, OutputInterface $output) - { - $stdErr = $output instanceof ConsoleOutputInterface - ? $output->getErrorOutput() - : ($input->hasParameterOption('--format', true) && 'txt' !== $input->getParameterOption('--format', null, true) ? null : $output) - ; - - if (null !== $stdErr) { - $warningsDetector = new WarningsDetector(); - $warningsDetector->detectOldVendor(); - $warningsDetector->detectOldMajor(); - - if (FixCommand::COMMAND_NAME === $this->getCommandName($input)) { - $warningsDetector->detectXdebug(); - } - - foreach ($warningsDetector->getWarnings() as $warning) { - $stdErr->writeln(sprintf($stdErr->isDecorated() ? '%s' : '%s', $warning)); - } - } - - return parent::doRun($input, $output); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/FixCommand.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/FixCommand.php deleted file mode 100644 index 3fe5d3b..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/FixCommand.php +++ /dev/null @@ -1,649 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Console\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\CS\Config\Config; -use Symfony\CS\ConfigInterface; -use Symfony\CS\ConfigurationException\InvalidConfigurationException; -use Symfony\CS\ConfigurationResolver; -use Symfony\CS\ErrorsManager; -use Symfony\CS\Fixer; -use Symfony\CS\FixerFileProcessedEvent; -use Symfony\CS\FixerInterface; -use Symfony\CS\LintManager; -use Symfony\CS\StdinFileInfo; -use Symfony\CS\Utils; - -/** - * @author Fabien Potencier - * @author Dariusz Rumiński - */ -class FixCommand extends Command -{ - const COMMAND_NAME = 'fix'; - - const EXIT_STATUS_FLAG_HAS_INVALID_CONFIG = 16; - const EXIT_STATUS_FLAG_HAS_INVALID_FIXER_CONFIG = 32; - - /** - * EventDispatcher instance. - * - * @var EventDispatcher - */ - protected $eventDispatcher; - - /** - * ErrorsManager instance. - * - * @var ErrorsManager - */ - protected $errorsManager; - - /** - * Stopwatch instance. - * - * @var Stopwatch - */ - protected $stopwatch; - - /** - * Fixer instance. - * - * @var Fixer - */ - protected $fixer; - - /** - * Config instance. - * - * @var ConfigInterface - */ - protected $defaultConfig; - - /** - * @param Fixer|null $fixer - * @param ConfigInterface|null $config - */ - public function __construct(Fixer $fixer = null, ConfigInterface $config = null) - { - $this->defaultConfig = $config ?: new Config(); - $this->eventDispatcher = new EventDispatcher(); - $this->errorsManager = new ErrorsManager(); - $this->stopwatch = new Stopwatch(); - - $this->fixer = $fixer ?: new Fixer(); - $this->fixer->registerBuiltInFixers(); - $this->fixer->registerBuiltInConfigs(); - $this->fixer->setStopwatch($this->stopwatch); - $this->fixer->setErrorsManager($this->errorsManager); - - parent::__construct(); - } - - /** - * @see Command - */ - protected function configure() - { - $this - ->setName(self::COMMAND_NAME) - ->setDefinition( - array( - new InputArgument('path', InputArgument::OPTIONAL, 'The path', null), - new InputOption('config', '', InputOption::VALUE_REQUIRED, 'The configuration name', null), - new InputOption('config-file', '', InputOption::VALUE_OPTIONAL, 'The path to a .php_cs file ', null), - new InputOption('dry-run', '', InputOption::VALUE_NONE, 'Only shows which files would have been modified'), - new InputOption('level', '', InputOption::VALUE_REQUIRED, 'The level of fixes (can be psr0, psr1, psr2, or symfony (formerly all))', null), - new InputOption('fixers', '', InputOption::VALUE_REQUIRED, 'A list of fixers to run'), - new InputOption('diff', '', InputOption::VALUE_NONE, 'Also produce diff for each file'), - new InputOption('format', '', InputOption::VALUE_REQUIRED, 'To output results in other formats', 'txt'), - ) - ) - ->setDescription('Fixes a directory or a file') - ->setHelp(<<%command.name% command tries to fix as much coding standards -problems as possible on a given file or files in a given directory and its subdirectories: - - $ php %command.full_name% /path/to/dir - $ php %command.full_name% /path/to/file - -The --format option for the output format. Supported formats are ``txt`` (default one), ``json`` and ``xml``. - -The --verbose option will show the applied fixers. When using the ``txt`` format it will also displays progress notifications. - -The --level option limits the fixers to apply on the -project: - - $ php %command.full_name% /path/to/project --level=psr0 - $ php %command.full_name% /path/to/project --level=psr1 - $ php %command.full_name% /path/to/project --level=psr2 - $ php %command.full_name% /path/to/project --level=symfony - -By default, all PSR-2 fixers and some additional ones are run. The "contrib -level" fixers cannot be enabled via this option; you should instead set them -manually by their name via the --fixers option. - -The --fixers option lets you choose the exact fixers to -apply (the fixer names must be separated by a comma): - - $ php %command.full_name% /path/to/dir --fixers=linefeed,short_tag,indentation - -You can also blacklist the fixers you don't want by placing a dash in front of the fixer name, if this is more convenient, -using -name_of_fixer: - - $ php %command.full_name% /path/to/dir --fixers=-short_tag,-indentation - -When using combination with exact and blacklist fixers, apply exact fixers along with above blacklisted result: - - $ php php-cs-fixer.phar fix /path/to/dir --fixers=linefeed,-short_tag - -A combination of --dry-run and --diff will -display summary of proposed fixes, leaving your files unchanged. - -The command can also read from standard input, in which case it won't -automatically fix anything: - - $ cat foo.php | php %command.full_name% --diff - - -Choose from the list of available fixers: - -{$this->getFixersHelp()} - -The --config option customizes the files to analyse, based -on some well-known directory structures: - - # For the Symfony 2.3+ branch - $ php %command.full_name% /path/to/sf23 --config=sf23 - -Choose from the list of available configurations: - -{$this->getConfigsHelp()} -The --dry-run option displays the files that need to be -fixed but without actually modifying them: - - $ php %command.full_name% /path/to/code --dry-run - -Instead of using command line options to customize the fixer, you can save the -configuration in a .php_cs file in the root directory of -your project. The file must return an instance of -``Symfony\CS\ConfigInterface``, which lets you configure the fixers, the level, the files, -and directories that need to be analyzed. The example below will add two contrib fixers -to the default list of symfony-level fixers: - - exclude('somedir') - ->notPath('src/Symfony/Component/Translation/Tests/fixtures/resources.php') - ->in(__DIR__) - ; - - return Symfony\CS\Config::create() - ->fixers(array('strict_param', 'short_array_syntax')) - ->finder(\$finder) - ; - - ?> - -**NOTE**: ``exclude`` will work only for directories, so if you need to exclude file, try ``notPath``. - -See `Symfony\\\\Finder `_ -online documentation for other `Finder` methods. - -If you want complete control over which fixers you use, you may use the empty level and -then specify all fixers to be used: - - in(__DIR__) - ; - - return Symfony\CS\Config::create() - ->level(Symfony\CS\FixerInterface::NONE_LEVEL) - ->fixers(array('trailing_spaces', 'encoding')) - ->finder(\$finder) - ; - - ?> - -You may also use a blacklist for the Fixers instead of the above shown whitelist approach. -The following example shows how to use all ``symfony`` Fixers but the ``psr0`` fixer. -Note the additional - in front of the Fixer name. - - exclude('somedir') - ->in(__DIR__) - ; - - return Symfony\CS\Config::create() - ->fixers(array('-psr0')) - ->finder(\$finder) - ; - - ?> - -The ``symfony`` level is set by default, you can also change the default level: - - level(Symfony\CS\FixerInterface::PSR2_LEVEL) - ; - - ?> - -In combination with these config and command line options, you can choose various usage. - -For example, default level is ``symfony``, but if you also don't want to use -the ``psr0`` fixer, you can specify the ``--fixers="-psr0"`` option. - -But if you use the ``--fixers`` option with only exact fixers, -only those exact fixers are enabled whether or not level is set. - -With the --config-file option you can specify the path to the -.php_cs file. - -Caching -------- - -You can enable caching by returning a custom config with caching enabled. This will -speed up further runs. - - setUsingCache(true) - ; - - ?> - -Exit codes ----------- -* 0 OK. -* 1 Changes made (or dry-run was used and files need changes) or PHP/HHVM minimal requirement to run the Fixer not match. -* 16 Configuration error of the application. -* 32 Configuration error of a Fixer. - -(applies to exit codes of the `fix` command only) -EOF - ); - } - - /** - * @see Command - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - // setup output - $stdErr = $output instanceof ConsoleOutputInterface - ? $output->getErrorOutput() - : ('txt' === $input->getOption('format') ? $output : null) - ; - - $verbosity = $output->getVerbosity(); - - // setup input - $path = $input->getArgument('path'); - - $stdin = false; - - if ('-' === $path) { - $stdin = true; - - // Can't write to STDIN - $input->setOption('dry-run', true); - } - - if (null !== $path) { - $filesystem = new Filesystem(); - if (!$filesystem->isAbsolutePath($path)) { - $path = getcwd().DIRECTORY_SEPARATOR.$path; - } - } - - // setup configuration location - $configFile = $input->getOption('config-file'); - if (null === $configFile) { - $configDir = $path; - - if (is_file($path) && $dirName = pathinfo($path, PATHINFO_DIRNAME)) { - $configDir = $dirName; - } elseif ($stdin || null === $path) { - $configDir = getcwd(); - // path is directory - } - $configFile = $configDir.DIRECTORY_SEPARATOR.'.php_cs'; - } - - if ($input->getOption('config')) { - $config = null; - foreach ($this->fixer->getConfigs() as $c) { - if ($c->getName() === $input->getOption('config')) { - $config = $c; - break; - } - } - - if (null === $config) { - throw new InvalidConfigurationException(sprintf('The configuration "%s" is not defined.', $input->getOption('config'))); - } - } elseif (file_exists($configFile)) { - $config = include $configFile; - // verify that the config has an instance of Config - if (!$config instanceof ConfigInterface) { - throw new InvalidConfigurationException(sprintf('The config file "%s" does not return a "Symfony\CS\ConfigInterface" instance. Got: "%s".', $configFile, is_object($config) ? get_class($config) : gettype($config))); - } - - if (null !== $stdErr && $configFile) { - $stdErr->writeln(sprintf('Loaded config from "%s".', $configFile)); - } - } else { - $config = $this->defaultConfig; - } - - // setup location of source(s) to fix - if (is_file($path)) { - $config->finder(new \ArrayIterator(array(new \SplFileInfo($path)))); - } elseif ($stdin) { - $config->finder(new \ArrayIterator(array(new StdinFileInfo()))); - } elseif (null !== $path) { - $config->setDir($path); - } - - // setup Linter - if ($config->usingLinter()) { - $this->fixer->setLintManager(new LintManager()); - } - - // register custom fixers from config - $this->fixer->registerCustomFixers($config->getCustomFixers()); - - $resolver = new ConfigurationResolver(); - $resolver - ->setAllFixers($this->fixer->getFixers()) - ->setConfig($config) - ->setOptions(array( - 'level' => $input->getOption('level'), - 'fixers' => $input->getOption('fixers'), - 'progress' => (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) && 'txt' === $input->getOption('format'), - 'format' => $input->getOption('format'), - )) - ->resolve(); - - $config->fixers($resolver->getFixers()); - $showProgress = null !== $stdErr && $resolver->getProgress(); - - if ($showProgress) { - $fileProcessedEventListener = function (FixerFileProcessedEvent $event) use ($stdErr) { - $stdErr->write($event->getStatusAsString()); - }; - - $this->fixer->setEventDispatcher($this->eventDispatcher); - $this->eventDispatcher->addListener(FixerFileProcessedEvent::NAME, $fileProcessedEventListener); - } - - $isDiff = $input->getOption('diff'); - $this->stopwatch->start('fixFiles'); - $changed = $this->fixer->fix($config, $input->getOption('dry-run'), $isDiff); - $this->stopwatch->stop('fixFiles'); - - if ($showProgress) { - $this->fixer->setEventDispatcher(null); - $this->eventDispatcher->removeListener(FixerFileProcessedEvent::NAME, $fileProcessedEventListener); - $stdErr->writeln(''); - - $legend = array(); - foreach (FixerFileProcessedEvent::getStatusMap() as $status) { - if ($status['symbol'] && $status['description']) { - $legend[] = $status['symbol'].'-'.$status['description']; - } - } - - $stdErr->writeln('Legend: '.implode(', ', array_unique($legend))); - } - - $i = 1; - - switch ($resolver->getFormat()) { - case 'txt': - - $fixerDetailLine = false; - if (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) { - $fixerDetailLine = $output->isDecorated() ? ' (%s)' : ' %s'; - } - - foreach ($changed as $file => $fixResult) { - $output->write(sprintf('%4d) %s', $i++, $file)); - - if ($fixerDetailLine) { - $output->write(sprintf($fixerDetailLine, implode(', ', $fixResult['appliedFixers']))); - } - - if ($isDiff) { - $output->writeln(''); - $output->writeln(' ---------- begin diff ----------'); - - if ($output->isDecorated()) { - $diff = implode( - PHP_EOL, - array_map( - function ($string) { - $string = preg_replace('/^(\+){3}/', '+++', $string); - $string = preg_replace('/^(\+){1}/', '+', $string); - $string = preg_replace('/^(\-){3}/', '---', $string); - $string = preg_replace('/^(\-){1}/', '-', $string); - $string = str_repeat(' ', 6).$string; - - return $string; - }, - explode(PHP_EOL, OutputFormatter::escape($fixResult['diff'])) - ) - ); - - $output->writeln($diff); - } else { - $output->writeln($fixResult['diff'], OutputInterface::OUTPUT_RAW); - } - - $output->writeln(' ---------- end diff ----------'); - } - - $output->writeln(''); - } - - if (OutputInterface::VERBOSITY_DEBUG <= $verbosity) { - $output->writeln('Fixing time per file:'); - - foreach ($this->stopwatch->getSectionEvents('fixFile') as $file => $event) { - if ('__section__' === $file) { - continue; - } - - $output->writeln(sprintf('[%.3f s] %s', $event->getDuration() / 1000, $file)); - } - - $output->writeln(''); - } - - $fixEvent = $this->stopwatch->getEvent('fixFiles'); - $output->writeln(sprintf('%s all files in %.3f seconds, %.3f MB memory used', $input->getOption('dry-run') ? 'Checked' : 'Fixed', $fixEvent->getDuration() / 1000, $fixEvent->getMemory() / 1024 / 1024)); - break; - case 'xml': - $dom = new \DOMDocument('1.0', 'UTF-8'); - $filesXML = $dom->createElement('files'); - $dom->appendChild($filesXML); - - foreach ($changed as $file => $fixResult) { - $fileXML = $dom->createElement('file'); - $fileXML->setAttribute('id', $i++); - $fileXML->setAttribute('name', $file); - $filesXML->appendChild($fileXML); - - if (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) { - $appliedFixersXML = $dom->createElement('applied_fixers'); - $fileXML->appendChild($appliedFixersXML); - - foreach ($fixResult['appliedFixers'] as $appliedFixer) { - $appliedFixerXML = $dom->createElement('applied_fixer'); - $appliedFixerXML->setAttribute('name', $appliedFixer); - $appliedFixersXML->appendChild($appliedFixerXML); - } - } - - if ($isDiff) { - $diffXML = $dom->createElement('diff'); - $diffXML->appendChild($dom->createCDATASection($fixResult['diff'])); - $fileXML->appendChild($diffXML); - } - } - - $dom->formatOutput = true; - $output->write($dom->saveXML(), false, OutputInterface::OUTPUT_RAW); - break; - case 'json': - $jFiles = array(); - - foreach ($changed as $file => $fixResult) { - $jfile = array('name' => $file); - - if (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) { - $jfile['appliedFixers'] = $fixResult['appliedFixers']; - } - - if ($isDiff) { - $jfile['diff'] = $fixResult['diff']; - } - - $jFiles[] = $jfile; - } - - $fixEvent = $this->stopwatch->getEvent('fixFiles'); - - $json = array( - 'files' => $jFiles, - 'memory' => round($fixEvent->getMemory() / 1024 / 1024, 3), - 'time' => array( - 'total' => round($fixEvent->getDuration() / 1000, 3), - ), - ); - - if (OutputInterface::VERBOSITY_DEBUG <= $verbosity) { - $jFileTime = array(); - - foreach ($this->stopwatch->getSectionEvents('fixFile') as $file => $event) { - if ('__section__' === $file) { - continue; - } - - $jFileTime[$file] = round($event->getDuration() / 1000, 3); - } - - $json['time']['files'] = $jFileTime; - } - - $output->write(json_encode($json), false, OutputInterface::OUTPUT_RAW); - break; - } - - if (null !== $stdErr && !$this->errorsManager->isEmpty()) { - $stdErr->writeln(''); - $stdErr->writeln('Files that were not fixed due to internal error:'); - - foreach ($this->errorsManager->getErrors() as $i => $error) { - $stdErr->writeln(sprintf('%4d) %s', $i + 1, $error['filepath'])); - } - } - - return 0 === count($changed) ? 0 : 1; - } - - protected function getFixersHelp() - { - $help = ''; - $fixers = $this->fixer->getFixers(); - - // sort fixers by level and name - usort( - $fixers, - function (FixerInterface $a, FixerInterface $b) { - $cmp = Utils::cmpInt($a->getLevel(), $b->getLevel()); - - if (0 !== $cmp) { - return $cmp; - } - - return strcmp($a->getName(), $b->getName()); - } - ); - - $count = count($fixers) - 1; - foreach ($fixers as $i => $fixer) { - $description = str_replace("\n", "\n ", wordwrap($fixer->getDescription(), 72, "\n")); - $help .= sprintf(" * %s [%s]\n %s\n", $fixer->getName(), $this->fixer->getLevelAsString($fixer), $description); - - if ($count !== $i) { - $help .= "\n"; - } - } - - return $help; - } - - protected function getConfigsHelp() - { - $help = ''; - $maxName = 0; - $configs = $this->fixer->getConfigs(); - - usort( - $configs, - function (ConfigInterface $a, ConfigInterface $b) { - return strcmp($a->getName(), $b->getName()); - } - ); - - foreach ($configs as $config) { - if (strlen($config->getName()) > $maxName) { - $maxName = strlen($config->getName()); - } - } - - $count = count($this->fixer->getConfigs()) - 1; - foreach ($configs as $i => $config) { - $chunks = explode("\n", wordwrap($config->getDescription(), 72 - $maxName, "\n")); - $help .= sprintf(" * %s%s %s\n", $config->getName(), str_repeat(' ', $maxName - strlen($config->getName())), array_shift($chunks)); - while ($c = array_shift($chunks)) { - $help .= str_repeat(' ', $maxName + 4).$c."\n"; - } - - if ($count !== $i) { - $help .= "\n"; - } - } - - return $help; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/ReadmeCommand.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/ReadmeCommand.php deleted file mode 100644 index 3635cab..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/ReadmeCommand.php +++ /dev/null @@ -1,268 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Console\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Fabien Potencier - */ -class ReadmeCommand extends Command -{ - const COMMAND_NAME = 'readme'; - - /** - * @see Command - */ - protected function configure() - { - $this - ->setName(self::COMMAND_NAME) - ->setDescription('Generates the README content, based on the fix command help') - ; - } - - /** - * @see Command - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $header = <<<'EOF' -PHP Coding Standards Fixer -========================== - -The PHP Coding Standards Fixer tool fixes *most* issues in your code when you -want to follow the PHP coding standards as defined in the PSR-1 and PSR-2 -documents and many more. - -If you are already using a linter to identify coding standards problems in your -code, you know that fixing them by hand is tedious, especially on large -projects. This tool does not only detect them, but also fixes them for you. - -Requirements ------------- - -PHP needs to be a minimum version of PHP 5.3.6. - -Installation ------------- - -Locally -~~~~~~~ - -Download the `php-cs-fixer.phar`_ file and store it somewhere on your computer. - -Globally (manual) -~~~~~~~~~~~~~~~~~ - -You can run these commands to easily access ``php-cs-fixer`` from anywhere on -your system: - -.. code-block:: bash - - $ wget %download.url% -O php-cs-fixer - -or with curl: - -.. code-block:: bash - - $ curl -L %download.url% -o php-cs-fixer - -then: - -.. code-block:: bash - - $ sudo chmod a+x php-cs-fixer - $ sudo mv php-cs-fixer /usr/local/bin/php-cs-fixer - -Then, just run ``php-cs-fixer``. - -Globally (Composer) -~~~~~~~~~~~~~~~~~~~ - -To install PHP CS Fixer, install Composer and issue the following command: - -.. code-block:: bash - - $ ./composer.phar global require friendsofphp/php-cs-fixer - -Please be aware that before v1.12 package name was different: - -.. code-block:: bash - - $ ./composer.phar global require fabpot/php-cs-fixer - -Then make sure you have ``~/.composer/vendor/bin`` in your ``PATH`` and -you're good to go: - -.. code-block:: bash - - $ export PATH="$PATH:$HOME/.composer/vendor/bin" - -Globally (homebrew) -~~~~~~~~~~~~~~~~~~~ - -PHP-CS-Fixer is part of the homebrew-php project. Follow the installation -instructions at https://github.com/homebrew/homebrew-php if you don't -already have it. - -.. code-block:: bash - - $ brew install homebrew/php/php-cs-fixer - -Update ------- - -Locally -~~~~~~~ - -The ``self-update`` command tries to update ``php-cs-fixer`` itself: - -.. code-block:: bash - - $ php php-cs-fixer.phar self-update - -Globally (manual) -~~~~~~~~~~~~~~~~~ - -You can update ``php-cs-fixer`` through this command: - -.. code-block:: bash - - $ sudo php-cs-fixer self-update - -Globally (Composer) -~~~~~~~~~~~~~~~~~~~ - -You can update ``php-cs-fixer`` through this command: - -.. code-block:: bash - - $ ./composer.phar global update friendsofphp/php-cs-fixer - -Globally (homebrew) -~~~~~~~~~~~~~~~~~~~ - -You can update ``php-cs-fixer`` through this command: - -.. code-block:: bash - - $ brew upgrade php-cs-fixer - -Usage ------ - -EOF; - - $footer = <<<'EOF' - -Helpers -------- - -Dedicated plugins exist for: - -* `Atom`_ -* `NetBeans`_ -* `PhpStorm`_ -* `Sublime Text`_ -* `Vim`_ - -Contribute ----------- - -The tool comes with quite a few built-in fixers and finders, but everyone is -more than welcome to `contribute`_ more of them. - -Fixers -~~~~~~ - -A *fixer* is a class that tries to fix one CS issue (a ``Fixer`` class must -implement ``FixerInterface``). - -Configs -~~~~~~~ - -A *config* knows about the CS level and the files and directories that must be -scanned by the tool when run in the directory of your project. It is useful for -projects that follow a well-known directory structures (like for Symfony -projects for instance). - -.. _php-cs-fixer.phar: %download.url% -.. _Atom: https://github.com/Glavin001/atom-beautify -.. _NetBeans: http://plugins.netbeans.org/plugin/49042/php-cs-fixer -.. _PhpStorm: http://tzfrs.de/2015/01/automatically-format-code-to-match-psr-standards-with-phpstorm -.. _Sublime Text: https://github.com/benmatselby/sublime-phpcs -.. _Vim: https://github.com/stephpy/vim-php-cs-fixer -.. _contribute: https://github.com/FriendsOfPhp/php-cs-fixer/blob/master/CONTRIBUTING.md - -EOF; - - $downloadUrl = $this->getLatestDownloadUrl(); - - $command = $this->getApplication()->get('fix'); - $help = $command->getHelp(); - $help = str_replace('%command.full_name%', 'php-cs-fixer.phar '.$command->getName(), $help); - $help = str_replace('%command.name%', $command->getName(), $help); - $help = preg_replace('##', '``', $help); - $help = preg_replace('#^(\s+)``(.+)``$#m', '$1$2', $help); - $help = preg_replace('#^ \* ``(.+)``#m', '* **$1**', $help); - $help = preg_replace("#^\n( +)#m", "\n.. code-block:: bash\n\n$1", $help); - $help = preg_replace("#^\.\. code-block:: bash\n\n( +<\?(\w+))#m", ".. code-block:: $2\n\n$1", $help); - $help = preg_replace_callback( - "#^\s*<\?(\w+).*?\?>#ms", - function ($matches) { - $result = preg_replace("#^\.\. code-block:: bash\n\n#m", '', $matches[0]); - - if ('php' !== $matches[1]) { - $result = preg_replace("#<\?{$matches[1]}\s*#", '', $result); - } - - $result = preg_replace("#\n\n +\?>#", '', $result); - - return $result; - }, - $help - ); - $help = preg_replace('#^ #m', ' ', $help); - $help = preg_replace('#\*\* +\[#', '** [', $help); - $header = str_replace('%download.url%', $downloadUrl, $header); - $footer = str_replace('%download.url%', $downloadUrl, $footer); - - $output->write($header."\n".$help."\n".$footer); - } - - private function getLatestDownloadUrl() - { - $version = $this->getApplication()->getVersion(); - $changelogFile = __DIR__.'/../../../../CHANGELOG.md'; - - if (is_file($changelogFile)) { - $currentMajor = (int) $version; - $changelog = file_get_contents($changelogFile); - preg_match('/Changelog for v('.$currentMajor.'.\d+.\d+)/', $changelog, $matches); - - if (2 !== count($matches)) { - throw new \RuntimeException('Invalid changelog data!'); - } - - $version = $matches[1]; - } - - return sprintf( - 'https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v%s/php-cs-fixer.phar', - $version - ); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/SelfUpdateCommand.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/SelfUpdateCommand.php deleted file mode 100644 index 9221834..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/Command/SelfUpdateCommand.php +++ /dev/null @@ -1,236 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Console\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\CS\ToolInfo; - -/** - * @author Igor Wiedler - * @author Stephane PY - * @author Grégoire Pineau - * @author Dariusz Rumiński - * @author SpacePossum - */ -class SelfUpdateCommand extends Command -{ - const COMMAND_NAME = 'self-update'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setName(self::COMMAND_NAME) - ->setAliases(array('selfupdate')) - ->setDefinition( - array( - new InputOption('--force', '-f', InputOption::VALUE_NONE, 'Force update to next major version if available.'), - ) - ) - ->setDescription('Update php-cs-fixer.phar to the latest stable version.') - ->setHelp(<<<'EOT' -The %command.name% command replace your php-cs-fixer.phar by the -latest version released on: -https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases - -$ php php-cs-fixer.phar %command.name% - -EOT - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - if (!ToolInfo::isInstalledAsPhar()) { - $output->writeln('Self-update is available only for PHAR version.'); - - return 1; - } - - $remoteTag = $this->getLatestTag(); - if (null === $remoteTag) { - $output->writeln('Unable to determine newest version.'); - - return 0; - } - - $currentVersion = 'v'.$this->getApplication()->getVersion(); - if ($currentVersion === $remoteTag) { - $output->writeln('php-cs-fixer is already up to date.'); - - return 0; - } - - $remoteVersionParsed = $this->parseVersion($remoteTag); - $currentVersionParsed = $this->parseVersion($currentVersion); - - if ($remoteVersionParsed[0] > $currentVersionParsed[0] && true !== $input->getOption('force')) { - $output->writeln(sprintf('A new major version of php-cs-fixer is available (%s)', $remoteTag)); - $output->writeln(sprintf('Before upgrading please read https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/%s/UPGRADE.md', $remoteTag)); - $output->writeln('If you are ready to upgrade run this command with -f'); - $output->writeln('Checking for new minor/patch version...'); - - // test if there is a new minor version available - $remoteTag = $this->getLatestNotMajorUpdateTag($currentVersion); - if ($currentVersion === $remoteTag) { - $output->writeln('no minor update for php-cs-fixer.'); - - return 0; - } - } - - $remoteFilename = sprintf('https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/%s/php-cs-fixer.phar', $remoteTag); - $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; - $tempFilename = basename($localFilename, '.phar').'-tmp.phar'; - - try { - $copyResult = @copy($remoteFilename, $tempFilename); - if (false === $copyResult) { - $output->writeln(sprintf('Unable to download new version %s from the server.', $remoteTag)); - - return 1; - } - - chmod($tempFilename, 0777 & ~umask()); - - // test the phar validity - $phar = new \Phar($tempFilename); - // free the variable to unlock the file - unset($phar); - rename($tempFilename, $localFilename); - - $output->writeln(sprintf('php-cs-fixer updated (%s)', $remoteTag)); - } catch (\Exception $e) { - if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) { - throw $e; - } - - unlink($tempFilename); - $output->writeln(sprintf('The download of %s is corrupt (%s).', $remoteTag, $e->getMessage())); - $output->writeln('Please re-run the self-update command to try again.'); - - return 1; - } - } - - /** - * @return string|null - */ - private function getLatestTag() - { - $raw = file_get_contents( - 'https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/releases/latest', - null, - stream_context_create($this->getStreamContextOptions()) - ); - - if (false === $raw) { - return null; - } - - $json = json_decode($raw, true); - - if (null === $json) { - return null; - } - - return $json['tag_name']; - } - - /** - * @param string $currentTag in format v?\d.\d.\d - * - * @return string in format v?\d.\d.\d - */ - private function getLatestNotMajorUpdateTag($currentTag) - { - $currentTagParsed = $this->parseVersion($currentTag); - $nextVersionParsed = $currentTagParsed; - do { - $nextTag = sprintf('v%d.%d.%d', $nextVersionParsed[0], ++$nextVersionParsed[1], 0); - } while ($this->hasRemoteTag($nextTag)); - - $nextVersionParsed = $this->parseVersion($nextTag); - --$nextVersionParsed[1]; - - // check if new minor found, otherwise start looking for new patch from the current patch number - if ($currentTagParsed[1] === $nextVersionParsed[1]) { - $nextVersionParsed[2] = $currentTagParsed[2]; - } - - do { - $nextTag = sprintf('v%d.%d.%d', $nextVersionParsed[0], $nextVersionParsed[1], ++$nextVersionParsed[2]); - } while ($this->hasRemoteTag($nextTag)); - - return sprintf('v%d.%d.%d', $nextVersionParsed[0], $nextVersionParsed[1], $nextVersionParsed[2] - 1); - } - - /** - * @param string $method HTTP method - * - * @return array - */ - private function getStreamContextOptions($method = 'GET') - { - return array( - 'http' => array( - 'header' => 'User-Agent: FriendsOfPHP/PHP-CS-Fixer', - 'method' => $method, - ), - ); - } - - /** - * @param string $tag - * - * @return bool - */ - private function hasRemoteTag($tag) - { - $url = 'https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/releases/tags/'.$tag; - stream_context_set_default( - $this->getStreamContextOptions('HEAD') - ); - - $headers = get_headers($url); - if (!is_array($headers) || count($headers) < 1) { - throw new \RuntimeException(sprintf('Failed to get headers for "%s".', $url)); - } - - return 1 === preg_match('#^HTTP\/\d.\d 200#', $headers[0]); - } - - /** - * @param string $tag version in format v?\d.\d.\d - * - * @return int[] - */ - private function parseVersion($tag) - { - $tag = explode('.', $tag); - if ('v' === $tag[0][0]) { - $tag[0] = substr($tag[0], 1); - } - - return array((int) $tag[0], (int) $tag[1], (int) $tag[2]); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Annotation.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Annotation.php deleted file mode 100644 index 47d81cb..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Annotation.php +++ /dev/null @@ -1,212 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\DocBlock; - -/** - * This represents an entire annotation from a docblock. - * - * @author Graham Campbell - */ -class Annotation -{ - /** - * All the annotation tag names with types. - * - * @var string[] - */ - private static $tags = array( - 'method', - 'param', - 'property', - 'property-read', - 'property-write', - 'return', - 'throws', - 'type', - 'var', - ); - - /** - * The lines that make up the annotation. - * - * @var Line[] - */ - private $lines; - - /** - * The position of the first line of the annotation in the docblock. - * - * @var int - */ - private $start; - - /** - * The position of the last line of the annotation in the docblock. - * - * @var int - */ - private $end; - - /** - * The associated tag. - * - * @var Tag|null - */ - private $tag; - - /** - * The cached types content. - * - * @var string|null - */ - private $typesContent; - - /** - * Create a new line instance. - * - * @param Line[] $lines - */ - public function __construct(array $lines) - { - $this->lines = array_values($lines); - - $keys = array_keys($lines); - - $this->start = $keys[0]; - $this->end = end($keys); - } - - /** - * Get the string representation of object. - * - * @return string - */ - public function __toString() - { - return $this->getContent(); - } - - /** - * Get all the annotation tag names with types. - * - * @return string[] - */ - public static function getTagsWithTypes() - { - return self::$tags; - } - - /** - * Get the start position of this annotation. - * - * @return int - */ - public function getStart() - { - return $this->start; - } - - /** - * Get the end position of this annotation. - * - * @return int - */ - public function getEnd() - { - return $this->end; - } - - /** - * Get the associated tag. - * - * @return Tag - */ - public function getTag() - { - if (null === $this->tag) { - $values = array_values($this->lines); - $this->tag = new Tag($values[0]->getContent()); - } - - return $this->tag; - } - - /** - * Get the types associated with this annotation. - * - * @return string[] - */ - public function getTypes() - { - return explode('|', $this->getTypesContent()); - } - - /** - * Set the types associated with this annotation. - * - * @param string[] $types - */ - public function setTypes(array $types) - { - $pattern = '/'.preg_quote($this->getTypesContent()).'/'; - - $this->lines[0]->setContent(preg_replace($pattern, implode('|', $types), $this->lines[0]->getContent(), 1)); - - $this->typesContent = null; - } - - /** - * Remove this annotation by removing all its lines. - */ - public function remove() - { - foreach ($this->lines as $line) { - $line->remove(); - } - } - - /** - * Get the annotation content. - * - * @return string - */ - public function getContent() - { - return implode($this->lines); - } - - /** - * Get the current types content. - * - * Be careful modifying the underlying line as that won't flush the cache. - * - * @return string - */ - private function getTypesContent() - { - if (null === $this->typesContent) { - $name = $this->getTag()->getName(); - - if (!in_array($name, self::$tags, true)) { - throw new \RuntimeException('This tag does not support types'); - } - - $tagSplit = preg_split('/\s*\@'.$name.'\s*/', $this->lines[0]->getContent(), 2); - $spaceSplit = preg_split('/\s/', $tagSplit[1], 2); - - $this->typesContent = $spaceSplit[0]; - } - - return $this->typesContent; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/DocBlock.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/DocBlock.php deleted file mode 100644 index 73d43f3..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/DocBlock.php +++ /dev/null @@ -1,189 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\DocBlock; - -use Symfony\CS\Utils; - -/** - * This class represents a docblock. - * - * It internally splits it up into "lines" that we can manipulate. - * - * @author Graham Campbell - */ -class DocBlock -{ - /** - * The array of lines. - * - * @var Line[] - */ - private $lines = array(); - - /** - * The array of annotations. - * - * @var Annotation[]|null - */ - private $annotations; - - /** - * Create a new docblock instance. - * - * @param string $content - */ - public function __construct($content) - { - foreach (Utils::splitLines($content) as $line) { - $this->lines[] = new Line($line); - } - } - - /** - * Get the string representation of object. - * - * @return string - */ - public function __toString() - { - return $this->getContent(); - } - - /** - * Get this docblock's lines. - * - * @return Line[] - */ - public function getLines() - { - return $this->lines; - } - - /** - * Get a single line. - * - * @param int $pos - * - * @return Line|null - */ - public function getLine($pos) - { - if (isset($this->lines[$pos])) { - return $this->lines[$pos]; - } - } - - /** - * Get this docblock's annotations. - * - * @return Annotation[] - */ - public function getAnnotations() - { - if (null === $this->annotations) { - $this->annotations = array(); - $total = count($this->lines); - - for ($index = 0; $index < $total; ++$index) { - if ($this->lines[$index]->containsATag()) { - // get all the lines that make up the annotation - $lines = array_slice($this->lines, $index, $this->findAnnotationLength($index), true); - $annotation = new Annotation($lines); - // move the index to the end of the annotation to avoid - // checking it again because we know the lines inside the - // current annotation cannot be part of another annotation - $index = $annotation->getEnd(); - // add the current annotation to the list of annotations - $this->annotations[] = $annotation; - } - } - } - - return $this->annotations; - } - - /** - * Get a single annotation. - * - * @param int $pos - * - * @return Annotation|null - */ - public function getAnnotation($pos) - { - $annotations = $this->getAnnotations(); - - if (isset($annotations[$pos])) { - return $annotations[$pos]; - } - } - - /** - * Get specific types of annotations only. - * - * If none exist, we're returning an empty array. - * - * @param string|string[] $types - * - * @return Annotation[] - */ - public function getAnnotationsOfType($types) - { - $annotations = array(); - $types = (array) $types; - - foreach ($this->getAnnotations() as $annotation) { - $tag = $annotation->getTag()->getName(); - foreach ($types as $type) { - if ($type === $tag) { - $annotations[] = $annotation; - } - } - } - - return $annotations; - } - - /** - * Get the actual content of this docblock. - * - * @return string - */ - public function getContent() - { - return implode($this->lines); - } - - private function findAnnotationLength($start) - { - $index = $start; - - while ($line = $this->getLine(++$index)) { - if ($line->containsATag()) { - // we've 100% reached the end of the description if we get here - break; - } - - if (!$line->containsUsefulContent()) { - // if we next line is also non-useful, or contains a tag, then we're done here - $next = $this->getLine($index + 1); - if (null === $next || !$next->containsUsefulContent() || $next->containsATag()) { - break; - } - // otherwise, continue, the annotation must have contained a blank line in its description - } - } - - return $index - $start; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Tag.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Tag.php deleted file mode 100644 index 3d7e041..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Tag.php +++ /dev/null @@ -1,80 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\DocBlock; - -/** - * This represents a tag, as defined by the proposed PSR PHPDoc standard. - * - * @author Graham Campbell - */ -class Tag -{ - /** - * All the tags defined by the proposed PSR PHPDoc standard. - * - * @var string[] - */ - private static $tags = array( - 'api', 'author', 'category', 'copyright', 'deprecated', 'example', - 'global', 'internal', 'license', 'link', 'method', 'package', 'param', - 'property', 'property-read', 'property-write', 'return', 'see', - 'since', 'struct', 'subpackage', 'throws', 'todo', 'typedef', 'uses', - 'var', 'version', - ); - - /** - * The tag name. - * - * @var string - */ - private $name; - - /** - * Create a new tag instance. - * - * @param string $content - */ - public function __construct($content) - { - $this->name = 'other'; - preg_match_all('/@[a-zA-Z0-9_-]+(?=\s|$)/', $content, $matches); - - if (isset($matches[0][0])) { - $this->name = ltrim($matches[0][0], '@'); - } - } - - /** - * Get the tag name. - * - * This may be "param", or "return", etc. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Is the tag a known tag. - * - * This is defined by if it exists in the proposed PSR PHPDoc standard. - * - * @return bool - */ - public function valid() - { - return in_array($this->name, self::$tags, true); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ErrorsManager.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ErrorsManager.php deleted file mode 100644 index 1bb59d3..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ErrorsManager.php +++ /dev/null @@ -1,67 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -/** - * Manager of errors that occur during fixing. - * - * @author Dariusz Rumiński - */ -class ErrorsManager -{ - const ERROR_TYPE_EXCEPTION = 1; - const ERROR_TYPE_LINT = 2; - - /** - * Errors. - * - * @var array - */ - private $errors = array(); - - /** - * Get all reported errors. - * - * @return array - */ - public function getErrors() - { - return $this->errors; - } - - /** - * Check if no errors was reported. - * - * @return bool - */ - public function isEmpty() - { - return empty($this->errors); - } - - /** - * Report error. - * - * @param int $type error type - * @param string $filepath file, on which error occurs - * @param string $message description of error - */ - public function report($type, $filepath, $message) - { - $this->errors[] = array( - 'type' => $type, - 'filepath' => $filepath, - 'message' => $message, - ); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FileCacheManager.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FileCacheManager.php deleted file mode 100644 index 80dfb11..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FileCacheManager.php +++ /dev/null @@ -1,159 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -use Symfony\Component\Filesystem\Exception\IOException; - -/** - * Class supports caching information about state of fixing files. - * - * Cache is supported only for phar version and version installed via composer. - * - * File will be processed by PHP CS Fixer only if any of the following conditions is fulfilled: - * - cache is not available, - * - fixer version changed, - * - fixers list is changed, - * - file is new, - * - file changed. - * - * @author Dariusz Rumiński - */ -class FileCacheManager -{ - const CACHE_FILE = '.php_cs.cache'; - - private $dir; - private $isEnabled; - private $fixers; - private $newHashes = array(); - private $oldHashes = array(); - - public function __construct($isEnabled, $dir, array $fixers) - { - $this->isEnabled = $isEnabled; - $this->dir = null !== $dir ? $dir.DIRECTORY_SEPARATOR : ''; - $this->fixers = array_map(function (FixerInterface $f) { - return $f->getName(); - }, $fixers); - sort($this->fixers); - - $this->readFromFile(); - } - - public function __destruct() - { - $this->saveToFile(); - } - - public function needFixing($file, $fileContent) - { - if (!$this->isCacheAvailable()) { - return true; - } - - if (!isset($this->oldHashes[$file])) { - return true; - } - - if ($this->oldHashes[$file] !== $this->calcHash($fileContent)) { - return true; - } - - // file do not change - keep hash in new collection - $this->newHashes[$file] = $this->oldHashes[$file]; - - return false; - } - - public function setFile($file, $fileContent) - { - if (!$this->isCacheAvailable()) { - return; - } - - $this->newHashes[$file] = $this->calcHash($fileContent); - } - - private function calcHash($content) - { - return crc32($content); - } - - private function isCacheAvailable() - { - static $result; - - if (null === $result) { - $result = $this->isEnabled && (ToolInfo::isInstalledAsPhar() || ToolInfo::isInstalledByComposer()); - } - - return $result; - } - - private function isCacheStale($cacheVersion, $fixers) - { - if (!$this->isCacheAvailable()) { - return true; - } - - return ToolInfo::getVersion() !== $cacheVersion || $this->fixers !== $fixers; - } - - private function readFromFile() - { - if (!$this->isCacheAvailable()) { - return; - } - - if (!file_exists($this->dir.self::CACHE_FILE)) { - return; - } - - $content = file_get_contents($this->dir.self::CACHE_FILE); - $data = @unserialize($content); - - // ignore corrupted serialized data - if (!is_array($data)) { - return; - } - - // BC for old cache without fixers list - if (!isset($data['fixers'])) { - $data['fixers'] = null; - } - - // Set hashes only if the cache is fresh, otherwise we need to parse all files - if (!$this->isCacheStale($data['version'], $data['fixers'])) { - $this->oldHashes = $data['hashes']; - } - } - - private function saveToFile() - { - if (!$this->isCacheAvailable()) { - return; - } - - $data = serialize( - array( - 'version' => ToolInfo::getVersion(), - 'fixers' => $this->fixers, - 'hashes' => $this->newHashes, - ) - ); - - if (false === @file_put_contents($this->dir.self::CACHE_FILE, $data, LOCK_EX)) { - throw new IOException(sprintf('Failed to write file "%s".', self::CACHE_FILE), 0, null, $this->dir.self::CACHE_FILE); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/DefaultFinder.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/DefaultFinder.php deleted file mode 100644 index 8d0755c..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/DefaultFinder.php +++ /dev/null @@ -1,88 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Finder; - -use Symfony\CS\Finder as BaseFinder; -use Symfony\CS\FinderInterface; - -/** - * @author Fabien Potencier - * - * @deprecated - */ -class DefaultFinder extends BaseFinder implements FinderInterface -{ - public function __construct() - { - @trigger_error( - sprintf( - 'The "%s" class is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "%s" instead.', - __CLASS__, - 'Symfony\CS\Finder' - ), - E_USER_DEPRECATED - ); - - parent::__construct(); - - $files = $this->getFilesToExclude(); - - $this - ->name('*.xml') - ->name('*.yml') - ->filter( - function (\SplFileInfo $file) use ($files) { - return !in_array($file->getRelativePathname(), $files, true); - } - ) - ; - } - - public function setDir($dir) - { - @trigger_error( - sprintf( - 'The "%s" method is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "%s" instead.', - __METHOD__, - 'in' - ), - E_USER_DEPRECATED - ); - - $this->in($this->getDirs($dir)); - } - - /** - * Gets the directories that needs to be scanned for files to validate. - * - * @param string $dir - * - * @return string[] - */ - protected function getDirs($dir) - { - return array($dir); - } - - /** - * Excludes files because modifying them would break. - * - * This is mainly useful for fixtures in unit tests. - * - * @return string[] - */ - protected function getFilesToExclude() - { - return array(); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/MagentoFinder.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/MagentoFinder.php deleted file mode 100644 index 841d06a..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/MagentoFinder.php +++ /dev/null @@ -1,83 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Finder; - -/** - * @author Myke Hines - * - * @deprecated - */ -class MagentoFinder extends DefaultFinder -{ - public function __construct() - { - @trigger_error( - sprintf( - 'The "%s" class is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "%s" instead.', - __CLASS__, - 'Symfony\CS\Finder' - ), - E_USER_DEPRECATED - ); - - parent::__construct(); - - $this - ->name('*.php') - ->name('*.phtml') - ->name('*.xml') - ->exclude( - array( - 'lib', - 'shell', - 'app/Mage.php', - 'app/code/core', - 'app/code/community', - 'app/design/frontend/default', - 'app/design/frontend/enterprise/default', - 'app/design/frontend/base', - 'app/design/adminhtml/default', - ) - ) - ; - } - - public function setDir($dir) - { - $this->in($this->getDirs($dir)); - } - - /** - * Gets the directories that needs to be scanned for files to validate. - * - * @param string $dir - * - * @return array - */ - protected function getDirs($dir) - { - return array($dir); - } - - /** - * Excludes files because modifying them would break. - * - * This is mainly useful for fixtures in unit tests. - * - * @return array - */ - protected function getFilesToExclude() - { - return array(); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/Symfony23Finder.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/Symfony23Finder.php deleted file mode 100644 index 5789385..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder/Symfony23Finder.php +++ /dev/null @@ -1,52 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Finder; - -/** - * @author Fabien Potencier - * - * @deprecated - */ -class Symfony23Finder extends DefaultFinder -{ - public function __construct() - { - @trigger_error( - sprintf( - 'The "%s" class is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "%s" instead.', - __CLASS__, - 'Symfony\CS\Finder' - ), - E_USER_DEPRECATED - ); - - parent::__construct(); - } - - protected function getDirs($dir) - { - return array($dir.'/src'); - } - - protected function getFilesToExclude() - { - return array( - 'Symfony/Component/Console/Tests/Fixtures/application_1.xml', - 'Symfony/Component/Console/Tests/Fixtures/application_2.xml', - 'Symfony/Component/Console/Tests/Helper/TableHelperTest.php', - 'Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml', - 'Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml', - 'Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml', - ); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer.php deleted file mode 100644 index 989b900..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer.php +++ /dev/null @@ -1,425 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -use SebastianBergmann\Diff\Differ; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\Finder\Finder as SymfonyFinder; -use Symfony\Component\Finder\SplFileInfo as SymfonySplFileInfo; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Fabien Potencier - * @author Dariusz Rumiński - */ -class Fixer -{ - const VERSION = '1.13.3'; - - protected $fixers = array(); - protected $configs = array(); - - /** - * Differ instance. - * - * @var Differ - */ - protected $diff; - - /** - * EventDispatcher instance. - * - * @var EventDispatcher|null - */ - protected $eventDispatcher; - - /** - * ErrorsManager instance. - * - * @var ErrorsManager|null - */ - protected $errorsManager; - - /** - * LintManager instance. - * - * @var LintManager|null - */ - protected $lintManager; - - /** - * Stopwatch instance. - * - * @var Stopwatch|null - */ - protected $stopwatch; - - public function __construct() - { - $this->diff = new Differ(); - } - - public function registerBuiltInFixers() - { - foreach (SymfonyFinder::create()->files()->in(__DIR__.'/Fixer') as $file) { - $relativeNamespace = $file->getRelativePath(); - $class = 'Symfony\\CS\\Fixer\\'.($relativeNamespace ? $relativeNamespace.'\\' : '').$file->getBasename('.php'); - $this->addFixer(new $class()); - } - } - - /** - * @param FixerInterface[] $fixers - */ - public function registerCustomFixers(array $fixers) - { - foreach ($fixers as $fixer) { - $this->addFixer($fixer); - } - } - - public function addFixer(FixerInterface $fixer) - { - $this->fixers[] = $fixer; - } - - /** - * @return FixerInterface[] - */ - public function getFixers() - { - $this->fixers = $this->sortFixers($this->fixers); - - return $this->fixers; - } - - public function registerBuiltInConfigs() - { - foreach (SymfonyFinder::create()->files()->in(__DIR__.'/Config') as $file) { - $relativeNamespace = $file->getRelativePath(); - $class = 'Symfony\\CS\\Config\\'.($relativeNamespace ? $relativeNamespace.'\\' : '').$file->getBasename('.php'); - $this->addConfig(new $class()); - } - } - - public function addConfig(ConfigInterface $config) - { - $this->configs[] = $config; - } - - public function getConfigs() - { - return $this->configs; - } - - /** - * Fixes all files for the given finder. - * - * @param ConfigInterface $config A ConfigInterface instance - * @param bool $dryRun Whether to simulate the changes or not - * @param bool $diff Whether to provide diff - * - * @return array - */ - public function fix(ConfigInterface $config, $dryRun = false, $diff = false) - { - $fixers = $this->prepareFixers($config); - $fixers = $this->sortFixers($fixers); - - $changed = array(); - if ($this->stopwatch) { - $this->stopwatch->openSection(); - } - - $fileCacheManager = new FileCacheManager($config->usingCache(), $config->getDir(), $fixers); - - $finder = $config->getFinder(); - $finderIterator = $finder instanceof \IteratorAggregate ? $finder->getIterator() : $finder; - - foreach (new UniqueFileIterator($finderIterator) as $file) { - if ($this->stopwatch) { - $this->stopwatch->start($this->getFileRelativePathname($file)); - } - - if ($fixInfo = $this->fixFile($file, $fixers, $dryRun, $diff, $fileCacheManager)) { - $changed[$this->getFileRelativePathname($file)] = $fixInfo; - } - - if ($this->stopwatch) { - $this->stopwatch->stop($this->getFileRelativePathname($file)); - } - } - - if ($this->stopwatch) { - $this->stopwatch->stopSection('fixFile'); - } - - return $changed; - } - - public function fixFile(\SplFileInfo $file, array $fixers, $dryRun, $diff, FileCacheManager $fileCacheManager) - { - $new = $old = file_get_contents($file->getRealPath()); - - if ( - '' === $old - || !$fileCacheManager->needFixing($this->getFileRelativePathname($file), $old) - // PHP 5.3 has a broken implementation of token_get_all when the file uses __halt_compiler() starting in 5.3.6 - || (PHP_VERSION_ID >= 50306 && PHP_VERSION_ID < 50400 && false !== stripos($old, '__halt_compiler()')) - ) { - if ($this->eventDispatcher) { - $this->eventDispatcher->dispatch( - FixerFileProcessedEvent::NAME, - FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_SKIPPED) - ); - } - - return; - } - - if ($this->lintManager && !$this->lintManager->createProcessForFile($file->getRealPath())->isSuccessful()) { - if ($this->eventDispatcher) { - $this->eventDispatcher->dispatch( - FixerFileProcessedEvent::NAME, - FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_INVALID) - ); - } - - return; - } - - $appliedFixers = array(); - - // we do not need Tokens to still caching previously fixed file - so clear the cache - Tokens::clearCache(); - - try { - foreach ($fixers as $fixer) { - if (!$fixer->supports($file)) { - continue; - } - - $newest = $fixer->fix($file, $new); - if ($newest !== $new) { - $appliedFixers[] = $fixer->getName(); - } - $new = $newest; - } - } catch (\ParseError $e) { - if ($this->eventDispatcher) { - $this->eventDispatcher->dispatch( - FixerFileProcessedEvent::NAME, - FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_LINT) - ); - } - - if ($this->errorsManager) { - $this->errorsManager->report(ErrorsManager::ERROR_TYPE_LINT, $this->getFileRelativePathname($file), sprintf('Linting error at line %d: "%s".', $e->getLine(), $e->getMessage())); - } - - return; - } catch (\Error $e) { - if ($this->eventDispatcher) { - $this->eventDispatcher->dispatch( - FixerFileProcessedEvent::NAME, - FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_EXCEPTION) - ); - } - - if ($this->errorsManager) { - $this->errorsManager->report(ErrorsManager::ERROR_TYPE_EXCEPTION, $this->getFileRelativePathname($file), $e->__toString()); - } - - return; - } catch (\Exception $e) { - if ($this->eventDispatcher) { - $this->eventDispatcher->dispatch( - FixerFileProcessedEvent::NAME, - FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_EXCEPTION) - ); - } - - if ($this->errorsManager) { - $this->errorsManager->report(ErrorsManager::ERROR_TYPE_EXCEPTION, $this->getFileRelativePathname($file), $e->__toString()); - } - - return; - } - - $fixInfo = null; - - if ($new !== $old) { - if ($this->lintManager) { - $lintProcess = $this->lintManager->createProcessForSource($new); - - if (!$lintProcess->isSuccessful()) { - if ($this->eventDispatcher) { - $this->eventDispatcher->dispatch( - FixerFileProcessedEvent::NAME, - FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_LINT) - ); - } - - if ($this->errorsManager) { - $this->errorsManager->report(ErrorsManager::ERROR_TYPE_LINT, $this->getFileRelativePathname($file), $lintProcess->getOutput()); - } - - return; - } - } - - if (!$dryRun) { - file_put_contents($file->getRealPath(), $new); - } - - $fixInfo = array('appliedFixers' => $appliedFixers); - - if ($diff) { - $fixInfo['diff'] = $this->stringDiff($old, $new); - } - } - - $fileCacheManager->setFile($this->getFileRelativePathname($file), $new); - - if ($this->eventDispatcher) { - $this->eventDispatcher->dispatch( - FixerFileProcessedEvent::NAME, - FixerFileProcessedEvent::create()->setStatus($fixInfo ? FixerFileProcessedEvent::STATUS_FIXED : FixerFileProcessedEvent::STATUS_NO_CHANGES) - ); - } - - return $fixInfo; - } - - public static function getLevelAsString(FixerInterface $fixer) - { - $level = $fixer->getLevel(); - - if (($level & FixerInterface::NONE_LEVEL) === $level) { - return 'none'; - } - - if (($level & FixerInterface::PSR0_LEVEL) === $level) { - return 'PSR-0'; - } - - if (($level & FixerInterface::PSR1_LEVEL) === $level) { - return 'PSR-1'; - } - - if (($level & FixerInterface::PSR2_LEVEL) === $level) { - return 'PSR-2'; - } - - if (($level & FixerInterface::CONTRIB_LEVEL) === $level) { - return 'contrib'; - } - - return 'symfony'; - } - - /** - * Set EventDispatcher instance. - * - * @param EventDispatcher|null $eventDispatcher - */ - public function setEventDispatcher(EventDispatcher $eventDispatcher = null) - { - $this->eventDispatcher = $eventDispatcher; - } - - /** - * Set ErrorsManager instance. - * - * @param ErrorsManager|null $errorsManager - */ - public function setErrorsManager(ErrorsManager $errorsManager = null) - { - $this->errorsManager = $errorsManager; - } - - /** - * Set LintManager instance. - * - * @param LintManager|null $lintManager - */ - public function setLintManager(LintManager $lintManager = null) - { - $this->lintManager = $lintManager; - } - - /** - * Set Stopwatch instance. - * - * @param Stopwatch|null $stopwatch - */ - public function setStopwatch(Stopwatch $stopwatch = null) - { - $this->stopwatch = $stopwatch; - } - - /** - * @deprecated Will be removed in the 2.0 - * - * @param string $old - * @param string $new - * - * @return string - */ - protected function stringDiff($old, $new) - { - return $this->diff->diff($old, $new); - } - - private function getFileRelativePathname(\SplFileInfo $file) - { - if ($file instanceof SymfonySplFileInfo) { - return $file->getRelativePathname(); - } - - return $file->getPathname(); - } - - /** - * @param FixerInterface[] $fixers - * - * @return FixerInterface[] - */ - private function sortFixers(array $fixers) - { - usort($fixers, function (FixerInterface $a, FixerInterface $b) { - return Utils::cmpInt($b->getPriority(), $a->getPriority()); - }); - - return $fixers; - } - - /** - * @param ConfigInterface $config - * - * @return FixerInterface[] - */ - private function prepareFixers(ConfigInterface $config) - { - $fixers = $config->getFixers(); - - foreach ($fixers as $fixer) { - if ($fixer instanceof ConfigAwareInterface) { - $fixer->setConfig($config); - } - } - - return $fixers; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/AlignEqualsFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/AlignEqualsFixer.php deleted file mode 100644 index eb91c95..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/AlignEqualsFixer.php +++ /dev/null @@ -1,95 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractAlignFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Carlos Cirello - * @author Graham Campbell - */ -class AlignEqualsFixer extends AbstractAlignFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $data = $this->injectAlignmentPlaceholders($content); - - return $this->replacePlaceholder($data['tokens'], $data['deepestLevel']); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Align equals symbols in consecutive lines.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the OperatorsSpacesFixer - return -10; - } - - /** - * Inject into the text placeholders of candidates of vertical alignment. - * - * Output structure: - * * Tokens $tokens - * * int $deepestLevel - * - * @param string $content - * - * @return array - */ - private function injectAlignmentPlaceholders($content) - { - $deepestLevel = 0; - $parenCount = 0; - $bracketCount = 0; - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $token) { - $tokenContent = $token->getContent(); - - if (0 === $parenCount && 0 === $bracketCount && $token->equals('=')) { - $token->setContent(sprintf(self::ALIGNABLE_PLACEHOLDER, $deepestLevel).$tokenContent); - continue; - } - - if ($token->isGivenKind(T_FUNCTION)) { - ++$deepestLevel; - } elseif ($token->equals('(')) { - ++$parenCount; - } elseif ($token->equals(')')) { - --$parenCount; - } elseif ($token->equals('[')) { - ++$bracketCount; - } elseif ($token->equals(']')) { - --$bracketCount; - } - } - - return array( - 'tokens' => $tokens, - 'deepestLevel' => $deepestLevel, - ); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ClassKeywordRemoveFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ClassKeywordRemoveFixer.php deleted file mode 100644 index a38f354..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ClassKeywordRemoveFixer.php +++ /dev/null @@ -1,202 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Sullivan Senechal - */ -final class ClassKeywordRemoveFixer extends AbstractFixer -{ - /** - * @var string[] - */ - private $imports = array(); - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $this->replaceClassKeywords($tokens); - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Converts ::class keywords to FQCN strings.'; - } - - /** - * Replaces ::class keyword, namespace by namespace. - * - * It uses recursive method to get rid of token index changes. - * - * @param Tokens $tokens - * @param int $namespaceNumber - */ - private function replaceClassKeywords(Tokens $tokens, $namespaceNumber = -1) - { - $namespaceIndexes = array_keys($tokens->findGivenKind(T_NAMESPACE)); - - // Namespace blocks - if (!empty($namespaceIndexes) && isset($namespaceIndexes[$namespaceNumber])) { - $startIndex = $namespaceIndexes[$namespaceNumber]; - - $namespaceBlockStartIndex = $tokens->getNextTokenOfKind($startIndex, array(';', '{')); - $endIndex = $tokens[$namespaceBlockStartIndex]->equals('{') - ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $namespaceBlockStartIndex) - : $tokens->getNextTokenOfKind($namespaceBlockStartIndex, array(T_NAMESPACE)); - $endIndex = $endIndex ?: $tokens->count() - 1; - } elseif (-1 === $namespaceNumber) { // Out of any namespace block - $startIndex = 0; - $endIndex = !empty($namespaceIndexes) ? $namespaceIndexes[0] : $tokens->count() - 1; - } else { - return; - } - - $this->storeImports($tokens, $startIndex, $endIndex); - $tokens->rewind(); - $this->replaceClassKeywordsSection($tokens, $startIndex, $endIndex); - $this->replaceClassKeywords($tokens, $namespaceNumber + 1); - } - - /** - * @param Tokens $tokens - */ - private function storeImports(Tokens $tokens, $startIndex, $endIndex) - { - $this->imports = array(); - - foreach ($tokens->getImportUseIndexes() as $index) { - if ($index < $startIndex || $index > $endIndex) { - continue; - } - - $import = ''; - while (($index = $tokens->getNextMeaningfulToken($index))) { - if ($tokens[$index]->equalsAny(array(';', '{')) || $tokens[$index]->isGivenKind(T_AS)) { - break; - } - - $import .= $tokens[$index]->getContent(); - } - - // Imports group (PHP 7 spec) - if ($tokens[$index]->equals('{')) { - $groupEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); - $groupImports = array_map( - 'trim', - explode(',', $tokens->generatePartialCode($index + 1, $groupEndIndex - 1)) - ); - foreach ($groupImports as $groupImport) { - $groupImportParts = array_map('trim', explode(' as ', $groupImport)); - if (2 === count($groupImportParts)) { - $this->imports[$groupImportParts[1]] = $import.$groupImportParts[0]; - } else { - $this->imports[] = $import.$groupImport; - } - } - } elseif ($tokens[$index]->isGivenKind(T_AS)) { - $aliasIndex = $tokens->getNextMeaningfulToken($index); - $alias = $tokens[$aliasIndex]->getContent(); - $this->imports[$alias] = $import; - } else { - $this->imports[] = $import; - } - } - } - - /** - * @param Tokens $tokens - */ - private function replaceClassKeywordsSection(Tokens $tokens, $startIndex, $endIndex) - { - $CTClassTokens = $tokens->findGivenKind(CT_CLASS_CONSTANT, $startIndex, $endIndex); - if (!empty($CTClassTokens)) { - $this->replaceClassKeyword($tokens, current(array_keys($CTClassTokens))); - $this->replaceClassKeywordsSection($tokens, $startIndex, $endIndex); - } - } - - /** - * @param Tokens $tokens - * @param int $classIndex - */ - private function replaceClassKeyword(Tokens $tokens, $classIndex) - { - $classEndIndex = $classIndex - 2; - $classBeginIndex = $classEndIndex; - while ($tokens[--$classBeginIndex]->isGivenKind(array(T_NS_SEPARATOR, T_STRING))); - ++$classBeginIndex; - $classString = $tokens->generatePartialCode($classBeginIndex, $classEndIndex); - - $classImport = false; - foreach ($this->imports as $alias => $import) { - if ($classString === $alias) { - $classImport = $import; - break; - } - - $classStringArray = explode('\\', $classString); - $namespaceToTest = $classStringArray[0]; - - if (0 === strcmp($namespaceToTest, substr($import, -strlen($namespaceToTest)))) { - $classImport = $import; - break; - } - } - - $tokens->clearRange($classBeginIndex, $classIndex); - $tokens->insertAt($classBeginIndex, new Token(array( - T_CONSTANT_ENCAPSED_STRING, - "'".$this->makeClassFQN($classImport, $classString)."'", - ))); - } - - /** - * @param string|false $classImport - * @param string $classString - * - * @return string - */ - private function makeClassFQN($classImport, $classString) - { - if (false === $classImport) { - return $classString; - } - - $classStringArray = explode('\\', $classString); - $classStringLength = count($classStringArray); - $classImportArray = explode('\\', $classImport); - $classImportLength = count($classImportArray); - - if (1 === $classStringLength) { - return $classImport; - } - - return implode('\\', array_merge( - array_slice($classImportArray, 0, $classImportLength - $classStringLength + 1), - $classStringArray - )); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ConcatWithSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ConcatWithSpacesFixer.php deleted file mode 100644 index 2a58784..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ConcatWithSpacesFixer.php +++ /dev/null @@ -1,85 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class ConcatWithSpacesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - if (!$tokens[$index]->equals('.')) { - continue; - } - - $this->fixWhiteSpaceAroundConcatToken($tokens, $index, 1); - $this->fixWhiteSpaceAroundConcatToken($tokens, $index, -1); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Concatenation should be used with at least one whitespace around.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the ConcatWithoutSpacesFixer - return -10; - } - - /** - * @param Tokens $tokens - * @param int $index Index of concat token - * @param int $offset 1 or -1 - */ - private function fixWhiteSpaceAroundConcatToken(Tokens $tokens, $index, $offset) - { - $offsetIndex = $index + $offset; - - if (!$tokens[$offsetIndex]->isWhitespace()) { - $tokens->insertAt($index + (1 === $offset ?: 0), new Token(array(T_WHITESPACE, ' '))); - - return; - } - - if (false !== strpos($tokens[$offsetIndex]->getContent(), "\n")) { - return; - } - - if ($tokens[$index + $offset * 2]->isComment()) { - return; - } - - $tokens[$offsetIndex]->setContent(' '); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EchoToPrintFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EchoToPrintFixer.php deleted file mode 100644 index cdcecf8..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EchoToPrintFixer.php +++ /dev/null @@ -1,91 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Sullivan Senechal - */ -final class EchoToPrintFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $echoTokens = $tokens->findGivenKind(T_ECHO); - - if (defined('HHVM_VERSION')) { - /* - * HHVM parses 'getContent(), ' $echoToken) { - $nextTokenIndex = $tokens->getNextMeaningfulToken($echoIndex); - $endTokenIndex = $tokens->getNextTokenOfKind($echoIndex, array(';', array(T_CLOSE_TAG))); - $canBeConverted = true; - for ($i = $nextTokenIndex; $i < $endTokenIndex; ++$i) { - if ($tokens[$i]->equalsAny(array('(', '['))) { - $blockType = $tokens->detectBlockType($tokens[$i]); - $i = $tokens->findBlockEnd($blockType['type'], $i); - } - - if ($tokens[$i]->equals(',')) { - $canBeConverted = false; - break; - } - } - - if (false === $canBeConverted) { - continue; - } - - $tokens->overrideAt($echoIndex, array(T_PRINT, 'print')); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Converts echo language construct to print if possible.'; - } - - /** - * EchoToPrintFixer should run after ShortEchoTagFixer. - * - * {@inheritdoc} - */ - public function getPriority() - { - return -10; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EmptyReturnFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EmptyReturnFixer.php deleted file mode 100644 index acab942..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EmptyReturnFixer.php +++ /dev/null @@ -1,120 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class EmptyReturnFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_RETURN) as $index => $token) { - if ($this->needFixing($tokens, $index)) { - $this->clear($tokens, $index); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'A return statement wishing to return nothing should be simply "return". Warning! This could change code behavior.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before NoUselessReturnFixer - return -17; - } - - /** - * Does the return statement located at a given index need fixing? - * - * @param Tokens $tokens - * @param int $index - * - * @return bool - */ - private function needFixing(Tokens $tokens, $index) - { - $content = ''; - - while (!$tokens[$index]->equals(';')) { - $index = $tokens->getNextMeaningfulToken($index); - $content .= $tokens[$index]->getContent(); - } - - $content = rtrim($content, ';'); - $content = ltrim($content, '('); - $content = rtrim($content, ')'); - - return 'null' === strtolower($content); - } - - /** - * Clear the return statement located at a given index. - * - * @param Tokens $tokens - * @param int $index - */ - private function clear(Tokens $tokens, $index) - { - while (!$tokens[++$index]->equals(';')) { - if ($this->shouldClearToken($tokens, $index)) { - $tokens[$index]->clear(); - } - } - } - - /** - * Should we clear the specific token? - * - * If the token is a comment, or is whitespace that is immediately before a - * comment, then we'll leave it alone. - * - * @param Tokens $tokens - * @param int $index - * - * @return bool - */ - private function shouldClearToken(Tokens $tokens, $index) - { - $token = $tokens[$index]; - - if ($token->isComment()) { - return false; - } - - if ($token->isWhitespace() && $tokens[$index + 1]->isComment()) { - return false; - } - - return true; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/HeaderCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/HeaderCommentFixer.php deleted file mode 100644 index c60a52f..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/HeaderCommentFixer.php +++ /dev/null @@ -1,156 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\ConfigurationException\InvalidFixerConfigurationException; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Antonio J. García Lagar - */ -class HeaderCommentFixer extends AbstractFixer -{ - private static $header = ''; - private static $headerComment = ''; - - /** - * Sets the desired header text. - * - * The given text will be trimmed and enclosed into a multiline comment. - * If the text is empty, when a file get fixed, the header comment will be - * erased. - * - * @param string $header - */ - public static function setHeader($header) - { - if (!is_string($header)) { - throw new InvalidFixerConfigurationException('header_comment', sprintf('Header configuration is invalid. Expected "string", got "%s".', is_object($header) ? get_class($header) : gettype($header))); - } - - self::$header = trim((string) $header); - self::$headerComment = ''; - - if ('' !== self::$header) { - self::$headerComment = self::encloseTextInComment(self::$header); - } - } - - /** - * @return string - */ - public static function getHeader() - { - return self::$header; - } - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - if (!$tokens[0]->isGivenKind(T_OPEN_TAG) || !$tokens->isMonolithicPhp()) { - return $content; - } - - $this->removeHeaderComment($tokens); - $insertionIndex = $this->findHeaderCommentInsertionIndex($tokens); - $tokens->clearRange(1, $insertionIndex - 1); - $this->insertHeaderComment($tokens, $insertionIndex); - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Add, replace or remove header comment.'; - } - - /** - * Encloses the given text in a comment block. - * - * @param string $header - * - * @return string - */ - private static function encloseTextInComment($header) - { - $comment = "/*\n"; - $lines = explode("\n", str_replace("\r", '', $header)); - foreach ($lines as $line) { - $comment .= rtrim(' * '.$line)."\n"; - } - $comment .= ' */'; - - return $comment; - } - - /** - * Removes the header comment, if any. - * - * @param Tokens $tokens - */ - private function removeHeaderComment(Tokens $tokens) - { - $index = $tokens->getNextNonWhitespace(0); - if (null !== $index && $tokens[$index]->isGivenKind(T_COMMENT)) { - $tokens[$index]->clear(); - } - } - - /** - * Finds the index where the header comment must be inserted. - * - * @param Tokens $tokens - * - * @return int - */ - private function findHeaderCommentInsertionIndex(Tokens $tokens) - { - $index = $tokens->getNextNonWhitespace(0); - - if (null === $index) { - //Empty file, insert at the end - $index = $tokens->getSize(); - } - - return $index; - } - - /** - * Inserts the header comment at the given index. - * - * @param Tokens $tokens - * @param int $index - */ - private function insertHeaderComment(Tokens $tokens, $index) - { - $headCommentTokens = array( - new Token(array(T_WHITESPACE, "\n")), - ); - - if ('' !== self::$headerComment) { - $headCommentTokens[] = new Token(array(T_COMMENT, self::$headerComment)); - $headCommentTokens[] = new Token(array(T_WHITESPACE, "\n\n")); - } - - $tokens->insertAt($index, $headCommentTokens); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LogicalNotOperatorsWithSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LogicalNotOperatorsWithSpacesFixer.php deleted file mode 100644 index 197ec5a..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LogicalNotOperatorsWithSpacesFixer.php +++ /dev/null @@ -1,64 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Javier Spagnoletti - */ -final class LogicalNotOperatorsWithSpacesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - $token = $tokens[$index]; - - if ($tokens->isUnaryPredecessorOperator($index) && $token->equals('!')) { - if (!$tokens[$index + 1]->isWhitespace()) { - $tokens->insertAt($index + 1, new Token(array(T_WHITESPACE, ' '))); - } - - if (!$tokens[$index - 1]->isWhitespace()) { - $tokens->insertAt($index, new Token(array(T_WHITESPACE, ' '))); - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Logical NOT operators (!) should have leading and trailing whitespaces.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the UnaryOperatorsSpacesFixer - return -10; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LogicalNotOperatorsWithSuccessorSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LogicalNotOperatorsWithSuccessorSpaceFixer.php deleted file mode 100644 index c4d5627..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LogicalNotOperatorsWithSuccessorSpaceFixer.php +++ /dev/null @@ -1,62 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Javier Spagnoletti - */ -final class LogicalNotOperatorsWithSuccessorSpaceFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - $token = $tokens[$index]; - - if ($tokens->isUnaryPredecessorOperator($index) && $token->equals('!')) { - if (!$tokens[$index + 1]->isWhitespace()) { - $tokens->insertAt($index + 1, new Token(array(T_WHITESPACE, ' '))); - } else { - $tokens[$index + 1]->setContent(' '); - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Logical NOT operators (!) should have one trailing whitespace.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the UnaryOperatorsSpacesFixer - return -10; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LongArraySyntaxFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LongArraySyntaxFixer.php deleted file mode 100644 index 24cd84b..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/LongArraySyntaxFixer.php +++ /dev/null @@ -1,54 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Gregor Harlan - */ -class LongArraySyntaxFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; 0 <= $index; --$index) { - if (!$tokens->isShortArray($index)) { - continue; - } - - $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $index); - - $tokens->overrideAt($index, '('); - $tokens->overrideAt($closeIndex, ')'); - - $tokens->insertAt($index, new Token(array(T_ARRAY, 'array'))); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Arrays should use the long syntax.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/MbStrFunctionsFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/MbStrFunctionsFixer.php deleted file mode 100644 index ce350e0..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/MbStrFunctionsFixer.php +++ /dev/null @@ -1,97 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Filippo Tessarotto - */ -final class MbStrFunctionsFixer extends AbstractFixer -{ - /** - * @var array the list of the string-related function names and their mb_ equivalent - */ - private static $functions = array( - 'strlen' => 'mb_strlen', - 'strpos' => 'mb_strpos', - 'strrpos' => 'mb_strrpos', - 'substr' => 'mb_substr', - 'strtolower' => 'mb_strtolower', - 'strtoupper' => 'mb_strtoupper', - 'stripos' => 'mb_stripos', - 'strripos' => 'mb_strripos', - 'strstr' => 'mb_strstr', - 'stristr' => 'mb_stristr', - 'strrchr' => 'mb_strrchr', - 'substr_count' => 'mb_substr_count', - ); - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - $end = $tokens->count() - 1; - - foreach (self::$functions as $originalName => $mbFunctionName) { - // the sequence is the function name, followed by "(" and a quoted string - $seq = array(array(T_STRING, $originalName), '('); - - $currIndex = 0; - while (null !== $currIndex) { - $match = $tokens->findSequence($seq, $currIndex, $end, false); - - // did we find a match? - if (null === $match) { - break; - } - - // findSequence also returns the tokens, but we're only interested in the indexes, i.e.: - // 0 => function name, - // 1 => bracket "(" - $match = array_keys($match); - - // advance tokenizer cursor - $currIndex = $match[1]; - - // ensure it's a function call (not a method / static call) - $prev = $tokens->getPrevMeaningfulToken($match[0]); - if (null === $prev || $tokens[$prev]->isGivenKind(array(T_OBJECT_OPERATOR, T_DOUBLE_COLON, T_NEW))) { - continue; - } - if ($tokens[$prev]->isGivenKind(T_NS_SEPARATOR)) { - $nsPrev = $tokens->getPrevMeaningfulToken($prev); - if ($tokens[$nsPrev]->isGivenKind(array(T_STRING, T_NEW))) { - continue; - } - } - - // modify function and argument - $tokens[$match[0]]->setContent($mbFunctionName); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Replace non multibyte-safe functions with corresponding mb function. Warning! This could change code behavior.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/MultilineSpacesBeforeSemicolonFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/MultilineSpacesBeforeSemicolonFixer.php deleted file mode 100644 index 3ebefdb..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/MultilineSpacesBeforeSemicolonFixer.php +++ /dev/null @@ -1,52 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class MultilineSpacesBeforeSemicolonFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->equals(';')) { - continue; - } - - $previous = $tokens[$index - 1]; - - if ($previous->isWhitespace() && false !== strpos($previous->getContent(), "\n")) { - $previous->clear(); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Multi-line whitespace before closing semicolon are prohibited.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NewlineAfterOpenTagFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NewlineAfterOpenTagFixer.php deleted file mode 100644 index 15a8285..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NewlineAfterOpenTagFixer.php +++ /dev/null @@ -1,61 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Ceeram - */ -class NewlineAfterOpenTagFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - // ignore files with short open tag and ignore non-monolithic files - if (!$tokens[0]->isGivenKind(T_OPEN_TAG) || !$tokens->isMonolithicPhp()) { - return $content; - } - - $newlineFound = false; - foreach ($tokens as $token) { - if ($token->isWhitespace() && false !== strpos($token->getContent(), "\n")) { - $newlineFound = true; - break; - } - } - - // ignore one-line files - if (!$newlineFound) { - return $content; - } - - $token = $tokens[0]; - $token->setContent(rtrim($token->getContent())."\n"); - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Ensure there is no code on the same line as the PHP open tag.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoBlankLinesBeforeNamespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoBlankLinesBeforeNamespaceFixer.php deleted file mode 100644 index 533fcc0..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoBlankLinesBeforeNamespaceFixer.php +++ /dev/null @@ -1,46 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractLinesBeforeNamespaceFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class NoBlankLinesBeforeNamespaceFixer extends AbstractLinesBeforeNamespaceFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if ($token->isGivenKind(T_NAMESPACE)) { - $this->fixLinesBeforeNamespace($tokens, $index, 1); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There should be no blank lines before a namespace declaration.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoUselessElseFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoUselessElseFixer.php deleted file mode 100644 index 794b393..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoUselessElseFixer.php +++ /dev/null @@ -1,225 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author SpacePossum - */ -final class NoUselessElseFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - foreach ($tokens as $index => $token) { - if (!$token->isGivenKind(T_ELSE)) { - continue; - } - - // `else if` vs. `else` and alternative syntax `else:` checks - if ($tokens[$tokens->getNextMeaningfulToken($index)]->equalsAny(array(':', array(T_IF)))) { - continue; - } - - // clean up `else` if it is an empty statement - $this->fixEmptyElse($tokens, $index); - if ($token->isEmpty()) { - continue; - } - - // clean up `else` if possible - $this->fixElse($tokens, $index); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There should not be useless else cases.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before DuplicateSemicolonFixer, WhitespacyLinesFixer, ExtraEmptyLinesFixer and BracesFixer. - return 25; - } - - /** - * @param Tokens $tokens - * @param int $index T_ELSE index - */ - private function fixElse(Tokens $tokens, $index) - { - $previousBlockStart = $index; - do { - // Check if all 'if', 'else if ' and 'elseif' blocks above this 'else' always end, - // if so this 'else' is overcomplete. - list($previousBlockStart, $previousBlockEnd) = $this->getPreviousBlock($tokens, $previousBlockStart); - - // short 'if' detection - $previous = $previousBlockEnd; - if ($tokens[$previous]->equals('}')) { - $previous = $tokens->getPrevMeaningfulToken($previous); - } - - if ( - !$tokens[$previous]->equals(';') || // 'if' block doesn't end with semicolon, keep 'else' - $tokens[$tokens->getPrevMeaningfulToken($previous)]->equals('{') // empty 'if' block, keep 'else' - ) { - return; - } - - $candidateIndex = $tokens->getTokenOfKindSibling( - $previous, - -1, - array( - ';', - array(T_CLOSE_TAG), - array(T_BREAK), - array(T_CONTINUE), - array(T_EXIT), - array(T_GOTO), - array(T_RETURN), - array(T_THROW), - ) - ); - - if ( - null === $candidateIndex || - $tokens[$candidateIndex]->equals(';') || - $tokens[$candidateIndex]->isGivenKind(T_CLOSE_TAG) || - $this->isInConditional($tokens, $candidateIndex, $previousBlockStart) - ) { - return; - } - - // implicit continue, i.e. delete candidate - } while (!$tokens[$previousBlockStart]->isGivenKind(T_IF)); - - // if we made it to here the 'else' can be removed - $this->clearElse($tokens, $index); - } - - /** - * Return the first and last token index of the previous block. - * - * [0] First is either T_IF, T_ELSE or T_ELSEIF - * [1] Last is either '}' or ';' / T_CLOSE_TAG for short notation blocks - * - * @param Tokens $tokens - * @param int $index T_IF, T_ELSE, T_ELSEIF - * - * @return int[] - */ - private function getPreviousBlock(Tokens $tokens, $index) - { - $close = $previous = $tokens->getPrevMeaningfulToken($index); - // short 'if' detection - if ($tokens[$close]->equals('}')) { - $previous = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $close, false); - } - - $open = $tokens->getPrevTokenOfKind($previous, array(array(T_IF), array(T_ELSE), array(T_ELSEIF))); - if ($tokens[$open]->isGivenKind(T_IF)) { - $elseCandidate = $tokens->getPrevMeaningfulToken($open); - if ($tokens[$elseCandidate]->isGivenKind(T_ELSE)) { - $open = $elseCandidate; - } - } - - return array($open, $close); - } - - /** - * Remove tokens part of an `else` statement if not empty (i.e. no meaningful tokens inside). - * - * @param Tokens $tokens - * @param int $index T_ELSE index - */ - private function fixEmptyElse(Tokens $tokens, $index) - { - $next = $tokens->getNextMeaningfulToken($index); - if ($tokens[$next]->equals('{')) { - $close = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $next); - if (1 === $close - $next) { // '{}' - $this->clearElse($tokens, $index); - } elseif ($tokens->getNextMeaningfulToken($next) === $close) { // '{/**/}' - $this->clearElse($tokens, $index); - } - - return; - } - - // short `else` - $end = $tokens->getNextTokenOfKind($index, array(';', array(T_CLOSE_TAG))); - if ($next === $end) { - $this->clearElse($tokens, $index); - } - } - - /** - * @param Tokens $tokens - * @param int $index index of T_ELSE - */ - private function clearElse(Tokens $tokens, $index) - { - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - - // clear T_ELSE and the '{' '}' if there are any - $next = $tokens->getNextMeaningfulToken($index); - if (!$tokens[$next]->equals('{')) { - return; - } - - $tokens->clearTokenAndMergeSurroundingWhitespace($tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $next)); - $tokens->clearTokenAndMergeSurroundingWhitespace($next); - } - - /** - * @param Tokens $tokens - * @param int $index Index of the token to check - * @param int $lowerLimitIndex Lower limit index. Since the token to check will always be in a conditional we must stop checking at this index - * - * @return bool - */ - private function isInConditional(Tokens $tokens, $index, $lowerLimitIndex) - { - $candidateIndex = $tokens->getTokenOfKindSibling($index, -1, array(')', ';', ':')); - if ($tokens[$candidateIndex]->equals(':')) { - return true; - } - - if (!$tokens[$candidateIndex]->equals(')')) { - return false; // token is ';' or close tag - } - - // token is always ')' here. - // If it is part of the condition the token is always in, return false. - // If it is not it is a nested condition so return true - $open = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $candidateIndex, false); - - return $tokens->getPrevMeaningfulToken($open) > $lowerLimitIndex; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/OrderedUseFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/OrderedUseFixer.php deleted file mode 100644 index 253bfae..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/OrderedUseFixer.php +++ /dev/null @@ -1,247 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Sebastiaan Stok - * @author Dariusz Rumiński - * @author SpacePossum - */ -class OrderedUseFixer extends AbstractFixer -{ - const IMPORT_TYPE_CLASS = 1; - const IMPORT_TYPE_CONST = 2; - const IMPORT_TYPE_FUNCTION = 3; - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - $namespacesImports = $tokens->getImportUseIndexes(true); - - if (0 === count($namespacesImports)) { - return $content; - } - - $usesOrder = array(); - foreach ($namespacesImports as $uses) { - $usesOrder = array_replace($usesOrder, $this->getNewOrder(array_reverse($uses), $tokens)); - } - - // First clean the old content - // This must be done first as the indexes can be scattered - foreach ($usesOrder as $use) { - $tokens->clearRange($use['startIndex'], $use['endIndex']); - } - - $usesOrder = array_reverse($usesOrder, true); - - // Now insert the new tokens, starting from the end - foreach ($usesOrder as $index => $use) { - $declarationTokens = Tokens::fromCode('clearRange(0, 2); // clear `clear(); // clear `;` - $declarationTokens->clearEmptyTokens(); - - $tokens->insertAt($index, $declarationTokens); - if ($use['group']) { - // a group import must start with `use` and cannot be part of comma separated import list - $prev = $tokens->getPrevMeaningfulToken($index); - if ($tokens[$prev]->equals(',')) { - $tokens[$prev]->setContent(';'); - $tokens->insertAt($prev + 1, new Token(array(T_USE, 'use'))); - if (!$tokens[$prev + 2]->isWhitespace()) { - $tokens->insertAt($prev + 2, new Token(array(T_WHITESPACE, ' '))); - } - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Ordering use statements.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the RemoveLeadingSlashUseFixer - return -30; - } - - /** - * This method is used for sorting the uses in a namespace. - * - * @param string[] $first - * @param string[] $second - * - * @return int - * - * @internal - */ - public static function sortingCallBack(array $first, array $second) - { - if ($first['importType'] !== $second['importType']) { - return $first['importType'] > $second['importType'] ? 1 : -1; - } - - $firstNamespace = trim(preg_replace('%/\*(.*)\*/%s', '', $first['namespace'])); - $secondNamespace = trim(preg_replace('%/\*(.*)\*/%s', '', $second['namespace'])); - - // Replace backslashes by spaces before sorting for correct sort order - return strcasecmp( - str_replace('\\', ' ', $firstNamespace), - str_replace('\\', ' ', $secondNamespace) - ); - } - - private function getNewOrder(array $uses, Tokens $tokens) - { - $indexes = array(); - $originalIndexes = array(); - - for ($i = count($uses) - 1; $i >= 0; --$i) { - $index = $uses[$i]; - - $startIndex = $tokens->getTokenNotOfKindSibling($index + 1, 1, array(array(T_WHITESPACE))); - $endIndex = $tokens->getNextTokenOfKind($startIndex, array(';', array(T_CLOSE_TAG))); - $previous = $tokens->getPrevMeaningfulToken($endIndex); - - $group = $tokens[$previous]->equals('}'); - if ($tokens[$startIndex]->isGivenKind(array(T_CONST))) { - $type = self::IMPORT_TYPE_CONST; - } elseif ($tokens[$startIndex]->isGivenKind(array(T_FUNCTION))) { - $type = self::IMPORT_TYPE_FUNCTION; - } else { - $type = self::IMPORT_TYPE_CLASS; - } - - $namespaceTokens = array(); - $index = $startIndex; - - while ($index <= $endIndex) { - $token = $tokens[$index]; - - if ($index === $endIndex || (!$group && $token->equals(','))) { - if ($group) { - // if group import, sort the items within the group definition - - // figure out where the list of namespace parts within the group def. starts - $namespaceTokensCount = count($namespaceTokens) - 1; - $namespace = ''; - for ($k = 0; $k < $namespaceTokensCount; ++$k) { - if ($namespaceTokens[$k]->equals('{')) { - $namespace .= '{'; - break; - } - - $namespace .= $namespaceTokens[$k]->getContent(); - } - - // fetch all parts, split up in an array of strings, move comments to the end - $parts = array(); - for ($k1 = $k + 1; $k1 < $namespaceTokensCount; ++$k1) { - $comment = ''; - $namespacePart = ''; - for ($k2 = $k1; ; ++$k2) { - if ($namespaceTokens[$k2]->equalsAny(array(',', '}'))) { - break; - } - - if ($namespaceTokens[$k2]->isComment()) { - $comment .= $namespaceTokens[$k2]->getContent(); - - continue; - } - - $namespacePart .= $namespaceTokens[$k2]->getContent(); - } - - $namespacePart = trim($namespacePart); - $comment = trim($comment); - if ('' !== $comment) { - $namespacePart .= ' '.$comment; - } - - $parts[] = $namespacePart.', '; - - $k1 = $k2; - } - - $sortedParts = $parts; - sort($parts); - - // check if the order needs to be updated, otherwise don't touch as we might change valid CS (to other valid CS). - if ($sortedParts === $parts) { - $namespace = Tokens::fromArray($namespaceTokens)->generateCode(); - } else { - $namespace .= substr(implode('', $parts), 0, -2).'}'; - } - } else { - $namespace = Tokens::fromArray($namespaceTokens)->generateCode(); - } - - $indexes[$startIndex] = array( - 'namespace' => $namespace, - 'startIndex' => $startIndex, - 'endIndex' => $index - 1, - 'importType' => $type, - 'group' => $group, - ); - - $originalIndexes[] = $startIndex; - - if ($index === $endIndex) { - break; - } - - $namespaceTokens = array(); - $nextPartIndex = $tokens->getTokenNotOfKindSibling($index, 1, array(array(','), array(T_WHITESPACE))); - $startIndex = $nextPartIndex; - $index = $nextPartIndex; - - continue; - } - - $namespaceTokens[] = $token; - ++$index; - } - } - - uasort($indexes, 'self::sortingCallBack'); - - $index = -1; - $usesOrder = array(); - - // Loop trough the index but use original index order - foreach ($indexes as $v) { - $usesOrder[$originalIndexes[++$index]] = $v; - } - - return $usesOrder; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitConstructFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitConstructFixer.php deleted file mode 100644 index dfc9d19..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitConstructFixer.php +++ /dev/null @@ -1,180 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\ConfigurationException\InvalidFixerConfigurationException; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -final class PhpUnitConstructFixer extends AbstractFixer -{ - private $configuration = array( - 'assertSame' => true, - 'assertEquals' => true, - 'assertNotEquals' => true, - 'assertNotSame' => true, - ); - - private $assertionFixers = array( - 'assertSame' => 'fixAssertPositive', - 'assertEquals' => 'fixAssertPositive', - 'assertNotEquals' => 'fixAssertNegative', - 'assertNotSame' => 'fixAssertNegative', - ); - - /** - * @param array $usingMethods - */ - public function configure(array $usingMethods) - { - foreach ($usingMethods as $method => $fix) { - if (!array_key_exists($method, $this->configuration)) { - throw new InvalidFixerConfigurationException($this->getName(), sprintf('Configured method "%s" cannot be fixed by this fixer.', $method)); - } - - $this->configuration[$method] = $fix; - } - } - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - // no assertions to be fixed - fast return - if (!in_array(true, $this->configuration, true)) { - return $content; - } - - $tokens = Tokens::fromCode($content); - - foreach ($this->configuration as $assertionMethod => $assertionShouldBeFixed) { - if (true !== $assertionShouldBeFixed) { - continue; - } - - $assertionFixer = $this->assertionFixers[$assertionMethod]; - - for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { - $index = $this->$assertionFixer($tokens, $index, $assertionMethod); - - if (null === $index) { - break; - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'PHPUnit assertion method calls like "->assertSame(true, $foo)" should be written with dedicated method like "->assertTrue($foo)". Warning! This could change code behavior.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the PhpUnitStrictFixer and before PhpUnitDedicateAssertFixer. - return -10; - } - - /** - * @param Tokens $tokens - * @param int $index - * @param string $method - * - * @return int|null - */ - private function fixAssertNegative(Tokens $tokens, $index, $method) - { - static $map = array( - 'false' => 'assertNotFalse', - 'null' => 'assertNotNull', - 'true' => 'assertNotTrue', - ); - - return $this->fixAssert($map, $tokens, $index, $method); - } - - /** - * @param Tokens $tokens - * @param int $index - * @param string $method - * - * @return int|null - */ - private function fixAssertPositive(Tokens $tokens, $index, $method) - { - static $map = array( - 'false' => 'assertFalse', - 'null' => 'assertNull', - 'true' => 'assertTrue', - ); - - return $this->fixAssert($map, $tokens, $index, $method); - } - - /** - * @param array $map - * @param Tokens $tokens - * @param int $index - * @param string $method - * - * @return int|null - */ - private function fixAssert(array $map, Tokens $tokens, $index, $method) - { - $sequence = $tokens->findSequence( - array( - array(T_VARIABLE, '$this'), - array(T_OBJECT_OPERATOR, '->'), - array(T_STRING, $method), - '(', - ), - $index - ); - - if (null === $sequence) { - return; - } - - $sequenceIndexes = array_keys($sequence); - $sequenceIndexes[4] = $tokens->getNextMeaningfulToken($sequenceIndexes[3]); - $firstParameterToken = $tokens[$sequenceIndexes[4]]; - - if (!$firstParameterToken->isNativeConstant()) { - return; - } - - $sequenceIndexes[5] = $tokens->getNextMeaningfulToken($sequenceIndexes[4]); - - // return if first method argument is an expression, not value - if (!$tokens[$sequenceIndexes[5]]->equals(',')) { - return; - } - - $tokens[$sequenceIndexes[2]]->setContent($map[$firstParameterToken->getContent()]); - $tokens->clearRange($sequenceIndexes[4], $tokens->getNextNonWhitespace($sequenceIndexes[5]) - 1); - - return $sequenceIndexes[5]; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitDedicateAssertFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitDedicateAssertFixer.php deleted file mode 100644 index db68230..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitDedicateAssertFixer.php +++ /dev/null @@ -1,264 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\ConfigurationException\InvalidFixerConfigurationException; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author SpacePossum - */ -final class PhpUnitDedicateAssertFixer extends AbstractFixer -{ - private $fixMap = array( - 'array_key_exists' => array('assertArrayNotHasKey', 'assertArrayHasKey'), - 'empty' => array('assertNotEmpty', 'assertEmpty'), - 'file_exists' => array('assertFileNotExists', 'assertFileExists'), - 'is_infinite' => array('assertFinite', 'assertInfinite'), - 'is_nan' => array(false, 'assertNan'), - 'is_null' => array('assertNotNull', 'assertNull'), - 'is_array' => true, - 'is_bool' => true, - 'is_boolean' => true, - 'is_callable' => true, - 'is_double' => true, - 'is_float' => true, - 'is_int' => true, - 'is_integer' => true, - 'is_long' => true, - 'is_​numeric' => true, - 'is_object' => true, - 'is_real' => true, - 'is_​resource' => true, - 'is_scalar' => true, - 'is_string' => true, - ); - - private $configuration = array( - 'array_key_exists', - 'empty', - 'file_exists', - 'is_infinite', - 'is_nan', - 'is_null', - 'is_array', - 'is_bool', - 'is_boolean', - 'is_callable', - 'is_double', - 'is_float', - 'is_int', - 'is_integer', - 'is_long', - 'is_​numeric', - 'is_object', - 'is_real', - 'is_​resource', - 'is_scalar', - 'is_string', - ); - - /** - * @param array|null $configuration - */ - public function configure(array $configuration = null) - { - if (null === $configuration) { - return; - } - - $this->configuration = array(); - foreach ($configuration as $method) { - if (!array_key_exists($method, $this->fixMap)) { - throw new InvalidFixerConfigurationException($this->getName(), sprintf('Unknown configuration method "%s".', $method)); - } - - $this->configuration[] = $method; - } - } - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - static $searchSequence = array( - array(T_VARIABLE, '$this'), - array(T_OBJECT_OPERATOR, '->'), - array(T_STRING), - ); - - $index = 1; - $candidate = $tokens->findSequence($searchSequence, $index); - while (null !== $candidate) { - end($candidate); - $index = $this->getAssertCandidate($tokens, key($candidate)); - if (is_array($index)) { - $index = $this->fixAssert($tokens, $index); - } - - ++$index; - $candidate = $tokens->findSequence($searchSequence, $index); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'PHPUnit assertions like "assertInternalType", "assertFileExists", should be used over "assertTrue". Warning! This could change code behavior.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the PhpUnitConstructFixer. - return -15; - } - - /** - * @param Tokens $tokens - * @param int $assertCallIndex Token index of assert method call - * - * @return int|int[] indexes of assert call, test call and positive flag, or last index checked - */ - private function getAssertCandidate(Tokens $tokens, $assertCallIndex) - { - $content = strtolower($tokens[$assertCallIndex]->getContent()); - if ('asserttrue' === $content) { - $isPositive = 1; - } elseif ('assertfalse' === $content) { - $isPositive = 0; - } else { - return $assertCallIndex; - } - - // test candidate for simple calls like: ([\]+'some fixable call'(...)) - $assertCallOpenIndex = $tokens->getNextMeaningfulToken($assertCallIndex); - if (!$tokens[$assertCallOpenIndex]->equals('(')) { - return $assertCallIndex; - } - - $testDefaultNamespaceTokenIndex = false; - $testIndex = $tokens->getNextMeaningfulToken($assertCallOpenIndex); - - if (!$tokens[$testIndex]->isGivenKind(array(T_EMPTY, T_STRING))) { - if (!$tokens[$testIndex]->isGivenKind(T_NS_SEPARATOR)) { - return $testIndex; - } - - $testDefaultNamespaceTokenIndex = $testIndex; - $testIndex = $tokens->getNextMeaningfulToken($testIndex); - } - - $testOpenIndex = $tokens->getNextMeaningfulToken($testIndex); - if (!$tokens[$testOpenIndex]->equals('(')) { - return $testOpenIndex; - } - - $testCloseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $testOpenIndex); - - $assertCallCloseIndex = $tokens->getNextMeaningfulToken($testCloseIndex); - if (!$tokens[$assertCallCloseIndex]->equalsAny(array(')', ','))) { - return $assertCallCloseIndex; - } - - return array( - $isPositive, - $assertCallIndex, - $assertCallOpenIndex, - $testDefaultNamespaceTokenIndex, - $testIndex, - $testOpenIndex, - $testCloseIndex, - $assertCallCloseIndex, - ); - } - - /** - * @param Tokens $tokens - * @param array $assertIndexes - * - * @return int index up till processed, number of tokens added - */ - private function fixAssert(Tokens $tokens, array $assertIndexes) - { - list( - $isPositive, - $assertCallIndex, - $assertCallOpenIndex, - $testDefaultNamespaceTokenIndex, - $testIndex, - $testOpenIndex, - $testCloseIndex, - $assertCallCloseIndex - ) = $assertIndexes; - - $content = strtolower($tokens[$testIndex]->getContent()); - if (!in_array($content, $this->configuration, true)) { - return $assertCallCloseIndex; - } - - if (is_array($this->fixMap[$content])) { - if (false !== $this->fixMap[$content][$isPositive]) { - $tokens[$assertCallIndex]->setContent($this->fixMap[$content][$isPositive]); - $this->removeFunctionCall($tokens, $testDefaultNamespaceTokenIndex, $testIndex, $testOpenIndex, $testCloseIndex); - } - - return $assertCallCloseIndex; - } - - $type = substr($content, 3); - $tokens[$assertCallIndex]->setContent($isPositive ? 'assertInternalType' : 'assertNotInternalType'); - $tokens->overrideAt($testIndex, array(T_CONSTANT_ENCAPSED_STRING, "'".$type."'", $tokens[$testIndex]->getLine())); - $tokens->overrideAt($testOpenIndex, ','); - $tokens->clearTokenAndMergeSurroundingWhitespace($testCloseIndex); - - if (!$tokens[$testOpenIndex + 1]->isWhitespace()) { - $tokens->insertAt($testOpenIndex + 1, new Token(array(T_WHITESPACE, ' '))); - } - - if (false !== $testDefaultNamespaceTokenIndex) { - $tokens->clearTokenAndMergeSurroundingWhitespace($testDefaultNamespaceTokenIndex); - } - - return $assertCallCloseIndex; - } - - /** - * @param Tokens $tokens - * @param int|false $callNSIndex - * @param int $callIndex - * @param int $openIndex - * @param int $closeIndex - */ - private function removeFunctionCall(Tokens $tokens, $callNSIndex, $callIndex, $openIndex, $closeIndex) - { - $tokens->clearTokenAndMergeSurroundingWhitespace($callIndex); - if (false !== $callNSIndex) { - $tokens->clearTokenAndMergeSurroundingWhitespace($callNSIndex); - } - - $tokens->clearTokenAndMergeSurroundingWhitespace($openIndex); - $tokens->clearTokenAndMergeSurroundingWhitespace($closeIndex); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitStrictFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitStrictFixer.php deleted file mode 100644 index 984885e..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpUnitStrictFixer.php +++ /dev/null @@ -1,79 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -final class PhpUnitStrictFixer extends AbstractFixer -{ - private $configuration = array( - 'assertAttributeEquals' => 'assertAttributeSame', - 'assertAttributeNotEquals' => 'assertAttributeNotSame', - 'assertEquals' => 'assertSame', - 'assertNotEquals' => 'assertNotSame', - ); - - public function configure(array $usingMethods) - { - foreach (array_keys($this->configuration) as $method) { - if (!in_array($method, $usingMethods, true)) { - unset($this->configuration[$method]); - } - } - } - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($this->configuration as $methodBefore => $methodAfter) { - for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { - $sequence = $tokens->findSequence( - array( - array(T_VARIABLE, '$this'), - array(T_OBJECT_OPERATOR, '->'), - array(T_STRING, $methodBefore), - '(', - ), - $index - ); - - if (null === $sequence) { - break; - } - - $sequenceIndexes = array_keys($sequence); - $tokens[$sequenceIndexes[2]]->setContent($methodAfter); - - $index = $sequenceIndexes[3]; - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'PHPUnit methods like "assertSame" should be used instead of "assertEquals". Warning! This could change code behavior.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpdocVarToTypeFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpdocVarToTypeFixer.php deleted file mode 100644 index 5223420..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpdocVarToTypeFixer.php +++ /dev/null @@ -1,57 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class PhpdocVarToTypeFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $token) { - $doc = new DocBlock($token->getContent()); - $annotations = $doc->getAnnotationsOfType('var'); - - if (empty($annotations)) { - continue; - } - - foreach ($annotations as $annotation) { - $line = $doc->getLine($annotation->getStart()); - $line->setContent(str_replace('@var', '@type', $line->getContent())); - } - - $token->setContent($doc->getContent()); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return '@var should always be written as @type.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ShortArraySyntaxFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ShortArraySyntaxFixer.php deleted file mode 100644 index f06bd8a..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ShortArraySyntaxFixer.php +++ /dev/null @@ -1,60 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Sebastiaan Stok - * @author Dariusz Rumiński - */ -class ShortArraySyntaxFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_ARRAY) as $index => $token) { - $openIndex = $tokens->getNextTokenOfKind($index, array('(')); - $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); - - $tokens->overrideAt($openIndex, '['); - $tokens->overrideAt($closeIndex, ']'); - - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'PHP arrays should use the PHP 5.4 short-syntax.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before the UnalignEqualsFixer and TernarySpacesFixer. - return 1; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ShortEchoTagFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ShortEchoTagFixer.php deleted file mode 100644 index c09fb3b..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ShortEchoTagFixer.php +++ /dev/null @@ -1,71 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Vincent Klaiber - */ -class ShortEchoTagFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - $i = count($tokens); - - while ($i--) { - $token = $tokens[$i]; - $nextIndex = $i + 1; - - if ( - !$token->isGivenKind(T_OPEN_TAG_WITH_ECHO) - && !( - /* - * HHVM parses 'equals(array(T_ECHO, 'overrideAt($i, array(T_OPEN_TAG, 'getLine())); - - if (!$tokens[$nextIndex]->isWhitespace()) { - $tokens->insertAt($nextIndex, new Token(array(T_WHITESPACE, ' '))); - } - - $tokens->insertAt($nextIndex, new Token(array(T_ECHO, 'echo'))); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Replace short-echo - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Jules Pietri - */ -final class SilencedDeprecationErrorFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - $token = $tokens[$index]; - if (!$token->equals(array(T_STRING, 'trigger_error'), false)) { - continue; - } - - $start = $index; - $prev = $tokens->getPrevMeaningfulToken($start); - if ($tokens[$prev]->isGivenKind(T_NS_SEPARATOR)) { - $start = $prev; - $prev = $tokens->getPrevMeaningfulToken($start); - } - - if ($tokens[$prev]->isGivenKind(T_STRING) || $tokens[$prev]->equals('@')) { - continue; - } - - $end = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextTokenOfKind($index, array(T_STRING, '('))); - if ($tokens[$tokens->getPrevMeaningfulToken($end)]->equals(array(T_STRING, 'E_USER_DEPRECATED'))) { - $tokens->insertAt($start, new Token('@')); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Ensures deprecation notices are silenced. Warning! This could change code behavior.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/StrictFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/StrictFixer.php deleted file mode 100644 index 284c6b7..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/StrictFixer.php +++ /dev/null @@ -1,59 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class StrictFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - static $map = array( - T_IS_EQUAL => array( - 'id' => T_IS_IDENTICAL, - 'content' => '===', - ), - T_IS_NOT_EQUAL => array( - 'id' => T_IS_NOT_IDENTICAL, - 'content' => '!==', - ), - ); - - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - $tokenId = $token->getId(); - - if (isset($map[$tokenId])) { - $tokens->overrideAt($index, array($map[$tokenId]['id'], $map[$tokenId]['content'], $token->getLine())); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Comparison should be strict. Warning! This could change code behavior.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/StrictParamFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/StrictParamFixer.php deleted file mode 100644 index cc3984d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/StrictParamFixer.php +++ /dev/null @@ -1,124 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class StrictParamFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - static $map = null; - - if (null === $map) { - $trueToken = new Token(array(T_STRING, 'true')); - - $map = array( - 'in_array' => array(null, null, $trueToken), - 'base64_decode' => array(null, $trueToken), - 'array_search' => array(null, null, $trueToken), - 'array_keys' => array(null, null, $trueToken), - 'mb_detect_encoding' => array(null, array(new Token(array(T_STRING, 'mb_detect_order')), new Token('('), new Token(')')), $trueToken), - ); - } - - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; 0 <= $index; --$index) { - $token = $tokens[$index]; - - if ($token->isGivenKind(T_STRING) && isset($map[$token->getContent()])) { - $this->fixFunction($tokens, $index, $map[$token->getContent()]); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Functions should be used with $strict param. Warning! This could change code behavior.'; - } - - private function fixFunction(Tokens $tokens, $functionIndex, array $functionParams) - { - $startBraceIndex = $tokens->getNextTokenOfKind($functionIndex, array('(')); - $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startBraceIndex); - $commaCounter = 0; - $sawParameter = false; - - for ($index = $startBraceIndex + 1; $index < $endBraceIndex; ++$index) { - $token = $tokens[$index]; - - if (!$token->isWhitespace() && !$token->isComment()) { - $sawParameter = true; - } - - if ($token->equals('(')) { - $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); - continue; - } - - if ($token->equals('[')) { - $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $index); - continue; - } - - if ($token->equals(',')) { - ++$commaCounter; - continue; - } - } - - $functionParamsQuantity = count($functionParams); - $paramsQuantity = ($sawParameter ? 1 : 0) + $commaCounter; - - if ($paramsQuantity === $functionParamsQuantity) { - return; - } - - $tokensToInsert = array(); - for ($i = $paramsQuantity; $i < $functionParamsQuantity; ++$i) { - // function call do not have all params that are required to set useStrict flag, exit from method! - if (!$functionParams[$i]) { - return; - } - - $tokensToInsert[] = new Token(','); - $tokensToInsert[] = new Token(array(T_WHITESPACE, ' ')); - - if (!is_array($functionParams[$i])) { - $tokensToInsert[] = clone $functionParams[$i]; - continue; - } - - foreach ($functionParams[$i] as $param) { - $tokensToInsert[] = clone $param; - } - } - - $beforeEndBraceIndex = $tokens->getPrevNonWhitespace($endBraceIndex, array()); - $tokens->insertAt($beforeEndBraceIndex + 1, $tokensToInsert); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR0/Psr0Fixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR0/Psr0Fixer.php deleted file mode 100644 index c6fb76d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR0/Psr0Fixer.php +++ /dev/null @@ -1,182 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR0; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\ConfigAwareInterface; -use Symfony\CS\ConfigInterface; -use Symfony\CS\StdinFileInfo; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Jordi Boggiano - * @author Dariusz Rumiński - * @author Bram Gotink - */ -class Psr0Fixer extends AbstractFixer implements ConfigAwareInterface -{ - protected $config; - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $namespace = false; - $namespaceIndex = 0; - $namespaceEndIndex = 0; - - $classyName = null; - $classyIndex = 0; - - foreach ($tokens as $index => $token) { - if ($token->isGivenKind(T_NAMESPACE)) { - if (false !== $namespace) { - return $content; - } - - $namespaceIndex = $tokens->getNextMeaningfulToken($index); - $namespaceEndIndex = $tokens->getNextTokenOfKind($index, array(';')); - - $namespace = trim($tokens->generatePartialCode($namespaceIndex, $namespaceEndIndex - 1)); - } elseif ($token->isClassy()) { - if (null !== $classyName) { - return $content; - } - - $classyIndex = $tokens->getNextMeaningfulToken($index); - $classyName = $tokens[$classyIndex]->getContent(); - } - } - - if (null === $classyName) { - return $content; - } - - if (false !== $namespace) { - $normNamespace = str_replace('\\', '/', $namespace); - $path = str_replace('\\', '/', $file->getRealPath()); - $dir = dirname($path); - - if ($this->config) { - $dir = substr($dir, strlen(realpath($this->config->getDir())) + 1); - if (strlen($normNamespace) > strlen($dir)) { - if ('' !== $dir) { - $normNamespace = substr($normNamespace, -strlen($dir)); - } else { - $normNamespace = ''; - } - } - } - - $dir = substr($dir, -strlen($normNamespace)); - if (false === $dir) { - $dir = ''; - } - - $filename = basename($path, '.php'); - - if ($classyName !== $filename) { - $tokens[$classyIndex]->setContent($filename); - } - - if ($normNamespace !== $dir && strtolower($normNamespace) === strtolower($dir)) { - for ($i = $namespaceIndex; $i <= $namespaceEndIndex; ++$i) { - $tokens[$i]->clear(); - } - $namespace = substr($namespace, 0, -strlen($dir)).str_replace('/', '\\', $dir); - - $newNamespace = Tokens::fromCode('clear(); - $newNamespace[1]->clear(); - $newNamespace[2]->clear(); - - $tokens->insertAt($namespaceIndex, $newNamespace); - } - } else { - $normClass = str_replace('_', '/', $classyName); - $path = str_replace('\\', '/', $file->getRealPath()); - $filename = substr($path, -strlen($normClass) - 4, -4); - - if ($normClass !== $filename && strtolower($normClass) === strtolower($filename)) { - $tokens[$classyIndex]->setContent(str_replace('/', '_', $filename)); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function setConfig(ConfigInterface $config) - { - $this->config = $config; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - return -10; - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Classes must be in a path that matches their namespace, be at least one namespace deep, and the class name should match the file name.'; - } - - /** - * {@inheritdoc} - */ - public function supports(\SplFileInfo $file) - { - if ($file instanceof StdinFileInfo) { - return false; - } - - $filenameParts = explode('.', $file->getBasename(), 2); - - if ( - // ignore file with extension other than php - (!isset($filenameParts[1]) || 'php' !== $filenameParts[1]) - // ignore file with name that cannot be a class name - || 0 === preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $filenameParts[0]) - // ignore filename that will halt compiler (and cannot be properly tokenized under PHP 5.3) - || '__halt_compiler' === $filenameParts[0] - ) { - return false; - } - - try { - $tokens = Tokens::fromCode(sprintf('isKeyword() || $tokens[3]->isMagicConstant()) { - // name can not be a class name - detected by PHP 5.x - return false; - } - } catch (\ParseError $e) { - // name can not be a class name - detected by PHP 7.x - return false; - } - - // ignore stubs/fixtures, since they are typically containing invalid files for various reasons - return !preg_match('{[/\\\\](stub|fixture)s?[/\\\\]}i', $file->getRealPath()); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR1/EncodingFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR1/EncodingFixer.php deleted file mode 100644 index f3afe46..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR1/EncodingFixer.php +++ /dev/null @@ -1,59 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR1; - -use Symfony\CS\AbstractFixer; - -/** - * Fixer for rules defined in PSR1 ¶2.2. - * - * @author Dariusz Rumiński - */ -class EncodingFixer extends AbstractFixer -{ - private $BOM; - - public function __construct() - { - $this->BOM = pack('CCC', 0xef, 0xbb, 0xbf); - } - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - if (0 === strncmp($content, $this->BOM, 3)) { - return substr($content, 3); - } - - return $content; - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'PHP code MUST use only UTF-8 without BOM (remove BOM).'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // must run first (at least before Fixers that using Tokens) - for speed reason of whole fixing process - return 100; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR1/ShortTagFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR1/ShortTagFixer.php deleted file mode 100644 index a018a4f..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR1/ShortTagFixer.php +++ /dev/null @@ -1,106 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR1; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR1 ¶2.1. - * - * @author Dariusz Rumiński - */ -class ShortTagFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - // replace all echo ' echo 'isGivenKind(T_OPEN_TAG)) { - $tokenContent = $token->getContent(); - - if ('isGivenKind(array(T_COMMENT, T_DOC_COMMENT, T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_STRING))) { - $tokenContent = ''; - $tokenContentLength = 0; - $parts = explode('getContent()); - $iLast = count($parts) - 1; - - foreach ($parts as $i => $part) { - $tokenContent .= $part; - $tokenContentLength += strlen($part); - - if ($i !== $iLast) { - if ('setContent($tokenContent); - } - - $tokensOldContent .= $token->getContent(); - $tokensOldContentLength += strlen($token->getContent()); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'PHP code must use the long tags or the short-echo tags; it must not use the other tag variations.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // must run before all Token-based fixers - return 98; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/BracesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/BracesFixer.php deleted file mode 100644 index 6203500..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/BracesFixer.php +++ /dev/null @@ -1,646 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶4.1, ¶4.4, ¶5. - * - * @author Dariusz Rumiński - */ -class BracesFixer extends AbstractFixer -{ - private $singleLineWhitespaceOptions = array('whitespaces' => " \t"); - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $this->fixCommentBeforeBrace($tokens); - $this->fixMissingControlBraces($tokens); - $this->fixIndents($tokens); - $this->fixControlContinuationBraces($tokens); - $this->fixSpaceAroundToken($tokens); - $this->fixDoWhile($tokens); - - // Set code to itself to redo tokenizer work, that will guard as against token collection corruption. - // TODO: This MUST be removed on 2.0-dev version, where we add more transformers (and lack of them causes corruption on 1.x line). - $code = $tokens->generateCode(); - $tokens->setCode($code); - - return $code; - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'The body of each structure MUST be enclosed by braces. Braces should be properly placed. Body of braces should be properly indented.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the ElseIfFixer, DuplicateSemicolonFixer and NoUselessElseFixer. - return -25; - } - - private function fixCommentBeforeBrace(Tokens $tokens) - { - $controlTokens = $this->getControlTokens(); - - for ($index = $tokens->count() - 1; 0 <= $index; --$index) { - $token = $tokens[$index]; - - if ($token->isGivenKind($controlTokens)) { - $prevIndex = $this->findParenthesisEnd($tokens, $index); - } elseif ( - $token->isGivenKind(T_FUNCTION) && $tokens->isLambda($index) || - $token->isGivenKind(T_CLASS) && $tokens->isAnonymousClass($index) - ) { - $prevIndex = $tokens->getNextTokenOfKind($index, array('{')); - $prevIndex = $tokens->getPrevMeaningfulToken($prevIndex); - } else { - continue; - } - - $commentIndex = $tokens->getNextNonWhitespace($prevIndex); - $commentToken = $tokens[$commentIndex]; - - if (!$commentToken->isGivenKind(T_COMMENT) || '/*' === substr($commentToken->getContent(), 0, 2)) { - continue; - } - - $braceIndex = $tokens->getNextMeaningfulToken($commentIndex); - $braceToken = $tokens[$braceIndex]; - - if (!$braceToken->equals('{')) { - continue; - } - - $tokenTmp = $tokens[$braceIndex]; - $trimIndex = $tokens->getPrevNonWhitespace($braceIndex); - $tokens[$trimIndex]->setContent(rtrim($tokens[$trimIndex]->getContent())); - $newBraceIndex = $prevIndex + 1; - for ($i = $braceIndex; $i > $newBraceIndex; --$i) { - $tokens[$i] = $tokens[$i - 1]; - } - $tokens[$newBraceIndex] = $tokenTmp; - if ($tokens[$braceIndex]->isWhitespace()) { - $tokens[$braceIndex]->clear(); - } - } - } - - private function fixControlContinuationBraces(Tokens $tokens) - { - $controlContinuationTokens = $this->getControlContinuationTokens(); - - for ($index = count($tokens) - 1; 0 <= $index; --$index) { - $token = $tokens[$index]; - - if (!$token->isGivenKind($controlContinuationTokens)) { - continue; - } - - $prevIndex = $tokens->getPrevNonWhitespace($index); - $prevToken = $tokens[$prevIndex]; - - if (!$prevToken->equals('}')) { - continue; - } - - $tokens->ensureWhitespaceAtIndex($index - 1, 1, ' '); - } - } - - private function fixDoWhile(Tokens $tokens) - { - for ($index = count($tokens) - 1; 0 <= $index; --$index) { - $token = $tokens[$index]; - - if (!$token->isGivenKind(T_DO)) { - continue; - } - - $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $index); - $startBraceIndex = $tokens->getNextNonWhitespace($parenthesisEndIndex); - $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startBraceIndex); - $nextNonWhitespaceIndex = $tokens->getNextNonWhitespace($endBraceIndex); - $nextNonWhitespaceToken = $tokens[$nextNonWhitespaceIndex]; - - if (!$nextNonWhitespaceToken->isGivenKind(T_WHILE)) { - continue; - } - - $tokens->ensureWhitespaceAtIndex($nextNonWhitespaceIndex - 1, 1, ' '); - } - } - - private function fixIndents(Tokens $tokens) - { - $classyTokens = $this->getClassyTokens(); - $classyAndFunctionTokens = array_merge(array(T_FUNCTION), $classyTokens); - $controlTokens = $this->getControlTokens(); - $indentTokens = array_filter( - array_merge($classyAndFunctionTokens, $controlTokens), - function ($item) { - return T_SWITCH !== $item; - } - ); - - for ($index = 0, $limit = count($tokens); $index < $limit; ++$index) { - $token = $tokens[$index]; - - // if token is not a structure element - continue - if (!$token->isGivenKind($indentTokens)) { - continue; - } - - if ( - $token->isGivenKind(T_FUNCTION) - // do not change import of functions - && $tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_USE) - ) { - continue; - } - - if ($token->isGivenKind($classyAndFunctionTokens)) { - $startBraceIndex = $tokens->getNextTokenOfKind($index, array(';', '{')); - $startBraceToken = $tokens[$startBraceIndex]; - } else { - $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $index); - $startBraceIndex = $tokens->getNextNonWhitespace($parenthesisEndIndex); - $startBraceToken = $tokens[$startBraceIndex]; - } - - // structure without braces block - nothing to do, e.g. do { } while (true); - if (!$startBraceToken->equals('{')) { - continue; - } - - $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startBraceIndex); - - $indent = $this->detectIndent($tokens, $index); - - // fix indent near closing brace - $tokens->ensureWhitespaceAtIndex($endBraceIndex - 1, 1, "\n".$indent); - - // fix indent between braces - $lastCommaIndex = $tokens->getPrevTokenOfKind($endBraceIndex - 1, array(';', '}')); - - $nestLevel = 1; - for ($nestIndex = $lastCommaIndex; $nestIndex >= $startBraceIndex; --$nestIndex) { - $nestToken = $tokens[$nestIndex]; - - if ($nestToken->equals(')')) { - $nestIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nestIndex, false); - continue; - } - - if (1 === $nestLevel && $nestToken->equalsAny(array(';', '}'))) { - $nextNonWhitespaceNestToken = $tokens[$tokens->getNextNonWhitespace($nestIndex)]; - - if ( - // next Token is not a comment - !$nextNonWhitespaceNestToken->isComment() && - // and it is not a `$foo = function () {};` situation - !($nestToken->equals('}') && $nextNonWhitespaceNestToken->equalsAny(array(';', ',', ']'))) && - // and it is not a `Foo::{bar}()` situation - !($nestToken->equals('}') && $nextNonWhitespaceNestToken->equals('(')) && - // and it is not a `${"a"}->...` and `${"b{$foo}"}->...` situation - !($nestToken->equals('}') && $tokens[$nestIndex - 1]->equalsAny(array('"', "'", array(T_CONSTANT_ENCAPSED_STRING)))) && - // and it is not a `$var{0} = ` situation (character access on string) - // TODO: remove on 2.x line - !($nestToken->equals('}') && $nextNonWhitespaceNestToken->equalsAny(array('=', array(T_OBJECT_OPERATOR)))) - ) { - if ($nextNonWhitespaceNestToken->isGivenKind($this->getControlContinuationTokens()) || $nextNonWhitespaceNestToken->isGivenKind(T_CLOSE_TAG)) { - $whitespace = ' '; - } else { - $nextToken = $tokens[$nestIndex + 1]; - $nextWhitespace = ''; - - if ($nextToken->isWhitespace()) { - $nextWhitespace = rtrim($nextToken->getContent(), " \t"); - - if (strlen($nextWhitespace) && "\n" === $nextWhitespace[strlen($nextWhitespace) - 1]) { - $nextWhitespace = substr($nextWhitespace, 0, -1); - } - } - - $whitespace = $nextWhitespace."\n".$indent; - - if (!$nextNonWhitespaceNestToken->equals('}')) { - $whitespace .= ' '; - } - } - - $tokens->ensureWhitespaceAtIndex($nestIndex + 1, 0, $whitespace); - } - } - - if ($nestToken->equals('}')) { - ++$nestLevel; - continue; - } - - if ($nestToken->equals('{')) { - --$nestLevel; - continue; - } - } - - // fix indent near opening brace - if (isset($tokens[$startBraceIndex + 2]) && $tokens[$startBraceIndex + 2]->equals('}')) { - $tokens->ensureWhitespaceAtIndex($startBraceIndex + 1, 0, "\n".$indent); - } else { - $nextToken = $tokens[$startBraceIndex + 1]; - $nextNonWhitespaceToken = $tokens[$tokens->getNextNonWhitespace($startBraceIndex)]; - - // set indent only if it is not a case, when comment is following { in same line - if ( - !$nextNonWhitespaceToken->isComment() - || !($nextToken->isWhitespace() && $nextToken->isWhitespace(array('whitespaces' => " \t"))) - && substr_count($nextToken->getContent(), "\n") === 1 // preserve blank lines - ) { - $tokens->ensureWhitespaceAtIndex($startBraceIndex + 1, 0, "\n".$indent.' '); - } - } - - if ($token->isGivenKind($classyTokens) && !$tokens->isAnonymousClass($index)) { - $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, "\n".$indent); - } elseif ($token->isGivenKind(T_FUNCTION) && !$tokens->isLambda($index)) { - $closingParenthesisIndex = $tokens->getPrevTokenOfKind($startBraceIndex, array(')')); - if (null === $closingParenthesisIndex) { - continue; - } - - $prevToken = $tokens[$closingParenthesisIndex - 1]; - if ($prevToken->isWhitespace() && false !== strpos($prevToken->getContent(), "\n")) { - if (!$tokens[$startBraceIndex - 2]->isComment()) { - $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); - } - } else { - $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, "\n".$indent); - } - } else { - $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); - } - - // reset loop limit due to collection change - $limit = count($tokens); - } - } - - private function fixMissingControlBraces(Tokens $tokens) - { - $controlTokens = $this->getControlTokens(); - - for ($index = $tokens->count() - 1; 0 <= $index; --$index) { - $token = $tokens[$index]; - - if (!$token->isGivenKind($controlTokens)) { - continue; - } - - $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $index); - $tokenAfterParenthesis = $tokens[$tokens->getNextMeaningfulToken($parenthesisEndIndex)]; - - // if Token after parenthesis is { then we do not need to insert brace, but to fix whitespace before it - if ($tokenAfterParenthesis->equals('{')) { - $tokens->ensureWhitespaceAtIndex($parenthesisEndIndex + 1, 0, ' '); - continue; - } - - // do not add braces for cases: - // - structure without block, e.g. while ($iter->next()); - // - structure with block, e.g. while ($i) {...}, while ($i) : {...} endwhile; - if ($tokenAfterParenthesis->equalsAny(array(';', '{', ':'))) { - continue; - } - - $statementEndIndex = $this->findStatementEnd($tokens, $parenthesisEndIndex); - - // insert closing brace - $tokens->insertAt($statementEndIndex + 1, array(new Token(array(T_WHITESPACE, ' ')), new Token('}'))); - - // insert missing `;` if needed - if (!$tokens[$statementEndIndex]->equalsAny(array(';', '}'))) { - $tokens->insertAt($statementEndIndex + 1, new Token(';')); - } - - // insert opening brace - $tokens->insertAt($parenthesisEndIndex + 1, new Token('{')); - $tokens->ensureWhitespaceAtIndex($parenthesisEndIndex + 1, 0, ' '); - } - } - - private function fixSpaceAroundToken(Tokens $tokens) - { - $controlTokens = $this->getControlTokens(); - - for ($index = $tokens->count() - 1; 0 <= $index; --$index) { - $token = $tokens[$index]; - - // Declare tokens don't follow the same rules are other control statements - if ($token->isGivenKind(T_DECLARE)) { - $this->fixDeclareStatement($tokens, $index); - } elseif ($token->isGivenKind($controlTokens) || $token->isGivenKind(T_USE)) { - $nextNonWhitespaceIndex = $tokens->getNextNonWhitespace($index); - - if (!$tokens[$nextNonWhitespaceIndex]->equals(':')) { - $tokens->ensureWhitespaceAtIndex($index + 1, 0, ' '); - } - - $prevToken = $tokens[$index - 1]; - - if (!$prevToken->isWhitespace() && !$prevToken->isComment() && !$prevToken->isGivenKind(T_OPEN_TAG)) { - $tokens->ensureWhitespaceAtIndex($index - 1, 1, ' '); - } - } - } - } - - /** - * @param Tokens $tokens - * @param int $index - * - * @return string - */ - private function detectIndent(Tokens $tokens, $index) - { - while (true) { - $whitespaceIndex = $tokens->getPrevTokenOfKind($index, array(array(T_WHITESPACE))); - - if (null === $whitespaceIndex) { - return ''; - } - - $whitespaceToken = $tokens[$whitespaceIndex]; - - if (false !== strpos($whitespaceToken->getContent(), "\n")) { - break; - } - - $prevToken = $tokens[$whitespaceIndex - 1]; - - if ($prevToken->isGivenKind(array(T_OPEN_TAG, T_COMMENT)) && "\n" === substr($prevToken->getContent(), -1)) { - break; - } - - $index = $whitespaceIndex; - } - - $explodedContent = explode("\n", $whitespaceToken->getContent()); - - return end($explodedContent); - } - - /** - * @param Tokens $tokens - * @param int $structureTokenIndex - * - * @return int - */ - private function findParenthesisEnd(Tokens $tokens, $structureTokenIndex) - { - $nextIndex = $tokens->getNextMeaningfulToken($structureTokenIndex); - $nextToken = $tokens[$nextIndex]; - - // return if next token is not opening parenthesis - if (!$nextToken->equals('(')) { - return $structureTokenIndex; - } - - return $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nextIndex); - } - - private function findStatementEnd(Tokens $tokens, $parenthesisEndIndex) - { - $nextIndex = $tokens->getNextMeaningfulToken($parenthesisEndIndex); - $nextToken = $tokens[$nextIndex]; - - if (!$nextToken) { - return $parenthesisEndIndex; - } - - if ($nextToken->equals('{')) { - return $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $nextIndex); - } - - if ($nextToken->isGivenKind($this->getControlTokens())) { - $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $nextIndex); - - $endIndex = $this->findStatementEnd($tokens, $parenthesisEndIndex); - - if ($nextToken->isGivenKind(array(T_IF, T_TRY))) { - $openingTokenKind = $nextToken->getId(); - - while (true) { - $nextIndex = $tokens->getNextMeaningfulToken($endIndex); - $nextToken = isset($nextIndex) ? $tokens[$nextIndex] : null; - if ($nextToken && $nextToken->isGivenKind($this->getControlContinuationTokensForOpeningToken($openingTokenKind))) { - $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $nextIndex); - - $endIndex = $this->findStatementEnd($tokens, $parenthesisEndIndex); - - if ($nextToken->isGivenKind($this->getFinalControlContinuationTokensForOpeningToken($openingTokenKind))) { - return $endIndex; - } - } else { - break; - } - } - } - - return $endIndex; - } - - $index = $parenthesisEndIndex; - - while (true) { - $token = $tokens[++$index]; - - // if there is some block in statement (eg lambda function) we need to skip it - if ($token->equals('{')) { - $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); - continue; - } - - if ($token->equals(';')) { - return $index; - } - - if ($token->isGivenKind(T_CLOSE_TAG)) { - return $tokens->getPrevNonWhitespace($index); - } - } - - throw new \RuntimeException('Statement end not found'); - } - - private function getClassyTokens() - { - static $tokens = null; - - if (null === $tokens) { - $tokens = array(T_CLASS, T_INTERFACE); - - if (defined('T_TRAIT')) { - $tokens[] = T_TRAIT; - } - } - - return $tokens; - } - - private function getControlTokens() - { - static $tokens = null; - - if (null === $tokens) { - $tokens = array( - T_DECLARE, - T_DO, - T_ELSE, - T_ELSEIF, - T_FOR, - T_FOREACH, - T_IF, - T_WHILE, - T_TRY, - T_CATCH, - T_SWITCH, - ); - - if (defined('T_FINALLY')) { - $tokens[] = T_FINALLY; - } - } - - return $tokens; - } - - private function getControlContinuationTokens() - { - static $tokens = null; - - if (null === $tokens) { - $tokens = array( - T_ELSE, - T_ELSEIF, - T_CATCH, - ); - - if (defined('T_FINALLY')) { - $tokens[] = T_FINALLY; - } - } - - return $tokens; - } - - private function getControlContinuationTokensForOpeningToken($openingTokenKind) - { - if ($openingTokenKind === T_IF) { - return array( - T_ELSE, - T_ELSEIF, - ); - } - - if ($openingTokenKind === T_TRY) { - $tokens = array(T_CATCH); - if (defined('T_FINALLY')) { - $tokens[] = T_FINALLY; - } - - return $tokens; - } - - return array(); - } - - private function getFinalControlContinuationTokensForOpeningToken($openingTokenKind) - { - if ($openingTokenKind === T_IF) { - return array(T_ELSE); - } - - if ($openingTokenKind === T_TRY && defined('T_FINALLY')) { - return array(T_FINALLY); - } - - return array(); - } - - /** - * @param Tokens $tokens - * @param int $index - */ - private function fixDeclareStatement(Tokens $tokens, $index) - { - $tokens->removeTrailingWhitespace($index); - - $startParenthesisIndex = $tokens->getNextTokenOfKind($index, array('(')); - $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex); - $startBraceIndex = $tokens->getNextTokenOfKind($endParenthesisIndex, array(';', '{')); - $startBraceToken = $tokens[$startBraceIndex]; - - if ($startBraceToken->equals('{')) { - $this->fixSingleLineWhitespaceForDeclare($tokens, $startBraceIndex); - } - - $this->removeWhitespaceInParenthesis($tokens, $startParenthesisIndex, $endParenthesisIndex); - } - - /** - * @param Tokens $tokens - * @param int $startBraceIndex - */ - private function fixSingleLineWhitespaceForDeclare(Tokens $tokens, $startBraceIndex) - { - // fix single-line whitespace before { - // eg: `declare(ticks=1){` => `declare(ticks=1) {` - // eg: `declare(ticks=1) {` => `declare(ticks=1) {` - if ( - !$tokens[$startBraceIndex - 1]->isWhitespace() || - $tokens[$startBraceIndex - 1]->isWhitespace($this->singleLineWhitespaceOptions) - ) { - $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); - } - } - - /** - * @param Tokens $tokens - * @param int $startParenthesisIndex - * @param int $endParenthesisIndex - */ - private function removeWhitespaceInParenthesis(Tokens $tokens, $startParenthesisIndex, $endParenthesisIndex) - { - for ($i = $startParenthesisIndex; $i < $endParenthesisIndex; ++$i) { - if ($tokens[$i]->isWhitespace()) { - $tokens[$i]->clear(); - } - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ClassDefinitionFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ClassDefinitionFixer.php deleted file mode 100644 index fe02cc5..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ClassDefinitionFixer.php +++ /dev/null @@ -1,338 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\ConfigurationException\InvalidFixerConfigurationException; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for part of the rules defined in PSR2 ¶4.1 Extends and Implements and PSR12 ¶8. Anonymous Classes. - * - * @author SpacePossum - */ -final class ClassDefinitionFixer extends AbstractFixer -{ - /** - * @var array - */ - private static $defaultConfig = array( - // put class declaration on one line - 'singleLine' => false, - // if a classy extends or implements only one element than put it on the same line - 'singleItemSingleLine' => false, - // if an interface extends multiple interfaces declared over multiple lines put each interface on its own line - 'multiLineExtendsEachSingleLine' => false, - ); - - /** - * @var array - */ - private static $config; - - /** - * @param array $configuration - * - * @throws \Symfony\CS\ConfigurationException\InvalidFixerConfigurationException - */ - public static function configure(array $configuration = null) - { - if (null === $configuration || count($configuration) < 1) { - self::$config = self::$defaultConfig; - - return; - } - - $configuration = array_merge(self::$defaultConfig, $configuration); - - foreach ($configuration as $item => $value) { - if (!array_key_exists($item, self::$defaultConfig)) { - throw new InvalidFixerConfigurationException('class_definition', sprintf('Unknown configuration item "%s", expected any of "%s".', $item, implode(', ', array_keys(self::$defaultConfig)))); - } - - if (!is_bool($value)) { - throw new InvalidFixerConfigurationException('class_definition', sprintf('Configuration value for item "%s" must be a bool, got "%s".', $item, is_object($value) ? get_class($value) : gettype($value))); - } - } - - self::$config = $configuration; - } - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - // -4, one for count to index, 3 because min. of tokens for a classy location. - for ($index = $tokens->getSize() - 4; $index > 0; --$index) { - if ($tokens[$index]->isClassy()) { - $this->fixClassyDefinition($tokens, $index); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Whitespace around the key words of a class, trait or interfaces definition should be one space.'; - } - - /** - * @param Tokens $tokens - * @param int $classyIndex Class definition token start index - */ - private function fixClassyDefinition(Tokens $tokens, $classyIndex) - { - $classDefInfo = $this->getClassyDefinitionInfo($tokens, $classyIndex); - - // PSR: class definition open curly brace must go on a new line - $classDefInfo['open'] = $this->fixClassyDefinitionOpenSpacing($tokens, $classDefInfo['open']); - - // PSR2 4.1 Lists of implements MAY be split across multiple lines, where each subsequent line is indented once. - // When doing so, the first item in the list MUST be on the next line, and there MUST be only one interface per line. - if (false !== $classDefInfo['implements']) { - $this->fixClassyDefinitionImplements($tokens, $classDefInfo); - } - - if (false !== $classDefInfo['extends']) { - $this->fixClassyDefinitionExtends( - $tokens, - false === $classDefInfo['implements'] ? $classDefInfo['open'] : 1 + $classDefInfo['implements']['start'], - $classDefInfo['extends'] - ); - } - - if ($classDefInfo['implements']) { - $end = $classDefInfo['implements']['start']; - } elseif ($classDefInfo['extends']) { - $end = $classDefInfo['extends']['start']; - } elseif ($classDefInfo['anonymousClass']) { - $end = $classDefInfo['open']; - } else { - $end = $tokens->getPrevNonWhitespace($classDefInfo['open']); - } - - // 4.1 The extends and implements keywords MUST be declared on the same line as the class name. - $this->makeClassyDefinitionSingleLine( - $tokens, - $classDefInfo['anonymousClass'] ? $tokens->getPrevMeaningfulToken($classyIndex) : $classDefInfo['start'], - $end - ); - } - - private function fixClassyDefinitionExtends(Tokens $tokens, $classOpenIndex, $classExtendsInfo) - { - $endIndex = $tokens->getPrevNonWhitespace($classOpenIndex); - - if (self::$config['singleLine'] || false === $classExtendsInfo['multiLine']) { - $this->makeClassyDefinitionSingleLine($tokens, $classExtendsInfo['start'], $endIndex); - } elseif (self::$config['singleItemSingleLine'] && 1 === $classExtendsInfo['numberOfExtends']) { - $this->makeClassyDefinitionSingleLine($tokens, $classExtendsInfo['start'], $endIndex); - } elseif (self::$config['multiLineExtendsEachSingleLine'] && $classExtendsInfo['multiLine']) { - $this->makeClassyInheritancePartMultiLine($tokens, $classExtendsInfo['start'], $endIndex); - } - } - - /** - * @param Tokens $tokens - * @param array $classDefInfo - */ - private function fixClassyDefinitionImplements(Tokens $tokens, array $classDefInfo) - { - $classImplementsInfo = $classDefInfo['implements']; - $endIndex = $tokens->getPrevNonWhitespace($classDefInfo['open']); - - if (self::$config['singleLine'] || false === $classImplementsInfo['multiLine']) { - $this->makeClassyDefinitionSingleLine($tokens, $classImplementsInfo['start'], $endIndex); - } elseif (self::$config['singleItemSingleLine'] && 1 === $classImplementsInfo['numberOfImplements']) { - $this->makeClassyDefinitionSingleLine($tokens, $classImplementsInfo['start'], $endIndex); - } else { - $this->makeClassyInheritancePartMultiLine( - $tokens, - $classImplementsInfo['start'], - $classDefInfo['anonymousClass'] ? $tokens->getPrevMeaningfulToken($endIndex) : $endIndex - ); - } - } - - /** - * @param Tokens $tokens - * @param int $openIndex - * - * @return int - */ - private function fixClassyDefinitionOpenSpacing(Tokens $tokens, $openIndex) - { - if (false !== strpos($tokens[$openIndex - 1]->getContent(), "\n")) { - return $openIndex; - } - - if ($tokens[$openIndex - 1]->isWhitespace()) { - $tokens[$openIndex - 1]->setContent("\n"); - - return $openIndex; - } - - $tokens->insertAt($openIndex, new Token(array(T_WHITESPACE, "\n"))); - - return $openIndex + 1; - } - - /** - * @param Tokens $tokens - * @param int $classyIndex - * - * @return array - */ - private function getClassyDefinitionInfo(Tokens $tokens, $classyIndex) - { - $openIndex = $tokens->getNextTokenOfKind($classyIndex, array('{')); - $prev = $tokens->getPrevMeaningfulToken($classyIndex); - $startIndex = $tokens[$prev]->isGivenKind(array(T_FINAL, T_ABSTRACT)) ? $prev : $classyIndex; - - $extends = false; - $implements = false; - $anonymousClass = false; - - if (!(defined('T_TRAIT') && $tokens[$classyIndex]->isGivenKind(T_TRAIT))) { - $extends = $tokens->findGivenKind(T_EXTENDS, $classyIndex, $openIndex); - $extends = count($extends) ? $this->getClassyInheritanceInfo($tokens, key($extends), $openIndex, 'numberOfExtends') : false; - - if (!$tokens[$classyIndex]->isGivenKind(T_INTERFACE)) { - $implements = $tokens->findGivenKind(T_IMPLEMENTS, $classyIndex, $openIndex); - $implements = count($implements) ? $this->getClassyInheritanceInfo($tokens, key($implements), $openIndex, 'numberOfImplements') : false; - $anonymousClass = $tokens->isAnonymousClass($classyIndex); - } - } - - return array( - 'start' => $startIndex, - 'classy' => $classyIndex, - 'open' => $openIndex, - 'extends' => $extends, - 'implements' => $implements, - 'anonymousClass' => $anonymousClass, - ); - } - - /** - * @param Tokens $tokens - * @param int $implementsIndex - * @param int $openIndex - * @param string $label - * - * @return array - */ - private function getClassyInheritanceInfo(Tokens $tokens, $implementsIndex, $openIndex, $label) - { - $implementsInfo = array('start' => $implementsIndex, $label => 1, 'multiLine' => false); - $lastMeaningFul = $tokens->getPrevMeaningfulToken($openIndex); - for ($i = $implementsIndex; $i < $lastMeaningFul; ++$i) { - if ($tokens[$i]->equals(',')) { - ++$implementsInfo[$label]; - - continue; - } - - if (!$implementsInfo['multiLine'] && false !== strpos($tokens[$i]->getContent(), "\n")) { - $implementsInfo['multiLine'] = true; - } - } - - return $implementsInfo; - } - - /** - * @param Tokens $tokens - * @param int $startIndex - * @param int $endIndex - */ - private function makeClassyDefinitionSingleLine(Tokens $tokens, $startIndex, $endIndex) - { - for ($i = $endIndex; $i >= $startIndex; --$i) { - if ($tokens[$i]->isWhitespace()) { - if ($tokens[$i + 1]->equalsAny(array(',', '(', ')')) || $tokens[$i - 1]->equals('(')) { - $tokens[$i]->clear(); - } elseif (!$tokens[$i + 1]->isComment()) { - $tokens[$i]->setContent(' '); - } - - --$i; - continue; - } - - if ($tokens[$i]->equals(',') && !$tokens[$i + 1]->isWhitespace()) { - $tokens->insertAt($i + 1, new Token(array(T_WHITESPACE, ' '))); - - continue; - } - - if (!$tokens[$i]->isComment()) { - continue; - } - - if (!$tokens[$i + 1]->isWhitespace() && !$tokens[$i + 1]->isComment() && false === strpos($tokens[$i]->getContent(), "\n")) { - $tokens->insertAt($i + 1, new Token(array(T_WHITESPACE, ' '))); - } - - if (!$tokens[$i - 1]->isWhitespace() && !$tokens[$i - 1]->isComment()) { - $tokens->insertAt($i, new Token(array(T_WHITESPACE, ' '))); - } - } - } - - /** - * @param Tokens $tokens - * @param int $startIndex - * @param int $endIndex - */ - private function makeClassyInheritancePartMultiLine(Tokens $tokens, $startIndex, $endIndex) - { - for ($i = $endIndex; $i > $startIndex; --$i) { - $previousInterfaceImplementingIndex = $tokens->getPrevTokenOfKind($i, array(',', array(T_IMPLEMENTS), array(T_EXTENDS))); - $breakAtIndex = $tokens->getNextMeaningfulToken($previousInterfaceImplementingIndex); - // make the part of a ',' or 'implements' single line - $this->makeClassyDefinitionSingleLine( - $tokens, - $breakAtIndex, - $i - ); - - // make sure the part is on its own line - $isOnOwnLine = false; - for ($j = $breakAtIndex; $j > $previousInterfaceImplementingIndex; --$j) { - if (false !== strpos($tokens[$j]->getContent(), "\n")) { - $isOnOwnLine = true; - - break; - } - } - - if (!$isOnOwnLine) { - if ($tokens[$breakAtIndex - 1]->isWhitespace()) { - $tokens[$breakAtIndex - 1]->setContent("\n"); - } else { - $tokens->insertAt($breakAtIndex, new Token(array(T_WHITESPACE, "\n"))); - } - } - - $i = $previousInterfaceImplementingIndex + 1; - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ElseifFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ElseifFixer.php deleted file mode 100644 index b6c8866..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ElseifFixer.php +++ /dev/null @@ -1,70 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶5.1. - * - * @author Dariusz Rumiński - */ -class ElseifFixer extends AbstractFixer -{ - /** - * Replace all `else if` (T_ELSE T_IF) with `elseif` (T_ELSEIF). - * - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - foreach ($tokens as $index => $token) { - if (!$tokens[$index]->isGivenKind(T_ELSE)) { - continue; - } - - $nextIndex = $tokens->getNextMeaningfulToken($index); - - // if next meaning token is not T_IF - continue searching, this is not the case for fixing - if (!$tokens[$nextIndex]->isGivenKind(T_IF)) { - continue; - } - - // now we have T_ELSE following by T_IF so we could fix this - // 1. clear whitespaces between T_ELSE and T_IF - for ($i = $index + 1; $i < $nextIndex; ++$i) { - if ($tokens[$i]->isWhitespace()) { - $tokens[$i]->clear(); - } - } - - // 2. change token from T_ELSE into T_ELSEIF - $tokens->overrideAt($index, array(T_ELSEIF, 'elseif', $tokens[$index]->getLine())); - - // 3. clear succeeding T_IF - $tokens[$nextIndex]->clear(); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'The keyword elseif should be used instead of else if so that all control keywords looks like single words.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/EofEndingFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/EofEndingFixer.php deleted file mode 100644 index 43dff3c..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/EofEndingFixer.php +++ /dev/null @@ -1,85 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶2.2. - * - * @author Fabien Potencier - */ -class EofEndingFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $count = $tokens->count(); - if (0 === $count) { - return ''; - } - - $token = $tokens[$count - 1]; - if ($token->isGivenKind(array(T_INLINE_HTML, T_CLOSE_TAG, T_OPEN_TAG))) { - return $content; - } - - $isSingleLineComment = function (Token $token) { - return $token->isComment() && '/*' !== substr($token->getContent(), 0, 2); - }; - $clearSingleLineComment = function (Token $token) { - $content = $token->getContent(); - $content = rtrim($content, "\n")."\n"; - $token->setContent($content); - }; - - if ($token->isWhitespace()) { - if ($count > 1 && $isSingleLineComment($tokens[$count - 2])) { - $clearSingleLineComment($tokens[$count - 2]); - $token->clear(); - } else { - $lineBreak = false === strrpos($token->getContent(), "\r") ? "\n" : "\r\n"; - $token->setContent($lineBreak); - } - } elseif ($isSingleLineComment($token)) { - $clearSingleLineComment($token); - } else { - $tokens->insertAt($count, new Token(array(T_WHITESPACE, "\n"))); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'A file must always end with a single empty line feed.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // must run last to be sure the file is properly formatted before it runs - return -50; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/FunctionDeclarationFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/FunctionDeclarationFixer.php deleted file mode 100644 index 2ff29ae..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/FunctionDeclarationFixer.php +++ /dev/null @@ -1,117 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 generally (¶1 and ¶6). - * - * @author Dariusz Rumiński - */ -class FunctionDeclarationFixer extends AbstractFixer -{ - private $singleLineWhitespaceOptions = array('whitespaces' => " \t"); - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - $token = $tokens[$index]; - - if (!$token->isGivenKind(T_FUNCTION)) { - continue; - } - - $startParenthesisIndex = $tokens->getNextTokenOfKind($index, array('(', ';', array(T_CLOSE_TAG))); - if (!$tokens[$startParenthesisIndex]->equals('(')) { - continue; - } - - $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex); - $startBraceIndex = $tokens->getNextTokenOfKind($endParenthesisIndex, array(';', '{')); - - // fix single-line whitespace before { - // eg: `function foo(){}` => `function foo() {}` - // eg: `function foo() {}` => `function foo() {}` - if ( - $tokens[$tokens->getPrevNonWhitespace($startBraceIndex)]->equals(')') && - $tokens[$startBraceIndex]->equals('{') && - ( - !$tokens[$startBraceIndex - 1]->isWhitespace() || - $tokens[$startBraceIndex - 1]->isWhitespace($this->singleLineWhitespaceOptions) - ) - ) { - $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); - } - - $afterParenthesisIndex = $tokens->getNextNonWhitespace($endParenthesisIndex); - $afterParenthesisToken = $tokens[$afterParenthesisIndex]; - - if ($afterParenthesisToken->isGivenKind(T_USE)) { - // fix whitespace after T_USE (we might add a token, so do this before determining start and end parenthesis) - $tokens->ensureWhitespaceAtIndex($afterParenthesisIndex + 1, 0, ' '); - - $useStartParenthesisIndex = $tokens->getNextTokenOfKind($afterParenthesisIndex, array('(')); - $useEndParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $useStartParenthesisIndex); - - // remove single-line edge whitespaces inside use parentheses - $this->fixParenthesisInnerEdge($tokens, $useStartParenthesisIndex, $useEndParenthesisIndex); - - // fix whitespace before T_USE - $tokens->ensureWhitespaceAtIndex($afterParenthesisIndex - 1, 1, ' '); - } - - // remove single-line edge whitespaces inside parameters list parentheses - $this->fixParenthesisInnerEdge($tokens, $startParenthesisIndex, $endParenthesisIndex); - - // remove whitespace before ( - // eg: `function foo () {}` => `function foo() {}` - if ($tokens[$startParenthesisIndex - 1]->isWhitespace()) { - $tokens[$startParenthesisIndex - 1]->clear(); - } - - // fix whitespace after T_FUNCTION - // eg: `function foo() {}` => `function foo() {}` - $tokens->ensureWhitespaceAtIndex($index + 1, 0, ' '); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Spaces should be properly placed in a function declaration.'; - } - - private function fixParenthesisInnerEdge(Tokens $tokens, $start, $end) - { - // remove single-line whitespace before ) - if ($tokens[$end - 1]->isWhitespace($this->singleLineWhitespaceOptions)) { - $tokens[$end - 1]->clear(); - } - - // remove single-line whitespace after ( - if ($tokens[$start + 1]->isWhitespace($this->singleLineWhitespaceOptions)) { - $tokens[$start + 1]->clear(); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/IndentationFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/IndentationFixer.php deleted file mode 100644 index c0e76dc..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/IndentationFixer.php +++ /dev/null @@ -1,68 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶2.4. - * - * @author Dariusz Rumiński - */ -class IndentationFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if ($token->isComment()) { - $content = preg_replace('/^(?:(?getContent(), -1, $count); - - // Also check for more tabs. - while ($count !== 0) { - $content = preg_replace('/^(\ +)?\t/m', '\1 ', $content, -1, $count); - } - - $tokens[$index]->setContent($content); - continue; - } - - if ($token->isWhitespace()) { - $tokens[$index]->setContent(preg_replace('/(?:(?getContent())); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Code MUST use an indent of 4 spaces, and MUST NOT use tabs for indenting.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - return 50; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LineAfterNamespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LineAfterNamespaceFixer.php deleted file mode 100644 index 512fb8a..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LineAfterNamespaceFixer.php +++ /dev/null @@ -1,77 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶3. - * - * @author Dariusz Rumiński - */ -class LineAfterNamespaceFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - $lastIndex = $tokens->count() - 1; - - for ($index = $lastIndex; $index >= 0; --$index) { - $token = $tokens[$index]; - - if ($token->isGivenKind(T_NAMESPACE)) { - $semicolonIndex = $tokens->getNextTokenOfKind($index, array(';', '{', array(T_CLOSE_TAG))); - $semicolonToken = $tokens[$semicolonIndex]; - - if (!isset($tokens[$semicolonIndex + 1]) || !$semicolonToken->equals(';')) { - continue; - } - - $nextIndex = $semicolonIndex + 1; - $nextToken = $tokens[$nextIndex]; - - if (!$nextToken->isWhitespace()) { - $tokens->insertAt($semicolonIndex + 1, new Token(array(T_WHITESPACE, "\n\n"))); - } else { - $nextToken->setContent( - ($nextIndex === $lastIndex ? "\n" : "\n\n").ltrim($nextToken->getContent()) - ); - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There MUST be one blank line after the namespace declaration.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the UnusedUseFixer - return -20; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LinefeedFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LinefeedFixer.php deleted file mode 100644 index e26d9d2..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LinefeedFixer.php +++ /dev/null @@ -1,66 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶2.2. - * - * @author Fabien Potencier - * @author SpacePossum - */ -class LinefeedFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - for ($index = 0, $count = count($tokens); $index < $count; ++$index) { - if ($tokens[$index]->isGivenKind(T_ENCAPSED_AND_WHITESPACE)) { - if ("\r\n" === substr($tokens[$index]->getContent(), -2) && $tokens[$tokens->getNextMeaningfulToken($index)]->isGivenKind(T_END_HEREDOC)) { - $tokens[$index]->setContent(substr($tokens[$index]->getContent(), 0, -2)."\n"); - } - - continue; - } - - if (!$tokens[$index]->isGivenKind(array(T_OPEN_TAG, T_WHITESPACE, T_COMMENT, T_DOC_COMMENT, T_START_HEREDOC))) { - continue; - } - - $tokens[$index]->setContent(str_replace("\r\n", "\n", $tokens[$index]->getContent())); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'All PHP files must use the Unix LF (linefeed) line ending.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - return 50; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LowercaseConstantsFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LowercaseConstantsFixer.php deleted file mode 100644 index f662e4b..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LowercaseConstantsFixer.php +++ /dev/null @@ -1,92 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶2.5. - * - * @author Dariusz Rumiński - */ -class LowercaseConstantsFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isNativeConstant()) { - continue; - } - - if ( - $this->isNeighbourAccepted($tokens, $tokens->getPrevMeaningfulToken($index)) && - $this->isNeighbourAccepted($tokens, $tokens->getNextMeaningfulToken($index)) - ) { - $token->setContent(strtolower($token->getContent())); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'The PHP constants true, false, and null MUST be in lower case.'; - } - - private function isNeighbourAccepted(Tokens $tokens, $index) - { - static $forbiddenTokens = null; - - if (null === $forbiddenTokens) { - $forbiddenTokens = array( - T_AS, - T_CLASS, - T_CONST, - T_EXTENDS, - T_IMPLEMENTS, - T_INSTANCEOF, - T_INTERFACE, - T_NEW, - T_NS_SEPARATOR, - T_PAAMAYIM_NEKUDOTAYIM, - T_USE, - ); - - if (defined('T_TRAIT')) { - $forbiddenTokens[] = T_TRAIT; - } - - if (defined('T_INSTEADOF')) { - $forbiddenTokens[] = T_INSTEADOF; - } - } - - $token = $tokens[$index]; - - if ($token->equalsAny(array('{', '}'))) { - return false; - } - - return !$token->isGivenKind($forbiddenTokens); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LowercaseKeywordsFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LowercaseKeywordsFixer.php deleted file mode 100644 index cd9a38f..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/LowercaseKeywordsFixer.php +++ /dev/null @@ -1,50 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶2.5. - * - * @author Dariusz Rumiński - */ -class LowercaseKeywordsFixer extends AbstractFixer -{ - private static $excludedTokens = array(T_HALT_COMPILER); - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $token) { - if ($token->isKeyword() && !$token->isGivenKind(self::$excludedTokens)) { - $token->setContent(strtolower($token->getContent())); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'PHP keywords MUST be in lower case.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/MethodArgumentSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/MethodArgumentSpaceFixer.php deleted file mode 100644 index 16c3b7e..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/MethodArgumentSpaceFixer.php +++ /dev/null @@ -1,86 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶4.4, ¶4.6. - * - * @author Kuanhung Chen - */ -class MethodArgumentSpaceFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - $token = $tokens[$index]; - - // looking for start of brace and skip array - if (!$token->equals('(') || $tokens[$index - 1]->isGivenKind(T_ARRAY)) { - continue; - } - - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); - - // fix for method argument and method call - for ($i = $endIndex - 1; $i > $index; --$i) { - if (!$tokens[$i]->equals(',')) { - continue; - } - - $this->fixSpace($tokens, $i); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'In method arguments and method call, there MUST NOT be a space before each comma and there MUST be one space after each comma.'; - } - - /** - * Method to insert space after comma and remove space before comma. - * - * @param Tokens $tokens - * @param int $index - */ - public function fixSpace(Tokens $tokens, $index) - { - // remove space before comma if exist - if ($tokens[$index - 1]->isWhitespace()) { - $prevIndex = $tokens->getPrevNonWhitespace($index - 1); - - if (!$tokens[$prevIndex]->equalsAny(array(',', array(T_END_HEREDOC)))) { - $tokens[$index - 1]->clear(); - } - } - - // add space after comma if not exist - if (!$tokens[$index + 1]->isWhitespace()) { - $tokens->insertAt($index + 1, new Token(array(T_WHITESPACE, ' '))); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/MultipleUseFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/MultipleUseFixer.php deleted file mode 100644 index 1622ca6..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/MultipleUseFixer.php +++ /dev/null @@ -1,208 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶3. - * - * @author Dariusz Rumiński - * @author SpacePossum - */ -class MultipleUseFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - $uses = array_reverse($tokens->getImportUseIndexes()); - - foreach ($uses as $index) { - $endIndex = $tokens->getNextTokenOfKind($index, array(';', array(T_CLOSE_TAG))); - $groupClose = $tokens->getPrevMeaningfulToken($endIndex); - $tokens[$groupClose]->equals('}') ? - $this->fixGroupUse($tokens, $index, $endIndex) : - $this->fixMultipleUse($tokens, $index, $endIndex) - ; - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There MUST be one use keyword per declaration.'; - } - - public function getPriority() - { - // must be run before UnusedUseFixer, OrderedUseFixer, SpacesBeforeSemicolonFixer, SpacesAfterSemicolonFixer and MultilineSpacesBeforeSemicolonFixer - - return 1; - } - - /** - * @param Tokens $tokens - * @param int $index - * - * @return string - */ - private function detectIndent(Tokens $tokens, $index) - { - if (!$tokens[$index - 1]->isWhitespace()) { - return ''; // cannot detect indent - } - - $explodedContent = explode("\n", $tokens[$index - 1]->getContent()); - - return end($explodedContent); - } - - /** - * @param Tokens $tokens - * @param int $index - * - * @return array - */ - private function getGroupDeclaration(Tokens $tokens, $index) - { - $groupPrefix = 'use'; - $comment = ''; - for ($i = $index + 1; ; ++$i) { - if ($tokens[$i]->equals('{')) { - $groupOpenIndex = $i; - - break; - } - - if ($tokens[$i]->isComment()) { - $comment .= $tokens[$i]->getContent(); - if (!$tokens[$i - 1]->isWhitespace() && !$tokens[$i + 1]->isWhitespace()) { - $groupPrefix .= ' '; - } - - continue; - } - - if ($tokens[$i]->isWhitespace()) { - $groupPrefix .= ' '; - - continue; - } - - $groupPrefix .= $tokens[$i]->getContent(); - } - - return array( - $groupPrefix, - $groupOpenIndex, - $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $groupOpenIndex), - $comment, - ); - } - - /** - * @param Tokens $tokens - * @param string $groupPrefix - * @param int $groupOpenIndex - * @param int $groupCloseIndex - * @param string $comment - * - * @return string[] - */ - private function getGroupStatements(Tokens $tokens, $groupPrefix, $groupOpenIndex, $groupCloseIndex, $comment) - { - $statements = array(); - $statement = $groupPrefix; - - for ($i = $groupOpenIndex + 1; $i <= $groupCloseIndex; ++$i) { - if ($tokens[$i]->equalsAny(array(',', '}'))) { - $statements[] = $statement.';'; - $statement = $groupPrefix; - - continue; - } - - if ($tokens[$i]->isWhitespace()) { - $j = $tokens->getNextMeaningfulToken($i); - if ($tokens[$j]->equals(array(T_AS))) { - $statement .= ' as '; - $i += 2; - } - - continue; - } - - $statement .= $tokens[$i]->getContent(); - } - - if ('' !== $comment) { - $statements[0] .= ' '.$comment; - } - - return $statements; - } - - private function fixGroupUse(Tokens $tokens, $index, $endIndex) - { - list($groupPrefix, $groupOpenIndex, $groupCloseIndex, $comment) = $this->getGroupDeclaration($tokens, $index); - $statements = $this->getGroupStatements($tokens, $groupPrefix, $groupOpenIndex, $groupCloseIndex, $comment); - - if (count($statements) < 2) { - return; - } - - $tokens->clearRange($index, $groupCloseIndex); - if ($tokens[$endIndex]->equals(';')) { - $tokens[$endIndex]->clear(); - } - - $importTokens = Tokens::fromCode('clear(); - - $tokens->insertAt($index, $importTokens); - } - - private function fixMultipleUse(Tokens $tokens, $index, $endIndex) - { - for ($i = $endIndex - 1; $i > $index; --$i) { - if (!$tokens[$i]->equals(',')) { - continue; - } - - $tokens[$i]->setContent(';'); - $i = $tokens->getNextMeaningfulToken($i); - $tokens->insertAt($i, new Token(array(T_USE, 'use'))); - $tokens->insertAt($i + 1, new Token(array(T_WHITESPACE, ' '))); - - $indent = $this->detectIndent($tokens, $index); - if ($tokens[$i - 1]->isWhitespace()) { - $tokens[$i - 1]->setContent("\n".$indent); - - continue; - } - - if (false === strpos($tokens[$i - 1]->getContent(), "\n")) { - $tokens->insertAt($i, new Token(array(T_WHITESPACE, "\n".$indent))); - } - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/NoTrailingWhitespaceInCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/NoTrailingWhitespaceInCommentFixer.php deleted file mode 100644 index 57e517b..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/NoTrailingWhitespaceInCommentFixer.php +++ /dev/null @@ -1,48 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -final class NoTrailingWhitespaceInCommentFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $token) { - if ($token->isComment()) { - $token->setContent( - preg_replace('/[ \t]+$/m', '', $token->getContent()) - ); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There MUST be no trailing spaces inside comments and phpdocs.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ParenthesisFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ParenthesisFixer.php deleted file mode 100644 index af7eb9d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/ParenthesisFixer.php +++ /dev/null @@ -1,93 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶4.3, ¶4.6, ¶5. - * - * @author Marc Aubé - * @author Dariusz Rumiński - */ -class ParenthesisFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->equals('(')) { - continue; - } - - $prevIndex = $tokens->getPrevMeaningfulToken($index); - - // ignore parenthesis for T_ARRAY - if (null !== $prevIndex && $tokens[$prevIndex]->isGivenKind(T_ARRAY)) { - continue; - } - - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); - - // remove space after opening `(` - $this->removeSpaceAroundToken($tokens, $index, 1); - - // remove space after closing `)` if it is not `list($a, $b, )` case - if (!$tokens[$tokens->getPrevMeaningfulToken($endIndex)]->equals(',')) { - $this->removeSpaceAroundToken($tokens, $endIndex, -1); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There MUST NOT be a space after the opening parenthesis. There MUST NOT be a space before the closing parenthesis.'; - } - - /** - * Remove spaces on one side of the token at a given index. - * - * @param Tokens $tokens A collection of code tokens - * @param int $index The token index - * @param int $offset The offset where to start looking for spaces - */ - private function removeSpaceAroundToken(Tokens $tokens, $index, $offset) - { - if (!isset($tokens[$index + $offset])) { - return; - } - - $token = $tokens[$index + $offset]; - - if ($token->isWhitespace() && false === strpos($token->getContent(), "\n")) { - if (isset($tokens[$index + $offset - 1])) { - $prevToken = $tokens[$index + $offset - 1]; - if ($prevToken->isComment() && false !== strpos($prevToken->getContent(), "\n")) { - return; - } - } - - $token->clear(); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/PhpClosingTagFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/PhpClosingTagFixer.php deleted file mode 100644 index 90fb530..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/PhpClosingTagFixer.php +++ /dev/null @@ -1,65 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶2.2. - * - * @author Dariusz Rumiński - */ -class PhpClosingTagFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - if (!$tokens->isMonolithicPhp()) { - return $content; - } - - $closeTags = $tokens->findGivenKind(T_CLOSE_TAG); - - if (empty($closeTags)) { - return $content; - } - - list($index, $token) = each($closeTags); - - $tokens->removeLeadingWhitespace($index); - $token->clear(); - - $prevIndex = $tokens->getPrevNonWhitespace($index); - $prevToken = $tokens[$prevIndex]; - - if (!$prevToken->equalsAny(array(';', '}'))) { - $tokens->insertAt($prevIndex + 1, new Token(';')); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'The closing ?> tag MUST be omitted from files containing only PHP.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SingleLineAfterImportsFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SingleLineAfterImportsFixer.php deleted file mode 100644 index 15d0e8c..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SingleLineAfterImportsFixer.php +++ /dev/null @@ -1,110 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; -use Symfony\CS\Utils; - -/** - * Fixer for rules defined in PSR2 ¶3. - * - * @author Ceeram - * @author Graham Campbell - */ -class SingleLineAfterImportsFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->getImportUseIndexes() as $index) { - $indent = ''; - - // if previous line ends with comment and current line starts with whitespace, use current indent - if ($tokens[$index - 1]->isWhitespace(array('whitespaces' => " \t")) && $tokens[$index - 2]->isGivenKind(T_COMMENT)) { - $indent = $tokens[$index - 1]->getContent(); - } elseif ($tokens[$index - 1]->isWhitespace()) { - $indent = Utils::calculateTrailingWhitespaceIndent($tokens[$index - 1]); - } - - $semicolonIndex = $tokens->getNextTokenOfKind($index, array(';', array(T_CLOSE_TAG))); // Handle insert index for inline T_COMMENT with whitespace after semicolon - $insertIndex = $semicolonIndex; - - if ($tokens[$semicolonIndex]->isGivenKind(T_CLOSE_TAG)) { - if ($tokens[$insertIndex - 1]->isWhitespace()) { - --$insertIndex; - } - - $tokens->insertAt($insertIndex, new Token(';')); - } - - if ($semicolonIndex === count($tokens) - 1) { - $tokens->insertAt($insertIndex + 1, new Token(array(T_WHITESPACE, "\n\n".$indent))); - } else { - $newline = "\n"; - $tokens[$semicolonIndex]->isGivenKind(T_CLOSE_TAG) ? --$insertIndex : ++$insertIndex; - if ($tokens[$insertIndex]->isWhitespace(array('whitespaces' => " \t")) && $tokens[$insertIndex + 1]->isComment()) { - ++$insertIndex; - } - - // Do not add newline after inline T_COMMENT as it is part of T_COMMENT already - // TODO: remove on 2.x line - if ($tokens[$insertIndex]->isGivenKind(T_COMMENT) && false !== strpos($tokens[$insertIndex]->getContent(), "\n")) { - $newline = ''; - } - - // Increment insert index for inline T_COMMENT or T_DOC_COMMENT - if ($tokens[$insertIndex]->isComment()) { - ++$insertIndex; - } - - $afterSemicolon = $tokens->getNextMeaningfulToken($semicolonIndex); - if (null === $afterSemicolon || !$tokens[$afterSemicolon]->isGivenKind(T_USE)) { - $newline .= "\n"; - } - - if ($tokens[$insertIndex]->isWhitespace()) { - $nextToken = $tokens[$insertIndex]; - $nextMeaningfulAfterUseIndex = $tokens->getNextMeaningfulToken($insertIndex); - if (null !== $nextMeaningfulAfterUseIndex && $tokens[$nextMeaningfulAfterUseIndex]->isGivenKind(T_USE)) { - if (substr_count($nextToken->getContent(), "\n") < 2) { - $nextToken->setContent($newline.$indent.ltrim($nextToken->getContent())); - } - } else { - $nextToken->setContent($newline.$indent.ltrim($nextToken->getContent())); - } - } else { - // TODO: remove check on 2.x line - if ('' !== $newline.$indent) { - $tokens->insertAt($insertIndex, new Token(array(T_WHITESPACE, $newline.$indent))); - } - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Each namespace use MUST go on its own line and there MUST be one blank line after the use statements block.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SwitchCaseSemicolonToColonFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SwitchCaseSemicolonToColonFixer.php deleted file mode 100644 index 5e68927..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SwitchCaseSemicolonToColonFixer.php +++ /dev/null @@ -1,68 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶5.2. - * - * @author SpacePossum - */ -final class SwitchCaseSemicolonToColonFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isGivenKind(array(T_CASE, T_DEFAULT))) { - continue; - } - - $ternariesCount = 0; - for ($colonIndex = $index + 1; ; ++$colonIndex) { - // We have to skip ternary case for colons. - if ($tokens[$colonIndex]->equals('?')) { - ++$ternariesCount; - } - - if ($tokens[$colonIndex]->equalsAny(array(':', ';'))) { - if (0 === $ternariesCount) { - break; - } - - --$ternariesCount; - } - } - - if ($tokens[$colonIndex]->equals(';')) { - $tokens[$colonIndex]->setContent(':'); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'A case should be followed by a colon and not a semicolon.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SwitchCaseSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SwitchCaseSpaceFixer.php deleted file mode 100644 index 340d15c..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/SwitchCaseSpaceFixer.php +++ /dev/null @@ -1,69 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶5.2. - * - * @author Sullivan Senechal - */ -final class SwitchCaseSpaceFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isGivenKind(array(T_CASE, T_DEFAULT))) { - continue; - } - - $ternariesCount = 0; - for ($colonIndex = $index + 1; ; ++$colonIndex) { - // We have to skip ternary case for colons. - if ($tokens[$colonIndex]->equals('?')) { - ++$ternariesCount; - } - - if ($tokens[$colonIndex]->equalsAny(array(':', ';'))) { - if (0 === $ternariesCount) { - break; - } - - --$ternariesCount; - } - } - - $valueIndex = $tokens->getPrevNonWhitespace($colonIndex); - if (2 + $valueIndex === $colonIndex) { - $tokens[$valueIndex + 1]->clear(); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Removes extra spaces between colon and case value.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/TrailingSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/TrailingSpacesFixer.php deleted file mode 100644 index 5a80c1f..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/TrailingSpacesFixer.php +++ /dev/null @@ -1,77 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶2.3. - * - * Don't add trailing spaces at the end of non-blank lines. - * - * @author Fabien Potencier - * @author Dariusz Rumiński - */ -class TrailingSpacesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isWhitespace()) { - continue; - } - - $lines = preg_split("/([\r\n]+)/", $token->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); - $linesSize = count($lines); - - // fix only multiline whitespaces or singleline whitespaces at the end of file - if ($linesSize > 1 || !isset($tokens[$index + 1])) { - $lines[0] = rtrim($lines[0], " \t"); - - for ($i = 1; $i < $linesSize; ++$i) { - $trimmedLine = rtrim($lines[$i], " \t"); - if ('' !== $trimmedLine) { - $lines[$i] = $trimmedLine; - } - } - - $token->setContent(implode($lines)); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Remove trailing whitespace at the end of non-blank lines.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after NoEmptyPhpdocFixer, UnneededControlParenthesesFixer, ClassDefinitionFixer, CombineConsecutiveUnsetsFixer, NoEmptyStatementFixer and NoUselessElseFixer. - return 0; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/VisibilityFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/VisibilityFixer.php deleted file mode 100644 index c6c45bb..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/VisibilityFixer.php +++ /dev/null @@ -1,198 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\PSR2; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for rules defined in PSR2 ¶4.3, ¶4.5. - * - * @author Dariusz Rumiński - */ -class VisibilityFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - $elements = $tokens->getClassyElements(); - - foreach (array_reverse($elements, true) as $index => $element) { - if ('method' === $element['type']) { - $this->applyAttribs($tokens, $index, $this->grabAttribsBeforeMethodToken($tokens, $index)); - - // force whitespace between function keyword and function name to be single space char - $tokens[++$index]->setContent(' '); - } elseif ('property' === $element['type']) { - $prevIndex = $tokens->getPrevTokenOfKind($index, array(';', ',', '{')); - - if (!$prevIndex || !$tokens[$prevIndex]->equals(',')) { - $this->applyAttribs($tokens, $index, $this->grabAttribsBeforePropertyToken($tokens, $index)); - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Visibility MUST be declared on all properties and methods; abstract and final MUST be declared before the visibility; static MUST be declared after the visibility.'; - } - - /** - * Apply token attributes. - * - * Token at given index is prepended by attributes. - * - * @param Tokens $tokens Tokens collection - * @param int $index token index - * @param array $attribs array of token attributes - */ - private function applyAttribs(Tokens $tokens, $index, array $attribs) - { - $toInsert = array(); - - foreach ($attribs as $attrib) { - if (null !== $attrib && '' !== $attrib->getContent()) { - $toInsert[] = $attrib; - $toInsert[] = new Token(array(T_WHITESPACE, ' ')); - } - } - - if (!empty($toInsert)) { - $tokens->insertAt($index, $toInsert); - } - } - - /** - * Grab attributes before method token at given index. - * - * It's a shorthand for grabAttribsBeforeToken method. - * - * @param Tokens $tokens Tokens collection - * @param int $index token index - * - * @return array array of grabbed attributes - */ - private function grabAttribsBeforeMethodToken(Tokens $tokens, $index) - { - static $tokenAttribsMap = array( - T_PRIVATE => 'visibility', - T_PROTECTED => 'visibility', - T_PUBLIC => 'visibility', - T_ABSTRACT => 'abstract', - T_FINAL => 'final', - T_STATIC => 'static', - ); - - return $this->grabAttribsBeforeToken( - $tokens, - $index, - $tokenAttribsMap, - array( - 'abstract' => null, - 'final' => null, - 'visibility' => new Token(array(T_PUBLIC, 'public')), - 'static' => null, - ) - ); - } - - /** - * Grab attributes before property token at given index. - * - * It's a shorthand for grabAttribsBeforeToken method. - * - * @param Tokens $tokens Tokens collection - * @param int $index token index - * - * @return array array of grabbed attributes - */ - private function grabAttribsBeforePropertyToken(Tokens $tokens, $index) - { - static $tokenAttribsMap = array( - T_VAR => null, // destroy T_VAR token! - T_PRIVATE => 'visibility', - T_PROTECTED => 'visibility', - T_PUBLIC => 'visibility', - T_STATIC => 'static', - ); - - return $this->grabAttribsBeforeToken( - $tokens, - $index, - $tokenAttribsMap, - array( - 'visibility' => new Token(array(T_PUBLIC, 'public')), - 'static' => null, - ) - ); - } - - /** - * Grab attributes before token at given index. - * - * Grabbed attributes are cleared by overriding them with empty string and should be manually applied with applyTokenAttribs method. - * - * @param Tokens $tokens Tokens collection - * @param int $index token index - * @param array $tokenAttribsMap token to attribute name map - * @param array $attribs array of token attributes - * - * @return array array of grabbed attributes - */ - private function grabAttribsBeforeToken(Tokens $tokens, $index, array $tokenAttribsMap, array $attribs) - { - while (true) { - $token = $tokens[--$index]; - - if (!$token->isArray()) { - if ($token->equalsAny(array('{', '}', '(', ')'))) { - break; - } - - continue; - } - - // if token is attribute - if (array_key_exists($token->getId(), $tokenAttribsMap)) { - // set token attribute if token map defines attribute name for token - if ($tokenAttribsMap[$token->getId()]) { - $attribs[$tokenAttribsMap[$token->getId()]] = clone $token; - } - - // clear the token and whitespaces after it - $tokens[$index]->clear(); - $tokens[$index + 1]->clear(); - - continue; - } - - if ($token->isGivenKind(array(T_WHITESPACE, T_COMMENT, T_DOC_COMMENT))) { - continue; - } - - break; - } - - return $attribs; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ArrayElementNoSpaceBeforeCommaFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ArrayElementNoSpaceBeforeCommaFixer.php deleted file mode 100644 index a758d94..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ArrayElementNoSpaceBeforeCommaFixer.php +++ /dev/null @@ -1,99 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Adam Marczuk - */ -final class ArrayElementNoSpaceBeforeCommaFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - if (!$tokens->isArray($index)) { - continue; - } - - $this->fixSpacing($index, $tokens); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'In array declaration, there MUST NOT be a whitespace before each comma.'; - } - - /** - * Method to fix spacing in array declaration. - * - * @param int $index - * @param Tokens $tokens - */ - private function fixSpacing($index, Tokens $tokens) - { - if ($tokens->isShortArray($index)) { - $startIndex = $index; - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $startIndex); - } else { - $startIndex = $tokens->getNextTokenOfKind($index, array('(')); - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); - } - - for ($i = $endIndex - 1; $i > $startIndex; --$i) { - $i = $this->skipNonArrayElements($i, $tokens); - $currentToken = $tokens[$i]; - $prevIndex = $tokens->getPrevNonWhitespace($i - 1); - if ($currentToken->equals(',') && !$tokens[$prevIndex]->equals(array(T_END_HEREDOC))) { - $tokens->removeLeadingWhitespace($i); - } - } - } - - /** - * Method to move index over the non-array elements like function calls or function declarations. - * - * @param int $index - * @param Tokens $tokens - * - * @return int New index - */ - private function skipNonArrayElements($index, Tokens $tokens) - { - if ($tokens[$index]->equals('}')) { - return $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index, false); - } - - if ($tokens[$index]->equals(')')) { - $startIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index, false); - $startIndex = $tokens->getPrevMeaningfulToken($startIndex); - if (!$tokens->isArray($startIndex)) { - return $startIndex; - } - } - - return $index; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ArrayElementWhiteSpaceAfterCommaFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ArrayElementWhiteSpaceAfterCommaFixer.php deleted file mode 100644 index 2ab656d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ArrayElementWhiteSpaceAfterCommaFixer.php +++ /dev/null @@ -1,98 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Adam Marczuk - */ -final class ArrayElementWhiteSpaceAfterCommaFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - if (!$tokens->isArray($index)) { - continue; - } - - $this->fixSpacing($index, $tokens); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'In array declaration, there MUST be a whitespace after each comma.'; - } - - /** - * Method to fix spacing in array declaration. - * - * @param int $index - * @param Tokens $tokens - */ - private function fixSpacing($index, Tokens $tokens) - { - if ($tokens->isShortArray($index)) { - $startIndex = $index; - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $startIndex); - } else { - $startIndex = $tokens->getNextTokenOfKind($index, array('(')); - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); - } - - for ($i = $endIndex - 1; $i > $startIndex; --$i) { - $i = $this->skipNonArrayElements($i, $tokens); - if ($tokens[$i]->equals(',') && !$tokens[$i + 1]->isWhitespace()) { - $tokens->insertAt($i + 1, new Token(array(T_WHITESPACE, ' '))); - } - } - } - - /** - * Method to move index over the non-array elements like function calls or function declarations. - * - * @param int $index - * @param Tokens $tokens - * - * @return int New index - */ - private function skipNonArrayElements($index, Tokens $tokens) - { - if ($tokens[$index]->equals('}')) { - return $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index, false); - } - - if ($tokens[$index]->equals(')')) { - $startIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index, false); - $startIndex = $tokens->getPrevMeaningfulToken($startIndex); - if (!$tokens->isArray($startIndex)) { - return $startIndex; - } - } - - return $index; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/BlanklineAfterOpenTagFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/BlanklineAfterOpenTagFixer.php deleted file mode 100644 index 7ea8018..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/BlanklineAfterOpenTagFixer.php +++ /dev/null @@ -1,79 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Ceeram - */ -class BlanklineAfterOpenTagFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - // ignore files with short open tag and ignore non-monolithic files - if (!$tokens[0]->isGivenKind(T_OPEN_TAG) || !$tokens->isMonolithicPhp()) { - return $content; - } - - $newlineFound = false; - /** @var Token $token */ - foreach ($tokens as $token) { - if ($token->isWhitespace() && false !== strpos($token->getContent(), "\n")) { - $newlineFound = true; - break; - } - } - - // ignore one-line files - if (!$newlineFound) { - return $content; - } - - $token = $tokens[0]; - - if (false === strpos($token->getContent(), "\n")) { - $token->setContent(rtrim($token->getContent())."\n"); - } - - if (!$tokens[1]->isWhitespace() && false === strpos($tokens[1]->getContent(), "\n")) { - $tokens->insertAt(1, new Token(array(T_WHITESPACE, "\n"))); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Ensure there is no code on the same line as the PHP open tag and it is followed by a blankline.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before the NoBlankLinesBeforeNamespaceFixer - return 1; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ConcatWithoutSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ConcatWithoutSpacesFixer.php deleted file mode 100644 index 57c3d02..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ConcatWithoutSpacesFixer.php +++ /dev/null @@ -1,55 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class ConcatWithoutSpacesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - $whitespaces = array('whitespaces' => " \t"); - - foreach ($tokens as $index => $token) { - if ($token->equals('.')) { - $previousNonWhiteIndex = $tokens->getPrevNonWhitespace($index); - if (!$tokens[$previousNonWhiteIndex]->isGivenKind(T_LNUMBER) && false === strpos($tokens[$previousNonWhiteIndex]->getContent(), "\n")) { - $tokens->removeLeadingWhitespace($index, $whitespaces); - } - - $nextNonWhiteIndex = $tokens->getNextNonWhitespace($index); - if (!$tokens[$nextNonWhiteIndex]->isGivenKind(array(T_LNUMBER, T_COMMENT, T_DOC_COMMENT))) { - $tokens->removeTrailingWhitespace($index, $whitespaces); - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Concatenation should be used without spaces.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DeclareEqualNormalizeFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DeclareEqualNormalizeFixer.php deleted file mode 100644 index b8d3b73..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DeclareEqualNormalizeFixer.php +++ /dev/null @@ -1,52 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -final class DeclareEqualNormalizeFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $count = $tokens->count(); - - for ($index = 0; $index < $count; ++$index) { - if (!$tokens[$index]->isGivenKind(T_DECLARE)) { - continue; - } - - while (!$tokens[++$index]->equals('=')); - $tokens->removeLeadingWhitespace($index); - $tokens->removeTrailingWhitespace($index); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Equal sign in declare statement should not be surrounded by spaces.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DoubleArrowMultilineWhitespacesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DoubleArrowMultilineWhitespacesFixer.php deleted file mode 100644 index 9315916..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DoubleArrowMultilineWhitespacesFixer.php +++ /dev/null @@ -1,67 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Carlos Cirello - * @author Dariusz Rumiński - * @author Graham Campbell - */ -class DoubleArrowMultilineWhitespacesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_DOUBLE_ARROW) as $index => $token) { - $this->fixWhitespace($tokens[$index - 1]); - // do not move anything about if there is a comment following the whitespace - if (!$tokens[$index + 2]->isComment()) { - $this->fixWhitespace($tokens[$index + 1]); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Operator => should not be surrounded by multi-line whitespaces.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before the MultilineArrayTrailingCommaFixer and AlignDoubleArrowFixer - return 1; - } - - private function fixWhitespace(Token $token) - { - if ($token->isWhitespace() && !$token->isWhitespace(array('whitespaces' => " \t"))) { - $token->setContent(rtrim($token->getContent()).' '); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DuplicateSemicolonFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DuplicateSemicolonFixer.php deleted file mode 100644 index e740167..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/DuplicateSemicolonFixer.php +++ /dev/null @@ -1,66 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class DuplicateSemicolonFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { - $token = $tokens[$index]; - - // skip T_FOR parenthesis to ignore duplicated `;` like `for ($i = 1; ; ++$i) {...}` - if ($token->isGivenKind(T_FOR)) { - $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextMeaningfulToken($index)) + 1; - continue; - } - - if (!$token->equals(';') || !$tokens[$tokens->getPrevMeaningfulToken($index)]->equals(';')) { - continue; - } - - $tokens->removeLeadingWhitespace($index); - $token->clear(); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Remove duplicated semicolons.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before the BracesFixer, SpacesBeforeSemicolonFixer, MultilineSpacesBeforeSemicolonFixer, SwitchCaseSemicolonToColonFixer, NoUselessReturnFixer and NoUselessElseFixer. - return 26; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ExtraEmptyLinesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ExtraEmptyLinesFixer.php deleted file mode 100644 index 160bb64..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ExtraEmptyLinesFixer.php +++ /dev/null @@ -1,76 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class ExtraEmptyLinesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - /** @var Token $token */ - foreach ($tokens->findGivenKind(T_WHITESPACE) as $index => $token) { - $content = ''; - $count = 0; - if ($index > 0 && $tokens[$index - 1]->isComment()) { - $prevContent = $tokens[$index - 1]->getContent(); - $count = strrpos($prevContent, "\n") === strlen($prevContent) - 1 ? 1 : 0; - } - - $parts = explode("\n", $token->getContent()); - - for ($i = 0, $last = count($parts) - 1; $i <= $last; ++$i) { - if ('' === $parts[$i]) { - // if part is empty then we between two \n - ++$count; - } else { - $content .= $parts[$i]; - } - - if ($i !== $last && $count < 3) { - $content .= "\n"; - } - } - - $token->setContent($content); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Removes extra empty lines.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the UnusedUseFixer, DuplicateSemicolonFixer, NoEmptyPhpdocFixer, CombineConsecutiveUnsetsFixer and NoUselessElseFixer. - return -20; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/FunctionTypehintSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/FunctionTypehintSpaceFixer.php deleted file mode 100644 index 64d7939..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/FunctionTypehintSpaceFixer.php +++ /dev/null @@ -1,80 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class FunctionTypehintSpaceFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - $token = $tokens[$index]; - - if (!$token->isGivenKind(T_FUNCTION)) { - continue; - } - - $startParenthesisIndex = $tokens->getNextTokenOfKind($index, array('(', ';', array(T_CLOSE_TAG))); - if (!$tokens[$startParenthesisIndex]->equals('(')) { - continue; - } - - $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex); - - for ($iter = $endParenthesisIndex - 1; $iter > $startParenthesisIndex; --$iter) { - if (!$tokens[$iter]->isGivenKind(T_VARIABLE)) { - continue; - } - - // skip ... before $variable for variadic parameter - if (defined('T_ELLIPSIS')) { - $prevNonWhitespaceIndex = $tokens->getPrevNonWhitespace($iter); - if ($tokens[$prevNonWhitespaceIndex]->isGivenKind(T_ELLIPSIS)) { - $iter = $prevNonWhitespaceIndex; - } - } - - // skip & before $variable for parameter passed by reference - $prevNonWhitespaceIndex = $tokens->getPrevNonWhitespace($iter); - if ($tokens[$prevNonWhitespaceIndex]->equals('&')) { - $iter = $prevNonWhitespaceIndex; - } - - if (!$tokens[$iter - 1]->equalsAny(array(array(T_WHITESPACE), array(T_COMMENT), array(T_DOC_COMMENT), '(', ','))) { - $tokens->insertAt($iter, new Token(array(T_WHITESPACE, ' ', $tokens[$iter]->getLine()))); - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Add missing space between function\'s argument and its typehint.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/HashToSlashCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/HashToSlashCommentFixer.php deleted file mode 100644 index 0525abf..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/HashToSlashCommentFixer.php +++ /dev/null @@ -1,47 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Changes single comments prefixes '#' with '//'. - * - * @author SpacePossum - */ -final class HashToSlashCommentFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - for ($i = 0, $count = count($tokens); $i < $count - 1; ++$i) { - if ($tokens[$i]->isGivenKind(T_COMMENT) && '#' === substr($tokens[$i]->getContent(), 0, 1)) { - $tokens[$i]->setContent('//'.substr($tokens[$i]->getContent(), 1)); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Single line comments should use double slashes (//) and not hash (#).'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/HeredocToNowdocFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/HeredocToNowdocFixer.php deleted file mode 100644 index d54c614..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/HeredocToNowdocFixer.php +++ /dev/null @@ -1,79 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Gregor Harlan - */ -final class HeredocToNowdocFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isGivenKind(T_START_HEREDOC) || false !== strpos($token->getContent(), "'")) { - continue; - } - - if ($tokens[$index + 1]->isGivenKind(T_END_HEREDOC)) { - $this->convertToNowdoc($token); - continue; - } - - if ( - !$tokens[$index + 1]->isGivenKind(T_ENCAPSED_AND_WHITESPACE) || - !$tokens[$index + 2]->isGivenKind(T_END_HEREDOC) - ) { - continue; - } - - $content = $tokens[$index + 1]->getContent(); - // regex: odd number of backslashes, not followed by dollar - if (preg_match('/(?convertToNowdoc($token); - $content = str_replace(array('\\\\', '\\$'), array('\\', '$'), $content); - $tokens[$index + 1]->setContent($content); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Convert heredoc to nowdoc if possible.'; - } - - /** - * Transforms the heredoc start token to nowdoc notation. - * - * @param Token $token - */ - private function convertToNowdoc(Token $token) - { - $token->setContent(preg_replace('/(?<=^<<<)(\s*)"?(.*?)"?$/', '$1\'$2\'', $token->getContent())); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/IncludeFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/IncludeFixer.php deleted file mode 100644 index fc84e7d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/IncludeFixer.php +++ /dev/null @@ -1,120 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Sebastiaan Stok - * @author Dariusz Rumiński - */ -class IncludeFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $includies = $this->findIncludies($tokens); - $this->clearIncludies($tokens, $includies); - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Include/Require and file path should be divided with a single space. File path should not be placed under brackets.'; - } - - private function clearIncludies(Tokens $tokens, array $includies) - { - foreach (array_reverse($includies) as $includy) { - if ($includy['end']) { - $tokens->removeLeadingWhitespace($includy['end']); - } - - $braces = $includy['braces']; - - if ($braces) { - $nextToken = $tokens[$tokens->getNextMeaningfulToken($braces['close'])]; - - if ($nextToken->equalsAny(array(';', array(T_CLOSE_TAG)))) { - $tokens->removeLeadingWhitespace($braces['open']); - $tokens->removeTrailingWhitespace($braces['open']); - $tokens->removeLeadingWhitespace($braces['close']); - $tokens->removeTrailingWhitespace($braces['close']); - - $tokens[$braces['open']] = new Token(array(T_WHITESPACE, ' ')); - $tokens[$braces['close']]->clear(); - } - } - - $nextIndex = $includy['begin'] + 1; - $nextToken = $tokens[$nextIndex]; - - while ($nextToken->isEmpty()) { - $nextToken = $tokens[++$nextIndex]; - } - - if ($nextToken->isWhitespace()) { - $nextToken->setContent(' '); - } elseif ($braces || $tokens[$nextIndex]->isGivenKind(array(T_VARIABLE, T_CONSTANT_ENCAPSED_STRING, T_COMMENT))) { - $tokens->insertAt($includy['begin'] + 1, new Token(array(T_WHITESPACE, ' '))); - } - } - } - - private function findIncludies(Tokens $tokens) - { - static $includyTokenKinds = array(T_REQUIRE, T_REQUIRE_ONCE, T_INCLUDE, T_INCLUDE_ONCE); - - $includies = array(); - - foreach ($tokens->findGivenKind($includyTokenKinds) as $includyTokens) { - foreach ($includyTokens as $index => $token) { - $includy = array( - 'begin' => $index, - 'braces' => null, - 'end' => $tokens->getNextTokenOfKind($index, array(';', array(T_CLOSE_TAG))), - ); - - $nextTokenIndex = $tokens->getNextMeaningfulToken($index); - $nextToken = $tokens[$nextTokenIndex]; - - if ($nextToken->equals('(')) { - // Don't remove braces when the statement is wrapped. - // Include is also legal as function parameter or condition statement but requires being wrapped then. - $braceCloseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nextTokenIndex); - - if ($tokens[$tokens->getNextMeaningfulToken($braceCloseIndex)]->equalsAny(array(';', array(T_CLOSE_TAG)))) { - $includy['braces'] = array( - 'open' => $nextTokenIndex, - 'close' => $braceCloseIndex, - ); - } - } - - $includies[] = $includy; - } - } - - return $includies; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/JoinFunctionFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/JoinFunctionFixer.php deleted file mode 100644 index d65ad2f..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/JoinFunctionFixer.php +++ /dev/null @@ -1,58 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class JoinFunctionFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_STRING) as $index => $token) { - if ('join' !== $token->getContent()) { - continue; - } - - $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; - if ($prevToken->isGivenKind(array(T_DOUBLE_COLON, T_NEW, T_NS_SEPARATOR, T_OBJECT_OPERATOR, T_FUNCTION))) { - continue; - } - - $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)]; - if ($nextToken->isGivenKind(array(T_DOUBLE_COLON, T_NS_SEPARATOR))) { - continue; - } - - $token->setContent('implode'); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Implode function should be used instead of join function.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/LowercaseCastFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/LowercaseCastFixer.php deleted file mode 100644 index 79ee9bd..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/LowercaseCastFixer.php +++ /dev/null @@ -1,48 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author SpacePossum - */ -final class LowercaseCastFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { - if (!$tokens[$index]->isCast()) { - continue; - } - - $tokens[$index]->setContent(strtolower($tokens[$index]->getContent())); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Cast should be written in lower case.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/MethodArgumentDefaultValueFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/MethodArgumentDefaultValueFixer.php deleted file mode 100644 index b5a718c..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/MethodArgumentDefaultValueFixer.php +++ /dev/null @@ -1,177 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Mark Scherer - * @author Lucas Manzke - * @author Gregor Harlan - */ -final class MethodArgumentDefaultValueFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'In method arguments there must not be arguments with default values before non-default ones.'; - } - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - for ($i = 0, $l = $tokens->count(); $i < $l; ++$i) { - if (!$tokens[$i]->isGivenKind(T_FUNCTION)) { - continue; - } - - $startIndex = $tokens->getNextTokenOfKind($i, array('(')); - $i = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); - - $this->fixFunctionDefinition($tokens, $startIndex, $i); - } - - return $tokens->generateCode(); - } - - /** - * @param Tokens $tokens - * @param int $startIndex - * @param int $endIndex - */ - private function fixFunctionDefinition(Tokens $tokens, $startIndex, $endIndex) - { - $lastArgumentIndex = $this->getLastNonDefaultArgumentIndex($tokens, $startIndex, $endIndex); - - if (!$lastArgumentIndex) { - return; - } - - for ($i = $lastArgumentIndex; $i > $startIndex; --$i) { - $token = $tokens[$i]; - - if ($token->isGivenKind(T_VARIABLE)) { - $lastArgumentIndex = $i; - continue; - } - - if (!$token->equals('=') || $this->isTypehintedNullableVariable($tokens, $i)) { - continue; - } - - $endIndex = $tokens->getPrevTokenOfKind($lastArgumentIndex, array(',')); - $endIndex = $tokens->getPrevMeaningfulToken($endIndex); - $this->removeDefaultArgument($tokens, $i, $endIndex); - } - } - - /** - * @param Tokens $tokens - * @param int $startIndex - * @param int $endIndex - * - * @return int|null - */ - private function getLastNonDefaultArgumentIndex(Tokens $tokens, $startIndex, $endIndex) - { - for ($i = $endIndex - 1; $i > $startIndex; --$i) { - $token = $tokens[$i]; - - if ($token->equals('=')) { - $i = $tokens->getPrevMeaningfulToken($i); - continue; - } - - if ($token->isGivenKind(T_VARIABLE) && !$this->isEllipsis($tokens, $i)) { - return $i; - } - } - } - - /** - * @param Tokens $tokens - * @param int $variableIndex - * - * @return bool - */ - private function isEllipsis(Tokens $tokens, $variableIndex) - { - if (!defined('T_ELLIPSIS')) { - return $tokens[$tokens->getPrevMeaningfulToken($variableIndex)]->equals('.'); - } - - return $tokens[$tokens->getPrevMeaningfulToken($variableIndex)]->isGivenKind(T_ELLIPSIS); - } - - /** - * @param Tokens $tokens - * @param int $startIndex - * @param int $endIndex - */ - private function removeDefaultArgument(Tokens $tokens, $startIndex, $endIndex) - { - for ($i = $startIndex; $i <= $endIndex;) { - $tokens[$i]->clear(); - $this->clearWhitespacesBeforeIndex($tokens, $i); - $i = $tokens->getNextMeaningfulToken($i); - } - } - - /** - * @param Tokens $tokens - * @param int $index Index of "=" - * - * @return bool - */ - private function isTypehintedNullableVariable(Tokens $tokens, $index) - { - $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)]; - - if (!$nextToken->equals(array(T_STRING, 'null'), false)) { - return false; - } - - $variableIndex = $tokens->getPrevMeaningfulToken($index); - - $searchTokens = array(',', '(', array(T_STRING), array(CT_ARRAY_TYPEHINT)); - $typehintKinds = array(T_STRING, CT_ARRAY_TYPEHINT); - - if (defined('T_CALLABLE')) { - $searchTokens[] = array(T_CALLABLE); - $typehintKinds[] = T_CALLABLE; - } - - $prevIndex = $tokens->getPrevTokenOfKind($variableIndex, $searchTokens); - - return $tokens[$prevIndex]->isGivenKind($typehintKinds); - } - - /** - * @param Tokens $tokens - * @param int $index - */ - private function clearWhitespacesBeforeIndex(Tokens $tokens, $index) - { - $token = $tokens[$index - 1]; - - if ($token->isGivenKind(T_WHITESPACE)) { - $token->clear(); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/MultilineArrayTrailingCommaFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/MultilineArrayTrailingCommaFixer.php deleted file mode 100644 index 1482d8e..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/MultilineArrayTrailingCommaFixer.php +++ /dev/null @@ -1,78 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Sebastiaan Stok - * @author Dariusz Rumiński - */ -class MultilineArrayTrailingCommaFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - if ($tokens->isArray($index)) { - $this->fixArray($tokens, $index); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'PHP multi-line arrays should have a trailing comma.'; - } - - private function fixArray(Tokens $tokens, $index) - { - if (!$tokens->isArrayMultiLine($index)) { - return; - } - - $startIndex = $index; - - if ($tokens[$startIndex]->isGivenKind(T_ARRAY)) { - $startIndex = $tokens->getNextTokenOfKind($startIndex, array('(')); - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); - } else { - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $startIndex); - } - - $beforeEndIndex = $tokens->getPrevMeaningfulToken($endIndex); - $beforeEndToken = $tokens[$beforeEndIndex]; - - // if there is some item between braces then add `,` after it - if ($startIndex !== $beforeEndIndex && !$beforeEndToken->equalsAny(array(',', array(T_END_HEREDOC)))) { - $tokens->insertAt($beforeEndIndex + 1, new Token(',')); - - $endToken = $tokens[$endIndex]; - - if (!$endToken->isComment() && !$endToken->isWhitespace()) { - $tokens->ensureWhitespaceAtIndex($endIndex, 1, ' '); - } - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NamespaceNoLeadingWhitespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NamespaceNoLeadingWhitespaceFixer.php deleted file mode 100644 index 259afae..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NamespaceNoLeadingWhitespaceFixer.php +++ /dev/null @@ -1,82 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Bram Gotink - */ -class NamespaceNoLeadingWhitespaceFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = count($tokens) - 1; 0 <= $index; --$index) { - $token = $tokens[$index]; - - if (!$token->isGivenKind(T_NAMESPACE)) { - continue; - } - - $beforeNamespace = $tokens[$index - 1]; - - if (!$beforeNamespace->isWhitespace()) { - if (!self::endsWithWhitespace($beforeNamespace->getContent())) { - $tokens->insertAt($index, new Token(array(T_WHITESPACE, "\n"))); - } - - continue; - } - - $lastNewline = strrpos($beforeNamespace->getContent(), "\n"); - - if (false === $lastNewline) { - $beforeBeforeNamespace = $tokens[$index - 2]; - - if (self::endsWithWhitespace($beforeBeforeNamespace->getContent())) { - $beforeNamespace->clear(); - } else { - $beforeNamespace->setContent(' '); - } - } else { - $beforeNamespace->setContent(substr($beforeNamespace->getContent(), 0, $lastNewline + 1)); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'The namespace declaration line shouldn\'t contain leading whitespace.'; - } - - private static function endsWithWhitespace($str) - { - if ('' === $str) { - return false; - } - - return '' === trim(substr($str, -1)); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoBlankLinesAfterClassOpeningFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoBlankLinesAfterClassOpeningFixer.php deleted file mode 100644 index 81c31a3..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoBlankLinesAfterClassOpeningFixer.php +++ /dev/null @@ -1,71 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; -use Symfony\CS\Utils; - -/** - * @author Ceeram - */ -class NoBlankLinesAfterClassOpeningFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isClassy()) { - continue; - } - - $startBraceIndex = $tokens->getNextTokenOfKind($index, array('{')); - if (!$tokens[$startBraceIndex + 1]->isWhitespace()) { - continue; - } - - $this->fixWhitespace($tokens[$startBraceIndex + 1]); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There should be no empty lines after class opening brace.'; - } - - /** - * Cleanup a whitespace token. - * - * @param Token $token - */ - private function fixWhitespace(Token $token) - { - $content = $token->getContent(); - // if there is more than one new line in the whitespace, then we need to fix it - if (substr_count($content, "\n") > 1) { - // the final bit of the whitespace must be the next statement's indentation - $lines = Utils::splitLines($content); - $token->setContent("\n".end($lines)); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyCommentFixer.php deleted file mode 100644 index 0b95a6b..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyCommentFixer.php +++ /dev/null @@ -1,128 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author SpacePossum - */ -final class NoEmptyCommentFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if ($token->isGivenKind(T_COMMENT)) { - $this->fixComment($tokens, $index); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There should not be an empty comments.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after PhpdocToCommentFixer and before ExtraEmptyLinesFixer, TrailingSpacesFixer and WhitespacyLinesFixer. - return 2; - } - - /** - * @param Tokens $tokens - * @param int $index T_COMMENT index - */ - private function fixComment(Tokens $tokens, $index) - { - $content = $tokens[$index]->getContent(); - - // single line comment starting with '#' - if ('#' === $content[0]) { - if (preg_match('|^#\s*$|', $content)) { - $this->clearCommentToken($tokens, $index); - } - - return; - } - - // single line comment starting with '//' - if ('/' === $content[1]) { - if (preg_match('|^//\s*$|', $content)) { - $this->clearCommentToken($tokens, $index); - } - - return; - } - - // comment starting with '/*' and ending with '*/' (but not a PHPDoc) - if (preg_match('|^/\*\s*\*/$|', $content)) { - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - } - } - - /** - * Clear comment token, but preserve trailing linebreak if there is any. - * - * @param Tokens $tokens - * @param int $index T_COMMENT index - * - * @deprecated Will be removed in the 2.0 - */ - private function clearCommentToken(Tokens $tokens, $index) - { - if ("\n" !== substr($tokens[$index]->getContent(), -1, 1)) { - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - - return; - } - - // if previous not-cleared token is whitespace; - // append line break to content - $previous = $tokens->getNonEmptySibling($index, -1); - if ($tokens[$previous]->isWhitespace()) { - $tokens[$previous]->setContent($tokens[$previous]->getContent()."\n"); - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - - return; - } - - // elseif the next not-cleared token is whitespace; - // prepend with line break - $next = $tokens->getNonEmptySibling($index, 1); - if (null !== $next && $tokens[$next]->isWhitespace()) { - $tokens[$next]->setContent("\n".$tokens[$next]->getContent()); - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - - return; - } - - // else - // override with whitespace token linebreak - $tokens->overrideAt($index, array(T_WHITESPACE, "\n", $tokens[$index]->getLine())); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyLinesAfterPhpdocsFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyLinesAfterPhpdocsFixer.php deleted file mode 100644 index f2fbf69..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyLinesAfterPhpdocsFixer.php +++ /dev/null @@ -1,87 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; -use Symfony\CS\Utils; - -/** - * @author Graham Campbell - */ -class NoEmptyLinesAfterPhpdocsFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - static $forbiddenSuccessors = array( - T_DOC_COMMENT, - T_COMMENT, - T_WHITESPACE, - T_RETURN, - T_THROW, - T_GOTO, - T_CONTINUE, - T_BREAK, - ); - - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $index => $token) { - // get the next non-whitespace token inc comments, provided - // that there is whitespace between it and the current token - $next = $tokens->getNextNonWhitespace($index); - if ($index + 2 === $next && false === $tokens[$next]->isGivenKind($forbiddenSuccessors)) { - $this->fixWhitespace($tokens[$index + 1]); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There should not be blank lines between docblock and the documented element.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be ran before the SingleBlankLineBeforeNamespaceFixer. - return 1; - } - - /** - * Cleanup a whitespace token. - * - * @param Token $token - */ - private function fixWhitespace(Token $token) - { - $content = $token->getContent(); - // if there is more than one new line in the whitespace, then we need to fix it - if (substr_count($content, "\n") > 1) { - // the final bit of the whitespace must be the next statement's indentation - $lines = Utils::splitLines($content); - $token->setContent("\n".end($lines)); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyPhpdocFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyPhpdocFixer.php deleted file mode 100644 index f33b586..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyPhpdocFixer.php +++ /dev/null @@ -1,60 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author SpacePossum - */ -final class NoEmptyPhpdocFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isGivenKind(T_DOC_COMMENT)) { - continue; - } - - if (preg_match('#^/\*\*[\s\*]*\*/$#', $token->getContent())) { - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There should not be empty PHPDoc blocks.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before ExtraEmptyLinesFixer, TrailingSpacesFixer, WhitespacyLinesFixer and - // after PhpdocNoAccessFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer. - return 5; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyStatementFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyStatementFixer.php deleted file mode 100644 index 6de84e3..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NoEmptyStatementFixer.php +++ /dev/null @@ -1,161 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author SpacePossum - * @author Dariusz Rumiński - */ -final class NoEmptyStatementFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { - // skip T_FOR parenthesis to ignore duplicated `;` like `for ($i = 1; ; ++$i) {...}` - if ($tokens[$index]->isGivenKind(T_FOR)) { - $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextMeaningfulToken($index)) + 1; - continue; - } - - if (!$tokens[$index]->equals(';')) { - continue; - } - - $previousMeaningfulIndex = $tokens->getPrevMeaningfulToken($index); - - // A semicolon can always be removed if it follows a semicolon, '{' or opening tag. - if ($tokens[$previousMeaningfulIndex]->equalsAny(array('{', ';', array(T_OPEN_TAG)))) { - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - continue; - } - - // A semicolon might be removed if it follows a '}' but only if the brace is part of certain structures. - if ($tokens[$previousMeaningfulIndex]->equals('}')) { - $this->fixSemicolonAfterCurlyBraceClose($tokens, $index, $previousMeaningfulIndex); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Remove useless semicolon statements.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before the BracesFixer, SpacesBeforeSemicolonFixer, SpacesAfterSemicolonFixer, WhitespacyLinesFixer, MultilineSpacesBeforeSemicolonFixer, CombineConsecutiveUnsetsFixer and ExtraEmptyLinesFixer. - return 25; - } - - /** - * Fix semicolon after closing curly brace if needed. - * - * Test for the following cases - * - just '{' '}' block (following open tag or ';') - * - if, else, elseif - * - interface, trait, class (but not anonymous) - * - catch, finally (but not try) - * - for, foreach, while (but not 'do - while') - * - switch - * - function (declaration, but not lambda) - * - declare (with '{' '}') - * - namespace (with '{' '}') - * - * @param Tokens $tokens - * @param int $index Semicolon index - * @param int $curlyCloseIndex - */ - private function fixSemicolonAfterCurlyBraceClose(Tokens $tokens, $index, $curlyCloseIndex) - { - static $beforeCurlyOpeningKinds = null; - if (null === $beforeCurlyOpeningKinds) { - $beforeCurlyOpeningKinds = array(T_ELSE, T_NAMESPACE, T_OPEN_TAG); - if (defined('T_FINALLY')) { - $beforeCurlyOpeningKinds[] = T_FINALLY; - } - } - - $curlyOpeningIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $curlyCloseIndex, false); - $beforeCurlyOpening = $tokens->getPrevMeaningfulToken($curlyOpeningIndex); - if ($tokens[$beforeCurlyOpening]->isGivenKind($beforeCurlyOpeningKinds) || $tokens[$beforeCurlyOpening]->equalsAny(array(';', '{', '}'))) { - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - - return; - } - - // check for namespaces and class, interface and trait definitions - if ($tokens[$beforeCurlyOpening]->isGivenKind(T_STRING)) { - $classyTest = $tokens->getPrevMeaningfulToken($beforeCurlyOpening); - while ($tokens[$classyTest]->equals(',') || $tokens[$classyTest]->isGivenKind(array(T_STRING, T_NS_SEPARATOR, T_EXTENDS, T_IMPLEMENTS))) { - $classyTest = $tokens->getPrevMeaningfulToken($classyTest); - } - - if ( - $tokens[$classyTest]->isGivenKind(T_NAMESPACE) || - ($tokens[$classyTest]->isClassy() && !$this->isAnonymousClass($tokens, $classyTest)) - ) { - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - } - - return; - } - - // early return check, below only control structures with conditions are fixed - if (!$tokens[$beforeCurlyOpening]->equals(')')) { - return; - } - - $openingBrace = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $beforeCurlyOpening, false); - $beforeOpeningBrace = $tokens->getPrevMeaningfulToken($openingBrace); - - if ($tokens[$beforeOpeningBrace]->isGivenKind(array(T_IF, T_ELSEIF, T_FOR, T_FOREACH, T_WHILE, T_SWITCH, T_CATCH, T_DECLARE))) { - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - - return; - } - - // check for function definition - if ($tokens[$beforeOpeningBrace]->isGivenKind(T_STRING)) { - $beforeString = $tokens->getPrevMeaningfulToken($beforeOpeningBrace); - if ($tokens[$beforeString]->isGivenKind(T_FUNCTION)) { - $tokens->clearTokenAndMergeSurroundingWhitespace($index); // implicit return - } - } - } - - /** - * @param Tokens $tokens - * @param int $index - * - * @return bool - */ - private function isAnonymousClass(Tokens $tokens, $index) - { - return $tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_NEW); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ObjectOperatorFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ObjectOperatorFixer.php deleted file mode 100644 index 3af4a18..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ObjectOperatorFixer.php +++ /dev/null @@ -1,54 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Fabien Potencier - * @author Dariusz Rumiński - */ -class ObjectOperatorFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - // [Structure] there should not be space before or after T_OBJECT_OPERATOR - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_OBJECT_OPERATOR) as $index => $token) { - // clear whitespace before -> - if ($tokens[$index - 1]->isWhitespace(array('whitespaces' => " \t")) && !$tokens[$index - 2]->isComment()) { - $tokens[$index - 1]->clear(); - } - - // clear whitespace after -> - if ($tokens[$index + 1]->isWhitespace(array('whitespaces' => " \t")) && !$tokens[$index + 2]->isComment()) { - $tokens[$index + 1]->clear(); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There should not be space before or after object T_OBJECT_OPERATOR.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/OperatorsSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/OperatorsSpacesFixer.php deleted file mode 100644 index 40a5a4c..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/OperatorsSpacesFixer.php +++ /dev/null @@ -1,107 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - * @author SpacePossum - */ -class OperatorsSpacesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - // last and first tokens cannot be an operator - for ($index = $tokens->count() - 2; $index > 0; --$index) { - if (!$tokens->isBinaryOperator($index)) { - continue; - } - - $isDeclare = $this->isDeclareStatement($tokens, $index); - if (false !== $isDeclare) { - $index = $isDeclare; // skip `declare(foo ==bar)`, see `declare_equal_normalize` - } else { - $this->fixWhiteSpaceAroundOperator($tokens, $index); - } - - // previous of binary operator is now never an operator / previous of declare statement cannot be an operator - --$index; - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Binary operators should be surrounded by at least one space.'; - } - - private function fixWhiteSpaceAroundOperator(Tokens $tokens, $index) - { - // do not change the alignment of `=>` or `=`, see `(un)align_double_arrow`, `(un)align_equals` - $preserveAlignment = $tokens[$index]->isGivenKind(T_DOUBLE_ARROW) || $tokens[$index]->equals('='); - - // fix white space after operator - if ($tokens[$index + 1]->isWhitespace()) { - $content = $tokens[$index + 1]->getContent(); - if (!$preserveAlignment && ' ' !== $content && false === strpos($content, "\n") && !$tokens[$tokens->getNextNonWhitespace($index + 1)]->isComment()) { - $tokens[$index + 1]->setContent(' '); - } - } else { - $tokens->insertAt($index + 1, new Token(array(T_WHITESPACE, ' '))); - } - - // fix white space before operator - if ($tokens[$index - 1]->isWhitespace()) { - $content = $tokens[$index - 1]->getContent(); - if (!$preserveAlignment && ' ' !== $content && false === strpos($content, "\n") && !$tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) { - $tokens[$index - 1]->setContent(' '); - } - } else { - $tokens->insertAt($index, new Token(array(T_WHITESPACE, ' '))); - } - } - - /** - * @param Tokens $tokens - * @param int $index - * - * @return bool|int - */ - private function isDeclareStatement(Tokens $tokens, $index) - { - $prevMeaningfulIndex = $tokens->getPrevMeaningfulToken($index); - if ($tokens[$prevMeaningfulIndex]->isGivenKind(T_STRING)) { - $prevMeaningfulIndex = $tokens->getPrevMeaningfulToken($prevMeaningfulIndex); - if ($tokens[$prevMeaningfulIndex]->equals('(')) { - $prevMeaningfulIndex = $tokens->getPrevMeaningfulToken($prevMeaningfulIndex); - if ($tokens[$prevMeaningfulIndex]->isGivenKind(T_DECLARE)) { - return $prevMeaningfulIndex; - } - } - } - - return false; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpUnitFqcnAnnotationFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpUnitFqcnAnnotationFixer.php deleted file mode 100644 index e28d5e6..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpUnitFqcnAnnotationFixer.php +++ /dev/null @@ -1,58 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Roland Franssen - */ -final class PhpUnitFqcnAnnotationFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $token) { - if ($token->isGivenKind(T_DOC_COMMENT)) { - $token->setContent(preg_replace( - '~^(\s*\*\s*@(?:expectedException|covers|coversDefaultClass|uses)\h+)(\w.*)$~m', '$1\\\\$2', - $token->getContent() - )); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'PHPUnit annotations should be a FQCNs including a root namespace.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before UnusedUseFixer - return -9; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocAnnotationWithoutDotFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocAnnotationWithoutDotFixer.php deleted file mode 100644 index f9ce106..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocAnnotationWithoutDotFixer.php +++ /dev/null @@ -1,67 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class PhpdocAnnotationWithoutDotFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $token) { - if (!$token->isGivenKind(T_DOC_COMMENT)) { - continue; - } - - $doc = new DocBlock($token->getContent()); - $annotations = $doc->getAnnotations(); - - if (empty($annotations)) { - continue; - } - - foreach ($annotations as $annotation) { - if ($annotation->getTag()->valid()) { - $line = $doc->getLine($annotation->getEnd()); - - $content = preg_replace('/(?getContent()); - - if (null !== $content) { - $line->setContent($content); - } - } - } - $token->setContent($doc->getContent()); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Phpdocs annotation descriptions should not end with a full stop.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocIndentFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocIndentFixer.php deleted file mode 100644 index b4f6e66..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocIndentFixer.php +++ /dev/null @@ -1,112 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; -use Symfony\CS\Utils; - -/** - * @author Ceeram - * @author Graham Campbell - */ -class PhpdocIndentFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $index => $token) { - $nextIndex = $tokens->getNextMeaningfulToken($index); - - // skip if there is no next token or if next token is block end `}` - if (null === $nextIndex || $tokens[$nextIndex]->equals('}')) { - continue; - } - - $prevToken = $tokens[$index - 1]; - - // ignore inline docblocks - if ( - $prevToken->isGivenKind(T_OPEN_TAG) - || ($prevToken->isWhitespace(array('whitespaces' => " \t")) && !$tokens[$index - 2]->isGivenKind(T_OPEN_TAG)) - || $prevToken->equalsAny(array(';', '{')) - ) { - continue; - } - - $indent = ''; - if ($tokens[$nextIndex - 1]->isWhitespace()) { - $indent = Utils::calculateTrailingWhitespaceIndent($tokens[$nextIndex - 1]); - } - - $prevToken->setContent($this->fixWhitespaceBefore($prevToken->getContent(), $indent)); - $token->setContent($this->fixDocBlock($token->getContent(), $indent)); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Docblocks should have the same indentation as the documented subject.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - /* - * Should be run before all other docblock fixers apart from the - * phpdoc_to_comment fixer to make sure all fixers apply correct - * indentation to new code they add, and the phpdoc_params fixer only - * works on correctly indented docblocks. We also need to be running - * after the psr2 indentation fixer for obvious reasons. - * comments. - */ - return 20; - } - - /** - * Fix indentation of Docblock. - * - * @param string $content Docblock contents - * @param string $indent Indentation to apply - * - * @return string Dockblock contents including correct indentation - */ - private function fixDocBlock($content, $indent) - { - return ltrim(preg_replace('/^[ \t]*/m', $indent.' ', $content)); - } - - /** - * Fix whitespace before the Docblock. - * - * @param string $content Whitespace before Docblock - * @param string $indent Indentation of the documented subject - * - * @return string Whitespace including correct indentation for Dockblock after this whitespace - */ - private function fixWhitespaceBefore($content, $indent) - { - return rtrim($content, " \t").$indent; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocInlineTagFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocInlineTagFixer.php deleted file mode 100644 index e28cfa4..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocInlineTagFixer.php +++ /dev/null @@ -1,76 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fix inline tags and make inheritdoc tag always inline. - */ -final class PhpdocInlineTagFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $token) { - if (!$token->isGivenKind(T_DOC_COMMENT)) { - continue; - } - - $content = $token->getContent(); - - // Move `@` inside tag, for example @{tag} -> {@tag}, replace multiple curly brackets, - // remove spaces between '{' and '@', remove 's' at the end of tag. - // Make sure the tags are written in lower case, remove white space between end - // of text and closing bracket and between the tag and inline comment. - $content = preg_replace_callback( - '#(?:@{+|{+[ \t]*@)[ \t]*(example|id|internal|inheritdoc|link|source|toc|tutorial)s?([^}]*)(?:}+)#i', - function (array $matches) { - $doc = trim($matches[2]); - - if ('' === $doc) { - return '{@'.strtolower($matches[1]).'}'; - } - - return '{@'.strtolower($matches[1]).' '.$doc.'}'; - }, - $content - ); - - // Always make inheritdoc inline using with '{' '}' when needed, remove trailing 's', - // make sure lowercase. - $content = preg_replace( - '#(?setContent($content); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Fix phpdoc inline tags, make inheritdoc always inline.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoAccessFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoAccessFixer.php deleted file mode 100644 index e4d33bb..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoAccessFixer.php +++ /dev/null @@ -1,42 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractAnnotationRemovalFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class PhpdocNoAccessFixer extends AbstractAnnotationRemovalFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $this->removeAnnotations($tokens, array('access')); - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return '@access annotations should be omitted from phpdocs.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoEmptyReturnFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoEmptyReturnFixer.php deleted file mode 100644 index a0828e5..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoEmptyReturnFixer.php +++ /dev/null @@ -1,79 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\DocBlock\Annotation; -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class PhpdocNoEmptyReturnFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $token) { - $doc = new DocBlock($token->getContent()); - $annotations = $doc->getAnnotationsOfType('return'); - - if (empty($annotations)) { - continue; - } - - foreach ($annotations as $annotation) { - $this->fixAnnotation($doc, $annotation); - } - - $token->setContent($doc->getContent()); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return '@return void and @return null annotations should be omitted from phpdocs.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // must be run before the PhpdocSeparationFixer and PhpdocOrderFixer - return 10; - } - - /** - * Remove return void or return null annotations.. - * - * @param DocBlock $doc - * @param Annotation $annotation - */ - private function fixAnnotation(DocBlock $doc, Annotation $annotation) - { - if (1 === preg_match('/@return\s+(void|null)(?!\|)/', $doc->getLine($annotation->getStart())->getContent())) { - $annotation->remove(); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoPackageFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoPackageFixer.php deleted file mode 100644 index bd67529..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocNoPackageFixer.php +++ /dev/null @@ -1,42 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractAnnotationRemovalFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class PhpdocNoPackageFixer extends AbstractAnnotationRemovalFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $this->removeAnnotations($tokens, array('package', 'subpackage')); - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return '@package and @subpackage annotations should be omitted from phpdocs.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocParamsFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocParamsFixer.php deleted file mode 100644 index c798bd4..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocParamsFixer.php +++ /dev/null @@ -1,206 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; -use Symfony\CS\Utils; - -/** - * @author Fabien Potencier - * @author Jordi Boggiano - * @author Sebastiaan Stok - * @author Graham Campbell - * @author Dariusz Rumiński - */ -class PhpdocParamsFixer extends AbstractFixer -{ - private $regex; - private $regexCommentLine; - - public function __construct() - { - // e.g. @param <$var> - $paramTag = '(?Pparam)\s+(?P[^$]+?)\s+(?P&?\$[^\s]+)'; - // e.g. @return - $otherTags = '(?Preturn|throws|var|type)\s+(?P[^\s]+?)'; - // optional - $desc = '(?:\s+(?P.*)|\s*)'; - - $this->regex = '/^(?P(?: {4})*) \* @(?:'.$paramTag.'|'.$otherTags.')'.$desc.'$/'; - $this->regexCommentLine = '/^(?P(?: {4})*) \*(?! @)(?:\s+(?P.+))(?findGivenKind(T_DOC_COMMENT) as $token) { - $token->setContent($this->fixDocBlock($token->getContent())); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'All items of the @param, @throws, @return, @var, and @type phpdoc tags must be aligned vertically.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - /* - * Should be run after all other docblock fixers. This because they - * modify other annotations to change their type and or separation - * which totally change the behavior of this fixer. It's important that - * annotations are of the correct type, and are grouped correctly - * before running this fixer. - */ - return -11; - } - - /** - * Fix a given docblock. - * - * @param string $content - * - * @return string - */ - private function fixDocBlock($content) - { - $lines = Utils::splitLines($content); - - $l = count($lines); - - for ($i = 0; $i < $l; ++$i) { - $items = array(); - $matches = $this->getMatches($lines[$i]); - - if (null === $matches) { - continue; - } - - $current = $i; - $items[] = $matches; - - while ($matches = $this->getMatches($lines[++$i], true)) { - $items[] = $matches; - } - - // compute the max length of the tag, hint and variables - $tagMax = 0; - $hintMax = 0; - $varMax = 0; - - foreach ($items as $item) { - if (null === $item['tag']) { - continue; - } - - $tagMax = max($tagMax, strlen($item['tag'])); - $hintMax = max($hintMax, strlen($item['hint'])); - $varMax = max($varMax, strlen($item['var'])); - } - - $currTag = null; - - // update - foreach ($items as $j => $item) { - if (null === $item['tag']) { - if ($item['desc'][0] === '@') { - $lines[$current + $j] = $item['indent'].' * '.$item['desc']."\n"; - continue; - } - - $line = - $item['indent'] - .' * ' - .str_repeat(' ', $tagMax + $hintMax + $varMax + ('param' === $currTag ? 3 : 2)) - .$item['desc'] - ."\n"; - - $lines[$current + $j] = $line; - - continue; - } - - $currTag = $item['tag']; - - $line = - $item['indent'] - .' * @' - .$item['tag'] - .str_repeat(' ', $tagMax - strlen($item['tag']) + 1) - .$item['hint'] - ; - - if (!empty($item['var'])) { - $line .= - str_repeat(' ', $hintMax - strlen($item['hint']) + 1) - .$item['var'] - .( - !empty($item['desc']) - ? str_repeat(' ', $varMax - strlen($item['var']) + 1).$item['desc']."\n" - : "\n" - ) - ; - } elseif (!empty($item['desc'])) { - $line .= str_repeat(' ', $hintMax - strlen($item['hint']) + 1).$item['desc']."\n"; - } else { - $line .= "\n"; - } - - $lines[$current + $j] = $line; - } - } - - return implode($lines); - } - - /** - * Get all matches. - * - * @param string $line - * @param bool $matchCommentOnly - * - * @return string[]|null - */ - private function getMatches($line, $matchCommentOnly = false) - { - if (preg_match($this->regex, $line, $matches)) { - if (!empty($matches['tag2'])) { - $matches['tag'] = $matches['tag2']; - $matches['hint'] = $matches['hint2']; - } - - return $matches; - } - - if ($matchCommentOnly && preg_match($this->regexCommentLine, $line, $matches)) { - $matches['tag'] = null; - $matches['var'] = ''; - $matches['hint'] = ''; - - return $matches; - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocScalarFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocScalarFixer.php deleted file mode 100644 index 1f02c04..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocScalarFixer.php +++ /dev/null @@ -1,67 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractPhpdocTypesFixer; - -/** - * @author Graham Campbell - */ -class PhpdocScalarFixer extends AbstractPhpdocTypesFixer -{ - /** - * The types to fix. - * - * @var array - */ - private static $types = array( - 'boolean' => 'bool', - 'double' => 'float', - 'integer' => 'int', - 'real' => 'float', - ); - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Scalar types should always be written in the same form. "int", not "integer"; "bool", not "boolean"; "float", not "real" or "double".'; - } - - public function getPriority() - { - /* - * Should be run before all other docblock fixers apart from the - * phpdoc_to_comment and phpdoc_indent fixer to make sure all fixers - * apply correct indentation to new code they add. This should run - * before alignment of params is done since this fixer might change - * the type and thereby un-aligning the params. We also must run after - * the phpdoc_types_fixer because it can convert types to things that - * we can fix. - */ - return 15; - } - - /** - * {@inheritdoc} - */ - protected function normalize($type) - { - if (array_key_exists($type, self::$types)) { - return self::$types[$type]; - } - - return $type; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocShortDescriptionFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocShortDescriptionFixer.php deleted file mode 100644 index e562cdb..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocShortDescriptionFixer.php +++ /dev/null @@ -1,105 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\DocBlock\Line; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class PhpdocShortDescriptionFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $token) { - $doc = new DocBlock($token->getContent()); - $end = $this->findShortDescriptionEnd($doc->getLines()); - - if (null !== $end) { - $line = $doc->getLine($end); - $content = rtrim($line->getContent()); - - if (!$this->isCorrectlyFormatted($content)) { - $line->setContent($content.".\n"); - $token->setContent($doc->getContent()); - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Phpdocs short descriptions should end in either a full stop, exclamation mark, or question mark.'; - } - - /** - * Find the line number of the line containing the end of the short - * description, if present. - * - * @param Line[] $lines - * - * @return int|null - */ - private function findShortDescriptionEnd(array $lines) - { - $reachedContent = false; - - foreach ($lines as $index => $line) { - // we went past a description, then hit a tag or blank line, so - // the last line of the description must be the one before this one - if ($reachedContent && ($line->containsATag() || !$line->containsUsefulContent())) { - return $index - 1; - } - - // no short description was found - if ($line->containsATag()) { - return; - } - - // we've reached content, but need to check the next lines too - // in case the short description is multi-line - if ($line->containsUsefulContent()) { - $reachedContent = true; - } - } - } - - /** - * Is the last line of the short description correctly formatted? - * - * @param string $content - * - * @return bool - */ - private function isCorrectlyFormatted($content) - { - if (false !== strpos(strtolower($content), '{@inheritdoc}')) { - return true; - } - - return $content !== rtrim($content, '.。!?¡¿!?'); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocSingleLineVarSpacingFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocSingleLineVarSpacingFixer.php deleted file mode 100644 index d29c1b5..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocSingleLineVarSpacingFixer.php +++ /dev/null @@ -1,95 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Fixer for part of rule defined in PSR5 ¶7.22. - * - * @author SpacePossum - */ -final class PhpdocSingleLineVarSpacingFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - /** @var Token $token */ - foreach ($tokens as $index => $token) { - if ($token->isGivenKind(T_DOC_COMMENT)) { - $token->setContent($this->fixTokenContent($token->getContent())); - continue; - } - - if (!$token->isGivenKind(T_COMMENT)) { - continue; - } - - $content = $token->getContent(); - $fixedContent = $this->fixTokenContent($content); - if ($content !== $fixedContent) { - $tokens->overrideAt($index, array(T_DOC_COMMENT, $fixedContent, $token->getLine())); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Single line @var PHPDoc should have proper spacing.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be ran after the PhpdocTypeToVarFixer. - return -10; - } - - /** - * @param string $content - * - * @return string - */ - private function fixTokenContent($content) - { - return preg_replace_callback( - '#^/\*\*[ \t]*@var[ \t]+(\S+)[ \t]*(\$\S+)?[ \t]*([^\n]*)\*/$#', - function (array $matches) { - $content = '/** @var'; - for ($i = 1, $m = count($matches); $i < $m; ++$i) { - if ('' !== $matches[$i]) { - $content .= ' '.$matches[$i]; - } - } - - $content = rtrim($content); - - return $content.' */'; - }, - $content - ); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocToCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocToCommentFixer.php deleted file mode 100644 index 712b22d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocToCommentFixer.php +++ /dev/null @@ -1,201 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Ceeram - * @author Dariusz Rumiński - */ -class PhpdocToCommentFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - static $controlStructures = array( - T_FOREACH, - T_IF, - T_SWITCH, - T_WHILE, - T_FOR, - ); - - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $index => $token) { - $nextIndex = $tokens->getNextMeaningfulToken($index); - $nextToken = null !== $nextIndex ? $tokens[$nextIndex] : null; - - if (null === $nextToken || $nextToken->equals('}')) { - $tokens->overrideAt($index, array(T_COMMENT, '/*'.ltrim($token->getContent(), '/*'), $token->getLine())); - continue; - } - - if ($this->isStructuralElement($nextToken)) { - continue; - } - - if ($nextToken->isGivenKind($controlStructures) && $this->isValidControl($tokens, $token, $nextIndex)) { - continue; - } - - if ($nextToken->isGivenKind(T_VARIABLE) && $this->isValidVariable($tokens, $token, $nextIndex)) { - continue; - } - - if ($nextToken->isGivenKind(T_LIST) && $this->isValidList($tokens, $token, $nextIndex)) { - continue; - } - - // First docblock after open tag can be file-level docblock, so its left as is. - $prevIndex = $tokens->getPrevMeaningfulToken($index); - if ($tokens[$prevIndex]->isGivenKind(array(T_OPEN_TAG, T_NAMESPACE))) { - continue; - } - - $tokens->overrideAt($index, array(T_COMMENT, '/*'.ltrim($token->getContent(), '/*'), $token->getLine())); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Docblocks should only be used on structural elements.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - /* - * Should be run before all other docblock fixers so that these fixers - * don't touch doc comments which are meant to be converted to regular - * comments. - */ - return 25; - } - - /** - * Check if token is a structural element. - * - * @see https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md#3-definitions - * - * @param Token $token - * - * @return bool - */ - private function isStructuralElement(Token $token) - { - static $skip = array( - T_PRIVATE, - T_PROTECTED, - T_PUBLIC, - T_VAR, - T_FUNCTION, - T_ABSTRACT, - T_CONST, - T_NAMESPACE, - T_REQUIRE, - T_REQUIRE_ONCE, - T_INCLUDE, - T_INCLUDE_ONCE, - T_FINAL, - T_STATIC, - ); - - return $token->isClassy() || $token->isGivenKind($skip); - } - - /** - * Checks control structures (while, if, foreach, switch) for correct docblock usage. - * - * @param Tokens $tokens - * @param Token $docsToken docs Token - * @param int $controlIndex index of control structure Token - * - * @return bool - */ - private function isValidControl(Tokens $tokens, Token $docsToken, $controlIndex) - { - $index = $tokens->getNextMeaningfulToken($controlIndex); - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); - $docsContent = $docsToken->getContent(); - - for ($index = $index + 1; $index < $endIndex; ++$index) { - $token = $tokens[$index]; - - if ( - $token->isGivenKind(T_VARIABLE) && - false !== strpos($docsContent, $token->getContent()) - ) { - return true; - } - } - - return false; - } - - /** - * Checks variable assignments for correct docblock usage. - * - * @param Tokens $tokens - * @param Token $docsToken docs Token - * @param int $variableIndex index of variable Token - * - * @return bool - */ - private function isValidVariable(Tokens $tokens, Token $docsToken, $variableIndex) - { - $nextIndex = $tokens->getNextMeaningfulToken($variableIndex); - - return $tokens[$nextIndex]->equals('='); - } - - /** - * Checks variable assignments through `list()` calls for correct docblock usage. - * - * @param Tokens $tokens - * @param Token $docsToken docs Token - * @param int $listIndex index of variable Token - * - * @return bool - */ - private function isValidList(Tokens $tokens, Token $docsToken, $listIndex) - { - $endIndex = $tokens->getNextTokenOfKind($listIndex, array(')')); - $docsContent = $docsToken->getContent(); - - for ($index = $listIndex + 1; $index < $endIndex; ++$index) { - $token = $tokens[$index]; - - if ( - $token->isGivenKind(T_VARIABLE) - && false !== strpos($docsContent, $token->getContent()) - ) { - return true; - } - } - - return false; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTrimFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTrimFixer.php deleted file mode 100644 index aed43c2..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTrimFixer.php +++ /dev/null @@ -1,117 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class PhpdocTrimFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $token) { - $content = $token->getContent(); - $content = $this->fixStart($content); - // we need re-parse the docblock after fixing the start before - // fixing the end in order for the lines to be correctly indexed - $content = $this->fixEnd($content); - $token->setContent($content); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Phpdocs should start and end with content, excluding the very first and last line of the docblocks.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - /* - * Should be run after all phpdoc fixers that add or remove tags, or - * alter descriptions. This is so that they don't leave behind blank - * lines this fixer would have otherwise cleaned up. - */ - return -5; - } - - /** - * Make sure the first useful line starts immediately after the first line. - * - * @param string $content - * - * @return string - */ - private function fixStart($content) - { - $doc = new DocBlock($content); - $lines = $doc->getLines(); - $total = count($lines); - - foreach ($lines as $index => $line) { - if (!$line->isTheStart()) { - // don't remove lines with content and don't entirely delete docblocks - if ($total - $index < 3 || $line->containsUsefulContent()) { - break; - } - - $line->remove(); - } - } - - return $doc->getContent(); - } - - /** - * Make sure the last useful is immediately before after the final line. - * - * @param string $content - * - * @return string - */ - private function fixEnd($content) - { - $doc = new DocBlock($content); - $lines = array_reverse($doc->getLines()); - $total = count($lines); - - foreach ($lines as $index => $line) { - if (!$line->isTheEnd()) { - // don't remove lines with content and don't entirely delete docblocks - if ($total - $index < 3 || $line->containsUsefulContent()) { - break; - } - - $line->remove(); - } - } - - return $doc->getContent(); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTypeToVarFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTypeToVarFixer.php deleted file mode 100644 index bfd1d42..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTypeToVarFixer.php +++ /dev/null @@ -1,70 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class PhpdocTypeToVarFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isGivenKind(T_DOC_COMMENT)) { - continue; - } - - $doc = new DocBlock($token->getContent()); - $annotations = $doc->getAnnotationsOfType('type'); - - if (empty($annotations)) { - continue; - } - - foreach ($annotations as $annotation) { - $line = $doc->getLine($annotation->getStart()); - $line->setContent(str_replace('@type', '@var', $line->getContent())); - } - - $token->setContent($doc->getContent()); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return '@type should always be written as @var.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be ran before the PhpdocSingleLineVarSpacingFixer. - return -9; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTypesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTypesFixer.php deleted file mode 100644 index b39c27b..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocTypesFixer.php +++ /dev/null @@ -1,85 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractPhpdocTypesFixer; - -/** - * @author Graham Campbell - */ -final class PhpdocTypesFixer extends AbstractPhpdocTypesFixer -{ - /** - * The types to process. - * - * @var string[] - */ - private static $types = array( - 'array', - 'bool', - 'boolean', - 'callable', - 'double', - 'false', - 'float', - 'int', - 'integer', - 'iterable', - 'mixed', - 'null', - 'object', - 'real', - 'resource', - 'self', - 'static', - 'string', - 'true', - 'void', - '$this', - ); - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'The correct case must be used for standard PHP types in phpdoc.'; - } - - public function getPriority() - { - /* - * Should be run before all other docblock fixers apart from the - * phpdoc_to_comment and phpdoc_indent fixer to make sure all fixers - * apply correct indentation to new code they add. This should run - * before alignment of params is done since this fixer might change - * the type and thereby un-aligning the params. We also must run before - * the phpdoc_scalar_fixer so that it can make changes after us. - */ - return 16; - } - - /** - * {@inheritdoc} - */ - protected function normalize($type) - { - $lower = strtolower($type); - - if (in_array($lower, self::$types, true)) { - return $lower; - } - - return $type; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocVarWithoutNameFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocVarWithoutNameFixer.php deleted file mode 100644 index 516475b..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocVarWithoutNameFixer.php +++ /dev/null @@ -1,73 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\DocBlock\Line; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class PhpdocVarWithoutNameFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $token) { - $doc = new DocBlock($token->getContent()); - - // don't process single line docblocks - if (1 === count($doc->getLines())) { - continue; - } - - $annotations = $doc->getAnnotationsOfType(array('param', 'return', 'type', 'var')); - - // only process docblocks where the first meaningful annotation is @type or @var - if (!isset($annotations[0]) || !in_array($annotations[0]->getTag()->getName(), array('type', 'var'), true)) { - continue; - } - - $this->fixLine($doc->getLine($annotations[0]->getStart())); - - $token->setContent($doc->getContent()); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return '@var and @type annotations should not contain the variable name.'; - } - - private function fixLine(Line $line) - { - $content = $line->getContent(); - - preg_match_all('/ \$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $content, $matches); - - if (isset($matches[0][0])) { - $line->setContent(str_replace($matches[0][0], '', $content)); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PreIncrementFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PreIncrementFixer.php deleted file mode 100644 index 69b7ca8..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PreIncrementFixer.php +++ /dev/null @@ -1,106 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Gregor Harlan - */ -class PreIncrementFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; 0 <= $index; --$index) { - $token = $tokens[$index]; - - if (!$token->isGivenKind(array(T_INC, T_DEC)) || !$tokens->isUnarySuccessorOperator($index)) { - continue; - } - - $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)]; - if (!$nextToken->equalsAny(array(';', ')'))) { - continue; - } - - $startIndex = $this->findStart($tokens, $index); - - $prevToken = $tokens[$tokens->getPrevMeaningfulToken($startIndex)]; - if ($prevToken->equalsAny(array(';', '{', '}', array(T_OPEN_TAG)))) { - $tokens->insertAt($startIndex, clone $token); - $token->clear(); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Pre incrementation/decrementation should be used if possible.'; - } - - /** - * @param Tokens $tokens - * @param int $index - * - * @return int - */ - private function findStart(Tokens $tokens, $index) - { - do { - $index = $tokens->getPrevMeaningfulToken($index); - $token = $tokens[$index]; - - $blockType = $tokens->detectBlockType($token); - if (null !== $blockType && !$blockType['isStart']) { - $index = $tokens->findBlockEnd($blockType['type'], $index, false); - $token = $tokens[$index]; - } - } while (!$token->equalsAny(array('$', array(T_VARIABLE)))); - - $prevIndex = $tokens->getPrevMeaningfulToken($index); - $prevToken = $tokens[$prevIndex]; - - if ($prevToken->equals('$')) { - $index = $prevIndex; - $prevIndex = $tokens->getPrevMeaningfulToken($index); - $prevToken = $tokens[$prevIndex]; - } - - if ($prevToken->isGivenKind(T_OBJECT_OPERATOR)) { - return $this->findStart($tokens, $prevIndex); - } - - if ($prevToken->isGivenKind(T_PAAMAYIM_NEKUDOTAYIM)) { - $prevPrevIndex = $tokens->getPrevMeaningfulToken($prevIndex); - if (!$tokens[$prevPrevIndex]->isGivenKind(T_STRING)) { - return $this->findStart($tokens, $prevIndex); - } - - $index = $tokens->getTokenNotOfKindSibling($prevIndex, -1, array(array(T_NS_SEPARATOR), array(T_STRING))); - $index = $tokens->getNextMeaningfulToken($index); - } - - return $index; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PrintToEchoFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PrintToEchoFixer.php deleted file mode 100644 index 6fc3b8d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PrintToEchoFixer.php +++ /dev/null @@ -1,51 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Sullivan Senechal - */ -final class PrintToEchoFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $printTokens = $tokens->findGivenKind(T_PRINT); - - foreach ($printTokens as $printIndex => $printToken) { - $prevToken = $tokens[$tokens->getPrevMeaningfulToken($printIndex)]; - if (!$prevToken->equalsAny(array(';', '{', '}', array(T_OPEN_TAG)))) { - continue; - } - - $tokens->overrideAt($printIndex, array(T_ECHO, 'echo')); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Converts print language construct to echo if possible.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/RemoveLeadingSlashUseFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/RemoveLeadingSlashUseFixer.php deleted file mode 100644 index 916c621..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/RemoveLeadingSlashUseFixer.php +++ /dev/null @@ -1,71 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Carlos Cirello - */ -class RemoveLeadingSlashUseFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $foundNamespace = $tokens->findGivenKind(T_NAMESPACE); - if (empty($foundNamespace)) { - return $content; - } - - $firstNamespaceIdx = key($foundNamespace); - - $usesIdxs = $tokens->getImportUseIndexes(); - - foreach ($usesIdxs as $idx) { - if ($idx < $firstNamespaceIdx) { - continue; - } - - $nextTokenIdx = $tokens->getNextNonWhitespace($idx); - $nextToken = $tokens[$nextTokenIdx]; - - if ($nextToken->isGivenKind(T_NS_SEPARATOR)) { - $nextToken->clear(); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the MultipleUseFixer (for fix separated use statements as well) and UnusedUseFixer (just for save performance) - return -20; - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Remove leading slashes in use clauses.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/RemoveLinesBetweenUsesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/RemoveLinesBetweenUsesFixer.php deleted file mode 100644 index 9434ac2..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/RemoveLinesBetweenUsesFixer.php +++ /dev/null @@ -1,95 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Luis Cordova - */ -class RemoveLinesBetweenUsesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - $this->removeLineBreaksBetweenUseStatements($tokens); - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before OrderedUseFixer - return -5; - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Removes line breaks between use statements.'; - } - - private function removeLineBreaksBetweenUseStatements(Tokens $tokens) - { - $namespacesImports = $tokens->getImportUseIndexes(true); - - if (!count($namespacesImports)) { - return; - } - - foreach ($namespacesImports as $uses) { - $uses = array_reverse($uses); - $this->fixLineBreaksPerImportGroup($tokens, $uses); - } - } - - /** - * Fix the line breaks per group. - * - * For each use token reach the nearest ; and ensure every - * token after has one \n before next non empty token (next line). - * It skips the first pass from the bottom. - * - * @param Tokens $tokens - * @param array $uses - */ - private function fixLineBreaksPerImportGroup(Tokens $tokens, array $uses) - { - foreach ($uses as $index) { - $endIndex = $tokens->getNextTokenOfKind($index, array(';', T_CLOSE_TAG)); - if ($endIndex === count($tokens) - 1) { - continue; - } - - $afterSemicolonIndex = $tokens->getNextNonWhitespace($endIndex); - if (null === $afterSemicolonIndex || !$tokens[$afterSemicolonIndex]->isGivenKind(T_USE)) { - continue; - } - - $nextToken = $tokens[$endIndex + 1]; - if ($nextToken->isWhitespace()) { - $nextToken->setContent(preg_replace('/\n{2,}/', "\n", $nextToken->getContent())); - } - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ReturnFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ReturnFixer.php deleted file mode 100644 index fdecc4f..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ReturnFixer.php +++ /dev/null @@ -1,82 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class ReturnFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { - $token = $tokens[$index]; - - if (!$token->isGivenKind(T_RETURN)) { - continue; - } - - $prevNonWhitespaceToken = $tokens[$tokens->getPrevNonWhitespace($index)]; - - if (!$prevNonWhitespaceToken->equalsAny(array(';', '}'))) { - continue; - } - - $prevToken = $tokens[$index - 1]; - - if ($prevToken->isWhitespace()) { - $parts = explode("\n", $prevToken->getContent()); - $countParts = count($parts); - - if (1 === $countParts) { - $prevToken->setContent(rtrim($prevToken->getContent(), " \t")."\n\n"); - } elseif (count($parts) <= 2) { - $prevToken->setContent("\n".$prevToken->getContent()); - } - } else { - $tokens->insertAt($index, new Token(array(T_WHITESPACE, "\n\n"))); - - ++$index; - ++$limit; - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'An empty line feed should precede a return statement.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after NoUselessReturnFixer - return -19; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SelfAccessorFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SelfAccessorFixer.php deleted file mode 100644 index a6b258d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SelfAccessorFixer.php +++ /dev/null @@ -1,102 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Gregor Harlan - */ -class SelfAccessorFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($i = 0, $c = $tokens->count(); $i < $c; ++$i) { - if (!$tokens[$i]->isClassy() || $tokens->isAnonymousClass($i)) { - continue; - } - - $nameIndex = $tokens->getNextTokenOfKind($i, array(array(T_STRING))); - $startIndex = $tokens->getNextTokenOfKind($nameIndex, array('{')); - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startIndex); - - $name = $tokens[$nameIndex]->getContent(); - - $this->replaceNameOccurrences($tokens, $name, $startIndex, $endIndex); - - // continue after the class declaration - $i = $endIndex; - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Inside a classy element "self" should be preferred to the class name itself.'; - } - - /** - * Replace occurrences of the name of the classy element by "self" (if possible). - * - * @param Tokens $tokens - * @param string $name - * @param int $startIndex - * @param int $endIndex - */ - private function replaceNameOccurrences(Tokens $tokens, $name, $startIndex, $endIndex) - { - for ($i = $startIndex; $i < $endIndex; ++$i) { - $token = $tokens[$i]; - - if ( - // skip anonymous classes - $token->isGivenKind(T_CLASS) && $tokens->isAnonymousClass($i) || - // skip lambda functions (PHP < 5.4 compatibility) - $token->isGivenKind(T_FUNCTION) && $tokens->isLambda($i) - ) { - $i = $tokens->getNextTokenOfKind($i, array('{')); - $i = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $i); - continue; - } - - if (!$token->equals(array(T_STRING, $name), false)) { - continue; - } - - $prevToken = $tokens[$tokens->getPrevMeaningfulToken($i)]; - $nextToken = $tokens[$tokens->getNextMeaningfulToken($i)]; - - // skip tokens that are part of a fully qualified name - if ($prevToken->isGivenKind(T_NS_SEPARATOR) || $nextToken->isGivenKind(T_NS_SEPARATOR)) { - continue; - } - - if ( - $prevToken->isGivenKind(array(T_INSTANCEOF, T_NEW)) || - $nextToken->isGivenKind(T_PAAMAYIM_NEKUDOTAYIM) - ) { - $token->setContent('self'); - } - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ShortBoolCastFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ShortBoolCastFixer.php deleted file mode 100644 index 1e1eee6..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ShortBoolCastFixer.php +++ /dev/null @@ -1,79 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -class ShortBoolCastFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - for ($index = count($tokens) - 1; $index > 1; --$index) { - if ($tokens[$index]->equals('!')) { - $index = $this->fixShortCast($tokens, $index); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Short cast bool using double exclamation mark should not be used.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run before the SpacesCastFixer - return -9; - } - - private function fixShortCast(Tokens $tokens, $index) - { - for ($i = $index - 1; $i > 1; --$i) { - if ($tokens[$i]->equals('!')) { - $this->fixShortCastToBoolCast($tokens, $i, $index); - break; - } - - if (!$tokens[$i]->isComment() && !$tokens[$i]->isWhitespace()) { - break; - } - } - - return $i; - } - - private function fixShortCastToBoolCast(Tokens $tokens, $start, $end) - { - for (; $start <= $end; ++$start) { - if (!$tokens[$start]->isComment()) { - $tokens[$start]->clear(); - } - } - - $tokens->insertAt($start, new Token(array(T_BOOL_CAST, '(bool)'))); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ShortScalarCastFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ShortScalarCastFixer.php deleted file mode 100644 index fd0e70c..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ShortScalarCastFixer.php +++ /dev/null @@ -1,61 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author SpacePossum - */ -final class ShortScalarCastFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - static $castMap = array( - 'boolean' => 'bool', - 'integer' => 'int', - 'double' => 'float', - 'real' => 'float', - ); - - $tokens = Tokens::fromCode($content); - - for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { - if (!$tokens[$index]->isCast()) { - continue; - } - - $castFrom = trim(substr($tokens[$index]->getContent(), 1, -1)); - $castFromLowered = strtolower($castFrom); - if (!array_key_exists($castFromLowered, $castMap)) { - continue; - } - - $tokens[$index]->setContent(str_replace($castFrom, $castMap[$castFromLowered], $tokens[$index]->getContent())); - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Cast "(boolean)" and "(integer)" should be written as "(bool)" and "(int)". "(double)" and "(real)" as "(float)".'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleBlankLineBeforeNamespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleBlankLineBeforeNamespaceFixer.php deleted file mode 100644 index 99f43b5..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleBlankLineBeforeNamespaceFixer.php +++ /dev/null @@ -1,46 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractLinesBeforeNamespaceFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class SingleBlankLineBeforeNamespaceFixer extends AbstractLinesBeforeNamespaceFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if ($token->isGivenKind(T_NAMESPACE)) { - $this->fixLinesBeforeNamespace($tokens, $index, 2); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'There should be exactly one blank line before a namespace declaration.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleQuoteFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleQuoteFixer.php deleted file mode 100644 index 951e625..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleQuoteFixer.php +++ /dev/null @@ -1,58 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Gregor Harlan - */ -class SingleQuoteFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $token) { - if (!$token->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) { - continue; - } - - $content = $token->getContent(); - if ( - '"' === $content[0] && - false === strpos($content, "'") && - // regex: odd number of backslashes, not followed by double quote or dollar - !preg_match('/(?setContent('\''.$content.'\''); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Convert double quotes to single quotes for simple strings.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesAfterSemicolonFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesAfterSemicolonFixer.php deleted file mode 100644 index 3afa1a0..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesAfterSemicolonFixer.php +++ /dev/null @@ -1,61 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author SpacePossum - */ -final class SpacesAfterSemicolonFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = count($tokens) - 2; $index > 0; --$index) { - if (!$tokens[$index]->equals(';')) { - continue; - } - - if (!$tokens[$index + 1]->isWhitespace()) { - if (!$tokens[$index + 1]->equalsAny(array(')', array(T_INLINE_HTML)))) { - $tokens->insertAt($index + 1, new Token(array(T_WHITESPACE, ' '))); - } - } elseif ( - isset($tokens[$index + 2]) - && !$tokens[$index + 1]->equals(array(T_WHITESPACE, ' ')) - && $tokens[$index + 1]->isWhitespace(array('whitespaces' => " \t")) - && !$tokens[$index + 2]->isComment() - && !$tokens[$index + 2]->equals(')') - ) { - $tokens[$index + 1]->setContent(' '); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Fix whitespace after a semicolon.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesBeforeSemicolonFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesBeforeSemicolonFixer.php deleted file mode 100644 index 4fe279d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesBeforeSemicolonFixer.php +++ /dev/null @@ -1,55 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Graham Campbell - */ -class SpacesBeforeSemicolonFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->equals(';') || !$tokens[$index - 1]->isWhitespace(array('whitespaces' => " \t"))) { - continue; - } - - if ($tokens[$index - 2]->equals(';')) { - // do not remove all whitespace before the semicolon because it is also whitespace after another semicolon - if (!$tokens[$index - 1]->equals(' ')) { - $tokens[$index - 1]->setContent(' '); - } - } elseif (!$tokens[$index - 2]->isComment()) { - $tokens[$index - 1]->clear(); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Single-line whitespace before closing semicolon are prohibited.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesCastFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesCastFixer.php deleted file mode 100644 index 5e8ecd9..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SpacesCastFixer.php +++ /dev/null @@ -1,74 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class SpacesCastFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - static $insideCastSpaceReplaceMap = array( - ' ' => '', - "\t" => '', - "\n" => '', - "\r" => '', - "\0" => '', - "\x0B" => '', - ); - - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if ($token->isCast()) { - $token->setContent(strtr($token->getContent(), $insideCastSpaceReplaceMap)); - - // force single whitespace after cast token: - if ($tokens[$index + 1]->isWhitespace(array('whitespaces' => " \t"))) { - // - if next token is whitespaces that contains only spaces and tabs - override next token with single space - $tokens[$index + 1]->setContent(' '); - } elseif (!$tokens[$index + 1]->isWhitespace()) { - // - if next token is not whitespaces that contains spaces, tabs and new lines - append single space to current token - $tokens->insertAt($index + 1, new Token(array(T_WHITESPACE, ' '))); - } - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'A single space should be between cast and variable.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be ran after the ShortBoolCastFixer - return -10; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/StandardizeNotEqualFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/StandardizeNotEqualFixer.php deleted file mode 100644 index f1a82cf..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/StandardizeNotEqualFixer.php +++ /dev/null @@ -1,46 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class StandardizeNotEqualFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if ($token->isGivenKind(T_IS_NOT_EQUAL)) { - $tokens[$index]->setContent('!='); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Replace all <> with !=.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/TernarySpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/TernarySpacesFixer.php deleted file mode 100644 index 48257ee..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/TernarySpacesFixer.php +++ /dev/null @@ -1,106 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class TernarySpacesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $ternaryLevel = 0; - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if ($token->isArray()) { - continue; - } - - if ($token->equals('?')) { - ++$ternaryLevel; - - $nextNonWhitespaceIndex = $tokens->getNextNonWhitespace($index); - $nextNonWhitespaceToken = $tokens[$nextNonWhitespaceIndex]; - - if ($nextNonWhitespaceToken->equals(':')) { - // for `$a ?: $b` remove spaces between `?` and `:` - if ($tokens[$index + 1]->isWhitespace()) { - $tokens[$index + 1]->clear(); - } - } else { - // for `$a ? $b : $c` ensure space after `?` - $this->ensureWhitespaceExistence($tokens, $index + 1, true); - } - - // for `$a ? $b : $c` ensure space before `?` - $this->ensureWhitespaceExistence($tokens, $index - 1, false); - - continue; - } - - if ($ternaryLevel && $token->equals(':')) { - // for `$a ? $b : $c` ensure space after `:` - $this->ensureWhitespaceExistence($tokens, $index + 1, true); - - $prevNonWhitespaceToken = $tokens[$tokens->getPrevNonWhitespace($index)]; - - if (!$prevNonWhitespaceToken->equals('?')) { - // for `$a ? $b : $c` ensure space before `:` - $this->ensureWhitespaceExistence($tokens, $index - 1, false); - } - - --$ternaryLevel; - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Standardize spaces around ternary operator.'; - } - - /** - * @param Tokens $tokens - * @param int $index - * @param bool $after - */ - private function ensureWhitespaceExistence(Tokens $tokens, $index, $after) - { - if ($tokens[$index]->isWhitespace()) { - if (false === strpos($tokens[$index]->getContent(), "\n")) { - // TODO: comment with trailing line break check should be removed on 2.0 line - if (!$tokens[$index - 1]->isComment() || false === strpos($tokens[$index - 1]->getContent(), "\n")) { - $tokens[$index]->setContent(' '); - } - } - - return; - } - - $indexChange = $after ? 0 : 1; - $tokens->insertAt($index + $indexChange, new Token(array(T_WHITESPACE, ' ', $tokens[$index]->getLine()))); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnalignDoubleArrowFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnalignDoubleArrowFixer.php deleted file mode 100644 index 6910cb1..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnalignDoubleArrowFixer.php +++ /dev/null @@ -1,62 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class UnalignDoubleArrowFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Unalign double arrow symbols.'; - } - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isGivenKind(T_DOUBLE_ARROW)) { - continue; - } - - $this->fixWhitespace($tokens[$index - 1]); - $this->fixWhitespace($tokens[$index + 1]); - } - - return $tokens->generateCode(); - } - - /** - * If given token is a single line whitespace then fix it to be a single space. - * - * @param Token $token - */ - private function fixWhitespace(Token $token) - { - if ($token->isWhitespace(array('whitespaces' => " \t"))) { - $token->setContent(' '); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnalignEqualsFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnalignEqualsFixer.php deleted file mode 100644 index 04e709b..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnalignEqualsFixer.php +++ /dev/null @@ -1,62 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class UnalignEqualsFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Unalign equals symbols.'; - } - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->equals('=')) { - continue; - } - - $this->fixWhitespace($tokens[$index - 1]); - $this->fixWhitespace($tokens[$index + 1]); - } - - return $tokens->generateCode(); - } - - /** - * If given token is a single line whitespace then fix it to be a single space. - * - * @param Token $token - */ - private function fixWhitespace(Token $token) - { - if ($token->isWhitespace(array('whitespaces' => " \t"))) { - $token->setContent(' '); - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnaryOperatorsSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnaryOperatorsSpacesFixer.php deleted file mode 100644 index 5270b9d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnaryOperatorsSpacesFixer.php +++ /dev/null @@ -1,51 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Gregor Harlan - */ -class UnaryOperatorsSpacesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - for ($index = $tokens->count() - 1; $index >= 0; --$index) { - if ($tokens->isUnarySuccessorOperator($index)) { - $tokens->removeLeadingWhitespace($index); - continue; - } - if ($tokens->isUnaryPredecessorOperator($index)) { - $tokens->removeTrailingWhitespace($index); - continue; - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Unary operators should be placed adjacent to their operands.'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnneededControlParenthesesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnneededControlParenthesesFixer.php deleted file mode 100644 index 0accf11..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnneededControlParenthesesFixer.php +++ /dev/null @@ -1,138 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Sullivan Senechal - * @author Dariusz Rumiński - * @author Gregor Harlan - */ -final class UnneededControlParenthesesFixer extends AbstractFixer -{ - /** - * To be removed when PHP support will be 5.5+. - * - * @var string[] List of statements to fix - */ - private static $controlStatements = array( - 'break', - 'continue', - 'clone', - 'echo_print', - 'return', - 'switch_case', - 'yield', - ); - - private static $loops = array( - 'break' => array('lookupTokens' => T_BREAK, 'neededSuccessors' => array(';')), - 'continue' => array('lookupTokens' => T_CONTINUE, 'neededSuccessors' => array(';')), - 'clone' => array('lookupTokens' => T_CLONE, 'neededSuccessors' => array(';', ':', ',', ')'), 'forbiddenContents' => array('?', ':')), - 'echo_print' => array('lookupTokens' => array(T_ECHO, T_PRINT), 'neededSuccessors' => array(';', array(T_CLOSE_TAG))), - 'return' => array('lookupTokens' => T_RETURN, 'neededSuccessors' => array(';', array(T_CLOSE_TAG))), - 'switch_case' => array('lookupTokens' => T_CASE, 'neededSuccessors' => array(';', ':')), - ); - - /** - * Dynamic yield option set on constructor. - */ - public function __construct() - { - // To be moved back on static when PHP support will be 5.5+ - if (defined('T_YIELD')) { - self::$loops['yield'] = array('lookupTokens' => T_YIELD, 'neededSuccessors' => array(';', ')')); - } - } - - /** - * @param array $controlStatements - */ - public static function configure(array $controlStatements) - { - self::$controlStatements = $controlStatements; - } - - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - // Checks if specific statements are set and uses them in this case. - $loops = array_intersect_key(self::$loops, array_flip(self::$controlStatements)); - - foreach ($tokens as $index => $token) { - if (!$token->equals('(')) { - continue; - } - - $blockStartIndex = $index; - $index = $tokens->getPrevMeaningfulToken($index); - $token = $tokens[$index]; - - foreach ($loops as $loop) { - if (!$token->isGivenKind($loop['lookupTokens'])) { - continue; - } - - $blockEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $blockStartIndex); - $blockEndNextIndex = $tokens->getNextMeaningfulToken($blockEndIndex); - - if (!$tokens[$blockEndNextIndex]->equalsAny($loop['neededSuccessors'])) { - continue; - } - - if (array_key_exists('forbiddenContents', $loop)) { - $forbiddenTokenIndex = $tokens->getNextTokenOfKind($blockStartIndex, $loop['forbiddenContents']); - // A forbidden token is found and is inside the parenthesis. - if (null !== $forbiddenTokenIndex && $forbiddenTokenIndex < $blockEndIndex) { - continue; - } - } - - if ($tokens[$blockStartIndex - 1]->isWhitespace() || $tokens[$blockStartIndex - 1]->isComment()) { - $tokens->clearTokenAndMergeSurroundingWhitespace($blockStartIndex); - } else { - // Adds a space to prevent broken code like `return2`. - $tokens->overrideAt($blockStartIndex, array(T_WHITESPACE, ' ')); - } - - $tokens->clearTokenAndMergeSurroundingWhitespace($blockEndIndex); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Removes unneeded parentheses around control statements.'; - } - - /** - * Should be run before trailing_spaces. - * - * {@inheritdoc} - */ - public function getPriority() - { - return 30; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnusedUseFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnusedUseFixer.php deleted file mode 100644 index 3aea5a1..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/UnusedUseFixer.php +++ /dev/null @@ -1,258 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class UnusedUseFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - $useDeclarationsIndexes = $tokens->getImportUseIndexes(); - if (0 === count($useDeclarationsIndexes)) { - return $tokens->generateCode(); - } - - $useDeclarations = $this->getNamespaceUseDeclarations($tokens, $useDeclarationsIndexes); - $namespaceDeclarations = $this->getNamespaceDeclarations($tokens); - $contentWithoutUseDeclarations = $this->generateCodeWithoutPartials($tokens, array_merge($namespaceDeclarations, $useDeclarations)); - $useUsages = $this->detectUseUsages($contentWithoutUseDeclarations, $useDeclarations); - - $this->removeUnusedUseDeclarations($tokens, $useDeclarations, $useUsages); - $this->removeUsesInSameNamespace($tokens, $useDeclarations, $namespaceDeclarations); - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Unused use statements must be removed.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the MultipleUseFixer - return -10; - } - - /** - * {@inheritdoc} - */ - public function supports(\SplFileInfo $file) - { - // some fixtures are auto-generated by Symfony and may contain unused use statements - if (false !== strpos($file, DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR) && - false === strpos($file, DIRECTORY_SEPARATOR.'CS'.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR) - ) { - return false; - } - - return true; - } - - /** - * @param string $content - * @param array $useDeclarations - * - * @return array - */ - private function detectUseUsages($content, array $useDeclarations) - { - $usages = array(); - - foreach ($useDeclarations as $shortName => $useDeclaration) { - $usages[$shortName] = (bool) preg_match('/(? $token) { - $allowToAppend = true; - - foreach ($partials as $partial) { - if ($partial['start'] <= $index && $index <= $partial['end']) { - $allowToAppend = false; - break; - } - } - - if ($allowToAppend) { - $content .= $token->getContent(); - } - } - - return $content; - } - - private function getNamespaceDeclarations(Tokens $tokens) - { - $namespaces = array(); - - foreach ($tokens as $index => $token) { - if (!$token->isGivenKind(T_NAMESPACE)) { - continue; - } - - $declarationEndIndex = $tokens->getNextTokenOfKind($index, array(';', '{')); - - $namespaces[] = array( - 'name' => trim($tokens->generatePartialCode($index + 1, $declarationEndIndex - 1)), - 'start' => $index, - 'end' => $declarationEndIndex, - ); - } - - return $namespaces; - } - - private function getNamespaceUseDeclarations(Tokens $tokens, array $useIndexes) - { - $uses = array(); - - foreach ($useIndexes as $index) { - $declarationEndIndex = $tokens->getNextTokenOfKind($index, array(';', array(T_CLOSE_TAG))); - $declarationContent = $tokens->generatePartialCode($index + 1, $declarationEndIndex - 1); - if ( - false !== strpos($declarationContent, ',') // ignore multiple use statements that should be split into few separate statements (for example: `use BarB, BarC as C;`) - || false !== strpos($declarationContent, '{') // do not touch group use declarations until the logic of this is added (for example: `use some\a\{ClassD};`) - ) { - continue; - } - - $declarationParts = preg_split('/\s+as\s+/i', $declarationContent); - - if (1 === count($declarationParts)) { - $fullName = $declarationContent; - $declarationParts = explode('\\', $fullName); - $shortName = end($declarationParts); - $aliased = false; - } else { - list($fullName, $shortName) = $declarationParts; - $declarationParts = explode('\\', $fullName); - $aliased = $shortName !== end($declarationParts); - } - - $shortName = trim($shortName); - - $uses[$shortName] = array( - 'fullName' => trim($fullName), - 'shortName' => $shortName, - 'aliased' => $aliased, - 'start' => $index, - 'end' => $declarationEndIndex, - ); - } - - return $uses; - } - - private function removeUnusedUseDeclarations(Tokens $tokens, array $useDeclarations, array $useUsages) - { - foreach ($useDeclarations as $shortName => $useDeclaration) { - if (!$useUsages[$shortName]) { - $this->removeUseDeclaration($tokens, $useDeclaration); - } - } - } - - private function removeUseDeclaration(Tokens $tokens, array $useDeclaration) - { - for ($index = $useDeclaration['end'] - 1; $index >= $useDeclaration['start']; --$index) { - $tokens->clearTokenAndMergeSurroundingWhitespace($index); - } - - if ($tokens[$useDeclaration['end']]->equals(';')) { - $tokens[$useDeclaration['end']]->clear(); - } - - $prevToken = $tokens[$useDeclaration['start'] - 1]; - - if ($prevToken->isWhitespace()) { - $prevToken->setContent(rtrim($prevToken->getContent(), " \t")); - } - - if (!isset($tokens[$useDeclaration['end'] + 1])) { - return; - } - - $nextIndex = $useDeclaration['end'] + 1; - $nextToken = $tokens[$nextIndex]; - - if ($nextToken->isWhitespace()) { - $content = ltrim($nextToken->getContent(), " \t"); - - if ($content && "\n" === $content[0]) { - $content = substr($content, 1); - } - - $nextToken->setContent($content); - } - - if ($prevToken->isWhitespace() && $nextToken->isWhitespace()) { - $tokens->overrideAt($nextIndex, array(T_WHITESPACE, $prevToken->getContent().$nextToken->getContent(), $prevToken->getLine())); - $prevToken->clear(); - } - } - - private function removeUsesInSameNamespace(Tokens $tokens, array $useDeclarations, array $namespaceDeclarations) - { - // safeguard for files with multiple namespaces to avoid breaking them until we support this case - if (1 !== count($namespaceDeclarations)) { - return; - } - - $namespace = $namespaceDeclarations[0]['name']; - $nsLength = strlen($namespace.'\\'); - - foreach ($useDeclarations as $useDeclaration) { - if ($useDeclaration['aliased']) { - continue; - } - - if (0 !== strpos($useDeclaration['fullName'], $namespace.'\\')) { - continue; - } - - $partName = substr($useDeclaration['fullName'], $nsLength); - - if (false === strpos($partName, '\\')) { - $this->removeUseDeclaration($tokens, $useDeclaration); - } - } - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/WhitespacyLinesFixer.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/WhitespacyLinesFixer.php deleted file mode 100644 index 49f472a..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/WhitespacyLinesFixer.php +++ /dev/null @@ -1,81 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Fixer\Symfony; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * @author Dariusz Rumiński - */ -class WhitespacyLinesFixer extends AbstractFixer -{ - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) - { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isWhitespace()) { - continue; - } - - $content = $token->getContent(); - $lines = preg_split("/([\r\n])/", $content); - - if ( - // fix T_WHITESPACES with at least 3 lines (eg `\n \n`) - count($lines) > 2 - // and T_WHITESPACES with at least 2 lines at the end of file - || (count($lines) > 1 && !isset($tokens[$index + 1])) - ) { - $lMax = count($lines) - 1; - if (!isset($tokens[$index + 1])) { - ++$lMax; - } - - $lStart = 1; - if (isset($tokens[$index - 1]) && $tokens[$index - 1]->isGivenKind(T_OPEN_TAG) && "\n" === substr($tokens[$index - 1]->getContent(), -1)) { - $lStart = 0; - } - - for ($l = $lStart; $l < $lMax; ++$l) { - $lines[$l] = preg_replace('/^\h+$/', '', $lines[$l]); - } - - $token->setContent(implode("\n", $lines)); - } - } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Remove trailing whitespace at the end of blank lines.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the NoUselessReturnFixer, NoEmptyPhpdocFixer and NoUselessElseFixer. - return -19; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FixerFileProcessedEvent.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FixerFileProcessedEvent.php deleted file mode 100644 index bcaa8fb..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FixerFileProcessedEvent.php +++ /dev/null @@ -1,112 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -use Symfony\Component\EventDispatcher\Event; - -/** - * Event that is fired when file was processed by Fixer. - * - * @author Dariusz Rumiński - */ -class FixerFileProcessedEvent extends Event -{ - /** - * Event name. - */ - const NAME = 'fixer.file_processed'; - - const STATUS_UNKNOWN = 0; - const STATUS_INVALID = 1; - const STATUS_SKIPPED = 2; - const STATUS_NO_CHANGES = 3; - const STATUS_FIXED = 4; - const STATUS_EXCEPTION = 5; - const STATUS_LINT = 6; - - /** - * File statuses map. - * - * @var array - */ - private static $statusMap = array( - self::STATUS_UNKNOWN => array('symbol' => '?', 'description' => 'unknown'), - self::STATUS_INVALID => array('symbol' => 'I', 'description' => 'invalid file syntax, file ignored'), - self::STATUS_SKIPPED => array('symbol' => '', 'description' => ''), - self::STATUS_NO_CHANGES => array('symbol' => '.', 'description' => 'no changes'), - self::STATUS_FIXED => array('symbol' => 'F', 'description' => 'fixed'), - self::STATUS_EXCEPTION => array('symbol' => 'E', 'description' => 'error'), - self::STATUS_LINT => array('symbol' => 'E', 'description' => 'error'), - ); - - /** - * File status. - * - * @var int - */ - private $status = self::STATUS_UNKNOWN; - - /** - * Create instance. - * - * @return FixerFileProcessedEvent - */ - public static function create() - { - return new static(); - } - - /** - * Get status map. - * - * @return array - */ - public static function getStatusMap() - { - return self::$statusMap; - } - - /** - * Get status. - * - * @return int - */ - public function getStatus() - { - return $this->status; - } - - /** - * Get status as string. - * - * @return string - */ - public function getStatusAsString() - { - return self::$statusMap[$this->status]['symbol']; - } - - /** - * Set status. - * - * @param int $status - * - * @return FixerFileProcessedEvent - */ - public function setStatus($status) - { - $this->status = $status; - - return $this; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/LintManager.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/LintManager.php deleted file mode 100644 index 37b34b9..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/LintManager.php +++ /dev/null @@ -1,90 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -use Symfony\Component\Process\Process; -use Symfony\Component\Process\ProcessUtils; - -/** - * Handle PHP code linting process. - * - * @author Dariusz Rumiński - */ -class LintManager -{ - /** - * Temporary file for code linting. - * - * @var string|null - */ - private $temporaryFile; - - /** - * Files removal handler. - * - * @var FileRemoval - */ - private $fileRemoval; - - public function __construct() - { - $this->fileRemoval = new FileRemoval(); - } - - public function __destruct() - { - if (null !== $this->temporaryFile) { - $this->fileRemoval->delete($this->temporaryFile); - } - } - - /** - * Create process that lint PHP file. - * - * @param string $path path to file - * - * @return Process - */ - public function createProcessForFile($path) - { - // in case php://stdin - if (!is_file($path)) { - return $this->createProcessForSource(file_get_contents($path)); - } - - $process = new Process('php -l '.ProcessUtils::escapeArgument($path)); - $process->setTimeout(null); - $process->run(); - - return $process; - } - - /** - * Create process that lint PHP code. - * - * @param string $source code - * - * @return Process - */ - public function createProcessForSource($source) - { - if (null === $this->temporaryFile) { - $this->temporaryFile = tempnam('.', 'cs_fixer_tmp_'); - $this->fileRemoval->observe($this->temporaryFile); - } - - file_put_contents($this->temporaryFile, $source); - - return $this->createProcessForFile($this->temporaryFile); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Resources/phar-stub.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Resources/phar-stub.php deleted file mode 100644 index b092dfe..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Resources/phar-stub.php +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env php - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -if (defined('HHVM_VERSION_ID')) { - if (HHVM_VERSION_ID < 30900) { - fwrite(STDERR, "HHVM needs to be a minimum version of HHVM 3.9.0\n"); - exit(1); - } -} elseif (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50306 || PHP_VERSION_ID >= 70200) { - fwrite(STDERR, "PHP needs to be a minimum version of PHP 5.3.6 and maximum version of PHP 7.1.*\n"); - exit(1); -} - -set_error_handler(function ($severity, $message, $file, $line) { - if ($severity & error_reporting()) { - throw new ErrorException($message, 0, $severity, $file, $line); - } -}); - -Phar::mapPhar('php-cs-fixer.phar'); - -require_once 'phar://php-cs-fixer.phar/vendor/autoload.php'; - -use Symfony\CS\Console\Application; - -$application = new Application(); -$application->run(); - -__HALT_COMPILER(); diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Test/IntegrationCaseFactory.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Test/IntegrationCaseFactory.php deleted file mode 100644 index 6e45a34..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Test/IntegrationCaseFactory.php +++ /dev/null @@ -1,245 +0,0 @@ - - * Dariusz Rumiński - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Test; - -use Symfony\CS\Fixer; -use Symfony\CS\FixerInterface; - -/** - * @author Dariusz Rumiński - * - * @internal - */ -final class IntegrationCaseFactory -{ - private static $builtInFixers; - - /** - * @param string $fileName - * @param string $content - * - * @return IntegrationCase - */ - public function create($fileName, $content) - { - try { - if (!preg_match('/--TEST--\n(?.*?)\s--CONFIG--\n(?<config>.*?)(\s--SETTINGS--\n(?<settings>.*?))?(\s--REQUIREMENTS--\n(?<requirements>.*?))?\s--EXPECT--\n(?<expect>.*?\n*)(?:\n--INPUT--\s(?<input>.*)|$)/s', $content, $match)) { - throw new \InvalidArgumentException('File format is invalid.'); - } - - return IntegrationCase::create() - ->setFileName($fileName) - ->setTitle($match['title']) - ->setFixers($this->determineFixers($match['config'])) - ->setRequirements($this->determineRequirements($match['requirements'])) - ->setSettings($this->determineSettings($match['settings'])) - ->setExpectedCode($match['expect']) - ->setInputCode(isset($match['input']) ? $match['input'] : null) - ; - } catch (\InvalidArgumentException $e) { - throw new \InvalidArgumentException( - sprintf('%s Test file: "%s".', $e->getMessage(), $fileName), - $e->getCode(), - $e - ); - } - } - - /** - * Parses the '--CONFIG--' block of a '.test' file and determines what fixers should be used. - * - * @param string $config - * - * @return FixerInterface[] - */ - protected function determineFixers($config) - { - static $levelMap = array( - 'none' => FixerInterface::NONE_LEVEL, - 'psr1' => FixerInterface::PSR1_LEVEL, - 'psr2' => FixerInterface::PSR2_LEVEL, - 'symfony' => FixerInterface::SYMFONY_LEVEL, - ); - - $lines = explode("\n", $config); - if (empty($lines)) { - throw new \InvalidArgumentException('No lines found in CONFIG section.'); - } - - $config = array('level' => null, 'fixers' => array(), '--fixers' => array()); - - foreach ($lines as $line) { - $labelValuePair = explode('=', $line); - if (2 !== count($labelValuePair)) { - throw new \InvalidArgumentException(sprintf('Invalid CONFIG line: "%d".', $line)); - } - - $label = strtolower(trim($labelValuePair[0])); - $value = trim($labelValuePair[1]); - - switch ($label) { - case 'level': - if (!array_key_exists($value, $levelMap)) { - throw new \InvalidArgumentException(sprintf('Unknown level "%s" set in CONFIG, expected any of "%s".', $value, implode(', ', array_keys($levelMap)))); - } - - if (null !== $config['level']) { - throw new \InvalidArgumentException('Cannot use multiple levels in configuration.'); - } - - $config['level'] = $value; - break; - case 'fixers': - case '--fixers': - foreach (explode(',', $value) as $fixer) { - $config[$label][] = strtolower(trim($fixer)); - } - - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown CONFIG line: "%d".', $line)); - } - } - - if (null === $config['level']) { - throw new \InvalidArgumentException('Level not set in CONFIG section.'); - } - - if (null === self::$builtInFixers) { - $fixer = new Fixer(); - $fixer->registerBuiltInFixers(); - self::$builtInFixers = $fixer->getFixers(); - } - - $fixers = array(); - for ($i = 0, $limit = count(self::$builtInFixers); $i < $limit; ++$i) { - $fixer = self::$builtInFixers[$i]; - $fixerName = $fixer->getName(); - if ('psr0' === $fixer->getName()) { - // File based fixer won't work - continue; - } - - if ($fixer->getLevel() !== ($fixer->getLevel() & $levelMap[$config['level']])) { - if (false !== $key = array_search($fixerName, $config['fixers'], true)) { - $fixers[] = $fixer; - unset($config['fixers'][$key]); - } - continue; - } - - if (false !== $key = array_search($fixerName, $config['--fixers'], true)) { - unset($config['--fixers'][$key]); - continue; - } - - if (in_array($fixerName, $config['fixers'], true)) { - throw new \InvalidArgumentException(sprintf('Additional fixer "%s" configured, but is already part of the level.', $fixerName)); - } - - $fixers[] = $fixer; - } - - if (!empty($config['fixers']) || !empty($config['--fixers'])) { - throw new \InvalidArgumentException(sprintf('Unknown fixers in CONFIG section: "%s".', implode(',', empty($config['fixers']) ? $config['--fixers'] : $config['fixers']))); - } - - return $fixers; - } - - /** - * Parses the '--REQUIREMENTS--' block of a '.test' file and determines requirements. - * - * @param string $config - * - * @return array - */ - protected function determineRequirements($config) - { - $requirements = array('hhvm' => true, 'php' => PHP_VERSION); - - if ('' === $config) { - return $requirements; - } - - $lines = explode("\n", $config); - if (empty($lines)) { - return $requirements; - } - - foreach ($lines as $line) { - $labelValuePair = explode('=', $line); - - if (2 !== count($labelValuePair)) { - throw new \InvalidArgumentException(sprintf('Invalid REQUIREMENTS line: "%d".', $line)); - } - - $label = strtolower(trim($labelValuePair[0])); - $value = trim($labelValuePair[1]); - - switch ($label) { - case 'hhvm': - $requirements['hhvm'] = 'false' !== $value; - break; - case 'php': - $requirements['php'] = $value; - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown REQUIREMENTS line: "%d".', $line)); - } - } - - return $requirements; - } - - /** - * Parses the '--SETTINGS--' block of a '.test' file and determines settings. - * - * @param string $config - * - * @return array - */ - protected function determineSettings($config) - { - $settings = array('checkPriority' => true); - - if ('' === $config) { - return $settings; - } - - $lines = explode("\n", $config); - if (empty($lines)) { - return $settings; - } - - foreach ($lines as $line) { - $labelValuePair = explode('=', $line); - if (2 !== count($labelValuePair)) { - throw new \InvalidArgumentException(sprintf('Invalid SETTINGS line: "%d".', $line)); - } - - $label = trim($labelValuePair[0]); - $value = trim($labelValuePair[1]); - - switch ($label) { - case 'checkPriority': - $settings['checkPriority'] = 'false' !== $value; - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown SETTINGS line: "%d".', $line)); - } - } - - return $settings; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Token.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Token.php deleted file mode 100644 index 6a27cc2..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Token.php +++ /dev/null @@ -1,509 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tokenizer; - -use Symfony\CS\Utils; - -/** - * Representation of single token. - * As a token prototype you should understand a single element generated by token_get_all. - * - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - */ -class Token -{ - /** - * Content of token prototype. - * - * @var string - */ - private $content; - - /** - * ID of token prototype, if available. - * - * @var int|null - */ - private $id; - - /** - * If token prototype is an array. - * - * @var bool - */ - private $isArray; - - /** - * Line of token prototype occurrence, if available. - * - * @var int|null - */ - private $line; - - /** - * Constructor. - * - * @param string|array $token token prototype - */ - public function __construct($token) - { - if (is_array($token)) { - $this->isArray = true; - $this->id = $token[0]; - $this->content = $token[1]; - $this->line = isset($token[2]) ? $token[2] : null; - } else { - $this->isArray = false; - $this->content = $token; - } - } - - /** - * Clear token at given index. - * - * Clearing means override token by empty string. - */ - public function clear() - { - $this->override(''); - } - - /** - * Check if token is equals to given one. - * - * If tokens are arrays, then only keys defined in parameter token are checked. - * - * @param Token|array|string $other token or it's prototype - * @param bool $caseSensitive perform a case sensitive comparison - * - * @return bool - */ - public function equals($other, $caseSensitive = true) - { - $otherPrototype = $other instanceof self ? $other->getPrototype() : $other; - - if ($this->isArray() !== is_array($otherPrototype)) { - return false; - } - - if (!$this->isArray()) { - return $this->content === $otherPrototype; - } - - $selfPrototype = $this->getPrototype(); - - foreach ($otherPrototype as $key => $val) { - // make sure the token has such key - if (!isset($selfPrototype[$key])) { - return false; - } - - if (1 === $key && !$caseSensitive) { - // case-insensitive comparison only applies to the content (key 1) - if (0 !== strcasecmp($val, $selfPrototype[1])) { - return false; - } - } else { - // regular comparison - if ($selfPrototype[$key] !== $val) { - return false; - } - } - } - - return true; - } - - /** - * Check if token is equals to one of given. - * - * @param array $others array of tokens or token prototypes - * @param bool|bool[] $caseSensitive global case sensitiveness or an array of booleans, whose keys should match - * the ones used in $others. If any is missing, the default case-sensitive - * comparison is used - * - * @return bool - */ - public function equalsAny(array $others, $caseSensitive = true) - { - foreach ($others as $key => $other) { - $cs = self::isKeyCaseSensitive($caseSensitive, $key); - - if ($this->equals($other, $cs)) { - return true; - } - } - - return false; - } - - /** - * A helper method used to find out whether or not a certain input token has to be case-sensitively matched. - * - * @param bool|bool[] $caseSensitive global case sensitiveness or an array of booleans, whose keys should match - * the ones used in $others. If any is missing, the default case-sensitive - * comparison is used - * @param int $key the key of the token that has to be looked up - * - * @return bool - */ - public static function isKeyCaseSensitive($caseSensitive, $key) - { - if (is_array($caseSensitive)) { - return isset($caseSensitive[$key]) ? $caseSensitive[$key] : true; - } - - return $caseSensitive; - } - - /** - * Get token prototype. - * - * @return string|array token prototype - */ - public function getPrototype() - { - if (!$this->isArray) { - return $this->content; - } - - return array( - $this->id, - $this->content, - $this->line, - ); - } - - /** - * Get token's content. - * - * @return string - */ - public function getContent() - { - return $this->content; - } - - /** - * Get token's id. - * - * @return int|null - */ - public function getId() - { - return $this->id; - } - - /** - * Get token's line. - * - * @deprecated Will be removed in the 2.0 - * - * @return int - */ - public function getLine() - { - return $this->line; - } - - /** - * Get token name. - * - * @return null|string token name - */ - public function getName() - { - if (!isset($this->id)) { - return; - } - - $transformers = Transformers::create(); - - if ($transformers->hasCustomToken($this->id)) { - return $transformers->getCustomToken($this->id); - } - - return token_name($this->id); - } - - /** - * Generate array containing all keywords that exists in PHP version in use. - * - * @return array<int, int> - */ - public static function getKeywords() - { - static $keywords = null; - - if (null === $keywords) { - $keywords = self::getTokenKindsForNames(array('T_ABSTRACT', 'T_ARRAY', 'T_AS', 'T_BREAK', 'T_CALLABLE', 'T_CASE', - 'T_CATCH', 'T_CLASS', 'T_CLONE', 'T_CONST', 'T_CONTINUE', 'T_DECLARE', 'T_DEFAULT', 'T_DO', - 'T_ECHO', 'T_ELSE', 'T_ELSEIF', 'T_EMPTY', 'T_ENDDECLARE', 'T_ENDFOR', 'T_ENDFOREACH', - 'T_ENDIF', 'T_ENDSWITCH', 'T_ENDWHILE', 'T_EVAL', 'T_EXIT', 'T_EXTENDS', 'T_FINAL', - 'T_FINALLY', 'T_FOR', 'T_FOREACH', 'T_FUNCTION', 'T_GLOBAL', 'T_GOTO', 'T_HALT_COMPILER', - 'T_IF', 'T_IMPLEMENTS', 'T_INCLUDE', 'T_INCLUDE_ONCE', 'T_INSTANCEOF', 'T_INSTEADOF', - 'T_INTERFACE', 'T_ISSET', 'T_LIST', 'T_LOGICAL_AND', 'T_LOGICAL_OR', 'T_LOGICAL_XOR', - 'T_NAMESPACE', 'T_NEW', 'T_PRINT', 'T_PRIVATE', 'T_PROTECTED', 'T_PUBLIC', 'T_REQUIRE', - 'T_REQUIRE_ONCE', 'T_RETURN', 'T_STATIC', 'T_SWITCH', 'T_THROW', 'T_TRAIT', 'T_TRY', - 'T_UNSET', 'T_USE', 'T_VAR', 'T_WHILE', 'T_YIELD', 'CT_ARRAY_TYPEHINT', 'CT_CLASS_CONSTANT', - )); - } - - return $keywords; - } - - /** - * Generate array containing all predefined constants that exists in PHP version in use. - * - * @see http://php.net/manual/en/language.constants.predefined.php - * - * @return array<int, int> - */ - public static function getMagicConstants() - { - static $magicConstants = null; - - if (null === $magicConstants) { - $magicConstants = self::getTokenKindsForNames(array('T_CLASS_C', 'T_DIR', 'T_FILE', 'T_FUNC_C', 'T_LINE', 'T_METHOD_C', 'T_NS_C', 'T_TRAIT_C')); - } - - return $magicConstants; - } - - /** - * Check if token prototype is an array. - * - * @return bool is array - */ - public function isArray() - { - return $this->isArray; - } - - /** - * Check if token is one of type cast tokens. - * - * @return bool - */ - public function isCast() - { - static $castTokens = array(T_ARRAY_CAST, T_BOOL_CAST, T_DOUBLE_CAST, T_INT_CAST, T_OBJECT_CAST, T_STRING_CAST, T_UNSET_CAST); - - return $this->isGivenKind($castTokens); - } - - /** - * Check if token is one of classy tokens: T_CLASS, T_INTERFACE or T_TRAIT. - * - * @return bool - */ - public function isClassy() - { - static $classTokens = null; - - if (null === $classTokens) { - $classTokens = array(T_CLASS, T_INTERFACE); - - if (defined('T_TRAIT')) { - $classTokens[] = constant('T_TRAIT'); - } - } - - return $this->isGivenKind($classTokens); - } - - /** - * Check if token is one of comment tokens: T_COMMENT or T_DOC_COMMENT. - * - * @return bool - */ - public function isComment() - { - static $commentTokens = array(T_COMMENT, T_DOC_COMMENT); - - return $this->isGivenKind($commentTokens); - } - - /** - * Check if token is empty, e.g. because of clearing. - * - * @return bool - */ - public function isEmpty() - { - return null === $this->id && ('' === $this->content || null === $this->content); - } - - /** - * Check if token is one of given kind. - * - * @param int|int[] $possibleKind kind or array of kinds - * - * @return bool - */ - public function isGivenKind($possibleKind) - { - return $this->isArray && (is_array($possibleKind) ? in_array($this->id, $possibleKind, true) : $this->id === $possibleKind); - } - - /** - * Check if token is a keyword. - * - * @return bool - */ - public function isKeyword() - { - $keywords = static::getKeywords(); - - return $this->isArray && isset($keywords[$this->id]); - } - - /** - * Check if token is a native PHP constant: true, false or null. - * - * @return bool - */ - public function isNativeConstant() - { - static $nativeConstantStrings = array('true', 'false', 'null'); - - return $this->isArray && in_array(strtolower($this->content), $nativeConstantStrings, true); - } - - /** - * Returns if the token is of a Magic constants type. - * - * @see http://php.net/manual/en/language.constants.predefined.php - * - * @return bool - */ - public function isMagicConstant() - { - $magicConstants = static::getMagicConstants(); - - return $this->isArray && isset($magicConstants[$this->id]); - } - - /** - * Check if token is one of structure alternative end syntax (T_END...). - * - * @return bool - */ - public function isStructureAlternativeEnd() - { - static $tokens = array(T_ENDDECLARE, T_ENDFOR, T_ENDFOREACH, T_ENDIF, T_ENDSWITCH, T_ENDWHILE, T_END_HEREDOC); - - return $this->isGivenKind($tokens); - } - - /** - * Check if token is a whitespace. - * - * @param array $opts Extra options, $opts['whitespaces'] string - * determining whitespaces chars, - * default is " \t\n\r\0\x0B" - * - * @return bool - */ - public function isWhitespace(array $opts = array()) - { - if ($this->isArray && !$this->isGivenKind(T_WHITESPACE)) { - return false; - } - - $whitespaces = isset($opts['whitespaces']) ? $opts['whitespaces'] : " \t\n\r\0\x0B"; - - return '' === trim($this->content, $whitespaces); - } - - /** - * Override token. - * - * If called on Token inside Tokens collection please use `Tokens::overrideAt` instead. - * - * @param string|array $prototype token prototype - */ - public function override($prototype) - { - if (is_array($prototype)) { - $this->isArray = true; - $this->id = $prototype[0]; - $this->content = $prototype[1]; - $this->line = isset($prototype[2]) ? $prototype[2] : null; - - return; - } - - $this->isArray = false; - $this->id = null; - $this->content = $prototype; - $this->line = null; - } - - /** - * Set token's content. - * - * @param string $content - */ - public function setContent($content) - { - // setting empty content is clearing the token - if ('' === $content) { - $this->clear(); - - return; - } - - $this->content = $content; - } - - public function toArray() - { - return array( - 'id' => $this->id, - 'name' => $this->getName(), - 'content' => $this->content, - 'line' => $this->line, - 'isArray' => $this->isArray, - ); - } - - public function toJson() - { - static $options = null; - - if (null === $options) { - $options = Utils::calculateBitmask(array('JSON_PRETTY_PRINT', 'JSON_NUMERIC_CHECK')); - } - - return json_encode($this->toArray(), $options); - } - - /** - * @param string[] $tokenNames - * - * @return array<int, int> - */ - private static function getTokenKindsForNames(array $tokenNames) - { - $keywords = array(); - foreach ($tokenNames as $keywordName) { - if (defined($keywordName)) { - $keyword = constant($keywordName); - $keywords[$keyword] = $keyword; - } - } - - return $keywords; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Tokens.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Tokens.php deleted file mode 100644 index 1b28d7e..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Tokens.php +++ /dev/null @@ -1,1448 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tokenizer; - -use Symfony\CS\Utils; - -/** - * Collection of code tokens. - * - * Its role is to provide the ability to manage collection and navigate through it. - * - * As a token prototype you should understand a single element generated by token_get_all. - * - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - * @author Gregor Harlan <gharlan@web.de> - * - * @method Token current() - */ -class Tokens extends \SplFixedArray -{ - const BLOCK_TYPE_PARENTHESIS_BRACE = 1; - const BLOCK_TYPE_CURLY_BRACE = 2; - const BLOCK_TYPE_SQUARE_BRACE = 3; - const BLOCK_TYPE_DYNAMIC_PROP_BRACE = 4; - const BLOCK_TYPE_DYNAMIC_VAR_BRACE = 5; - - /** - * Static class cache. - * - * @var array - */ - private static $cache = array(); - - /** - * crc32 hash of code string. - * - * @var string - */ - private $codeHash; - - /** - * Clone tokens collection. - */ - public function __clone() - { - foreach ($this as $key => $val) { - $this[$key] = clone $val; - } - } - - /** - * Clear cache - one position or all of them. - * - * @param string|null $key position to clear, when null clear all - */ - public static function clearCache($key = null) - { - if (null === $key) { - self::$cache = array(); - - return; - } - - if (self::hasCache($key)) { - unset(self::$cache[$key]); - } - } - - /** - * Detect type of block. - * - * @param Token $token token - * - * @return null|array array with 'type' and 'isStart' keys or null if not found - */ - public static function detectBlockType(Token $token) - { - foreach (self::getBlockEdgeDefinitions() as $type => $definition) { - if ($token->equals($definition['start'])) { - return array('type' => $type, 'isStart' => true); - } - - if ($token->equals($definition['end'])) { - return array('type' => $type, 'isStart' => false); - } - } - } - - /** - * Create token collection from array. - * - * @param Token[] $array the array to import - * @param bool $saveIndexes save the numeric indexes used in the original array, default is yes - * - * @return Tokens - */ - public static function fromArray($array, $saveIndexes = null) - { - $tokens = new self(count($array)); - - if (null === $saveIndexes || $saveIndexes) { - foreach ($array as $key => $val) { - $tokens[$key] = $val; - } - - return $tokens; - } - - $index = 0; - - foreach ($array as $val) { - $tokens[$index++] = $val; - } - - return $tokens; - } - - /** - * Create token collection directly from code. - * - * @param string $code PHP code - * - * @return Tokens - */ - public static function fromCode($code) - { - $codeHash = self::calculateCodeHash($code); - - if (self::hasCache($codeHash)) { - $tokens = self::getCache($codeHash); - - // generate the code to recalculate the hash - $tokens->generateCode(); - - if ($codeHash === $tokens->codeHash) { - $tokens->clearEmptyTokens(); - - return $tokens; - } - } - - $tokens = new self(); - $tokens->setCode($code); - - return $tokens; - } - - /** - * Check whether passed method name is one of magic methods. - * - * @param string $name name of method - * - * @return bool is method a magical - */ - public static function isMethodNameIsMagic($name) - { - static $magicMethods = array( - '__construct', '__destruct', '__call', '__callStatic', '__get', '__set', '__isset', '__unset', - '__sleep', '__wakeup', '__toString', '__invoke', '__set_state', '__clone', - ); - - return in_array($name, $magicMethods, true); - } - - /** - * Clear empty tokens. - * - * Empty tokens can occur e.g. after calling clear on element of collection. - */ - public function clearEmptyTokens() - { - $count = 0; - - foreach ($this as $token) { - if (!$token->isEmpty()) { - $this[$count++] = $token; - } - } - - $this->setSize($count); - } - - /** - * Ensure that on given index is a whitespace with given kind. - * - * If there is a whitespace then it's content will be modified. - * If not - the new Token will be added. - * - * @param int $index index - * @param int $indexOffset index offset for Token insertion - * @param string $whitespace whitespace to set - * - * @return bool if new Token was added - */ - public function ensureWhitespaceAtIndex($index, $indexOffset, $whitespace) - { - $removeLastCommentLine = function (Token $token, $indexOffset) { - // because comments tokens are greedy and may consume single \n if we are putting whitespace after it let trim that \n - if (1 === $indexOffset && $token->isComment()) { - $content = $token->getContent(); - - if ("\n" === $content[strlen($content) - 1]) { - $token->setContent(substr($content, 0, -1)); - } - } - }; - - if ($this[$index]->isWhitespace()) { - $removeLastCommentLine($this[$index - 1], $indexOffset); - $this->overrideAt($index, array(T_WHITESPACE, $whitespace, $this[$index]->getLine())); - - return false; - } - - $removeLastCommentLine($this[$index], $indexOffset); - - $this->insertAt( - $index + $indexOffset, - array( - new Token(array(T_WHITESPACE, $whitespace)), - ) - ); - - return true; - } - - /** - * Find block end. - * - * @param int $type type of block, one of BLOCK_TYPE_* - * @param int $searchIndex index of opening brace - * @param bool $findEnd if method should find block's end, default true, otherwise method find block's start - * - * @return int index of closing brace - */ - public function findBlockEnd($type, $searchIndex, $findEnd = true) - { - $blockEdgeDefinitions = self::getBlockEdgeDefinitions(); - - if (!isset($blockEdgeDefinitions[$type])) { - throw new \InvalidArgumentException(sprintf('Invalid param type: %s.', $type)); - } - - $startEdge = $blockEdgeDefinitions[$type]['start']; - $endEdge = $blockEdgeDefinitions[$type]['end']; - $startIndex = $searchIndex; - $endIndex = $this->count() - 1; - $indexOffset = 1; - - if (!$findEnd) { - list($startEdge, $endEdge) = array($endEdge, $startEdge); - $indexOffset = -1; - $endIndex = 0; - } - - if (!$this[$startIndex]->equals($startEdge)) { - throw new \InvalidArgumentException(sprintf('Invalid param $startIndex - not a proper block %s.', $findEnd ? 'start' : 'end')); - } - - $blockLevel = 0; - - for ($index = $startIndex; $index !== $endIndex; $index += $indexOffset) { - $token = $this[$index]; - - if ($token->equals($startEdge)) { - ++$blockLevel; - - continue; - } - - if ($token->equals($endEdge)) { - --$blockLevel; - - if (0 === $blockLevel) { - break; - } - - continue; - } - } - - if (!$this[$index]->equals($endEdge)) { - throw new \UnexpectedValueException(sprintf('Missing block %s.', $findEnd ? 'end' : 'start')); - } - - return $index; - } - - /** - * Find tokens of given kind. - * - * @param int|array $possibleKind kind or array of kind - * @param int $start optional offset - * @param int|null $end optional limit - * - * @return array array of tokens of given kinds or assoc array of arrays - */ - public function findGivenKind($possibleKind, $start = 0, $end = null) - { - $this->rewind(); - if (null === $end) { - $end = $this->count(); - } - - $elements = array(); - $possibleKinds = (array) $possibleKind; - - foreach ($possibleKinds as $kind) { - $elements[$kind] = array(); - } - - for ($i = $start; $i < $end; ++$i) { - $token = $this[$i]; - if ($token->isGivenKind($possibleKinds)) { - $elements[$token->getId()][$i] = $token; - } - } - - return is_array($possibleKind) ? $elements : $elements[$possibleKind]; - } - - /** - * Generate code from tokens. - * - * @return string - */ - public function generateCode() - { - $code = $this->generatePartialCode(0, count($this) - 1); - $this->changeCodeHash(self::calculateCodeHash($code)); - - return $code; - } - - /** - * Generate code from tokens between given indexes. - * - * @param int $start start index - * @param int $end end index - * - * @return string - */ - public function generatePartialCode($start, $end) - { - $code = ''; - - for ($i = $start; $i <= $end; ++$i) { - $code .= $this[$i]->getContent(); - } - - return $code; - } - - /** - * Get indexes of methods and properties in classy code (classes, interfaces and traits). - * - * @return array - */ - public function getClassyElements() - { - $this->rewind(); - - $elements = array(); - $inClass = false; - $curlyBracesLevel = 0; - $bracesLevel = 0; - - foreach ($this as $index => $token) { - if ($token->isGivenKind(T_ENCAPSED_AND_WHITESPACE)) { - continue; - } - - if (!$inClass) { - $inClass = $token->isClassy(); - continue; - } - - if ($token->equals('(')) { - ++$bracesLevel; - continue; - } - - if ($token->equals(')')) { - --$bracesLevel; - continue; - } - - if ($token->equals('{')) { - ++$curlyBracesLevel; - continue; - } - - if ($token->equals('}')) { - --$curlyBracesLevel; - - if (0 === $curlyBracesLevel) { - $inClass = false; - } - - continue; - } - - if (1 !== $curlyBracesLevel || !$token->isArray()) { - continue; - } - - if (0 === $bracesLevel && $token->isGivenKind(T_VARIABLE)) { - $elements[$index] = array('token' => $token, 'type' => 'property'); - continue; - } - - if ($token->isGivenKind(T_FUNCTION)) { - $elements[$index] = array('token' => $token, 'type' => 'method'); - } - } - - return $elements; - } - - /** - * Get indexes of namespace uses. - * - * @param bool $perNamespace Return namespace uses per namespace - * - * @return array|array[] - */ - public function getImportUseIndexes($perNamespace = false) - { - $this->rewind(); - - $uses = array(); - $namespaceIndex = 0; - - for ($index = 0, $limit = $this->count(); $index < $limit; ++$index) { - $token = $this[$index]; - - if ($token->isGivenKind(T_NAMESPACE)) { - $nextTokenIndex = $this->getNextTokenOfKind($index, array(';', '{')); - $nextToken = $this[$nextTokenIndex]; - - if ($nextToken->equals('{')) { - $index = $nextTokenIndex; - } - - if ($perNamespace) { - ++$namespaceIndex; - } - - continue; - } - - // Skip whole class braces content. - // The only { that interest us is the one directly after T_NAMESPACE and is handled above - // That way we can skip for example whole tokens in class declaration, therefore skip `T_USE` for traits. - if ($token->equals('{')) { - $index = $this->findBlockEnd(self::BLOCK_TYPE_CURLY_BRACE, $index); - continue; - } - - if (!$token->isGivenKind(T_USE)) { - continue; - } - - $nextToken = $this[$this->getNextMeaningfulToken($index)]; - - // ignore function () use ($foo) {} - if ($nextToken->equals('(')) { - continue; - } - - $uses[$namespaceIndex][] = $index; - } - - if (!$perNamespace && isset($uses[$namespaceIndex])) { - return $uses[$namespaceIndex]; - } - - return $uses; - } - - /** - * Get index for closest next token which is non whitespace. - * - * This method is shorthand for getNonWhitespaceSibling method. - * - * @param int $index token index - * @param array $opts array of extra options for isWhitespace method - * - * @return int|null - */ - public function getNextNonWhitespace($index, array $opts = array()) - { - return $this->getNonWhitespaceSibling($index, 1, $opts); - } - - /** - * Get index for closest next token of given kind. - * - * This method is shorthand for getTokenOfKindSibling method. - * - * @param int $index token index - * @param array $tokens possible tokens - * @param bool|bool[] $caseSensitive global case sensitiveness or an array of booleans, whose keys should match - * the ones used in $others. If any is missing, the default case-sensitive - * comparison is used - * - * @return int|null - */ - public function getNextTokenOfKind($index, array $tokens = array(), $caseSensitive = true) - { - return $this->getTokenOfKindSibling($index, 1, $tokens, $caseSensitive); - } - - /** - * Get index for closest sibling token which is non whitespace. - * - * @param int $index token index - * @param int $direction direction for looking, +1 or -1 - * @param array $opts array of extra options for isWhitespace method - * - * @return int|null - */ - public function getNonWhitespaceSibling($index, $direction, array $opts = array()) - { - while (true) { - $index += $direction; - - if (!$this->offsetExists($index)) { - return; - } - - $token = $this[$index]; - - if (!$token->isWhitespace($opts)) { - return $index; - } - } - } - - /** - * Get index for closest sibling token which is not empty. - * - * @param int $index token index - * @param int $direction direction for looking, +1 or -1 - * - * @return int|null - */ - public function getNonEmptySibling($index, $direction) - { - while (true) { - $index += $direction; - - if (!$this->offsetExists($index)) { - return; - } - - if (!$this[$index]->isEmpty()) { - return $index; - } - } - } - - /** - * Get index for closest previous token which is non whitespace. - * - * This method is shorthand for getNonWhitespaceSibling method. - * - * @param int $index token index - * @param array $opts array of extra options for isWhitespace method - * - * @return int|null - */ - public function getPrevNonWhitespace($index, array $opts = array()) - { - return $this->getNonWhitespaceSibling($index, -1, $opts); - } - - /** - * Get index for closest previous token of given kind. - * This method is shorthand for getTokenOfKindSibling method. - * - * @param int $index token index - * @param array $tokens possible tokens - * @param bool|bool[] $caseSensitive global case sensitiveness or an array of booleans, whose keys should match - * the ones used in $others. If any is missing, the default case-sensitive - * comparison is used - * - * @return int|null - */ - public function getPrevTokenOfKind($index, array $tokens = array(), $caseSensitive = true) - { - return $this->getTokenOfKindSibling($index, -1, $tokens, $caseSensitive); - } - - /** - * Get index for closest sibling token of given kind. - * - * @param int $index token index - * @param int $direction direction for looking, +1 or -1 - * @param array $tokens possible tokens - * @param bool|bool[] $caseSensitive global case sensitiveness or an array of booleans, whose keys should match - * the ones used in $others. If any is missing, the default case-sensitive - * comparison is used - * - * @return int|null - */ - public function getTokenOfKindSibling($index, $direction, array $tokens = array(), $caseSensitive = true) - { - while (true) { - $index += $direction; - - if (!$this->offsetExists($index)) { - return; - } - - $token = $this[$index]; - - if ($token->equalsAny($tokens, $caseSensitive)) { - return $index; - } - } - } - - /** - * Get index for closest sibling token not of given kind. - * - * @param int $index token index - * @param int $direction direction for looking, +1 or -1 - * @param array $tokens possible tokens - * - * @return int|null - */ - public function getTokenNotOfKindSibling($index, $direction, array $tokens = array()) - { - while (true) { - $index += $direction; - - if (!$this->offsetExists($index)) { - return; - } - - $token = $this[$index]; - - if ($token->isEmpty()) { - continue; - } - - if ($token->equalsAny($tokens)) { - continue; - } - - return $index; - } - } - - /** - * Get index for closest sibling token that is not a whitespace or comment. - * - * @param int $index token index - * @param int $direction direction for looking, +1 or -1 - * - * @return int|null - */ - public function getMeaningfulTokenSibling($index, $direction) - { - return $this->getTokenNotOfKindSibling( - $index, - $direction, - array(array(T_WHITESPACE), array(T_COMMENT), array(T_DOC_COMMENT)) - ); - } - - /** - * Get index for closest next token that is not a whitespace or comment. - * - * @param int $index token index - * - * @return int|null - */ - public function getNextMeaningfulToken($index) - { - return $this->getMeaningfulTokenSibling($index, 1); - } - - /** - * Get index for closest previous token that is not a whitespace or comment. - * - * @param int $index token index - * - * @return int|null - */ - public function getPrevMeaningfulToken($index) - { - return $this->getMeaningfulTokenSibling($index, -1); - } - - /** - * Find a sequence of meaningful tokens and returns the array of their locations. - * - * @param array $sequence an array of tokens (same format used by getNextTokenOfKind) - * @param int $start start index, defaulting to the start of the file - * @param int $end end index, defaulting to the end of the file - * @param bool|array $caseSensitive global case sensitiveness or an array of booleans, whose keys should match - * the ones used in $others. If any is missing, the default case-sensitive - * comparison is used - * - * @return array|null an array containing the tokens matching the sequence elements, indexed by their position - */ - public function findSequence(array $sequence, $start = 0, $end = null, $caseSensitive = true) - { - // $end defaults to the end of the collection - if (null === $end) { - $end = count($this) - 1; - } - - if (!count($sequence)) { - throw new \InvalidArgumentException('Invalid sequence.'); - } - - // make sure the sequence content is "meaningful" - foreach ($sequence as $key => $token) { - // if not a Token instance already, we convert it to verify the meaningfulness - if (!$token instanceof Token) { - if (is_array($token) && !isset($token[1])) { - // fake some content as it is required by the Token constructor, - // although optional for search purposes - $token[1] = ''; - } - $token = new Token($token); - } - if ($token->isWhitespace() || $token->isComment() || $token->isEmpty()) { - throw new \InvalidArgumentException(sprintf('Non-meaningful token at position: %s.', $key)); - } - } - - // remove the first token from the sequence, so we can freely iterate through the sequence after a match to - // the first one is found - $key = key($sequence); - $firstCs = Token::isKeyCaseSensitive($caseSensitive, $key); - $firstToken = $sequence[$key]; - unset($sequence[$key]); - - // begin searching for the first token in the sequence (start included) - $index = $start - 1; - while (null !== $index && $index <= $end) { - $index = $this->getNextTokenOfKind($index, array($firstToken), $firstCs); - - // ensure we found a match and didn't get past the end index - if (null === $index || $index > $end) { - return; - } - - // initialise the result array with the current index - $result = array($index => $this[$index]); - - // advance cursor to the current position - $currIdx = $index; - - // iterate through the remaining tokens in the sequence - foreach ($sequence as $key => $token) { - $currIdx = $this->getNextMeaningfulToken($currIdx); - - // ensure we didn't go too far - if (null === $currIdx || $currIdx > $end) { - return; - } - - if (!$this[$currIdx]->equals($token, Token::isKeyCaseSensitive($caseSensitive, $key))) { - // not a match, restart the outer loop - continue 2; - } - - // append index to the result array - $result[$currIdx] = $this[$currIdx]; - } - - // do we have a complete match? - // hint: $result is bigger than $sequence since the first token has been removed from the latter - if (count($sequence) < count($result)) { - return $result; - } - } - } - - /** - * Insert instances of Token inside collection. - * - * @param int $index start inserting index - * @param Tokens|Token[]|Token $items instances of Token to insert - */ - public function insertAt($index, $items) - { - $items = is_array($items) || $items instanceof self ? $items : array($items); - $itemsCnt = count($items); - $oldSize = count($this); - - $this->setSize($oldSize + $itemsCnt); - - for ($i = $oldSize + $itemsCnt - 1; $i >= $index; --$i) { - $this[$i] = isset($this[$i - $itemsCnt]) ? $this[$i - $itemsCnt] : new Token(''); - } - - for ($i = 0; $i < $itemsCnt; ++$i) { - $this[$i + $index] = $items[$i]; - } - } - - /** - * Check if there is an array at given index. - * - * @param int $index - * - * @return bool - */ - public function isArray($index) - { - return $this[$index]->isGivenKind(T_ARRAY) || $this->isShortArray($index); - } - - /** - * Check if the array at index is multiline. - * - * This only checks the root-level of the array. - * - * @param int $index - * - * @return bool - */ - public function isArrayMultiLine($index) - { - if (!$this->isArray($index)) { - throw new \InvalidArgumentException(sprintf('Not an array at given index "%d".', $index)); - } - - // Skip only when its an array, for short arrays we need the brace for correct - // level counting - if ($this[$index]->isGivenKind(T_ARRAY)) { - $index = $this->getNextMeaningfulToken($index); - } - - $endIndex = $this[$index]->equals('(') - ? $this->findBlockEnd(self::BLOCK_TYPE_PARENTHESIS_BRACE, $index) - : $this->findBlockEnd(self::BLOCK_TYPE_SQUARE_BRACE, $index) - ; - - for (++$index; $index < $endIndex; ++$index) { - $token = $this[$index]; - $blockType = static::detectBlockType($token); - - if ($blockType && $blockType['isStart']) { - $index = $this->findBlockEnd($blockType['type'], $index); - continue; - } - - if ( - $token->isGivenKind(T_WHITESPACE) && - !$this[$index - 1]->isGivenKind(T_END_HEREDOC) && - false !== strpos($token->getContent(), "\n") - ) { - return true; - } - } - - return false; - } - - /** - * Check if there is an anonymous class under given index. - * - * @param int $index - * - * @return bool - */ - public function isAnonymousClass($index) - { - $token = $this[$index]; - - if (!$token->isClassy()) { - throw new \LogicException('No classy token at given index'); - } - - if (!$token->isGivenKind(T_CLASS)) { - return false; - } - - return $this[$this->getPrevMeaningfulToken($index)]->isGivenKind(T_NEW); - } - - /** - * Check if there is a lambda function under given index. - * - * @param int $index - * - * @return bool - */ - public function isLambda($index) - { - $token = $this[$index]; - - if (!$token->isGivenKind(T_FUNCTION)) { - throw new \LogicException(sprintf('No T_FUNCTION at given index "%d".', $index)); - } - - $nextIndex = $this->getNextMeaningfulToken($index); - $nextToken = $this[$nextIndex]; - - // skip & for `function & () {}` syntax - if ($nextToken->equals('&')) { - $nextIndex = $this->getNextMeaningfulToken($nextIndex); - $nextToken = $this[$nextIndex]; - } - - return $nextToken->equals('('); - } - - /** - * Check if partial code is multiline. - * - * @param int $start start index - * @param int $end end index - * - * @return bool - */ - public function isPartialCodeMultiline($start, $end) - { - for ($i = $start; $i <= $end; ++$i) { - if (false !== strpos($this[$i]->getContent(), "\n")) { - return true; - } - } - - return false; - } - - /** - * Check if the array at index uses the short-syntax. - * - * @param int $index - * - * @return bool - */ - public function isShortArray($index) - { - static $disallowedPrevTokens = array( - ']', - '}', - ')', - '"', - array(T_CONSTANT_ENCAPSED_STRING), - array(T_STRING), - array(T_STRING_VARNAME), - array(T_VARIABLE), - array(CT_DYNAMIC_PROP_BRACE_CLOSE), - array(CT_DYNAMIC_VAR_BRACE_CLOSE), - ); - - $token = $this[$index]; - - if (!$token->equals('[')) { - return false; - } - - $prevToken = $this[$this->getPrevMeaningfulToken($index)]; - - if (!$prevToken->equalsAny($disallowedPrevTokens)) { - return true; - } - - return false; - } - - /** - * Checks if there is an unary successor operator under given index. - * - * @param int $index - * - * @return bool - */ - public function isUnarySuccessorOperator($index) - { - static $allowedPrevToken = array( - ']', - array(T_STRING), - array(T_VARIABLE), - array(CT_DYNAMIC_PROP_BRACE_CLOSE), - array(CT_DYNAMIC_VAR_BRACE_CLOSE), - ); - - $token = $this[$index]; - - if (!$token->isGivenKind(array(T_INC, T_DEC))) { - return false; - } - - $prevToken = $this[$this->getPrevMeaningfulToken($index)]; - - return $prevToken->equalsAny($allowedPrevToken); - } - - /** - * Checks if there is an unary predecessor operator under given index. - * - * @param int $index - * - * @return bool - */ - public function isUnaryPredecessorOperator($index) - { - static $potentialSuccessorOperator = array(T_INC, T_DEC); - - static $potentialBinaryOperator = array('+', '-', '&'); - - static $otherOperators; - if (null === $otherOperators) { - $otherOperators = array('!', '~', '@'); - if (defined('T_ELLIPSIS')) { - $otherOperators[] = array(T_ELLIPSIS); - } - } - - static $disallowedPrevTokens; - if (null === $disallowedPrevTokens) { - $disallowedPrevTokens = array( - ']', - '}', - ')', - '"', - '`', - array(CT_DYNAMIC_PROP_BRACE_CLOSE), - array(CT_DYNAMIC_VAR_BRACE_CLOSE), - array(T_CLASS_C), - array(T_CONSTANT_ENCAPSED_STRING), - array(T_DEC), - array(T_DIR), - array(T_DNUMBER), - array(T_FILE), - array(T_FUNC_C), - array(T_INC), - array(T_LINE), - array(T_LNUMBER), - array(T_METHOD_C), - array(T_NS_C), - array(T_STRING), - array(T_VARIABLE), - ); - if (defined('T_TRAIT_C')) { - $disallowedPrevTokens[] = array(T_TRAIT_C); - } - } - - $token = $this[$index]; - - if ($token->isGivenKind($potentialSuccessorOperator)) { - return !$this->isUnarySuccessorOperator($index); - } - - if ($token->equalsAny($otherOperators)) { - return true; - } - - if (!$token->equalsAny($potentialBinaryOperator)) { - return false; - } - - $prevToken = $this[$this->getPrevMeaningfulToken($index)]; - - if (!$prevToken->equalsAny($disallowedPrevTokens)) { - return true; - } - - if (!$token->equals('&') || !$prevToken->isGivenKind(T_STRING)) { - return false; - } - - static $searchTokens = array( - ';', - '{', - '}', - array(T_FUNCTION), - array(T_OPEN_TAG), - array(T_OPEN_TAG_WITH_ECHO), - ); - $prevToken = $this[$this->getPrevTokenOfKind($index, $searchTokens)]; - - return $prevToken->isGivenKind(T_FUNCTION); - } - - /** - * Checks if there is a binary operator under given index. - * - * @param int $index - * - * @return bool - */ - public function isBinaryOperator($index) - { - static $nonArrayOperators = array( - '=' => true, - '*' => true, - '/' => true, - '%' => true, - '<' => true, - '>' => true, - '|' => true, - '^' => true, - ); - - static $potentialUnaryNonArrayOperators = array( - '+' => true, - '-' => true, - '&' => true, - ); - - static $arrayOperators; - if (null === $arrayOperators) { - $arrayOperators = array( - T_AND_EQUAL => true, // &= - T_BOOLEAN_AND => true, // && - T_BOOLEAN_OR => true, // || - T_CONCAT_EQUAL => true, // .= - T_DIV_EQUAL => true, // /= - T_DOUBLE_ARROW => true, // => - T_IS_EQUAL => true, // == - T_IS_GREATER_OR_EQUAL => true, // >= - T_IS_IDENTICAL => true, // === - T_IS_NOT_EQUAL => true, // !=, <> - T_IS_NOT_IDENTICAL => true, // !== - T_IS_SMALLER_OR_EQUAL => true, // <= - T_LOGICAL_AND => true, // and - T_LOGICAL_OR => true, // or - T_LOGICAL_XOR => true, // xor - T_MINUS_EQUAL => true, // -= - T_MOD_EQUAL => true, // %= - T_MUL_EQUAL => true, // *= - T_OR_EQUAL => true, // |= - T_PLUS_EQUAL => true, // += - T_SL => true, // << - T_SL_EQUAL => true, // <<= - T_SR => true, // >> - T_SR_EQUAL => true, // >>= - T_XOR_EQUAL => true, // ^= - ); - if (defined('T_POW')) { - $arrayOperators[T_POW] = true; // ** - $arrayOperators[T_POW_EQUAL] = true; // **= - } - if (defined('T_SPACESHIP')) { - $arrayOperators[T_SPACESHIP] = true; // <=> - } - if (defined('T_COALESCE')) { - $arrayOperators[T_COALESCE] = true; // ?? - } - } - - $token = $this[$index]; - - if ($token->isArray()) { - return isset($arrayOperators[$token->getId()]); - } - - if (isset($nonArrayOperators[$token->getContent()])) { - return true; - } - - if (isset($potentialUnaryNonArrayOperators[$token->getContent()])) { - return !$this->isUnaryPredecessorOperator($index); - } - - return false; - } - - /* - * Override token at given index and register it. - * - * @param Token|array|string $token token prototype - */ - public function overrideAt($index, $token) - { - $this[$index]->override($token); - } - - /** - * Removes all the leading whitespace. - * - * @param int $index - * @param array $opts optional array of extra options for Token::isWhitespace method - */ - public function removeLeadingWhitespace($index, array $opts = array()) - { - if (isset($this[$index - 1]) && $this[$index - 1]->isWhitespace($opts)) { - $this[$index - 1]->clear(); - } - } - - /** - * Removes all the trailing whitespace. - * - * @param int $index - * @param array $opts optional array of extra options for Token::isWhitespace method - */ - public function removeTrailingWhitespace($index, array $opts = array()) - { - if (isset($this[$index + 1]) && $this[$index + 1]->isWhitespace($opts)) { - $this[$index + 1]->clear(); - } - } - - /** - * Set code. Clear all current content and replace it by new Token items generated from code directly. - * - * @param string $code PHP code - */ - public function setCode($code) - { - // clear memory - $this->setSize(0); - - $tokens = defined('TOKEN_PARSE') - ? token_get_all($code, TOKEN_PARSE) - : token_get_all($code); - - $this->setSize(count($tokens)); - - foreach ($tokens as $index => $token) { - $this[$index] = new Token($token); - } - - $transformers = Transformers::create(); - $transformers->transform($this); - - $this->rewind(); - $this->changeCodeHash(crc32($code)); - } - - public function toJson() - { - static $options = null; - - if (null === $options) { - $options = Utils::calculateBitmask(array('JSON_PRETTY_PRINT', 'JSON_NUMERIC_CHECK')); - } - - $output = new \SplFixedArray(count($this)); - - foreach ($this as $index => $token) { - $output[$index] = $token->toArray(); - } - - $this->rewind(); - - return json_encode($output, $options); - } - - /** - * Clear tokens in the given range. - * - * @param int $indexStart - * @param int $indexEnd - */ - public function clearRange($indexStart, $indexEnd) - { - for ($i = $indexStart; $i <= $indexEnd; ++$i) { - $this[$i]->clear(); - } - } - - /** - * Checks for monolithic PHP code. - * - * Checks that the code is pure PHP code, in a single code block, starting - * with an open tag. - * - * @return bool - */ - public function isMonolithicPhp() - { - $size = $this->count(); - - if (0 === $size) { - return false; - } - - // If code is not monolithic there is a great chance that first or last token is `T_INLINE_HTML`: - if ($this[0]->isGivenKind(T_INLINE_HTML) || $this[$size - 1]->isGivenKind(T_INLINE_HTML)) { - return false; - } - - for ($index = 1; $index < $size; ++$index) { - if ( - $this[$index]->isGivenKind(array(T_INLINE_HTML, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO)) - || ( - /* - * HHVM parses '<?=' as T_ECHO instead of T_OPEN_TAG_WITH_ECHO - * - * @see https://github.com/facebook/hhvm/issues/4809 - * @see https://github.com/facebook/hhvm/issues/7161 - */ - defined('HHVM_VERSION') - && $this[$index]->equals(array(T_ECHO, '<?=')) - ) - ) { - return false; - } - } - - return true; - } - - /** - * Clear token and merge surrounding whitespace tokens. - * - * @param int $index - */ - public function clearTokenAndMergeSurroundingWhitespace($index) - { - $count = count($this); - $this[$index]->clear(); - - if ($index === $count - 1) { - return; - } - - $nextIndex = $this->getNonEmptySibling($index, 1); - - if (null === $nextIndex || !$this[$nextIndex]->isWhitespace()) { - return; - } - - $prevIndex = $this->getNonEmptySibling($index, -1); - - if ($this[$prevIndex]->isWhitespace()) { - $this[$prevIndex]->setContent($this[$prevIndex]->getContent().$this[$nextIndex]->getContent()); - } elseif ($this[$prevIndex + 1]->isEmpty()) { - $this[$prevIndex + 1]->override(array(T_WHITESPACE, $this[$nextIndex]->getContent(), $this[$prevIndex + 1]->getLine())); - } - - $this[$nextIndex]->clear(); - } - - /** - * Return block edge definitions. - * - * @return array - */ - private static function getBlockEdgeDefinitions() - { - return array( - self::BLOCK_TYPE_CURLY_BRACE => array( - 'start' => '{', - 'end' => '}', - ), - self::BLOCK_TYPE_PARENTHESIS_BRACE => array( - 'start' => '(', - 'end' => ')', - ), - self::BLOCK_TYPE_SQUARE_BRACE => array( - 'start' => '[', - 'end' => ']', - ), - self::BLOCK_TYPE_DYNAMIC_PROP_BRACE => array( - 'start' => array(CT_DYNAMIC_PROP_BRACE_OPEN, '{'), - 'end' => array(CT_DYNAMIC_PROP_BRACE_CLOSE, '}'), - ), - self::BLOCK_TYPE_DYNAMIC_VAR_BRACE => array( - 'start' => array(CT_DYNAMIC_VAR_BRACE_OPEN, '{'), - 'end' => array(CT_DYNAMIC_VAR_BRACE_CLOSE, '}'), - ), - ); - } - - /** - * Calculate hash for code. - * - * @param string $code - * - * @return string - */ - private static function calculateCodeHash($code) - { - return crc32($code); - } - - /** - * Get cache value for given key. - * - * @param string $key item key - * - * @return Tokens - */ - private static function getCache($key) - { - if (!self::hasCache($key)) { - throw new \OutOfBoundsException(sprintf('Unknown cache key: "%s".', $key)); - } - - return self::$cache[$key]; - } - - /** - * Check if given key exists in cache. - * - * @param string $key item key - * - * @return bool - */ - private static function hasCache($key) - { - return isset(self::$cache[$key]); - } - - /** - * Set cache item. - * - * @param string $key item key - * @param Tokens $value item value - */ - private static function setCache($key, Tokens $value) - { - self::$cache[$key] = $value; - } - - /** - * Change code hash. - * - * Remove old cache and set new one. - * - * @param string $codeHash new code hash - */ - private function changeCodeHash($codeHash) - { - if (null !== $this->codeHash) { - self::clearCache($this->codeHash); - } - - $this->codeHash = $codeHash; - self::setCache($this->codeHash, $this); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/ArrayTypehint.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/ArrayTypehint.php deleted file mode 100644 index 1578849..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/ArrayTypehint.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tokenizer\Transformer; - -use Symfony\CS\Tokenizer\AbstractTransformer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Transform `array` typehint from T_ARRAY into T_ARRAY_TYPEHINT. - * - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - */ -class ArrayTypehint extends AbstractTransformer -{ - /** - * {@inheritdoc} - */ - public function process(Tokens $tokens) - { - foreach ($tokens->findGivenKind(T_ARRAY) as $index => $token) { - $nextIndex = $tokens->getNextMeaningfulToken($index); - $nextToken = $tokens[$nextIndex]; - - if (!$nextToken->equals('(')) { - $token->override(array(CT_ARRAY_TYPEHINT, $token->getContent(), $token->getLine())); - } - } - } - - /** - * {@inheritdoc} - */ - public function getCustomTokenNames() - { - return array('CT_ARRAY_TYPEHINT'); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/ClassConstant.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/ClassConstant.php deleted file mode 100644 index 6e0eb37..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/ClassConstant.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tokenizer\Transformer; - -use Symfony\CS\Tokenizer\AbstractTransformer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Transform `class` class' constant from T_CLASS into CT_CLASS_CONSTANT. - * - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - */ -class ClassConstant extends AbstractTransformer -{ - /** - * {@inheritdoc} - */ - public function process(Tokens $tokens) - { - foreach ($tokens as $index => $token) { - if (!$token->equalsAny(array( - array(T_CLASS, 'class'), - array(T_STRING, 'class'), - ), false)) { - continue; - } - - $prevIndex = $tokens->getPrevMeaningfulToken($index); - $prevToken = $tokens[$prevIndex]; - - if ($prevToken->isGivenKind(T_DOUBLE_COLON)) { - $token->override(array(CT_CLASS_CONSTANT, $token->getContent(), $token->getLine())); - } - } - } - - /** - * {@inheritdoc} - */ - public function getCustomTokenNames() - { - return array('CT_CLASS_CONSTANT'); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/CurlyClose.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/CurlyClose.php deleted file mode 100644 index d452c9e..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/CurlyClose.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tokenizer\Transformer; - -use Symfony\CS\Tokenizer\AbstractTransformer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Transform closing `}` for T_CURLY_OPEN into CT_CURLY_CLOSE. - * - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - */ -class CurlyClose extends AbstractTransformer -{ - /** - * {@inheritdoc} - */ - public function process(Tokens $tokens) - { - foreach ($tokens->findGivenKind(T_CURLY_OPEN) as $index => $token) { - $level = 1; - $nestIndex = $index; - - while (0 < $level) { - ++$nestIndex; - - // we count all kind of { - if ('{' === $tokens[$nestIndex]->getContent()) { - ++$level; - continue; - } - - // we count all kind of } - if ('}' === $tokens[$nestIndex]->getContent()) { - --$level; - } - } - - $tokens[$nestIndex]->override(array(CT_CURLY_CLOSE, '}', $tokens[$nestIndex]->getLine())); - } - } - - /** - * {@inheritdoc} - */ - public function getCustomTokenNames() - { - return array('CT_CURLY_CLOSE'); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DollarCloseCurlyBraces.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DollarCloseCurlyBraces.php deleted file mode 100644 index 06875f9..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DollarCloseCurlyBraces.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tokenizer\Transformer; - -use Symfony\CS\Tokenizer\AbstractTransformer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Transform closing `}` for T_DOLLAR_OPEN_CURLY_BRACES into CT_DOLLAR_CLOSE_CURLY_BRACES. - * - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - */ -class DollarCloseCurlyBraces extends AbstractTransformer -{ - /** - * {@inheritdoc} - */ - public function process(Tokens $tokens) - { - foreach ($tokens->findGivenKind(T_DOLLAR_OPEN_CURLY_BRACES) as $index => $token) { - $nextIndex = $tokens->getNextTokenOfKind($index, array('}')); - $tokens[$nextIndex]->override(array(CT_DOLLAR_CLOSE_CURLY_BRACES, '}', $tokens[$nextIndex]->getLine())); - } - } - - /** - * {@inheritdoc} - */ - public function getCustomTokenNames() - { - return array('CT_DOLLAR_CLOSE_CURLY_BRACES'); - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the CurlyClose - return -10; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DynamicPropBrace.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DynamicPropBrace.php deleted file mode 100644 index adfed2d..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DynamicPropBrace.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tokenizer\Transformer; - -use Symfony\CS\Tokenizer\AbstractTransformer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Transform curly braces in `$foo->{$bar}` into CT_DYNAMIC_PROP_BRACE_OPEN and CT_DYNAMIC_PROP_BRACE_CLOSE. - * - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - */ -class DynamicPropBrace extends AbstractTransformer -{ - /** - * {@inheritdoc} - */ - public function process(Tokens $tokens) - { - foreach ($tokens->findGivenKind(T_OBJECT_OPERATOR) as $index => $token) { - if (!$tokens[$index + 1]->equals('{')) { - continue; - } - - $openIndex = $index + 1; - $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $openIndex); - - $tokens[$openIndex]->override(array(CT_DYNAMIC_PROP_BRACE_OPEN, '{', $tokens[$openIndex]->getLine())); - $tokens[$closeIndex]->override(array(CT_DYNAMIC_PROP_BRACE_CLOSE, '}', $tokens[$closeIndex]->getLine())); - } - } - - /** - * {@inheritdoc} - */ - public function getCustomTokenNames() - { - return array('CT_DYNAMIC_PROP_BRACE_OPEN', 'CT_DYNAMIC_PROP_BRACE_CLOSE'); - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the CurlyClose - return -10; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DynamicVarBrace.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DynamicVarBrace.php deleted file mode 100644 index 3ddce6e..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformer/DynamicVarBrace.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tokenizer\Transformer; - -use Symfony\CS\Tokenizer\AbstractTransformer; -use Symfony\CS\Tokenizer\Tokens; - -/** - * Transform curly braces in `${$foo}` into CT_DYNAMIC_VAR_BRACE_OPEN and CT_DYNAMIC_VAR_BRACE_CLOSE. - * - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - */ -class DynamicVarBrace extends AbstractTransformer -{ - /** - * {@inheritdoc} - */ - public function process(Tokens $tokens) - { - foreach ($tokens as $index => $token) { - if (!$token->equals('$')) { - continue; - } - - $openIndex = $tokens->getNextMeaningfulToken($index); - - if (null === $openIndex) { - continue; - } - - $openToken = $tokens[$openIndex]; - - if (!$openToken->equals('{')) { - continue; - } - - $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $openIndex); - $closeToken = $tokens[$closeIndex]; - - $openToken->override(array(CT_DYNAMIC_VAR_BRACE_OPEN, '{', $openToken->getLine())); - $closeToken->override(array(CT_DYNAMIC_VAR_BRACE_CLOSE, '}', $closeToken->getLine())); - } - } - - /** - * {@inheritdoc} - */ - public function getCustomTokenNames() - { - return array('CT_DYNAMIC_VAR_BRACE_OPEN', 'CT_DYNAMIC_VAR_BRACE_CLOSE'); - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the CurlyClose - return -10; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformers.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformers.php deleted file mode 100644 index 733cf53..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/Transformers.php +++ /dev/null @@ -1,175 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS\Tokenizer; - -use Symfony\Component\Finder\Finder; -use Symfony\CS\Utils; - -/** - * Collection of Transformer classes. - * - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - */ -class Transformers -{ - /** - * The registered transformers. - * - * @var TransformerInterface[] - */ - private $items = array(); - - /** - * Array mapping custom token value => custom token name. - * - * @var array - */ - private $customTokens = array(); - - /** - * Constructor. Register built in Transformers. - */ - private function __construct() - { - $this->registerBuiltInTransformers(); - } - - /** - * Create Transformers instance. - * - * @return Transformers - */ - public static function create() - { - static $instance = null; - - if (!$instance) { - $instance = new self(); - } - - return $instance; - } - - /** - * Get name for registered custom token. - * - * @param int $value custom token value - * - * @return string - */ - public function getCustomToken($value) - { - if (!$this->hasCustomToken($value)) { - throw new \InvalidArgumentException(sprintf('No custom token was found for: %s', $value)); - } - - return $this->customTokens[$value]; - } - - public function getTransformers() - { - $this->sortTransformers(); - - return $this->items; - } - - /** - * Check if given custom token was added to collection. - * - * @param int $value custom token value - * - * @return bool - */ - public function hasCustomToken($value) - { - return isset($this->customTokens[$value]); - } - - /** - * Register Transformer. - * - * @param TransformerInterface $transformer Transformer - */ - public function registerTransformer(TransformerInterface $transformer) - { - $this->items[] = $transformer; - - $transformer->registerCustomTokens(); - - foreach ($transformer->getCustomTokenNames() as $name) { - $this->addCustomToken(constant($name), $name); - } - } - - /** - * Transform given Tokens collection through all Transformer classes. - * - * @param Tokens $tokens Tokens collection - */ - public function transform(Tokens $tokens) - { - foreach ($this->getTransformers() as $transformer) { - $transformer->process($tokens); - } - } - - /** - * Add custom token. - * - * @param int $value custom token value - * @param string $name custom token name - */ - private function addCustomToken($value, $name) - { - if ($this->hasCustomToken($value)) { - throw new \LogicException( - sprintf( - 'Trying to register token %s (%s), token with this value was already defined: %s', - $name, $value, $this->getCustomToken($value) - ) - ); - } - - $this->customTokens[$value] = $name; - } - - /** - * Register all built in Transformers. - */ - private function registerBuiltInTransformers() - { - static $registered = false; - - if ($registered) { - return; - } - - $registered = true; - - foreach (Finder::create()->files()->in(__DIR__.'/Transformer') as $file) { - $relativeNamespace = $file->getRelativePath(); - $class = __NAMESPACE__.'\\Transformer\\'.($relativeNamespace ? $relativeNamespace.'\\' : '').$file->getBasename('.php'); - $this->registerTransformer(new $class()); - } - } - - /** - * Sort registered Transformers. - */ - private function sortTransformers() - { - usort($this->items, function (TransformerInterface $a, TransformerInterface $b) { - return Utils::cmpInt($b->getPriority(), $a->getPriority()); - }); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ToolInfo.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ToolInfo.php deleted file mode 100644 index ebab4fd..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ToolInfo.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -/** - * Obtain information about using version of tool. - * - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - */ -class ToolInfo -{ - /** - * @deprecated - */ - const COMPOSER_INSTALLED_FILE = '/../../composer/installed.json'; - - const COMPOSER_PACKAGE_NAME = 'friendsofphp/php-cs-fixer'; - - /** - * @internal - */ - const COMPOSER_LEGACY_PACKAGE_NAME = 'fabpot/php-cs-fixer'; - - /** - * @internal - */ - public static function getComposerInstallationDetails() - { - static $result; - - if (!self::isInstalledByComposer()) { - throw new \LogicException('Cannot get composer version for tool not installed by composer.'); - } - - if (null === $result) { - $composerInstalled = json_decode(file_get_contents(self::getComposerInstalledFile()), true); - - foreach ($composerInstalled as $package) { - if (in_array($package['name'], array(self::COMPOSER_PACKAGE_NAME, self::COMPOSER_LEGACY_PACKAGE_NAME), true)) { - $result = $package; - break; - } - } - } - - return $result; - } - - public static function getComposerVersion() - { - static $result; - - if (null === $result) { - $package = self::getComposerInstallationDetails(); - $result = $package['version'].'#'.$package['dist']['reference']; - } - - return $result; - } - - public static function getVersion() - { - if (self::isInstalledByComposer()) { - return Fixer::VERSION.':'.self::getComposerVersion(); - } - - return Fixer::VERSION; - } - - public static function isInstalledAsPhar() - { - static $result; - - if (null === $result) { - $result = 'phar://' === substr(__DIR__, 0, 7); - } - - return $result; - } - - public static function isInstalledByComposer() - { - static $result; - - if (null === $result) { - $result = !self::isInstalledAsPhar() && file_exists(self::getComposerInstalledFile()); - } - - return $result; - } - - private static function getComposerInstalledFile() - { - return __DIR__.'/../../../../composer/installed.json'; - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/UniqueFileIterator.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/UniqueFileIterator.php deleted file mode 100644 index e7787c9..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/UniqueFileIterator.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -use Symfony\Component\Finder\SplFileInfo; - -/** - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * @internal - */ -final class UniqueFileIterator extends \FilterIterator -{ - private $visitedElements = array(); - - public function accept() - { - /** @var SplFileInfo $file */ - $file = $this->current(); - - $path = $file->getRealPath(); - - if (isset($this->visitedElements[$path])) { - return false; - } - - $this->visitedElements[$path] = true; - - return !$file->isDir() && !$file->isLink(); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Utils.php b/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Utils.php deleted file mode 100644 index acd3402..0000000 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Utils.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php - -/* - * This file is part of PHP CS Fixer. - * - * (c) Fabien Potencier <fabien@symfony.com> - * Dariusz Rumiński <dariusz.ruminski@gmail.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Symfony\CS; - -use Symfony\CS\Tokenizer\Token; - -/** - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - * @author Graham Campbell <graham@alt-three.com> - * @author Odín del Río <odin.drp@gmail.com> - */ -class Utils -{ - /** - * Calculate a bitmask for given constant names. - * - * @param string[] $options constant names - * - * @return int - */ - public static function calculateBitmask(array $options) - { - $bitmask = 0; - - foreach ($options as $optionName) { - if (defined($optionName)) { - $bitmask |= constant($optionName); - } - } - - return $bitmask; - } - - /** - * Converts a camel cased string to an snake cased string. - * - * @param string $string - * - * @return string - */ - public static function camelCaseToUnderscore($string) - { - return preg_replace_callback( - '/(^|[a-z0-9])([A-Z])/', - function (array $matches) { - return strtolower(strlen($matches[1]) ? $matches[1].'_'.$matches[2] : $matches[2]); - }, - $string - ); - } - - /** - * Compare two integers for equality. - * - * We'll return 0 if they're equal, 1 if the first is bigger than the - * second, and -1 if the second is bigger than the first. - * - * @param int $a - * @param int $b - * - * @return int - */ - public static function cmpInt($a, $b) - { - if ($a === $b) { - return 0; - } - - return $a < $b ? -1 : 1; - } - - /** - * Split a multi-line string up into an array of strings. - * - * We're retaining a newline character at the end of non-blank lines, and - * discarding other lines, so this function is unsuitable for anyone for - * wishing to retain the exact number of line endings. If a single-line - * string is passed, we'll just return an array with a element. - * - * @param string $content - * - * @return string[] - */ - public static function splitLines($content) - { - preg_match_all("/[^\n\r]+[\r\n]*/", $content, $matches); - - return $matches[0]; - } - - /** - * Calculate the trailing whitespace indentation. - * - * What we're doing here is grabbing everything after the final newline. - * - * @param Token $token - * - * @return string - */ - public static function calculateTrailingWhitespaceIndent(Token $token) - { - if (!$token->isWhitespace()) { - throw new \InvalidArgumentException(sprintf('The given token must be whitespace, got "%s".', $token->getName())); - } - - return ltrim(strrchr(str_replace(array("\r\n", "\r"), "\n", $token->getContent()), 10), "\n"); - } -} diff --git a/vendor/friendsofphp/php-cs-fixer/UPGRADE.md b/vendor/friendsofphp/php-cs-fixer/UPGRADE.md new file mode 100644 index 0000000..ca92285 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/UPGRADE.md @@ -0,0 +1,185 @@ +UPGRADE GUIDE FROM 1.x to 2.0 +============================= + +This is guide for upgrade from version 1.x to 2.0 for using the CLI tool. + +Rules and sets +-------------- +To configure which fixers should be used you must now set rules and sets instead of fixers and level. This affects both configuration file and CLI arguments. + +Default ruleset was changed from Symfony standard to more generic PSR2. You can still use Symfony standard, which in fact extends PSR2. + +The term of risky fixers was introduced. Risky fixer is a fixer that may change the meaning of code (like `StrictComparisonFixer` fixer, which will change `==` into `===`). No rules that are followed by risky fixers are run by default. You need to explicitly permit risky fixers to run them. + +Default configuration changes +----------------------------- +By default, PSR2 rules are used instead of Symfony rules. +Files that will be fixed are php/phpt/twig instead of php/twig/xml/yml. +Finally, the caching mechanism is enabled by default. + +CLI options +----------- + +| 1.x | 2.0 | Description | Note | +| --------------- | --------------- | ------------------------------------------------------------------------------ | ------------------------------- | +|     | --allow-risky | Are risky fixers allowed                                                 | | +| | --cache-file | The path to the cache file | option was added | +| --config | | Config class codename | option was removed | +| --config-file | --config | The path to a .php_cs file | option was renamed | +| --diff | --diff | Show diff | | +| --dry-run | --dry-run | Run in dry-run mode | | +| --fixers | | Coding standard fixers | option was removed, see --rules | +| --format | --format | Choose format | | +| --level | | Coding standard level | option was removed, see --rules | +| | --path-mode | Should the finder from config be<br/>overridden or intersected with `path` arg | option was added | +| | --rules | Rules to be used | option was added | +| | --using-cache | Does cache should be used | option was added | + + +CLI argument +------------ + +On 2.x line `path` argument is an array, so you may pass multiple paths. + +Intersection path mode makes the `path` argument a mask for finder you have defined in your configuration file. +Only files pointed by both finder and CLI `path` argument will be fixed. + +Exit codes +---------- + +Exit codes for `fix` command have been changed and are build using the following bit flags: + +| 1.x bit | 2.0 bit | Description | Note | +| -------:| -------:| ----------------------------------------------------------- | ---------------------------------------------------------------- | +| 0 | 0 | OK | | +| 1 | 1 | General error (or PHP/HHVM minimal requirement not matched) | no longer used for other states, never combined with other flags | +| | 4 | Some files have invalid syntax | flag was added, works only in dry-run mode | +| | 8 | Some files need fixing | flag was added, works only in dry-run mode | +| 16 | 16 | Configuration error of the application | | +| 32 | 32 | Configuration error of a Fixer | | +| | 64 | Exception within the application | flag was added | + +Namespace +--------- +`Symfony\CS` namespace was renamed into `PhpCsFixer`. + +Config file +----------- +From now you can create new configuration file: `.php_cs.dist`. This file is used if no `.php_cs` file was found. It is recommended to create `.php_cs.dist` file attached in your repository and add `.php_cs` file to `.gitignore` for allowing your contributors to have theirs own configuration file. + +Config and Finder classes +------------------------- +All off `Symfony\CS\Config\*` and `Symfony\CS\Finder\*` classes have been removed, instead use `PhpCsFixer\Config` and `PhpCsFixer\Finder`. + +For that reason you can not set config class by `--config` CLI argument, from now it is used to set configuration file. Therefor the `--config-file` CLI argument is no longer available. + +Renamed rules +------------- + +Old name | New name | Note +-------- | -------- | ---- +align_double_arrow | binary_operator_spaces | use configuration ['align_double_arrow' => true] +align_equals | binary_operator_spaces | use configuration ['align_equals' => true] +array_element_no_space_before_comma | no_whitespace_before_comma_in_array +array_element_white_space_after_comma | whitespace_after_comma_in_array +blankline_after_open_tag | blank_line_after_opening_tag +concat_with_spaces | concat_space | use configuration ['spacing' => 'one'] +concat_without_spaces | concat_space | use configuration ['spacing' => 'none'] +double_arrow_multiline_whitespaces | no_multiline_whitespace_around_double_arrow +duplicate_semicolon | no_empty_statement | new one fixes more cases +empty_return | simplified_null_return +echo_to_print | no_mixed_echo_print | use configuration ['use' => 'print'] +eof_ending | single_blank_line_at_eof +extra_empty_lines | no_extra_consecutive_blank_lines +function_call_space | no_spaces_after_function_name +general_phpdoc_annotation_rename | phpdoc_no_alias_tag | use configuration ['property-read' => 'property', 'property-write' => 'property'] +indentation | indentation_type +join_function | no_alias_functions | new one fixes more aliases +line_after_namespace | blank_line_after_namespace +linefeed | line_ending | whitespaces type aware +list_commas | no_trailing_comma_in_list_call +logical_not_operators_with_spaces | not_operator_with_space +logical_not_operators_with_successor_space | not_operator_with_successor_space +long_array_syntax | array_syntax | use configuration ['syntax' => 'long'] +method_argument_default_value | no_unreachable_default_argument_value +multiline_array_trailing_comma | trailing_comma_in_multiline_array +multiline_spaces_before_semicolon | no_multiline_whitespace_before_semicolons +multiple_use | single_import_per_statement +namespace_no_leading_whitespace | no_leading_namespace_whitespace +newline_after_open_tag | linebreak_after_opening_tag +no_empty_lines_after_phpdocs | no_blank_lines_after_phpdoc +no_short_echo_tag | echo_tag_syntax +object_operator | object_operator_without_whitespace +operators_spaces | binary_operator_spaces +ordered_use | ordered_imports +parenthesis | no_spaces_inside_parenthesis +php4_constructor | no_php4_constructor +php_closing_tag | no_closing_tag +phpdoc_params | phpdoc_align +phpdoc_property | phpdoc_no_alias_tag | use configuration ['type' => 'var'] +phpdoc_short_description | phpdoc_summary +phpdoc_type_to_var | phpdoc_no_alias_tag | use configuration ['type' => 'var'] +phpdoc_var_to_type | phpdoc_no_alias_tag | use configuration ['var' => 'type'] +print_to_echo | no_mixed_echo_print | use configuration ['use' => 'echo'] +remove_leading_slash_use | no_leading_import_slash +remove_lines_between_uses | no_extra_consecutive_blank_lines | use configuration ['use'] +return | blank_line_before_return +short_array_syntax | array_syntax | use configuration ['syntax' => 'short'] +short_bool_cast | no_short_bool_cast +short_echo_tag | no_short_echo_tag +short_tag | full_opening_tag +single_array_no_trailing_comma | no_trailing_comma_in_singleline_array +spaces_after_semicolon | space_after_semicolon +spaces_before_semicolon | no_singleline_whitespace_before_semicolons +spaces_cast | cast_spaces +standardize_not_equal | standardize_not_equals +strict | strict_comparison +ternary_spaces | ternary_operator_spaces +trailing_spaces | no_trailing_whitespace +unalign_double_arrow | binary_operator_spaces | use configuration ['align_double_arrow' => false] +unalign_equals | binary_operator_spaces | use configuration ['align_equals' => false] +unary_operators_spaces | unary_operator_spaces +unneeded_control_parentheses | no_unneeded_control_parentheses +unused_use | no_unused_imports +visibility | visibility_required +whitespacy_lines | no_whitespace_in_blank_line + +Changes to Fixers +----------------- + +Fixer | Note +----- | ---- +psr0 | Fixer no longer takes base dir from `ConfigInterface::getDir`, instead you may configure the fixer with `['dir' => 'my/path']`. + +Custom fixers +------------- + +If you have registered custom fixers in your config file `*.php_cs` using `addCustomFixer()` method... +``` +<?php +// phpcs-fixer v1.* +$config = Symfony\CS\Config\Config::create() + ->fixers([ + 'blankline_after_open_tag', + // ... + ]) + ->addCustomFixer(new ShopSys\CodingStandards\CsFixer\MissingButtonTypeFixer()) + ->addCustomFixer(new ShopSys\CodingStandards\CsFixer\OrmJoinColumnRequireNullableFixer()); +``` +...now you have to use `registerCustomFixers()` method instead and enable the custom fixers by their names in the `setRules()` method: +``` +<?php +// phpcs-fixer v2.* +$config = (new PhpCsFixer\Config()) + ->registerCustomFixers([ + new ShopSys\CodingStandards\CsFixer\MissingButtonTypeFixer(), + new ShopSys\CodingStandards\CsFixer\OrmJoinColumnRequireNullableFixer(), + ]) + ->setRules([ + 'blankline_after_open_tag', + 'Shopsys/missing_button_type' => true, + 'Shopsys/orm_join_column_require_nullable' => true, + // ... + ]); + +``` diff --git a/vendor/friendsofphp/php-cs-fixer/benchmark.sh b/vendor/friendsofphp/php-cs-fixer/benchmark.sh deleted file mode 100644 index 9b59281..0000000 --- a/vendor/friendsofphp/php-cs-fixer/benchmark.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -command -v php >/dev/null 2>&1 || { echo "I require `php` but it's not available. Aborting." >&2; exit 255; } -command -v grep >/dev/null 2>&1 || { echo "I require `grep` but it's not available. Aborting." >&2; exit 255; } -command -v awk >/dev/null 2>&1 || { echo "I require `awk` but it's not available. Aborting." >&2; exit 255; } - -if [ "" == "$1" ] || [ "" == "$2" ]; -then - echo "Usage: bash benchmark.sh BRANCH1 BRANCH2 ...BRANCHN" - exit 1; -fi - -for BRANCH in $@ -do - git checkout $BRANCH &> /dev/null && - git reset --hard &> /dev/null && - echo -n $BRANCH - (for i in {1..10}; do php php-cs-fixer fix . ; done) | grep -i fixed | awk ' - { - total += $5; - ++count; - } - END { - print " mean:" (total/count) " total:" total " rounds:" count - }' -done diff --git a/vendor/friendsofphp/php-cs-fixer/box.json b/vendor/friendsofphp/php-cs-fixer/box.json deleted file mode 100644 index 679f428..0000000 --- a/vendor/friendsofphp/php-cs-fixer/box.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "output": "php-cs-fixer.phar", - "chmod": "0755", - "compactors": [ - "Herrera\\Box\\Compactor\\Php" - ], - "extract": false, - "files": [ - "LICENSE" - ], - "finder": [ - { - "name": ["*.php"], - "exclude": ["Tests", "tests"], - "in": ["vendor", "Symfony"] - } - ], - "git-commit": "git-commit", - "stub": "Symfony/CS/Resources/phar-stub.php", - "web": false -} diff --git a/vendor/friendsofphp/php-cs-fixer/ci-integration.sh b/vendor/friendsofphp/php-cs-fixer/ci-integration.sh new file mode 100644 index 0000000..2521e24 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/ci-integration.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -eu + +IFS=' +' +CHANGED_FILES=$(git diff --name-only --diff-filter=ACMRTUXB "${COMMIT_RANGE}") +if ! echo "${CHANGED_FILES}" | grep -qE "^(\\.php-cs-fixer(\\.dist)?\\.php|composer\\.lock)$"; then EXTRA_ARGS=$(printf -- '--path-mode=intersection\n--\n%s' "${CHANGED_FILES}"); else EXTRA_ARGS=''; fi +vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --dry-run --stop-on-violation --using-cache=no ${EXTRA_ARGS} diff --git a/vendor/friendsofphp/php-cs-fixer/composer.json b/vendor/friendsofphp/php-cs-fixer/composer.json index 24a8660..b53d2b4 100644 --- a/vendor/friendsofphp/php-cs-fixer/composer.json +++ b/vendor/friendsofphp/php-cs-fixer/composer.json @@ -14,25 +14,78 @@ } ], "require": { - "php": "^5.3.6 || >=7.0 <7.2", + "php": "^5.6 || ^7.0 || ^8.0", + "ext-json": "*", "ext-tokenizer": "*", - "symfony/console": "^2.3 || ^3.0", - "symfony/event-dispatcher": "^2.1 || ^3.0", - "symfony/filesystem": "^2.1 || ^3.0", - "symfony/finder": "^2.1 || ^3.0", - "symfony/process": "^2.3 || ^3.0", - "symfony/stopwatch": "^2.5 || ^3.0", - "sebastian/diff": "^1.1" + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^1.2 || ^2.0", + "doctrine/annotations": "^1.2", + "php-cs-fixer/diff": "^1.3", + "symfony/console": "^3.4.43 || ^4.1.6 || ^5.0", + "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", + "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^3.0 || ^4.0 || ^5.0", + "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^3.0 || ^4.0 || ^5.0", + "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" }, "require-dev": { - "phpunit/phpunit": "^4.5|^5", - "satooshi/php-coveralls": "^1.0" + "justinrainbow/json-schema": "^5.0", + "keradus/cli-executor": "^1.4", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.4.2", + "php-cs-fixer/accessible-object": "^1.0", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", + "phpspec/prophecy-phpunit": "^1.1 || ^2.0", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.13 || ^9.5", + "phpunitgoodpractices/polyfill": "^1.5", + "phpunitgoodpractices/traits": "^1.9.1", + "sanmai/phpunit-legacy-adapter": "^6.4 || ^8.2.1", + "symfony/phpunit-bridge": "^5.2.1", + "symfony/yaml": "^3.0 || ^4.0 || ^5.0" }, - "conflict": { - "hhvm": "<3.9" + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters.", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "config": { + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-master": "2.19-dev" + } }, "autoload": { - "psr-4": { "Symfony\\CS\\": "Symfony/CS/" } + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "classmap": [ + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationCaseFactory.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/Assert/AssertTokensTrait.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php", + "tests/Test/IntegrationCaseFactoryInterface.php", + "tests/Test/InternalIntegrationCaseFactory.php", + "tests/Test/IsIdenticalConstraint.php", + "tests/Test/TokensWithObservedTransformers.php", + "tests/TestCase.php" + ] + }, + "autoload-dev": { + "psr-4": { + "PhpCsFixer\\Tests\\": "tests/" + } }, - "bin": ["php-cs-fixer"] + "bin": [ + "php-cs-fixer" + ] } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/config.rst b/vendor/friendsofphp/php-cs-fixer/doc/config.rst new file mode 100644 index 0000000..a5302d6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/config.rst @@ -0,0 +1,73 @@ +=========== +Config file +=========== + +Instead of using command line options to customize rules and rule sets, you can save the +project configuration in a ``.php-cs-fixer.dist.php`` file in the root directory of your project. +The file must return an instance of `PhpCsFixer\\ConfigInterface <../src/ConfigInterface.php>`_ +which lets you configure the rules, the files and directories that +need to be analyzed. You may also create ``.php-cs-fixer.php`` file, which is +the local configuration that will be used instead of the project configuration. It +is a good practice to add that file into your ``.gitignore`` file. +With the ``--config`` option you can specify the path to the +``.php-cs-fixer.php`` file. + +The example below will add two rules to the default list of PSR2 set rules: + +.. code-block:: php + + <?php + + $finder = PhpCsFixer\Finder::create() + ->exclude('somedir') + ->notPath('src/Symfony/Component/Translation/Tests/fixtures/resources.php') + ->in(__DIR__) + ; + + $config = new PhpCsFixer\Config(); + return $config->setRules([ + '@PSR2' => true, + 'strict_param' => true, + 'array_syntax' => ['syntax' => 'short'], + ]) + ->setFinder($finder) + ; + +**NOTE**: ``exclude`` will work only for directories, so if you need to exclude file, try ``notPath``. +Both ``exclude`` and ``notPath`` methods accept only relative paths to the ones defined with the ``in`` method. + +See `Symfony\\Finder <https://symfony.com/doc/current/components/finder.html>`_ +online documentation for other `Finder` methods. + +You may also use an exclude list for the rules instead of the above shown include approach. +The following example shows how to use all ``Symfony`` rules but the ``full_opening_tag`` rule. + +.. code-block:: php + + <?php + + $finder = PhpCsFixer\Finder::create() + ->in(__DIR__) + ->exclude('somedir') + ; + + $config = new PhpCsFixer\Config(); + return $config->setRules([ + '@Symfony' => true, + 'full_opening_tag' => false, + ]) + ->setFinder($finder) + ; + +You may want to use non-linux whitespaces in your project. Then you need to +configure them in your config file. + +.. code-block:: php + + <?php + + $config = new PhpCsFixer\Config(); + return $config + ->setIndent("\t") + ->setLineEnding("\r\n") + ; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/cookbook_fixers.rst b/vendor/friendsofphp/php-cs-fixer/doc/cookbook_fixers.rst new file mode 100644 index 0000000..5cb0314 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/cookbook_fixers.rst @@ -0,0 +1,563 @@ +============================================== +Cookbook - Making a new Fixer for PHP CS Fixer +============================================== + +You want to make a new fixer to PHP CS Fixer and do not know how to +start. Follow this document and you will be able to do it. + +Background +---------- + +In order to be able to create a new fixer, you need some background. +PHP CS Fixer is a transcompiler which takes valid PHP code and pretty +print valid PHP code. It does all transformations in multiple passes, +a.k.a., multi-pass compiler. + +Therefore, a new fixer is meant to be ideally idempotent_, or at least atomic +in its actions. More on this later. + +All contributions go through a code review process. Do not feel +discouraged - it is meant only to give more people more chance to +contribute, and to detect bugs (`Linus's Law`_). + +If possible, try to get acquainted with the public interface for the +`Tokens class`_ and `Token class`_ classes. + +Assumptions +----------- + +* You are familiar with Test Driven Development. +* Forked FriendsOfPHP/PHP-CS-Fixer into your own GitHub Account. +* Cloned your forked repository locally. +* Installed the dependencies of PHP CS Fixer using Composer_. +* You have read `CONTRIBUTING.md`_. + +Step by step +------------ + +For this step-by-step, we are going to create a simple fixer that +removes all comments from the code that are preceded by ';' (semicolon). + +We are calling it ``remove_comments`` (code name), or, +``RemoveCommentsFixer`` (class name). + +Step 1 - Creating files +_______________________ + +Create a new file in ``src/Fixer/Comment/RemoveCommentsFixer.php``. +Put this content inside: + +.. code-block:: php + + <?php + + /* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + + namespace PhpCsFixer\Fixer\Comment; + + use PhpCsFixer\AbstractFixer; + use PhpCsFixer\Tokenizer\Tokens; + + /** + * @author Your name <your@email.com> + */ + final class RemoveCommentsFixer extends AbstractFixer + { + /** + * {@inheritdoc} + */ + public function getDefinition() + { + // Return a definition of the fixer, it will be used in the documentation. + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + // Check whether the collection is a candidate for fixing. + // Has to be ultra cheap to execute. + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // Add the fixing logic of the fixer here. + } + } + +Note how the class and file name match. Also keep in mind that all +fixers must implement ``Fixer\FixerInterface``. In this case, the fixer is +inheriting from ``AbstractFixer``, which fulfills the interface with some +default behavior. + +Now let us create the test file at +``tests/Fixer/Comment/RemoveCommentsFixerTest.php``. Put this content inside: + +.. code-block:: php + + <?php + + /* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + + namespace PhpCsFixer\Tests\Fixer\Comment; + + use PhpCsFixer\Tests\Test\AbstractFixerTestCase; + + /** + * @author Your name <your@email.com> + * + * @internal + * + * @covers \PhpCsFixer\Fixer\Comment\RemoveCommentsFixer + */ + final class RemoveCommentsFixerTest extends AbstractFixerTestCase + { + /** + * @param string $expected + * @param null|string $input + * + * @dataProvider provideFixCases + */ + public function testFix($expected, $input = null) + { + $this->doTest($expected, $input); + } + + public function provideFixCases() + { + return []; + } + } + +Step 2 - Using tests to define fixers behavior +______________________________________________ + +Now that the files are created, you can start writing tests to define the +behavior of the fixer. You have to do it in two ways: first, ensuring +the fixer changes what it should be changing; second, ensuring that +fixer does not change what is not supposed to change. Thus: + +Keeping things as they are: + +.. code-block:: php + + // tests/Fixer/Comment/RemoveCommentsFixerTest.php + + // ... + public function provideFixCases() + { + return [ + ['<?php echo "This should not be changed";'], // Each sub-array is a test + ]; + } + // ... + +Ensuring things change: + +.. code-block:: php + + // tests/Fixer/Comment/RemoveCommentsFixerTest.php + + // ... + public function provideFixCases() + { + return [ + [ + '<?php echo "This should be changed"; ', // This is expected output + '<?php echo "This should be changed"; /* Comment */', // This is input + ], + ]; + } + // ... + +Note that expected outputs are **always** tested alone to ensure your fixer will not change it. + +We want to have a failing test to start with, so the test file now looks +like: + +.. code-block:: php + + <?php + // tests/Fixer/Comment/RemoveCommentsFixerTest.php + + /* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + + namespace PhpCsFixer\Tests\Fixer\Comment; + + use PhpCsFixer\Tests\Fixer\AbstractFixerTestBase; + + /** + * @author Your name <your@email.com> + * + * @internal + */ + final class RemoveCommentsFixerTest extends AbstractFixerTestBase + { + /** + * @param string $expected + * @param null|string $input + * + * @dataProvider provideFixCases + */ + public function testFix($expected, $input = null) + { + $this->doTest($expected, $input); + } + + public function provideFixCases() + { + return [ + [ + '<?php echo "This should be changed"; ', // This is expected output + '<?php echo "This should be changed"; /* Comment */', // This is input + ], + ]; + } + } + +Step 3 - Implement your solution +________________________________ + +You have defined the behavior of your fixer in tests. Now it is time to +implement it. + +First, we need to create one method to describe what this fixer does: + +.. code-block:: php + + // src/Fixer/Comment/RemoveCommentsFixer.php + + final class RemoveCommentsFixer extends AbstractFixer + { + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Removes all comments of the code that are preceded by ";" (semicolon).', // Trailing dot is important. We thrive to use English grammar properly. + [ + new CodeSample( + '<?php echo 123; /* Comment */' + ), + ] + ); + } + } + +Next, we need to update the documentation. +Fortunately, PHP CS Fixer can help you here. +Execute the following command in your command shell: + +.. code-block:: console + + $ php dev-tools/doc.php + +Next, we must filter what type of tokens we want to fix. Here, we are interested in code that contains ``T_COMMENT`` tokens: + +.. code-block:: php + + // src/Fixer/Comment/RemoveCommentsFixer.php + + final class RemoveCommentsFixer extends AbstractFixer + { + // ... + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_COMMENT); + } + } + +For now, let us just make a fixer that applies no modification: + +.. code-block:: php + + // src/Fixer/Comment/RemoveCommentsFixer.php + + class RemoveCommentsFixer extends AbstractFixer + { + // ... + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // no action + } + } + +Run ``$ phpunit tests/Fixer/Comment/RemoveCommentsFixerTest.php``. +You are going to see that the tests fail. + +Break +_____ + +Now we have pretty much a cradle to work with. A file with a failing +test, and the fixer, that for now does not do anything. + +How do fixers work? In the PHP CS Fixer, they work by iterating through +pieces of codes (each being a Token), and inspecting what exists before +and after that bit and making a decision, usually: + +* Adding code. +* Modifying code. +* Deleting code. +* Ignoring code. + +In our case, we want to find all comments, and foreach (pun intended) +one of them check if they are preceded by a semicolon symbol. + +Now you need to do some reading, because all these symbols obey a list +defined by the PHP compiler. It is the `List of Parser Tokens`_. + +Internally, PHP CS Fixer transforms some of PHP native tokens into custom +tokens through the use of Transformers_, they aim to help you reason about the +changes you may want to do in the fixers. + +So we can get to move forward, humor me in believing that comments have +one symbol name: ``T_COMMENT``. + +Step 3 - Implement your solution - continuation. +________________________________________________ + +We do not want all symbols to be analysed. Only ``T_COMMENT``. So let us +iterate the token(s) we are interested in. + +.. code-block:: php + + // src/Fixer/Comment/RemoveCommentsFixer.php + + final class RemoveCommentsFixer extends AbstractFixer + { + // ... + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_COMMENT)) { + continue; + } + + // need to figure out what to do here! + } + } + } + +OK, now for each ``T_COMMENT``, all we need to do is check if the previous +token is a semicolon. + +.. code-block:: php + + // src/Fixer/Comment/RemoveCommentsFixer.php + + final class RemoveCommentsFixer extends AbstractFixer + { + // ... + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_COMMENT)) { + continue; + } + + $prevTokenIndex = $tokens->getPrevMeaningfulToken($index); + $prevToken = $tokens[$prevTokenIndex]; + + if ($prevToken->equals(';')) { + $tokens->clearAt($index); + } + } + } + } + +So the fixer in the end looks like this: + +.. code-block:: php + + <?php + + /* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + + namespace PhpCsFixer\Fixer\Comment; + + use PhpCsFixer\AbstractFixer; + use PhpCsFixer\Tokenizer\Tokens; + + /** + * @author Your name <your@email.com> + */ + final class RemoveCommentsFixer extends AbstractFixer + { + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Removes all comments of the code that are preceded by ";" (semicolon).', // Trailing dot is important. We thrive to use English grammar properly. + [ + new CodeSample( + '<?php echo 123; /* Comment */' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) { + foreach($tokens as $index => $token){ + if (!$token->isGivenKind(T_COMMENT)) { + continue; + } + + $prevTokenIndex = $tokens->getPrevMeaningfulToken($index); + $prevToken = $tokens[$prevTokenIndex]; + + if ($prevToken->equals(';')) { + $tokens->clearAt($index); + } + } + } + } + +Step 4 - Format, Commit, PR. +____________________________ + +Note that so far, we have not coded adhering to PSR-1/2. This is done on +purpose. For every commit you make, you must use PHP CS Fixer to fix +itself. Thus, on the command line call: + +.. code-block:: console + + $ php php-cs-fixer fix + +This will fix all the coding style mistakes. + +After the final CS fix, you are ready to commit. Do it. + +Now, go to GitHub and open a Pull Request. + +Step 5 - Peer review: it is all about code and community building. +__________________________________________________________________ + +Congratulations, you have made your first fixer. Be proud. Your work +will be reviewed carefully by PHP CS Fixer community. + +The review usually flows like this: + +1. People will check your code for common mistakes and logical + caveats. Usually, the person building a fixer is blind about some + behavior mistakes of fixers. Expect to write few more tests to cater for + the reviews. +2. People will discuss the relevance of your fixer. If it is + something that goes along with Symfony style standards, or PSR-1/PSR-2 + standards, they will ask you to add it to existing ruleset. +3. People will also discuss whether your fixer is idempotent or not. + If they understand that your fixer must always run before or after a + certain fixer, they will ask you to override a method named + ``getPriority()``. Do not be afraid of asking the reviewer for help on how + to do it. +4. People may ask you to rebase your code to unify commits or to get + rid of merge commits. +5. Go to 1 until no actions are needed anymore. + +Your fixer will be incorporated in the next release. + +Congratulations! You have done it. + +Q&A +--- + +Why is not my PR merged yet? + PHP CS Fixer is used by many people, that expect it to be stable. So + sometimes, few PR are delayed a bit so to avoid cluttering at @dev + channel on composer. + + Other possibility is that reviewers are giving time to other members of + PHP CS Fixer community to partake on the review debates of your fixer. + + In any case, we care a lot about what you do and we want to see it being + part of the application as soon as possible. + +Why am I asked to use ``getPrevMeaningfulToken()`` instead of ``getPrevNonWhitespace()``? + The main difference is that ``getPrevNonWhitespace()`` ignores only + whitespaces (``T_WHITESPACE``), while ``getPrevMeaningfulToken()`` ignores + whitespaces and comments. And usually that is what you want. For + example: + + .. code-block:: php + + $a->/*comment*/func(); + + If you are inspecting ``func()``, and you want to check whether this is + part of an object, if you use ``getPrevNonWhitespace()`` you are going to + get ``/*comment*/``, which might belie your test. On the other hand, if + you use ``getPrevMeaningfulToken()``, no matter if you have got a comment + or a whitespace, the returned token will always be ``->``. + +.. _Composer: https://getcomposer.org +.. _CONTRIBUTING.md: ../CONTRIBUTING.md +.. _idempotent: https://en.wikipedia.org/wiki/Idempotence#Computer_science_meaning +.. _Linus's Law: https://en.wikipedia.org/wiki/Linus%27s_Law +.. _List of Parser Tokens: https://php.net/manual/en/tokens.php +.. _Token class: ../src/Tokenizer/Token.php +.. _Tokens class: ../src/Tokenizer/Tokens.php +.. _Transformers: ../src/Tokenizer/Transformer diff --git a/vendor/friendsofphp/php-cs-fixer/doc/custom_rules.rst b/vendor/friendsofphp/php-cs-fixer/doc/custom_rules.rst new file mode 100644 index 0000000..76ec6d1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/custom_rules.rst @@ -0,0 +1,38 @@ +===================== +Creating custom rules +===================== + +If you need to enforce some specific code style rules, you can implement your +own fixers. + +For each rule you want to add, create a class that implements +`PhpCsFixer\\Fixer\\FixerInterface <../src/Fixer/FixerInterface.php>`_. +Note that there is a specific constraint +regarding custom rules names: they must match the pattern +``/^[A-Z][a-zA-Z0-9]*\/[a-z][a-z0-9_]*$/``. + +Then register your custom fixers and enable them in the config file: + +.. code-block:: php + + <?php + // ... + return (new PhpCsFixer\Config()) + // ... + ->registerCustomFixers([ + new CustomerFixer1(), + new CustomerFixer2(), + ]) + ->setRules([ + // ... + 'YourVendorName/custome_rule' => true, + 'YourVendorName/custome_rule_2' => true, + ]) + ; + +There are several interfaces that your fixers can also implement if needed: + +* `PhpCsFixer\\Fixer\\DefinedFixerInterface <../src/Fixer/DefinedFixerInterface.php>`_: allows to describe what the fixer does in details; +* `PhpCsFixer\\Fixer\\WhitespacesAwareFixerInterface <../src/Fixer/WhitespacesAwareFixerInterface.php>`_: for fixers that need to know the configured indentation and line endings; +* `PhpCsFixer\\Fixer\\ConfigurableFixerInterface <../src/Fixer/ConfigurableFixerInterface.php>`_: to create a configurable fixer; +* `PhpCsFixer\\Fixer\\DeprecatedFixerInterface <../src/Fixer/DeprecatedFixerInterface.php>`_: to deprecate a fixer. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/installation.rst b/vendor/friendsofphp/php-cs-fixer/doc/installation.rst new file mode 100644 index 0000000..0901fb0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/installation.rst @@ -0,0 +1,126 @@ +============ +Installation +============ + +Requirements +------------ + +PHP needs to be a minimum version of PHP 5.6.0. + +Installation +------------ + +Locally +~~~~~~~ + +Download the `php-cs-fixer.phar`_ file and store it somewhere on your computer. + +Globally (manual) +~~~~~~~~~~~~~~~~~ + +You can run these commands to easily access latest ``php-cs-fixer`` from anywhere on +your system: + +.. code-block:: console + + $ wget https://cs.symfony.com/download/php-cs-fixer-v2.phar -O php-cs-fixer + +or with specified version: + +.. code-block:: console + + $ wget https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v2.15.8/php-cs-fixer.phar -O php-cs-fixer + +or with curl: + +.. code-block:: console + + $ curl -L https://cs.symfony.com/download/php-cs-fixer-v2.phar -o php-cs-fixer + +then: + +.. code-block:: console + + $ sudo chmod a+x php-cs-fixer + $ sudo mv php-cs-fixer /usr/local/bin/php-cs-fixer + +Then, just run ``php-cs-fixer``. + +Globally (Composer) +~~~~~~~~~~~~~~~~~~~ + +To install PHP CS Fixer, `install Composer <https://getcomposer.org/download/>`_ and issue the following command: + +.. code-block:: console + + $ composer global require friendsofphp/php-cs-fixer + +Then make sure you have the global Composer binaries directory in your ``PATH``. This directory is platform-dependent, see `Composer documentation <https://getcomposer.org/doc/03-cli.md#composer-home>`_ for details. Example for some Unix systems: + +.. code-block:: console + + $ export PATH="$PATH:$HOME/.composer/vendor/bin" + +Globally (homebrew) +~~~~~~~~~~~~~~~~~~~ + +.. code-block:: console + + $ brew install php-cs-fixer + +Locally (PHIVE) +~~~~~~~~~~~~~~~ + +Install `PHIVE <https://phar.io>`_ and issue the following command: + +.. code-block:: console + + $ phive install php-cs-fixer # use `--global` for global install + +Update +------ + +Locally +~~~~~~~ + +The ``self-update`` command tries to update ``php-cs-fixer`` itself: + +.. code-block:: console + + $ php php-cs-fixer.phar self-update + +Globally (manual) +~~~~~~~~~~~~~~~~~ + +You can update ``php-cs-fixer`` through this command: + +.. code-block:: console + + $ sudo php-cs-fixer self-update + +Globally (Composer) +~~~~~~~~~~~~~~~~~~~ + +You can update ``php-cs-fixer`` through this command: + +.. code-block:: console + + $ ./composer.phar global update friendsofphp/php-cs-fixer + +Globally (homebrew) +~~~~~~~~~~~~~~~~~~~ + +You can update ``php-cs-fixer`` through this command: + +.. code-block:: console + + $ brew upgrade php-cs-fixer + +Locally (PHIVE) +~~~~~~~~~~~~~~~ + +.. code-block:: console + + $ phive update php-cs-fixer + +.. _php-cs-fixer.phar: https://cs.symfony.com/download/php-cs-fixer-v2.phar diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/DoctrineAnnotation.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/DoctrineAnnotation.rst new file mode 100644 index 0000000..50de7d6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/DoctrineAnnotation.rst @@ -0,0 +1,17 @@ +================================ +Rule set ``@DoctrineAnnotation`` +================================ + +Rules covering Doctrine annotations with configuration based on examples found in `Doctrine Annotation documentation <http://docs.doctrine-project.org/projects/doctrine-common/en/latest/reference/annotations.html>`_ and `Symfony documentation <http://symfony.com/doc/master/bundles/SensioFrameworkExtraBundle/annotations/routing.html>`_. + +Rules +----- + +- `doctrine_annotation_array_assignment <./../rules/doctrine_annotation/doctrine_annotation_array_assignment.rst>`_ + config: + ``['operator' => ':']`` +- `doctrine_annotation_braces <./../rules/doctrine_annotation/doctrine_annotation_braces.rst>`_ +- `doctrine_annotation_indentation <./../rules/doctrine_annotation/doctrine_annotation_indentation.rst>`_ +- `doctrine_annotation_spaces <./../rules/doctrine_annotation/doctrine_annotation_spaces.rst>`_ + config: + ``['before_array_assignments_colon' => false]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP54Migration.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP54Migration.rst new file mode 100644 index 0000000..39757f6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP54Migration.rst @@ -0,0 +1,12 @@ +============================ +Rule set ``@PHP54Migration`` +============================ + +Rules to improve code for PHP 5.4 compatibility. + +Rules +----- + +- `array_syntax <./../rules/array_notation/array_syntax.rst>`_ + config: + ``['syntax' => 'short']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP56Migration.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP56Migration.rst new file mode 100644 index 0000000..81f66f1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP56Migration.rst @@ -0,0 +1,10 @@ +============================ +Rule set ``@PHP56Migration`` +============================ + +Rules to improve code for PHP 5.6 compatibility. + +Rules +----- + +- `@PHP54Migration <./PHP54Migration.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP56MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP56MigrationRisky.rst new file mode 100644 index 0000000..51b6fba --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP56MigrationRisky.rst @@ -0,0 +1,10 @@ +================================== +Rule set ``@PHP56Migration:risky`` +================================== + +Rules to improve code for PHP 5.6 compatibility. This set contains rules that are risky. + +Rules +----- + +- `pow_to_exponentiation <./../rules/alias/pow_to_exponentiation.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP70Migration.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP70Migration.rst new file mode 100644 index 0000000..5f2e6ff --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP70Migration.rst @@ -0,0 +1,11 @@ +============================ +Rule set ``@PHP70Migration`` +============================ + +Rules to improve code for PHP 7.0 compatibility. + +Rules +----- + +- `@PHP56Migration <./PHP56Migration.rst>`_ +- `ternary_to_null_coalescing <./../rules/operator/ternary_to_null_coalescing.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP70MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP70MigrationRisky.rst new file mode 100644 index 0000000..6cb72b2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP70MigrationRisky.rst @@ -0,0 +1,18 @@ +================================== +Rule set ``@PHP70Migration:risky`` +================================== + +Rules to improve code for PHP 7.0 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHP56Migration:risky <./PHP56MigrationRisky.rst>`_ +- `combine_nested_dirname <./../rules/function_notation/combine_nested_dirname.rst>`_ +- `declare_strict_types <./../rules/strict/declare_strict_types.rst>`_ +- `non_printable_character <./../rules/basic/non_printable_character.rst>`_ + config: + ``['use_escape_sequences_in_strings' => true]`` +- `random_api_migration <./../rules/alias/random_api_migration.rst>`_ + config: + ``['replacements' => ['mt_rand' => 'random_int', 'rand' => 'random_int']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP71Migration.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP71Migration.rst new file mode 100644 index 0000000..48d74dc --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP71Migration.rst @@ -0,0 +1,16 @@ +============================ +Rule set ``@PHP71Migration`` +============================ + +Rules to improve code for PHP 7.1 compatibility. + +Rules +----- + +- `@PHP70Migration <./PHP70Migration.rst>`_ +- `list_syntax <./../rules/list_notation/list_syntax.rst>`_ + config: + ``['syntax' => 'short']`` +- `visibility_required <./../rules/class_notation/visibility_required.rst>`_ + config: + ``['elements' => ['const', 'method', 'property']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP71MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP71MigrationRisky.rst new file mode 100644 index 0000000..be57091 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP71MigrationRisky.rst @@ -0,0 +1,11 @@ +================================== +Rule set ``@PHP71Migration:risky`` +================================== + +Rules to improve code for PHP 7.1 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHP70Migration:risky <./PHP70MigrationRisky.rst>`_ +- `void_return <./../rules/function_notation/void_return.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP73Migration.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP73Migration.rst new file mode 100644 index 0000000..1d4403e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP73Migration.rst @@ -0,0 +1,20 @@ +============================ +Rule set ``@PHP73Migration`` +============================ + +Rules to improve code for PHP 7.3 compatibility. + +Rules +----- + +- `@PHP71Migration <./PHP71Migration.rst>`_ +- `heredoc_indentation <./../rules/whitespace/heredoc_indentation.rst>`_ +- `method_argument_space <./../rules/function_notation/method_argument_space.rst>`_ + config: + ``['after_heredoc' => true]`` +- `no_whitespace_before_comma_in_array <./../rules/array_notation/no_whitespace_before_comma_in_array.rst>`_ + config: + ``['after_heredoc' => true]`` +- `trailing_comma_in_multiline <./../rules/control_structure/trailing_comma_in_multiline.rst>`_ + config: + ``['after_heredoc' => true]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP74Migration.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP74Migration.rst new file mode 100644 index 0000000..61b05aa --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP74Migration.rst @@ -0,0 +1,12 @@ +============================ +Rule set ``@PHP74Migration`` +============================ + +Rules to improve code for PHP 7.4 compatibility. + +Rules +----- + +- `@PHP73Migration <./PHP73Migration.rst>`_ +- `normalize_index_brace <./../rules/array_notation/normalize_index_brace.rst>`_ +- `short_scalar_cast <./../rules/cast_notation/short_scalar_cast.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP74MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP74MigrationRisky.rst new file mode 100644 index 0000000..d867208 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP74MigrationRisky.rst @@ -0,0 +1,13 @@ +================================== +Rule set ``@PHP74Migration:risky`` +================================== + +Rules to improve code for PHP 7.4 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHP71Migration:risky <./PHP71MigrationRisky.rst>`_ +- `implode_call <./../rules/function_notation/implode_call.rst>`_ +- `no_alias_functions <./../rules/alias/no_alias_functions.rst>`_ +- `use_arrow_functions <./../rules/function_notation/use_arrow_functions.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP80Migration.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP80Migration.rst new file mode 100644 index 0000000..afd71b9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP80Migration.rst @@ -0,0 +1,12 @@ +============================ +Rule set ``@PHP80Migration`` +============================ + +Rules to improve code for PHP 8.0 compatibility. + +Rules +----- + +- `@PHP74Migration <./PHP74Migration.rst>`_ +- `clean_namespace <./../rules/namespace_notation/clean_namespace.rst>`_ +- `no_unset_cast <./../rules/cast_notation/no_unset_cast.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP80MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP80MigrationRisky.rst new file mode 100644 index 0000000..6942647 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHP80MigrationRisky.rst @@ -0,0 +1,16 @@ +================================== +Rule set ``@PHP80Migration:risky`` +================================== + +Rules to improve code for PHP 8.0 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHP74Migration:risky <./PHP74MigrationRisky.rst>`_ +- `no_alias_functions <./../rules/alias/no_alias_functions.rst>`_ + config: + ``['sets' => ['@all']]`` +- `no_php4_constructor <./../rules/class_notation/no_php4_constructor.rst>`_ +- `no_unneeded_final_method <./../rules/class_notation/no_unneeded_final_method.rst>`_ +- `no_unreachable_default_argument_value <./../rules/function_notation/no_unreachable_default_argument_value.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit30MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit30MigrationRisky.rst new file mode 100644 index 0000000..38bba8d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit30MigrationRisky.rst @@ -0,0 +1,12 @@ +====================================== +Rule set ``@PHPUnit30Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 3.0 compatibility. This set contains rules that are risky. + +Rules +----- + +- `php_unit_dedicate_assert <./../rules/php_unit/php_unit_dedicate_assert.rst>`_ + config: + ``['target' => '3.0']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit32MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit32MigrationRisky.rst new file mode 100644 index 0000000..a18018e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit32MigrationRisky.rst @@ -0,0 +1,13 @@ +====================================== +Rule set ``@PHPUnit32Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 3.2 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit30Migration:risky <./PHPUnit30MigrationRisky.rst>`_ +- `php_unit_no_expectation_annotation <./../rules/php_unit/php_unit_no_expectation_annotation.rst>`_ + config: + ``['target' => '3.2']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit35MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit35MigrationRisky.rst new file mode 100644 index 0000000..25bd340 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit35MigrationRisky.rst @@ -0,0 +1,13 @@ +====================================== +Rule set ``@PHPUnit35Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 3.5 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit32Migration:risky <./PHPUnit32MigrationRisky.rst>`_ +- `php_unit_dedicate_assert <./../rules/php_unit/php_unit_dedicate_assert.rst>`_ + config: + ``['target' => '3.5']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit43MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit43MigrationRisky.rst new file mode 100644 index 0000000..ab0cde1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit43MigrationRisky.rst @@ -0,0 +1,13 @@ +====================================== +Rule set ``@PHPUnit43Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 4.3 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit35Migration:risky <./PHPUnit35MigrationRisky.rst>`_ +- `php_unit_no_expectation_annotation <./../rules/php_unit/php_unit_no_expectation_annotation.rst>`_ + config: + ``['target' => '4.3']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit48MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit48MigrationRisky.rst new file mode 100644 index 0000000..637e270 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit48MigrationRisky.rst @@ -0,0 +1,13 @@ +====================================== +Rule set ``@PHPUnit48Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 4.8 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit43Migration:risky <./PHPUnit43MigrationRisky.rst>`_ +- `php_unit_namespaced <./../rules/php_unit/php_unit_namespaced.rst>`_ + config: + ``['target' => '4.8']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit50MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit50MigrationRisky.rst new file mode 100644 index 0000000..bca7b8e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit50MigrationRisky.rst @@ -0,0 +1,11 @@ +====================================== +Rule set ``@PHPUnit50Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 5.0 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit48Migration:risky <./PHPUnit48MigrationRisky.rst>`_ +- `php_unit_dedicate_assert <./../rules/php_unit/php_unit_dedicate_assert.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit52MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit52MigrationRisky.rst new file mode 100644 index 0000000..9204eef --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit52MigrationRisky.rst @@ -0,0 +1,13 @@ +====================================== +Rule set ``@PHPUnit52Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 5.2 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit50Migration:risky <./PHPUnit50MigrationRisky.rst>`_ +- `php_unit_expectation <./../rules/php_unit/php_unit_expectation.rst>`_ + config: + ``['target' => '5.2']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit54MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit54MigrationRisky.rst new file mode 100644 index 0000000..447d148 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit54MigrationRisky.rst @@ -0,0 +1,13 @@ +====================================== +Rule set ``@PHPUnit54Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 5.4 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit52Migration:risky <./PHPUnit52MigrationRisky.rst>`_ +- `php_unit_mock <./../rules/php_unit/php_unit_mock.rst>`_ + config: + ``['target' => '5.4']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit55MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit55MigrationRisky.rst new file mode 100644 index 0000000..cbdfcd1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit55MigrationRisky.rst @@ -0,0 +1,13 @@ +====================================== +Rule set ``@PHPUnit55Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 5.5 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit54Migration:risky <./PHPUnit54MigrationRisky.rst>`_ +- `php_unit_mock <./../rules/php_unit/php_unit_mock.rst>`_ + config: + ``['target' => '5.5']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit56MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit56MigrationRisky.rst new file mode 100644 index 0000000..6decb6c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit56MigrationRisky.rst @@ -0,0 +1,16 @@ +====================================== +Rule set ``@PHPUnit56Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 5.6 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit55Migration:risky <./PHPUnit55MigrationRisky.rst>`_ +- `php_unit_dedicate_assert <./../rules/php_unit/php_unit_dedicate_assert.rst>`_ + config: + ``['target' => '5.6']`` +- `php_unit_expectation <./../rules/php_unit/php_unit_expectation.rst>`_ + config: + ``['target' => '5.6']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit57MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit57MigrationRisky.rst new file mode 100644 index 0000000..edbfbf9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit57MigrationRisky.rst @@ -0,0 +1,13 @@ +====================================== +Rule set ``@PHPUnit57Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 5.7 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit56Migration:risky <./PHPUnit56MigrationRisky.rst>`_ +- `php_unit_namespaced <./../rules/php_unit/php_unit_namespaced.rst>`_ + config: + ``['target' => '5.7']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit60MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit60MigrationRisky.rst new file mode 100644 index 0000000..69d9539 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit60MigrationRisky.rst @@ -0,0 +1,13 @@ +====================================== +Rule set ``@PHPUnit60Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 6.0 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit57Migration:risky <./PHPUnit57MigrationRisky.rst>`_ +- `php_unit_namespaced <./../rules/php_unit/php_unit_namespaced.rst>`_ + config: + ``['target' => '6.0']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit75MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit75MigrationRisky.rst new file mode 100644 index 0000000..ba4d716 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit75MigrationRisky.rst @@ -0,0 +1,13 @@ +====================================== +Rule set ``@PHPUnit75Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 7.5 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit60Migration:risky <./PHPUnit60MigrationRisky.rst>`_ +- `php_unit_dedicate_assert_internal_type <./../rules/php_unit/php_unit_dedicate_assert_internal_type.rst>`_ + config: + ``['target' => '7.5']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit84MigrationRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit84MigrationRisky.rst new file mode 100644 index 0000000..7192e08 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PHPUnit84MigrationRisky.rst @@ -0,0 +1,14 @@ +====================================== +Rule set ``@PHPUnit84Migration:risky`` +====================================== + +Rules to improve tests code for PHPUnit 8.4 compatibility. This set contains rules that are risky. + +Rules +----- + +- `@PHPUnit60Migration:risky <./PHPUnit60MigrationRisky.rst>`_ +- `@PHPUnit75Migration:risky <./PHPUnit75MigrationRisky.rst>`_ +- `php_unit_expectation <./../rules/php_unit/php_unit_expectation.rst>`_ + config: + ``['target' => '8.4']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR1.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR1.rst new file mode 100644 index 0000000..fa4bdf7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR1.rst @@ -0,0 +1,11 @@ +================== +Rule set ``@PSR1`` +================== + +Rules that follow `PSR-1 <https://www.php-fig.org/psr/psr-1/>`_ standard. + +Rules +----- + +- `encoding <./../rules/basic/encoding.rst>`_ +- `full_opening_tag <./../rules/php_tag/full_opening_tag.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR12.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR12.rst new file mode 100644 index 0000000..e57218e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR12.rst @@ -0,0 +1,36 @@ +=================== +Rule set ``@PSR12`` +=================== + +Rules that follow `PSR-12 <https://www.php-fig.org/psr/psr-12/>`_ standard. + +Rules +----- + +- `@PSR2 <./PSR2.rst>`_ +- `blank_line_after_opening_tag <./../rules/php_tag/blank_line_after_opening_tag.rst>`_ +- `braces <./../rules/basic/braces.rst>`_ + config: + ``['allow_single_line_anonymous_class_with_empty_body' => true]`` +- `compact_nullable_typehint <./../rules/whitespace/compact_nullable_typehint.rst>`_ +- `declare_equal_normalize <./../rules/language_construct/declare_equal_normalize.rst>`_ +- `lowercase_cast <./../rules/cast_notation/lowercase_cast.rst>`_ +- `lowercase_static_reference <./../rules/casing/lowercase_static_reference.rst>`_ +- `new_with_braces <./../rules/operator/new_with_braces.rst>`_ +- `no_blank_lines_after_class_opening <./../rules/class_notation/no_blank_lines_after_class_opening.rst>`_ +- `no_leading_import_slash <./../rules/import/no_leading_import_slash.rst>`_ +- `no_whitespace_in_blank_line <./../rules/whitespace/no_whitespace_in_blank_line.rst>`_ +- `ordered_class_elements <./../rules/class_notation/ordered_class_elements.rst>`_ + config: + ``['order' => ['use_trait']]`` +- `ordered_imports <./../rules/import/ordered_imports.rst>`_ + config: + ``['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'none']`` +- `return_type_declaration <./../rules/function_notation/return_type_declaration.rst>`_ +- `short_scalar_cast <./../rules/cast_notation/short_scalar_cast.rst>`_ +- `single_blank_line_before_namespace <./../rules/namespace_notation/single_blank_line_before_namespace.rst>`_ +- `single_trait_insert_per_statement <./../rules/class_notation/single_trait_insert_per_statement.rst>`_ +- `ternary_operator_spaces <./../rules/operator/ternary_operator_spaces.rst>`_ +- `visibility_required <./../rules/class_notation/visibility_required.rst>`_ + config: + ``['elements' => ['const', 'method', 'property']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR12Risky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR12Risky.rst new file mode 100644 index 0000000..efb8165 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR12Risky.rst @@ -0,0 +1,11 @@ +========================= +Rule set ``@PSR12:risky`` +========================= + +Rules that follow `PSR-12 <https://www.php-fig.org/psr/psr-12/>`_ standard. This set contains rules that are risky. + +Rules +----- + +- `no_trailing_whitespace_in_string <./../rules/string_notation/no_trailing_whitespace_in_string.rst>`_ +- `no_unreachable_default_argument_value <./../rules/function_notation/no_unreachable_default_argument_value.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR2.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR2.rst new file mode 100644 index 0000000..aea43c5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PSR2.rst @@ -0,0 +1,37 @@ +================== +Rule set ``@PSR2`` +================== + +Rules that follow `PSR-2 <https://www.php-fig.org/psr/psr-2/>`_ standard. + +Rules +----- + +- `@PSR1 <./PSR1.rst>`_ +- `blank_line_after_namespace <./../rules/namespace_notation/blank_line_after_namespace.rst>`_ +- `braces <./../rules/basic/braces.rst>`_ +- `class_definition <./../rules/class_notation/class_definition.rst>`_ +- `constant_case <./../rules/casing/constant_case.rst>`_ +- `elseif <./../rules/control_structure/elseif.rst>`_ +- `function_declaration <./../rules/function_notation/function_declaration.rst>`_ +- `indentation_type <./../rules/whitespace/indentation_type.rst>`_ +- `line_ending <./../rules/whitespace/line_ending.rst>`_ +- `lowercase_keywords <./../rules/casing/lowercase_keywords.rst>`_ +- `method_argument_space <./../rules/function_notation/method_argument_space.rst>`_ + config: + ``['on_multiline' => 'ensure_fully_multiline']`` +- `no_break_comment <./../rules/control_structure/no_break_comment.rst>`_ +- `no_closing_tag <./../rules/php_tag/no_closing_tag.rst>`_ +- `no_spaces_after_function_name <./../rules/function_notation/no_spaces_after_function_name.rst>`_ +- `no_spaces_inside_parenthesis <./../rules/whitespace/no_spaces_inside_parenthesis.rst>`_ +- `no_trailing_whitespace <./../rules/whitespace/no_trailing_whitespace.rst>`_ +- `no_trailing_whitespace_in_comment <./../rules/comment/no_trailing_whitespace_in_comment.rst>`_ +- `single_blank_line_at_eof <./../rules/whitespace/single_blank_line_at_eof.rst>`_ +- `single_class_element_per_statement <./../rules/class_notation/single_class_element_per_statement.rst>`_ + config: + ``['elements' => ['property']]`` +- `single_import_per_statement <./../rules/import/single_import_per_statement.rst>`_ +- `single_line_after_imports <./../rules/import/single_line_after_imports.rst>`_ +- `switch_case_semicolon_to_colon <./../rules/control_structure/switch_case_semicolon_to_colon.rst>`_ +- `switch_case_space <./../rules/control_structure/switch_case_space.rst>`_ +- `visibility_required <./../rules/class_notation/visibility_required.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PhpCsFixer.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PhpCsFixer.rst new file mode 100644 index 0000000..a91229a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PhpCsFixer.rst @@ -0,0 +1,52 @@ +======================== +Rule set ``@PhpCsFixer`` +======================== + +Rule set as used by the PHP-CS-Fixer development team, highly opinionated. + +Rules +----- + +- `@Symfony <./Symfony.rst>`_ +- `align_multiline_comment <./../rules/phpdoc/align_multiline_comment.rst>`_ +- `array_indentation <./../rules/whitespace/array_indentation.rst>`_ +- `blank_line_before_statement <./../rules/whitespace/blank_line_before_statement.rst>`_ + config: + ``['statements' => ['break', 'case', 'continue', 'declare', 'default', 'exit', 'goto', 'include', 'include_once', 'require', 'require_once', 'return', 'switch', 'throw', 'try']]`` +- `combine_consecutive_issets <./../rules/language_construct/combine_consecutive_issets.rst>`_ +- `combine_consecutive_unsets <./../rules/language_construct/combine_consecutive_unsets.rst>`_ +- `escape_implicit_backslashes <./../rules/string_notation/escape_implicit_backslashes.rst>`_ +- `explicit_indirect_variable <./../rules/language_construct/explicit_indirect_variable.rst>`_ +- `explicit_string_variable <./../rules/string_notation/explicit_string_variable.rst>`_ +- `heredoc_to_nowdoc <./../rules/string_notation/heredoc_to_nowdoc.rst>`_ +- `method_argument_space <./../rules/function_notation/method_argument_space.rst>`_ + config: + ``['on_multiline' => 'ensure_fully_multiline']`` +- `method_chaining_indentation <./../rules/whitespace/method_chaining_indentation.rst>`_ +- `multiline_comment_opening_closing <./../rules/comment/multiline_comment_opening_closing.rst>`_ +- `multiline_whitespace_before_semicolons <./../rules/semicolon/multiline_whitespace_before_semicolons.rst>`_ + config: + ``['strategy' => 'new_line_for_chained_calls']`` +- `no_extra_blank_lines <./../rules/whitespace/no_extra_blank_lines.rst>`_ + config: + ``['tokens' => ['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait']]`` +- `no_null_property_initialization <./../rules/class_notation/no_null_property_initialization.rst>`_ +- `no_superfluous_elseif <./../rules/control_structure/no_superfluous_elseif.rst>`_ +- `no_useless_else <./../rules/control_structure/no_useless_else.rst>`_ +- `no_useless_return <./../rules/return_notation/no_useless_return.rst>`_ +- `operator_linebreak <./../rules/operator/operator_linebreak.rst>`_ + config: + ``['only_booleans' => true]`` +- `ordered_class_elements <./../rules/class_notation/ordered_class_elements.rst>`_ +- `php_unit_internal_class <./../rules/php_unit/php_unit_internal_class.rst>`_ +- `php_unit_test_class_requires_covers <./../rules/php_unit/php_unit_test_class_requires_covers.rst>`_ +- `phpdoc_add_missing_param_annotation <./../rules/phpdoc/phpdoc_add_missing_param_annotation.rst>`_ +- `phpdoc_no_empty_return <./../rules/phpdoc/phpdoc_no_empty_return.rst>`_ +- `phpdoc_order <./../rules/phpdoc/phpdoc_order.rst>`_ +- `phpdoc_order_by_value <./../rules/phpdoc/phpdoc_order_by_value.rst>`_ +- `phpdoc_types_order <./../rules/phpdoc/phpdoc_types_order.rst>`_ +- `phpdoc_var_annotation_correct_order <./../rules/phpdoc/phpdoc_var_annotation_correct_order.rst>`_ +- `return_assignment <./../rules/return_notation/return_assignment.rst>`_ +- `simple_to_complex_string_variable <./../rules/string_notation/simple_to_complex_string_variable.rst>`_ +- `single_line_comment_style <./../rules/comment/single_line_comment_style.rst>`_ +- `single_line_throw <./../rules/function_notation/single_line_throw.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PhpCsFixerRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PhpCsFixerRisky.rst new file mode 100644 index 0000000..288bf9a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/PhpCsFixerRisky.rst @@ -0,0 +1,24 @@ +============================== +Rule set ``@PhpCsFixer:risky`` +============================== + +Rule set as used by the PHP-CS-Fixer development team, highly opinionated. This set contains rules that are risky. + +Rules +----- + +- `@Symfony:risky <./SymfonyRisky.rst>`_ +- `comment_to_phpdoc <./../rules/comment/comment_to_phpdoc.rst>`_ +- `final_internal_class <./../rules/class_notation/final_internal_class.rst>`_ +- `native_constant_invocation <./../rules/constant_notation/native_constant_invocation.rst>`_ + config: + ``['fix_built_in' => false, 'include' => ['DIRECTORY_SEPARATOR', 'PHP_INT_SIZE', 'PHP_SAPI', 'PHP_VERSION_ID'], 'scope' => 'namespaced', 'strict' => true]`` +- `no_alias_functions <./../rules/alias/no_alias_functions.rst>`_ + config: + ``['sets' => ['@all']]`` +- `no_unreachable_default_argument_value <./../rules/function_notation/no_unreachable_default_argument_value.rst>`_ +- `no_unset_on_property <./../rules/language_construct/no_unset_on_property.rst>`_ +- `php_unit_strict <./../rules/php_unit/php_unit_strict.rst>`_ +- `php_unit_test_case_static_method_calls <./../rules/php_unit/php_unit_test_case_static_method_calls.rst>`_ +- `strict_comparison <./../rules/strict/strict_comparison.rst>`_ +- `strict_param <./../rules/strict/strict_param.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/Symfony.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/Symfony.rst new file mode 100644 index 0000000..80d6f7e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/Symfony.rst @@ -0,0 +1,127 @@ +===================== +Rule set ``@Symfony`` +===================== + +Rules that follow the official `Symfony Coding Standards <https://symfony.com/doc/current/contributing/code/standards.html>`_. + +Rules +----- + +- `@PSR12 <./PSR12.rst>`_ +- `array_syntax <./../rules/array_notation/array_syntax.rst>`_ + config: + ``['syntax' => 'short']`` +- `backtick_to_shell_exec <./../rules/alias/backtick_to_shell_exec.rst>`_ +- `binary_operator_spaces <./../rules/operator/binary_operator_spaces.rst>`_ +- `blank_line_before_statement <./../rules/whitespace/blank_line_before_statement.rst>`_ + config: + ``['statements' => ['return']]`` +- `braces <./../rules/basic/braces.rst>`_ + config: + ``['allow_single_line_anonymous_class_with_empty_body' => true, 'allow_single_line_closure' => true]`` +- `cast_spaces <./../rules/cast_notation/cast_spaces.rst>`_ +- `class_attributes_separation <./../rules/class_notation/class_attributes_separation.rst>`_ + config: + ``['elements' => ['method' => 'one']]`` +- `class_definition <./../rules/class_notation/class_definition.rst>`_ + config: + ``['single_line' => true]`` +- `clean_namespace <./../rules/namespace_notation/clean_namespace.rst>`_ +- `concat_space <./../rules/operator/concat_space.rst>`_ +- `echo_tag_syntax <./../rules/php_tag/echo_tag_syntax.rst>`_ +- `fully_qualified_strict_types <./../rules/import/fully_qualified_strict_types.rst>`_ +- `function_typehint_space <./../rules/function_notation/function_typehint_space.rst>`_ +- `general_phpdoc_tag_rename <./../rules/phpdoc/general_phpdoc_tag_rename.rst>`_ + config: + ``['replacements' => ['inheritDocs' => 'inheritDoc']]`` +- `include <./../rules/control_structure/include.rst>`_ +- `increment_style <./../rules/operator/increment_style.rst>`_ +- `lambda_not_used_import <./../rules/function_notation/lambda_not_used_import.rst>`_ +- `linebreak_after_opening_tag <./../rules/php_tag/linebreak_after_opening_tag.rst>`_ +- `magic_constant_casing <./../rules/casing/magic_constant_casing.rst>`_ +- `magic_method_casing <./../rules/casing/magic_method_casing.rst>`_ +- `method_argument_space <./../rules/function_notation/method_argument_space.rst>`_ +- `native_function_casing <./../rules/casing/native_function_casing.rst>`_ +- `native_function_type_declaration_casing <./../rules/casing/native_function_type_declaration_casing.rst>`_ +- `no_alias_language_construct_call <./../rules/alias/no_alias_language_construct_call.rst>`_ +- `no_alternative_syntax <./../rules/control_structure/no_alternative_syntax.rst>`_ +- `no_binary_string <./../rules/string_notation/no_binary_string.rst>`_ +- `no_blank_lines_after_phpdoc <./../rules/phpdoc/no_blank_lines_after_phpdoc.rst>`_ +- `no_empty_comment <./../rules/comment/no_empty_comment.rst>`_ +- `no_empty_phpdoc <./../rules/phpdoc/no_empty_phpdoc.rst>`_ +- `no_empty_statement <./../rules/semicolon/no_empty_statement.rst>`_ +- `no_extra_blank_lines <./../rules/whitespace/no_extra_blank_lines.rst>`_ + config: + ``['tokens' => ['case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait']]`` +- `no_leading_namespace_whitespace <./../rules/namespace_notation/no_leading_namespace_whitespace.rst>`_ +- `no_mixed_echo_print <./../rules/alias/no_mixed_echo_print.rst>`_ +- `no_multiline_whitespace_around_double_arrow <./../rules/array_notation/no_multiline_whitespace_around_double_arrow.rst>`_ +- `no_short_bool_cast <./../rules/cast_notation/no_short_bool_cast.rst>`_ +- `no_singleline_whitespace_before_semicolons <./../rules/semicolon/no_singleline_whitespace_before_semicolons.rst>`_ +- `no_spaces_around_offset <./../rules/whitespace/no_spaces_around_offset.rst>`_ +- `no_superfluous_phpdoc_tags <./../rules/phpdoc/no_superfluous_phpdoc_tags.rst>`_ + config: + ``['allow_mixed' => true, 'allow_unused_params' => true]`` +- `no_trailing_comma_in_list_call <./../rules/control_structure/no_trailing_comma_in_list_call.rst>`_ +- `no_trailing_comma_in_singleline_array <./../rules/array_notation/no_trailing_comma_in_singleline_array.rst>`_ +- `no_unneeded_control_parentheses <./../rules/control_structure/no_unneeded_control_parentheses.rst>`_ + config: + ``['statements' => ['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield', 'yield_from']]`` +- `no_unneeded_curly_braces <./../rules/control_structure/no_unneeded_curly_braces.rst>`_ + config: + ``['namespaces' => true]`` +- `no_unset_cast <./../rules/cast_notation/no_unset_cast.rst>`_ +- `no_unused_imports <./../rules/import/no_unused_imports.rst>`_ +- `no_whitespace_before_comma_in_array <./../rules/array_notation/no_whitespace_before_comma_in_array.rst>`_ +- `normalize_index_brace <./../rules/array_notation/normalize_index_brace.rst>`_ +- `object_operator_without_whitespace <./../rules/operator/object_operator_without_whitespace.rst>`_ +- `ordered_imports <./../rules/import/ordered_imports.rst>`_ +- `php_unit_fqcn_annotation <./../rules/php_unit/php_unit_fqcn_annotation.rst>`_ +- `php_unit_method_casing <./../rules/php_unit/php_unit_method_casing.rst>`_ +- `phpdoc_align <./../rules/phpdoc/phpdoc_align.rst>`_ + config: + ``['tags' => ['method', 'param', 'property', 'return', 'throws', 'type', 'var']]`` +- `phpdoc_annotation_without_dot <./../rules/phpdoc/phpdoc_annotation_without_dot.rst>`_ +- `phpdoc_indent <./../rules/phpdoc/phpdoc_indent.rst>`_ +- `phpdoc_inline_tag_normalizer <./../rules/phpdoc/phpdoc_inline_tag_normalizer.rst>`_ +- `phpdoc_no_access <./../rules/phpdoc/phpdoc_no_access.rst>`_ +- `phpdoc_no_alias_tag <./../rules/phpdoc/phpdoc_no_alias_tag.rst>`_ +- `phpdoc_no_package <./../rules/phpdoc/phpdoc_no_package.rst>`_ +- `phpdoc_no_useless_inheritdoc <./../rules/phpdoc/phpdoc_no_useless_inheritdoc.rst>`_ +- `phpdoc_return_self_reference <./../rules/phpdoc/phpdoc_return_self_reference.rst>`_ +- `phpdoc_scalar <./../rules/phpdoc/phpdoc_scalar.rst>`_ +- `phpdoc_separation <./../rules/phpdoc/phpdoc_separation.rst>`_ +- `phpdoc_single_line_var_spacing <./../rules/phpdoc/phpdoc_single_line_var_spacing.rst>`_ +- `phpdoc_summary <./../rules/phpdoc/phpdoc_summary.rst>`_ +- `phpdoc_tag_type <./../rules/phpdoc/phpdoc_tag_type.rst>`_ + config: + ``['tags' => ['inheritDoc' => 'inline']]`` +- `phpdoc_to_comment <./../rules/phpdoc/phpdoc_to_comment.rst>`_ +- `phpdoc_trim <./../rules/phpdoc/phpdoc_trim.rst>`_ +- `phpdoc_trim_consecutive_blank_line_separation <./../rules/phpdoc/phpdoc_trim_consecutive_blank_line_separation.rst>`_ +- `phpdoc_types <./../rules/phpdoc/phpdoc_types.rst>`_ +- `phpdoc_types_order <./../rules/phpdoc/phpdoc_types_order.rst>`_ + config: + ``['null_adjustment' => 'always_last', 'sort_algorithm' => 'none']`` +- `phpdoc_var_without_name <./../rules/phpdoc/phpdoc_var_without_name.rst>`_ +- `protected_to_private <./../rules/class_notation/protected_to_private.rst>`_ +- `semicolon_after_instruction <./../rules/semicolon/semicolon_after_instruction.rst>`_ +- `single_class_element_per_statement <./../rules/class_notation/single_class_element_per_statement.rst>`_ +- `single_line_comment_style <./../rules/comment/single_line_comment_style.rst>`_ + config: + ``['comment_types' => ['hash']]`` +- `single_line_throw <./../rules/function_notation/single_line_throw.rst>`_ +- `single_quote <./../rules/string_notation/single_quote.rst>`_ +- `single_space_after_construct <./../rules/language_construct/single_space_after_construct.rst>`_ +- `space_after_semicolon <./../rules/semicolon/space_after_semicolon.rst>`_ + config: + ``['remove_in_empty_for_expressions' => true]`` +- `standardize_increment <./../rules/operator/standardize_increment.rst>`_ +- `standardize_not_equals <./../rules/operator/standardize_not_equals.rst>`_ +- `switch_continue_to_break <./../rules/control_structure/switch_continue_to_break.rst>`_ +- `trailing_comma_in_multiline <./../rules/control_structure/trailing_comma_in_multiline.rst>`_ +- `trim_array_spaces <./../rules/array_notation/trim_array_spaces.rst>`_ +- `unary_operator_spaces <./../rules/operator/unary_operator_spaces.rst>`_ +- `visibility_required <./../rules/class_notation/visibility_required.rst>`_ +- `whitespace_after_comma_in_array <./../rules/array_notation/whitespace_after_comma_in_array.rst>`_ +- `yoda_style <./../rules/control_structure/yoda_style.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/SymfonyRisky.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/SymfonyRisky.rst new file mode 100644 index 0000000..628f61e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/SymfonyRisky.rst @@ -0,0 +1,50 @@ +=========================== +Rule set ``@Symfony:risky`` +=========================== + +Rules that follow the official `Symfony Coding Standards <https://symfony.com/doc/current/contributing/code/standards.html>`_. This set contains rules that are risky. + +Rules +----- + +- `@PHP56Migration:risky <./PHP56MigrationRisky.rst>`_ +- `@PSR12:risky <./PSR12Risky.rst>`_ +- `array_push <./../rules/alias/array_push.rst>`_ +- `combine_nested_dirname <./../rules/function_notation/combine_nested_dirname.rst>`_ +- `dir_constant <./../rules/language_construct/dir_constant.rst>`_ +- `ereg_to_preg <./../rules/alias/ereg_to_preg.rst>`_ +- `error_suppression <./../rules/language_construct/error_suppression.rst>`_ +- `fopen_flag_order <./../rules/function_notation/fopen_flag_order.rst>`_ +- `fopen_flags <./../rules/function_notation/fopen_flags.rst>`_ + config: + ``['b_mode' => false]`` +- `function_to_constant <./../rules/language_construct/function_to_constant.rst>`_ + config: + ``['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']]`` +- `implode_call <./../rules/function_notation/implode_call.rst>`_ +- `is_null <./../rules/language_construct/is_null.rst>`_ +- `logical_operators <./../rules/operator/logical_operators.rst>`_ +- `modernize_types_casting <./../rules/cast_notation/modernize_types_casting.rst>`_ +- `native_constant_invocation <./../rules/constant_notation/native_constant_invocation.rst>`_ +- `native_function_invocation <./../rules/function_notation/native_function_invocation.rst>`_ + config: + ``['include' => ['@compiler_optimized'], 'scope' => 'namespaced', 'strict' => true]`` +- `no_alias_functions <./../rules/alias/no_alias_functions.rst>`_ +- `no_homoglyph_names <./../rules/naming/no_homoglyph_names.rst>`_ +- `no_php4_constructor <./../rules/class_notation/no_php4_constructor.rst>`_ +- `no_unneeded_final_method <./../rules/class_notation/no_unneeded_final_method.rst>`_ +- `no_unreachable_default_argument_value <./../rules/function_notation/no_unreachable_default_argument_value.rst>`_ +- `no_useless_sprintf <./../rules/function_notation/no_useless_sprintf.rst>`_ +- `non_printable_character <./../rules/basic/non_printable_character.rst>`_ + config: + ``['use_escape_sequences_in_strings' => true]`` +- `ordered_traits <./../rules/class_notation/ordered_traits.rst>`_ +- `php_unit_construct <./../rules/php_unit/php_unit_construct.rst>`_ +- `php_unit_mock_short_will_return <./../rules/php_unit/php_unit_mock_short_will_return.rst>`_ +- `php_unit_set_up_tear_down_visibility <./../rules/php_unit/php_unit_set_up_tear_down_visibility.rst>`_ +- `php_unit_test_annotation <./../rules/php_unit/php_unit_test_annotation.rst>`_ +- `psr_autoloading <./../rules/basic/psr_autoloading.rst>`_ +- `self_accessor <./../rules/class_notation/self_accessor.rst>`_ +- `set_type_to_cast <./../rules/alias/set_type_to_cast.rst>`_ +- `string_line_ending <./../rules/string_notation/string_line_ending.rst>`_ +- `ternary_to_elvis_operator <./../rules/operator/ternary_to_elvis_operator.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/index.rst b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/index.rst new file mode 100644 index 0000000..9331fed --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/ruleSets/index.rst @@ -0,0 +1,38 @@ +=========================== +List of Available Rule sets +=========================== +- `@DoctrineAnnotation <./DoctrineAnnotation.rst>`_ +- `@PHP54Migration <./PHP54Migration.rst>`_ +- `@PHP56Migration <./PHP56Migration.rst>`_ +- `@PHP56Migration:risky <./PHP56MigrationRisky.rst>`_ +- `@PHP70Migration <./PHP70Migration.rst>`_ +- `@PHP70Migration:risky <./PHP70MigrationRisky.rst>`_ +- `@PHP71Migration <./PHP71Migration.rst>`_ +- `@PHP71Migration:risky <./PHP71MigrationRisky.rst>`_ +- `@PHP73Migration <./PHP73Migration.rst>`_ +- `@PHP74Migration <./PHP74Migration.rst>`_ +- `@PHP74Migration:risky <./PHP74MigrationRisky.rst>`_ +- `@PHP80Migration <./PHP80Migration.rst>`_ +- `@PHP80Migration:risky <./PHP80MigrationRisky.rst>`_ +- `@PHPUnit30Migration:risky <./PHPUnit30MigrationRisky.rst>`_ +- `@PHPUnit32Migration:risky <./PHPUnit32MigrationRisky.rst>`_ +- `@PHPUnit35Migration:risky <./PHPUnit35MigrationRisky.rst>`_ +- `@PHPUnit43Migration:risky <./PHPUnit43MigrationRisky.rst>`_ +- `@PHPUnit48Migration:risky <./PHPUnit48MigrationRisky.rst>`_ +- `@PHPUnit50Migration:risky <./PHPUnit50MigrationRisky.rst>`_ +- `@PHPUnit52Migration:risky <./PHPUnit52MigrationRisky.rst>`_ +- `@PHPUnit54Migration:risky <./PHPUnit54MigrationRisky.rst>`_ +- `@PHPUnit55Migration:risky <./PHPUnit55MigrationRisky.rst>`_ +- `@PHPUnit56Migration:risky <./PHPUnit56MigrationRisky.rst>`_ +- `@PHPUnit57Migration:risky <./PHPUnit57MigrationRisky.rst>`_ +- `@PHPUnit60Migration:risky <./PHPUnit60MigrationRisky.rst>`_ +- `@PHPUnit75Migration:risky <./PHPUnit75MigrationRisky.rst>`_ +- `@PHPUnit84Migration:risky <./PHPUnit84MigrationRisky.rst>`_ +- `@PSR1 <./PSR1.rst>`_ +- `@PSR12 <./PSR12.rst>`_ +- `@PSR12:risky <./PSR12Risky.rst>`_ +- `@PSR2 <./PSR2.rst>`_ +- `@PhpCsFixer <./PhpCsFixer.rst>`_ +- `@PhpCsFixer:risky <./PhpCsFixerRisky.rst>`_ +- `@Symfony <./Symfony.rst>`_ +- `@Symfony:risky <./SymfonyRisky.rst>`_ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/array_push.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/array_push.rst new file mode 100644 index 0000000..d92d876 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/array_push.rst @@ -0,0 +1,34 @@ +=================== +Rule ``array_push`` +=================== + +Converts simple usages of ``array_push($x, $y);`` to ``$x[] = $y;``. + +.. warning:: Using this rule is risky. + + Risky when the function ``array_push`` is overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -array_push($x, $y); + +$x[] = $y; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``array_push`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``array_push`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/backtick_to_shell_exec.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/backtick_to_shell_exec.rst new file mode 100644 index 0000000..3591834 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/backtick_to_shell_exec.rst @@ -0,0 +1,38 @@ +=============================== +Rule ``backtick_to_shell_exec`` +=============================== + +Converts backtick operators to ``shell_exec`` calls. + +Description +----------- + +Conversion is done only when it is non risky, so when special chars like +single-quotes, double-quotes and backticks are not used inside the command. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$plain = `ls -lah`; + -$withVar = `ls -lah $var1 ${var2} {$var3} {$var4[0]} {$var5->call()}`; + +$plain = shell_exec("ls -lah"); + +$withVar = shell_exec("ls -lah $var1 ${var2} {$var3} {$var4[0]} {$var5->call()}"); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``backtick_to_shell_exec`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``backtick_to_shell_exec`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/ereg_to_preg.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/ereg_to_preg.rst new file mode 100644 index 0000000..37f4e2d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/ereg_to_preg.rst @@ -0,0 +1,33 @@ +===================== +Rule ``ereg_to_preg`` +===================== + +Replace deprecated ``ereg`` regular expression functions with ``preg``. + +.. warning:: Using this rule is risky. + + Risky if the ``ereg`` function is overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $x = ereg('[A-Z]'); + +<?php $x = preg_match('/[A-Z]/D'); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``ereg_to_preg`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``ereg_to_preg`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/mb_str_functions.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/mb_str_functions.rst new file mode 100644 index 0000000..04ce58a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/mb_str_functions.rst @@ -0,0 +1,45 @@ +========================= +Rule ``mb_str_functions`` +========================= + +Replace non multibyte-safe functions with corresponding mb function. + +.. warning:: Using this rule is risky. + + Risky when any of the functions are overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = strlen($a); + -$a = strpos($a, $b); + -$a = strrpos($a, $b); + -$a = substr($a, $b); + -$a = strtolower($a); + -$a = strtoupper($a); + -$a = stripos($a, $b); + -$a = strripos($a, $b); + -$a = strstr($a, $b); + -$a = stristr($a, $b); + -$a = strrchr($a, $b); + -$a = substr_count($a, $b); + +$a = mb_strlen($a); + +$a = mb_strpos($a, $b); + +$a = mb_strrpos($a, $b); + +$a = mb_substr($a, $b); + +$a = mb_strtolower($a); + +$a = mb_strtoupper($a); + +$a = mb_stripos($a, $b); + +$a = mb_strripos($a, $b); + +$a = mb_strstr($a, $b); + +$a = mb_stristr($a, $b); + +$a = mb_strrchr($a, $b); + +$a = mb_substr_count($a, $b); diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_alias_functions.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_alias_functions.rst new file mode 100644 index 0000000..e0624a8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_alias_functions.rst @@ -0,0 +1,113 @@ +=========================== +Rule ``no_alias_functions`` +=========================== + +Master functions shall be used instead of aliases. + +.. warning:: Using this rule is risky. + + Risky when any of the alias functions are overridden. + +Configuration +------------- + +``sets`` +~~~~~~~~ + +List of sets to fix. Defined sets are ``@internal`` (native functions), +``@IMAP`` (IMAP functions), ``@mbreg`` (from ``ext-mbstring``) ``@all`` (all +listed sets). + +Allowed values: a subset of ``['@internal', '@IMAP', '@mbreg', '@all', '@time', '@exif']`` + +Default value: ``['@internal', '@IMAP']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = chop($b); + -close($b); + -$a = doubleval($b); + -$a = fputs($b, $c); + -$a = get_required_files(); + -ini_alter($b, $c); + -$a = is_double($b); + -$a = is_integer($b); + -$a = is_long($b); + -$a = is_real($b); + -$a = is_writeable($b); + -$a = join($glue, $pieces); + -$a = key_exists($key, $array); + -magic_quotes_runtime($new_setting); + -$a = pos($array); + -$a = show_source($filename, true); + -$a = sizeof($b); + -$a = strchr($haystack, $needle); + -$a = imap_header($imap_stream, 1); + -user_error($message); + +$a = rtrim($b); + +closedir($b); + +$a = floatval($b); + +$a = fwrite($b, $c); + +$a = get_included_files(); + +ini_set($b, $c); + +$a = is_float($b); + +$a = is_int($b); + +$a = is_int($b); + +$a = is_float($b); + +$a = is_writable($b); + +$a = implode($glue, $pieces); + +$a = array_key_exists($key, $array); + +set_magic_quotes_runtime($new_setting); + +$a = current($array); + +$a = highlight_file($filename, true); + +$a = count($b); + +$a = strstr($haystack, $needle); + +$a = imap_headerinfo($imap_stream, 1); + +trigger_error($message); + mbereg_search_getregs(); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['sets' => ['@mbreg']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = is_double($b); + -mbereg_search_getregs(); + +mb_ereg_search_getregs(); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP74Migration:risky + Using the `@PHP74Migration:risky <./../../ruleSets/PHP74MigrationRisky.rst>`_ rule set will enable the ``no_alias_functions`` rule with the default config. + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``no_alias_functions`` rule with the config below: + + ``['sets' => ['@all']]`` + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``no_alias_functions`` rule with the config below: + + ``['sets' => ['@all']]`` + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``no_alias_functions`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_alias_language_construct_call.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_alias_language_construct_call.rst new file mode 100644 index 0000000..a58d8a5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_alias_language_construct_call.rst @@ -0,0 +1,30 @@ +========================================= +Rule ``no_alias_language_construct_call`` +========================================= + +Master language constructs shall be used instead of aliases. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -die; + +exit; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_alias_language_construct_call`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_alias_language_construct_call`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_mixed_echo_print.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_mixed_echo_print.rst new file mode 100644 index 0000000..49f2fa1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/no_mixed_echo_print.rst @@ -0,0 +1,55 @@ +============================ +Rule ``no_mixed_echo_print`` +============================ + +Either language construct ``print`` or ``echo`` should be used. + +Configuration +------------- + +``use`` +~~~~~~~ + +The desired language construct. + +Allowed values: ``'echo'``, ``'print'`` + +Default value: ``'echo'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + -<?php print 'example'; + +<?php echo 'example'; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['use' => 'print']``. + +.. code-block:: diff + + --- Original + +++ New + -<?php echo('example'); + +<?php print('example'); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_mixed_echo_print`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_mixed_echo_print`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/pow_to_exponentiation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/pow_to_exponentiation.rst new file mode 100644 index 0000000..5fe1db3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/pow_to_exponentiation.rst @@ -0,0 +1,49 @@ +============================== +Rule ``pow_to_exponentiation`` +============================== + +Converts ``pow`` to the ``**`` operator. + +.. warning:: Using this rule is risky. + + Risky when the function ``pow`` is overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + - pow($a, 1); + + $a** 1; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP56Migration:risky + Using the `@PHP56Migration:risky <./../../ruleSets/PHP56MigrationRisky.rst>`_ rule set will enable the ``pow_to_exponentiation`` rule. + +@PHP70Migration:risky + Using the `@PHP70Migration:risky <./../../ruleSets/PHP70MigrationRisky.rst>`_ rule set will enable the ``pow_to_exponentiation`` rule. + +@PHP71Migration:risky + Using the `@PHP71Migration:risky <./../../ruleSets/PHP71MigrationRisky.rst>`_ rule set will enable the ``pow_to_exponentiation`` rule. + +@PHP74Migration:risky + Using the `@PHP74Migration:risky <./../../ruleSets/PHP74MigrationRisky.rst>`_ rule set will enable the ``pow_to_exponentiation`` rule. + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``pow_to_exponentiation`` rule. + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``pow_to_exponentiation`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``pow_to_exponentiation`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/random_api_migration.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/random_api_migration.rst new file mode 100644 index 0000000..14d979d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/random_api_migration.rst @@ -0,0 +1,95 @@ +============================= +Rule ``random_api_migration`` +============================= + +Replaces ``rand``, ``srand``, ``getrandmax`` functions calls with their ``mt_*`` +analogs or ``random_int``. + +.. warning:: Using this rule is risky. + + Risky when the configured functions are overridden. Or when relying on the + seed based generating of the numbers. + +Configuration +------------- + +``replacements`` +~~~~~~~~~~~~~~~~ + +Mapping between replaced functions with the new ones. + +Allowed types: ``array`` + +Default value: ``['getrandmax' => 'mt_getrandmax', 'rand' => 'mt_rand', 'srand' => 'mt_srand']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = getrandmax(); + -$a = rand($b, $c); + -$a = srand(); + +$a = mt_getrandmax(); + +$a = mt_rand($b, $c); + +$a = mt_srand(); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['replacements' => ['getrandmax' => 'mt_getrandmax']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = getrandmax(); + +$a = mt_getrandmax(); + $a = rand($b, $c); + $a = srand(); + +Example #3 +~~~~~~~~~~ + +With configuration: ``['replacements' => ['rand' => 'random_int']]``. + +.. code-block:: diff + + --- Original + +++ New + -<?php $a = rand($b, $c); + +<?php $a = random_int($b, $c); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP70Migration:risky + Using the `@PHP70Migration:risky <./../../ruleSets/PHP70MigrationRisky.rst>`_ rule set will enable the ``random_api_migration`` rule with the config below: + + ``['replacements' => ['mt_rand' => 'random_int', 'rand' => 'random_int']]`` + +@PHP71Migration:risky + Using the `@PHP71Migration:risky <./../../ruleSets/PHP71MigrationRisky.rst>`_ rule set will enable the ``random_api_migration`` rule with the config below: + + ``['replacements' => ['mt_rand' => 'random_int', 'rand' => 'random_int']]`` + +@PHP74Migration:risky + Using the `@PHP74Migration:risky <./../../ruleSets/PHP74MigrationRisky.rst>`_ rule set will enable the ``random_api_migration`` rule with the config below: + + ``['replacements' => ['mt_rand' => 'random_int', 'rand' => 'random_int']]`` + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``random_api_migration`` rule with the config below: + + ``['replacements' => ['mt_rand' => 'random_int', 'rand' => 'random_int']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/set_type_to_cast.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/set_type_to_cast.rst new file mode 100644 index 0000000..500cb1f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/alias/set_type_to_cast.rst @@ -0,0 +1,39 @@ +========================= +Rule ``set_type_to_cast`` +========================= + +Cast shall be used, not ``settype``. + +.. warning:: Using this rule is risky. + + Risky when the ``settype`` function is overridden or when used as the 2nd or + 3rd expression in a ``for`` loop . + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -settype($foo, "integer"); + -settype($bar, "string"); + -settype($bar, "null"); + +$foo = (int) $foo; + +$bar = (string) $bar; + +$bar = null; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``set_type_to_cast`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``set_type_to_cast`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/array_syntax.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/array_syntax.rst new file mode 100644 index 0000000..ea4c3a9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/array_syntax.rst @@ -0,0 +1,96 @@ +===================== +Rule ``array_syntax`` +===================== + +PHP arrays should be declared using the configured syntax. + +Configuration +------------- + +``syntax`` +~~~~~~~~~~ + +Whether to use the ``long`` or ``short`` array syntax. + +Allowed values: ``'long'``, ``'short'`` + +Default value: ``'long'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -[1,2]; + +array(1,2); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['syntax' => 'short']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -array(1,2); + +[1,2]; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP54Migration + Using the `@PHP54Migration <./../../ruleSets/PHP54Migration.rst>`_ rule set will enable the ``array_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@PHP56Migration + Using the `@PHP56Migration <./../../ruleSets/PHP56Migration.rst>`_ rule set will enable the ``array_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@PHP70Migration + Using the `@PHP70Migration <./../../ruleSets/PHP70Migration.rst>`_ rule set will enable the ``array_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@PHP71Migration + Using the `@PHP71Migration <./../../ruleSets/PHP71Migration.rst>`_ rule set will enable the ``array_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@PHP73Migration + Using the `@PHP73Migration <./../../ruleSets/PHP73Migration.rst>`_ rule set will enable the ``array_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@PHP74Migration + Using the `@PHP74Migration <./../../ruleSets/PHP74Migration.rst>`_ rule set will enable the ``array_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``array_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``array_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``array_syntax`` rule with the config below: + + ``['syntax' => 'short']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_multiline_whitespace_around_double_arrow.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_multiline_whitespace_around_double_arrow.rst new file mode 100644 index 0000000..de9c2d2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_multiline_whitespace_around_double_arrow.rst @@ -0,0 +1,32 @@ +==================================================== +Rule ``no_multiline_whitespace_around_double_arrow`` +==================================================== + +Operator ``=>`` should not be surrounded by multi-line whitespaces. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = array(1 + - + -=> 2); + +$a = array(1 => 2); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_multiline_whitespace_around_double_arrow`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_multiline_whitespace_around_double_arrow`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_trailing_comma_in_singleline_array.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_trailing_comma_in_singleline_array.rst new file mode 100644 index 0000000..3154b6b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_trailing_comma_in_singleline_array.rst @@ -0,0 +1,30 @@ +============================================== +Rule ``no_trailing_comma_in_singleline_array`` +============================================== + +PHP single-line arrays should not have trailing comma. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = array('sample', ); + +$a = array('sample'); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_trailing_comma_in_singleline_array`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_trailing_comma_in_singleline_array`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_whitespace_before_comma_in_array.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_whitespace_before_comma_in_array.rst new file mode 100644 index 0000000..cac0987 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/no_whitespace_before_comma_in_array.rst @@ -0,0 +1,75 @@ +============================================ +Rule ``no_whitespace_before_comma_in_array`` +============================================ + +In array declaration, there MUST NOT be a whitespace before each comma. + +Configuration +------------- + +``after_heredoc`` +~~~~~~~~~~~~~~~~~ + +Whether the whitespace between heredoc end and comma should be removed. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + -<?php $x = array(1 , "2"); + +<?php $x = array(1, "2"); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['after_heredoc' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $x = [<<<EOD + foo + -EOD + - , 'bar' + +EOD, 'bar' + ]; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP73Migration + Using the `@PHP73Migration <./../../ruleSets/PHP73Migration.rst>`_ rule set will enable the ``no_whitespace_before_comma_in_array`` rule with the config below: + + ``['after_heredoc' => true]`` + +@PHP74Migration + Using the `@PHP74Migration <./../../ruleSets/PHP74Migration.rst>`_ rule set will enable the ``no_whitespace_before_comma_in_array`` rule with the config below: + + ``['after_heredoc' => true]`` + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``no_whitespace_before_comma_in_array`` rule with the config below: + + ``['after_heredoc' => true]`` + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_whitespace_before_comma_in_array`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_whitespace_before_comma_in_array`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/normalize_index_brace.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/normalize_index_brace.rst new file mode 100644 index 0000000..6886082 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/normalize_index_brace.rst @@ -0,0 +1,36 @@ +============================== +Rule ``normalize_index_brace`` +============================== + +Array index should always be written by using square braces. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -echo $sample{$index}; + +echo $sample[$index]; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP74Migration + Using the `@PHP74Migration <./../../ruleSets/PHP74Migration.rst>`_ rule set will enable the ``normalize_index_brace`` rule. + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``normalize_index_brace`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``normalize_index_brace`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``normalize_index_brace`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/trailing_comma_in_multiline_array.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/trailing_comma_in_multiline_array.rst new file mode 100644 index 0000000..32f8020 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/trailing_comma_in_multiline_array.rst @@ -0,0 +1,58 @@ +========================================== +Rule ``trailing_comma_in_multiline_array`` +========================================== + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``trailing_comma_in_multiline`` instead. + +PHP multi-line arrays should have a trailing comma. + +Configuration +------------- + +``after_heredoc`` +~~~~~~~~~~~~~~~~~ + +Whether a trailing comma should also be placed after heredoc end. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + array( + 1, + - 2 + + 2, + ); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['after_heredoc' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $x = [ + 'foo', + <<<EOD + bar + - EOD + + EOD, + ]; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/trim_array_spaces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/trim_array_spaces.rst new file mode 100644 index 0000000..9db9b10 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/trim_array_spaces.rst @@ -0,0 +1,33 @@ +========================== +Rule ``trim_array_spaces`` +========================== + +Arrays should be formatted like function/method arguments, without leading or +trailing single line space. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$sample = array( ); + -$sample = array( 'a', 'b' ); + +$sample = array(); + +$sample = array('a', 'b'); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``trim_array_spaces`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``trim_array_spaces`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/whitespace_after_comma_in_array.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/whitespace_after_comma_in_array.rst new file mode 100644 index 0000000..94a021c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/array_notation/whitespace_after_comma_in_array.rst @@ -0,0 +1,30 @@ +======================================== +Rule ``whitespace_after_comma_in_array`` +======================================== + +In array declaration, there MUST be a whitespace after each comma. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$sample = array(1,'a',$b,); + +$sample = array(1, 'a', $b, ); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``whitespace_after_comma_in_array`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``whitespace_after_comma_in_array`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/braces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/braces.rst new file mode 100644 index 0000000..11e3864 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/braces.rst @@ -0,0 +1,198 @@ +=============== +Rule ``braces`` +=============== + +The body of each structure MUST be enclosed by braces. Braces should be properly +placed. Body of braces should be properly indented. + +Configuration +------------- + +``allow_single_line_anonymous_class_with_empty_body`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether single line anonymous class with empty body notation should be allowed. + +Allowed types: ``bool`` + +Default value: ``false`` + +``allow_single_line_closure`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether single line lambda notation should be allowed. + +Allowed types: ``bool`` + +Default value: ``false`` + +``position_after_functions_and_oop_constructs`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +whether the opening brace should be placed on "next" or "same" line after classy +constructs (non-anonymous classes, interfaces, traits, methods and non-lambda +functions). + +Allowed values: ``'next'``, ``'same'`` + +Default value: ``'next'`` + +``position_after_control_structures`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +whether the opening brace should be placed on "next" or "same" line after +control structures. + +Allowed values: ``'next'``, ``'same'`` + +Default value: ``'same'`` + +``position_after_anonymous_constructs`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +whether the opening brace should be placed on "next" or "same" line after +anonymous constructs (anonymous classes and lambda functions). + +Allowed values: ``'next'``, ``'same'`` + +Default value: ``'same'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -class Foo { + - public function bar($baz) { + - if ($baz = 900) echo "Hello!"; + +class Foo + +{ + + public function bar($baz) + + { + + if ($baz = 900) { + + echo "Hello!"; + + } + + - if ($baz = 9000) + + if ($baz = 9000) { + echo "Wait!"; + + } + + - if ($baz == true) + - { + + if ($baz == true) { + echo "Why?"; + - } + - else + - { + + } else { + echo "Ha?"; + } + + - if (is_array($baz)) + - foreach ($baz as $b) + - { + + if (is_array($baz)) { + + foreach ($baz as $b) { + echo $b; + } + + } + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['allow_single_line_closure' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $positive = function ($item) { return $item >= 0; }; + $negative = function ($item) { + - return $item < 0; }; + + return $item < 0; + +}; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['position_after_functions_and_oop_constructs' => 'same']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -class Foo + -{ + - public function bar($baz) + - { + - if ($baz = 900) echo "Hello!"; + +class Foo { + + public function bar($baz) { + + if ($baz = 900) { + + echo "Hello!"; + + } + + - if ($baz = 9000) + + if ($baz = 9000) { + echo "Wait!"; + + } + + - if ($baz == true) + - { + + if ($baz == true) { + echo "Why?"; + - } + - else + - { + + } else { + echo "Ha?"; + } + + - if (is_array($baz)) + - foreach ($baz as $b) + - { + + if (is_array($baz)) { + + foreach ($baz as $b) { + echo $b; + } + + } + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``braces`` rule with the config below: + + ``['allow_single_line_anonymous_class_with_empty_body' => true]`` + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``braces`` rule with the default config. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``braces`` rule with the config below: + + ``['allow_single_line_anonymous_class_with_empty_body' => true, 'allow_single_line_closure' => true]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``braces`` rule with the config below: + + ``['allow_single_line_anonymous_class_with_empty_body' => true, 'allow_single_line_closure' => true]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/encoding.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/encoding.rst new file mode 100644 index 0000000..43e08e1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/encoding.rst @@ -0,0 +1,40 @@ +================= +Rule ``encoding`` +================= + +PHP code MUST use only UTF-8 without BOM (remove BOM). + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php + +<?php + + echo "Hello!"; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR1 + Using the `@PSR1 <./../../ruleSets/PSR1.rst>`_ rule set will enable the ``encoding`` rule. + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``encoding`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``encoding`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``encoding`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``encoding`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/non_printable_character.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/non_printable_character.rst new file mode 100644 index 0000000..1e19f87 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/non_printable_character.rst @@ -0,0 +1,84 @@ +================================ +Rule ``non_printable_character`` +================================ + +Remove Zero-width space (ZWSP), Non-breaking space (NBSP) and other invisible +unicode symbols. + +.. warning:: Using this rule is risky. + + Risky when strings contain intended invisible characters. + +Configuration +------------- + +``use_escape_sequences_in_strings`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether characters should be replaced with escape sequences in strings. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + -<?php echo "​Hello World !"; + +<?php echo "Hello World !"; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['use_escape_sequences_in_strings' => true]``. + +.. code-block:: diff + + --- Original + +++ New + -<?php echo "​Hello World !"; + +<?php echo "\u{200b}Hello\u{2007}World\u{a0}!"; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP70Migration:risky + Using the `@PHP70Migration:risky <./../../ruleSets/PHP70MigrationRisky.rst>`_ rule set will enable the ``non_printable_character`` rule with the config below: + + ``['use_escape_sequences_in_strings' => true]`` + +@PHP71Migration:risky + Using the `@PHP71Migration:risky <./../../ruleSets/PHP71MigrationRisky.rst>`_ rule set will enable the ``non_printable_character`` rule with the config below: + + ``['use_escape_sequences_in_strings' => true]`` + +@PHP74Migration:risky + Using the `@PHP74Migration:risky <./../../ruleSets/PHP74MigrationRisky.rst>`_ rule set will enable the ``non_printable_character`` rule with the config below: + + ``['use_escape_sequences_in_strings' => true]`` + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``non_printable_character`` rule with the config below: + + ``['use_escape_sequences_in_strings' => true]`` + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``non_printable_character`` rule with the config below: + + ``['use_escape_sequences_in_strings' => true]`` + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``non_printable_character`` rule with the config below: + + ``['use_escape_sequences_in_strings' => true]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr0.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr0.rst new file mode 100644 index 0000000..d78ce49 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr0.rst @@ -0,0 +1,59 @@ +============= +Rule ``psr0`` +============= + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``psr_autoloading`` instead. + +Classes must be in a path that matches their namespace, be at least one +namespace deep and the class name should match the file name. + +.. warning:: Using this rule is risky. + + This fixer may change your class name, which will break the code that depends + on the old name. + +Configuration +------------- + +``dir`` +~~~~~~~ + +The directory where the project code is placed. + +Allowed types: ``string`` + +Default value: ``''`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace PhpCsFixer\FIXER\Basic; + -class InvalidName {} + +class PsrAutoloadingFixer {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['dir' => './src']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -namespace PhpCsFixer\FIXER\Basic; + -class InvalidName {} + +namespace PhpCsFixer\Fixer\Basic; + +class PsrAutoloadingFixer {} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr4.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr4.rst new file mode 100644 index 0000000..b9775c4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr4.rst @@ -0,0 +1,29 @@ +============= +Rule ``psr4`` +============= + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``psr_autoloading`` instead. + +Class names should match the file name. + +.. warning:: Using this rule is risky. + + This fixer may change your class name, which will break the code that depends + on the old name. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace PhpCsFixer\FIXER\Basic; + -class InvalidName {} + +class PsrAutoloadingFixer {} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr_autoloading.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr_autoloading.rst new file mode 100644 index 0000000..a5460ce --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/basic/psr_autoloading.rst @@ -0,0 +1,66 @@ +======================== +Rule ``psr_autoloading`` +======================== + +Classes must be in a path that matches their namespace, be at least one +namespace deep and the class name should match the file name. + +.. warning:: Using this rule is risky. + + This fixer may change your class name, which will break the code that depends + on the old name. + +Configuration +------------- + +``dir`` +~~~~~~~ + +If provided, the directory where the project code is placed. + +Allowed types: ``null``, ``string`` + +Default value: ``null`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace PhpCsFixer\FIXER\Basic; + -class InvalidName {} + +class PsrAutoloadingFixer {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['dir' => './src']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -namespace PhpCsFixer\FIXER\Basic; + -class InvalidName {} + +namespace PhpCsFixer\Fixer\Basic; + +class PsrAutoloadingFixer {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``psr_autoloading`` rule with the default config. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``psr_autoloading`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/constant_case.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/constant_case.rst new file mode 100644 index 0000000..97f8508 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/constant_case.rst @@ -0,0 +1,71 @@ +====================== +Rule ``constant_case`` +====================== + +The PHP constants ``true``, ``false``, and ``null`` MUST be written using the +correct casing. + +Configuration +------------- + +``case`` +~~~~~~~~ + +Whether to use the ``upper`` or ``lower`` case syntax. + +Allowed values: ``'lower'``, ``'upper'`` + +Default value: ``'lower'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = FALSE; + -$b = True; + -$c = nuLL; + +$a = false; + +$b = true; + +$c = null; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['case' => 'upper']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = FALSE; + -$b = True; + -$c = nuLL; + +$b = TRUE; + +$c = NULL; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``constant_case`` rule with the default config. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``constant_case`` rule with the default config. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``constant_case`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``constant_case`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_constants.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_constants.rst new file mode 100644 index 0000000..79a6ca7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_constants.rst @@ -0,0 +1,27 @@ +============================ +Rule ``lowercase_constants`` +============================ + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``constant_case`` instead. + +The PHP constants ``true``, ``false``, and ``null`` MUST be in lower case. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = FALSE; + -$b = True; + -$c = nuLL; + +$a = false; + +$b = true; + +$c = null; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_keywords.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_keywords.rst new file mode 100644 index 0000000..1d5479a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_keywords.rst @@ -0,0 +1,51 @@ +=========================== +Rule ``lowercase_keywords`` +=========================== + +PHP keywords MUST be in lower case. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + - FOREACH($a AS $B) { + - TRY { + - NEW $C($a, ISSET($B)); + - WHILE($B) { + - INCLUDE "test.php"; + + foreach($a as $B) { + + try { + + new $C($a, isset($B)); + + while($B) { + + include "test.php"; + } + - } CATCH(\Exception $e) { + - EXIT(1); + + } catch(\Exception $e) { + + exit(1); + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``lowercase_keywords`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``lowercase_keywords`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``lowercase_keywords`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``lowercase_keywords`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_static_reference.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_static_reference.rst new file mode 100644 index 0000000..02b5879 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/lowercase_static_reference.rst @@ -0,0 +1,69 @@ +=================================== +Rule ``lowercase_static_reference`` +=================================== + +Class static references ``self``, ``static`` and ``parent`` MUST be in lower +case. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo extends Bar + { + public function baz1() + { + - return STATIC::baz2(); + + return static::baz2(); + } + + public function baz2($x) + { + - return $x instanceof Self; + + return $x instanceof self; + } + + - public function baz3(PaRent $x) + + public function baz3(parent $x) + { + return true; + } + } + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo extends Bar + { + - public function baz(?self $x) : SELF + + public function baz(?self $x) : self + { + return false; + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``lowercase_static_reference`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``lowercase_static_reference`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``lowercase_static_reference`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/magic_constant_casing.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/magic_constant_casing.rst new file mode 100644 index 0000000..c9842b9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/magic_constant_casing.rst @@ -0,0 +1,30 @@ +============================== +Rule ``magic_constant_casing`` +============================== + +Magic constants should be referred to using the correct casing. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -echo __dir__; + +echo __DIR__; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``magic_constant_casing`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``magic_constant_casing`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/magic_method_casing.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/magic_method_casing.rst new file mode 100644 index 0000000..6a12e2a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/magic_method_casing.rst @@ -0,0 +1,46 @@ +============================ +Rule ``magic_method_casing`` +============================ + +Magic method definitions and calls must be using the correct casing. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo + { + - public function __Sleep() + + public function __sleep() + { + } + } + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$foo->__INVOKE(1); + +$foo->__invoke(1); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``magic_method_casing`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``magic_method_casing`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/native_function_casing.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/native_function_casing.rst new file mode 100644 index 0000000..bc5be0e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/native_function_casing.rst @@ -0,0 +1,30 @@ +=============================== +Rule ``native_function_casing`` +=============================== + +Function defined by PHP should be called using the correct casing. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -STRLEN($str); + +strlen($str); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``native_function_casing`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``native_function_casing`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/native_function_type_declaration_casing.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/native_function_type_declaration_casing.rst new file mode 100644 index 0000000..3474a32 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/casing/native_function_type_declaration_casing.rst @@ -0,0 +1,77 @@ +================================================ +Rule ``native_function_type_declaration_casing`` +================================================ + +Native type hints for functions should use the correct case. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Bar { + - public function Foo(CALLABLE $bar) + + public function Foo(callable $bar) + { + return 1; + } + } + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -function Foo(INT $a): Bool + +function Foo(int $a): bool + { + return true; + } + +Example #3 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -function Foo(Iterable $a): VOID + +function Foo(iterable $a): void + { + echo 'Hello world'; + } + +Example #4 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -function Foo(Object $a) + +function Foo(object $a) + { + return 'hi!'; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``native_function_type_declaration_casing`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``native_function_type_declaration_casing`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/cast_spaces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/cast_spaces.rst new file mode 100644 index 0000000..a73c114 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/cast_spaces.rst @@ -0,0 +1,76 @@ +==================== +Rule ``cast_spaces`` +==================== + +A single space or none should be between cast and variable. + +Configuration +------------- + +``space`` +~~~~~~~~~ + +spacing to apply between cast and variable. + +Allowed values: ``'none'``, ``'single'`` + +Default value: ``'single'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$bar = ( string ) $a; + -$foo = (int)$b; + +$bar = (string) $a; + +$foo = (int) $b; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['space' => 'single']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$bar = ( string ) $a; + -$foo = (int)$b; + +$bar = (string) $a; + +$foo = (int) $b; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['space' => 'none']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$bar = ( string ) $a; + -$foo = (int) $b; + +$bar = (string)$a; + +$foo = (int)$b; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``cast_spaces`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``cast_spaces`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/lowercase_cast.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/lowercase_cast.rst new file mode 100644 index 0000000..b910979 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/lowercase_cast.rst @@ -0,0 +1,90 @@ +======================= +Rule ``lowercase_cast`` +======================= + +Cast should be written in lower case. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + - $a = (BOOLEAN) $b; + - $a = (BOOL) $b; + - $a = (INTEGER) $b; + - $a = (INT) $b; + - $a = (DOUBLE) $b; + - $a = (FLoaT) $b; + - $a = (reaL) $b; + - $a = (flOAT) $b; + - $a = (sTRING) $b; + - $a = (ARRAy) $b; + - $a = (OBJect) $b; + - $a = (UNset) $b; + - $a = (Binary) $b; + + $a = (boolean) $b; + + $a = (bool) $b; + + $a = (integer) $b; + + $a = (int) $b; + + $a = (double) $b; + + $a = (float) $b; + + $a = (real) $b; + + $a = (float) $b; + + $a = (string) $b; + + $a = (array) $b; + + $a = (object) $b; + + $a = (unset) $b; + + $a = (binary) $b; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + - $a = (BOOLEAN) $b; + - $a = (BOOL) $b; + - $a = (INTEGER) $b; + - $a = (INT) $b; + - $a = (DOUBLE) $b; + - $a = (FLoaT) $b; + - $a = (flOAT) $b; + - $a = (sTRING) $b; + - $a = (ARRAy) $b; + - $a = (OBJect) $b; + - $a = (UNset) $b; + - $a = (Binary) $b; + + $a = (boolean) $b; + + $a = (bool) $b; + + $a = (integer) $b; + + $a = (int) $b; + + $a = (double) $b; + + $a = (float) $b; + + $a = (float) $b; + + $a = (string) $b; + + $a = (array) $b; + + $a = (object) $b; + + $a = (unset) $b; + + $a = (binary) $b; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``lowercase_cast`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``lowercase_cast`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``lowercase_cast`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/modernize_types_casting.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/modernize_types_casting.rst new file mode 100644 index 0000000..8b575f2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/modernize_types_casting.rst @@ -0,0 +1,44 @@ +================================ +Rule ``modernize_types_casting`` +================================ + +Replaces ``intval``, ``floatval``, ``doubleval``, ``strval`` and ``boolval`` +function calls with according type casting operator. + +.. warning:: Using this rule is risky. + + Risky if any of the functions ``intval``, ``floatval``, ``doubleval``, + ``strval`` or ``boolval`` are overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + - $a = intval($b); + - $a = floatval($b); + - $a = doubleval($b); + - $a = strval ($b); + - $a = boolval($b); + + $a = (int) $b; + + $a = (float) $b; + + $a = (float) $b; + + $a = (string) $b; + + $a = (bool) $b; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``modernize_types_casting`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``modernize_types_casting`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/no_short_bool_cast.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/no_short_bool_cast.rst new file mode 100644 index 0000000..25008de --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/no_short_bool_cast.rst @@ -0,0 +1,30 @@ +=========================== +Rule ``no_short_bool_cast`` +=========================== + +Short cast ``bool`` using double exclamation mark should not be used. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = !!$b; + +$a = (bool)$b; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_short_bool_cast`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_short_bool_cast`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/no_unset_cast.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/no_unset_cast.rst new file mode 100644 index 0000000..f972fb8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/no_unset_cast.rst @@ -0,0 +1,33 @@ +====================== +Rule ``no_unset_cast`` +====================== + +Variables must be set ``null`` instead of using ``(unset)`` casting. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = (unset) $b; + +$a = null; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``no_unset_cast`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_unset_cast`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_unset_cast`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/short_scalar_cast.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/short_scalar_cast.rst new file mode 100644 index 0000000..e470fb3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/cast_notation/short_scalar_cast.rst @@ -0,0 +1,68 @@ +========================== +Rule ``short_scalar_cast`` +========================== + +Cast ``(boolean)`` and ``(integer)`` should be written as ``(bool)`` and +``(int)``, ``(double)`` and ``(real)`` as ``(float)``, ``(binary)`` as +``(string)``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = (boolean) $b; + -$a = (integer) $b; + -$a = (double) $b; + -$a = (real) $b; + +$a = (bool) $b; + +$a = (int) $b; + +$a = (float) $b; + +$a = (float) $b; + + -$a = (binary) $b; + +$a = (string) $b; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = (boolean) $b; + -$a = (integer) $b; + -$a = (double) $b; + +$a = (bool) $b; + +$a = (int) $b; + +$a = (float) $b; + + -$a = (binary) $b; + +$a = (string) $b; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP74Migration + Using the `@PHP74Migration <./../../ruleSets/PHP74Migration.rst>`_ rule set will enable the ``short_scalar_cast`` rule. + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``short_scalar_cast`` rule. + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``short_scalar_cast`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``short_scalar_cast`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``short_scalar_cast`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/class_attributes_separation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/class_attributes_separation.rst new file mode 100644 index 0000000..fe7087d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/class_attributes_separation.rst @@ -0,0 +1,96 @@ +==================================== +Rule ``class_attributes_separation`` +==================================== + +Class, trait and interface elements must be separated with one or none blank +line. + +Configuration +------------- + +``elements`` +~~~~~~~~~~~~ + +Dictionary of ``const|method|property|trait_import`` => ``none|one`` values. + +Allowed types: ``array`` + +Default value: ``['const' => 'one', 'method' => 'one', 'property' => 'one', 'trait_import' => 'one']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Sample + { + protected function foo() + { + } + + + protected function bar() + { + } + - + - + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['elements' => ['property' => 'one']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Sample + -{private $a; // a is awesome + +{ + +private $a; // a is awesome + + + /** second in a hour */ + private $b; + } + +Example #3 +~~~~~~~~~~ + +With configuration: ``['elements' => ['const' => 'one']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Sample + { + const A = 1; + + + /** seconds in some hours */ + const B = 3600; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``class_attributes_separation`` rule with the config below: + + ``['elements' => ['method' => 'one']]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``class_attributes_separation`` rule with the config below: + + ``['elements' => ['method' => 'one']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/class_definition.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/class_definition.rst new file mode 100644 index 0000000..d94f66a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/class_definition.rst @@ -0,0 +1,158 @@ +========================= +Rule ``class_definition`` +========================= + +Whitespace around the keywords of a class, trait or interfaces definition should +be one space. + +Configuration +------------- + +``multi_line_extends_each_single_line`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether definitions should be multiline. + +.. note:: The previous name of this option was ``multiLineExtendsEachSingleLine`` but it is now deprecated and will be removed on next major version. + +Allowed types: ``bool`` + +Default value: ``false`` + +``single_item_single_line`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether definitions should be single line when including a single item. + +.. note:: The previous name of this option was ``singleItemSingleLine`` but it is now deprecated and will be removed on next major version. + +Allowed types: ``bool`` + +Default value: ``false`` + +``single_line`` +~~~~~~~~~~~~~~~ + +Whether definitions should be single line. + +.. note:: The previous name of this option was ``singleLine`` but it is now deprecated and will be removed on next major version. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -class Foo extends Bar implements Baz, BarBaz + +class Foo extends Bar implements Baz, BarBaz + { + } + + -final class Foo extends Bar implements Baz, BarBaz + +final class Foo extends Bar implements Baz, BarBaz + { + } + + -trait Foo + +trait Foo + { + } + +Example #2 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -$foo = new class extends Bar implements Baz, BarBaz {}; + +$foo = new class extends Bar implements Baz, BarBaz {}; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['single_line' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -class Foo + -extends Bar + -implements Baz, BarBaz + +class Foo extends Bar implements Baz, BarBaz + {} + +Example #4 +~~~~~~~~~~ + +With configuration: ``['single_item_single_line' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -class Foo + -extends Bar + -implements Baz + +class Foo extends Bar implements Baz + {} + +Example #5 +~~~~~~~~~~ + +With configuration: ``['multi_line_extends_each_single_line' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + interface Bar extends + - Bar, BarBaz, FooBarBaz + + Bar, + + BarBaz, + + FooBarBaz + {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``class_definition`` rule with the default config. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``class_definition`` rule with the default config. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``class_definition`` rule with the config below: + + ``['single_line' => true]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``class_definition`` rule with the config below: + + ``['single_line' => true]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_class.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_class.rst new file mode 100644 index 0000000..c727078 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_class.rst @@ -0,0 +1,36 @@ +==================== +Rule ``final_class`` +==================== + +All classes must be final, except abstract ones and Doctrine entities. + +Description +----------- + +No exception and no configuration are intentional. Beside Doctrine entities and +of course abstract classes, there is no single reason not to declare all classes +final. If you want to subclass a class, mark the parent class as abstract and +create two child classes, one empty if necessary: you'll gain much more fine +grained type-hinting. If you need to mock a standalone class, create an +interface, or maybe it's a value-object that shouldn't be mocked at all. If you +need to extend a standalone class, create an interface and use the Composite +pattern. If you aren't ready yet for serious OOP, go with +FinalInternalClassFixer, it's fine. + +.. warning:: Using this rule is risky. + + Risky when subclassing non-abstract classes. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -class MyApp {} + +final class MyApp {} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_internal_class.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_internal_class.rst new file mode 100644 index 0000000..eb9ddb2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_internal_class.rst @@ -0,0 +1,98 @@ +============================= +Rule ``final_internal_class`` +============================= + +Internal classes should be ``final``. + +.. warning:: Using this rule is risky. + + Changing classes to ``final`` might cause code execution to break. + +Configuration +------------- + +``annotation_include`` +~~~~~~~~~~~~~~~~~~~~~~ + +Class level annotations tags that must be set in order to fix the class. (case +insensitive) + +.. note:: The previous name of this option was ``annotation-white-list`` but it is now deprecated and will be removed on next major version. + +Allowed types: ``array`` + +Default value: ``['@internal']`` + +``annotation_exclude`` +~~~~~~~~~~~~~~~~~~~~~~ + +Class level annotations tags that must be omitted to fix the class, even if all +of the white list ones are used as well. (case insensitive) + +.. note:: The previous name of this option was ``annotation-black-list`` but it is now deprecated and will be removed on next major version. + +Allowed types: ``array`` + +Default value: ``['@final', '@Entity', '@ORM\\Entity', '@ORM\\Mapping\\Entity', '@Mapping\\Entity', '@Document', '@ODM\\Document']`` + +``consider_absent_docblock_as_internal_class`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Should classes without any DocBlock be fixed to final? + +.. note:: The previous name of this option was ``consider-absent-docblock-as-internal-class`` but it is now deprecated and will be removed on next major version. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @internal + */ + -class Sample + +final class Sample + { + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['annotation_include' => ['@Custom'], 'annotation_exclude' => ['@not-fix']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @CUSTOM + */ + -class A{} + +final class A{} + + /** + * @CUSTOM + * @not-fix + */ + class B{} + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``final_internal_class`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_public_method_for_abstract_class.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_public_method_for_abstract_class.rst new file mode 100644 index 0000000..6645548 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_public_method_for_abstract_class.rst @@ -0,0 +1,34 @@ +=============================================== +Rule ``final_public_method_for_abstract_class`` +=============================================== + +All ``public`` methods of ``abstract`` classes should be ``final``. + +Description +----------- + +Enforce API encapsulation in an inheritance architecture. If you want to +override a method, use the Template method pattern. + +.. warning:: Using this rule is risky. + + Risky when overriding ``public`` methods of ``abstract`` classes. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + abstract class AbstractMachine + { + - public function start() + + final public function start() + {} + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_static_access.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_static_access.rst new file mode 100644 index 0000000..59ea115 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/final_static_access.rst @@ -0,0 +1,29 @@ +============================ +Rule ``final_static_access`` +============================ + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``self_static_accessor`` instead. + +Converts ``static`` access to ``self`` access in ``final`` classes. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Sample + { + public function getFoo() + { + - return static::class; + + return self::class; + } + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/method_separation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/method_separation.rst new file mode 100644 index 0000000..9594530 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/method_separation.rst @@ -0,0 +1,31 @@ +========================== +Rule ``method_separation`` +========================== + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``class_attributes_separation`` instead. + +Methods must be separated with one blank line. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Sample + { + protected function foo() + { + } + + + protected function bar() + { + } + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_blank_lines_after_class_opening.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_blank_lines_after_class_opening.rst new file mode 100644 index 0000000..f871836 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_blank_lines_after_class_opening.rst @@ -0,0 +1,38 @@ +=========================================== +Rule ``no_blank_lines_after_class_opening`` +=========================================== + +There should be no empty lines after class opening brace. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Sample + { + - + protected function foo() + { + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``no_blank_lines_after_class_opening`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_blank_lines_after_class_opening`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_blank_lines_after_class_opening`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_null_property_initialization.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_null_property_initialization.rst new file mode 100644 index 0000000..d4c23e5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_null_property_initialization.rst @@ -0,0 +1,43 @@ +======================================== +Rule ``no_null_property_initialization`` +======================================== + +Properties MUST not be explicitly initialized with ``null`` except when they +have a type declaration (PHP 7.4). + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo { + - public $foo = null; + + public $foo; + } + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo { + - public static $foo = null; + + public static $foo; + } + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_null_property_initialization`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_php4_constructor.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_php4_constructor.rst new file mode 100644 index 0000000..e268ca9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_php4_constructor.rst @@ -0,0 +1,43 @@ +============================ +Rule ``no_php4_constructor`` +============================ + +Convert PHP4-style constructors to ``__construct``. + +.. warning:: Using this rule is risky. + + Risky when old style constructor being fixed is overridden or overrides + parent one. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo + { + - public function Foo($bar) + + public function __construct($bar) + { + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``no_php4_constructor`` rule. + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``no_php4_constructor`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``no_php4_constructor`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_unneeded_final_method.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_unneeded_final_method.rst new file mode 100644 index 0000000..1544c22 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/no_unneeded_final_method.rst @@ -0,0 +1,86 @@ +================================= +Rule ``no_unneeded_final_method`` +================================= + +A ``final`` class must not have ``final`` methods and ``private`` methods must +not be ``final``. + +.. warning:: Using this rule is risky. + + Risky when child class overrides a ``private`` method. + +Configuration +------------- + +``private_methods`` +~~~~~~~~~~~~~~~~~~~ + +Private methods of non-``final`` classes must not be declared ``final``. + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Foo + { + - final public function foo1() {} + - final protected function bar() {} + - final private function baz() {} + + public function foo1() {} + + protected function bar() {} + + private function baz() {} + } + + class Bar + { + - final private function bar1() {} + + private function bar1() {} + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['private_methods' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Foo + { + - final private function baz() {} + + private function baz() {} + } + + class Bar + { + final private function bar1() {} + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``no_unneeded_final_method`` rule with the default config. + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``no_unneeded_final_method`` rule with the default config. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``no_unneeded_final_method`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_class_elements.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_class_elements.rst new file mode 100644 index 0000000..811a9a7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_class_elements.rst @@ -0,0 +1,135 @@ +=============================== +Rule ``ordered_class_elements`` +=============================== + +Orders the elements of classes/interfaces/traits. + +Configuration +------------- + +``order`` +~~~~~~~~~ + +List of strings defining order of elements. + +Allowed values: a subset of ``['use_trait', 'public', 'protected', 'private', 'constant', 'constant_public', 'constant_protected', 'constant_private', 'property', 'property_static', 'property_public', 'property_protected', 'property_private', 'property_public_static', 'property_protected_static', 'property_private_static', 'method', 'method_abstract', 'method_static', 'method_public', 'method_protected', 'method_private', 'method_public_abstract', 'method_protected_abstract', 'method_public_abstract_static', 'method_protected_abstract_static', 'method_public_static', 'method_protected_static', 'method_private_static', 'construct', 'destruct', 'magic', 'phpunit']`` + +Default value: ``['use_trait', 'constant_public', 'constant_protected', 'constant_private', 'property_public', 'property_protected', 'property_private', 'construct', 'destruct', 'magic', 'phpunit', 'method_public', 'method_protected', 'method_private']`` + +``sort_algorithm`` +~~~~~~~~~~~~~~~~~~ + +How multiple occurrences of same type statements should be sorted + +.. note:: The previous name of this option was ``sortAlgorithm`` but it is now deprecated and will be removed on next major version. + +Allowed values: ``'alpha'``, ``'none'`` + +Default value: ``'none'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Example + { + use BarTrait; + use BazTrait; + const C1 = 1; + const C2 = 2; + - protected static $protStatProp; + public static $pubStatProp1; + public $pubProp1; + + var $pubProp2; + + public static $pubStatProp2; + + public $pubProp3; + + protected static $protStatProp; + protected $protProp; + - var $pubProp2; + private static $privStatProp; + private $privProp; + - public static $pubStatProp2; + - public $pubProp3; + protected function __construct() {} + - private static function privStatFunc() {} + + public function __destruct() {} + + public function __toString() {} + public function pubFunc1() {} + - public function __toString() {} + - protected function protFunc() {} + function pubFunc2() {} + public static function pubStatFunc1() {} + public function pubFunc3() {} + static function pubStatFunc2() {} + - private function privFunc() {} + public static function pubStatFunc3() {} + + protected function protFunc() {} + protected static function protStatFunc() {} + - public function __destruct() {} + + private static function privStatFunc() {} + + private function privFunc() {} + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['order' => ['method_private', 'method_public']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Example + { + + private function B(){} + public function A(){} + - private function B(){} + } + +Example #3 +~~~~~~~~~~ + +With configuration: ``['order' => ['method_public'], 'sort_algorithm' => 'alpha']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Example + { + - public function D(){} + + public function A(){} + public function B(){} + - public function A(){} + public function C(){} + + public function D(){} + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``ordered_class_elements`` rule with the config below: + + ``['order' => ['use_trait']]`` + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``ordered_class_elements`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``ordered_class_elements`` rule with the config below: + + ``['order' => ['use_trait']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_interfaces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_interfaces.rst new file mode 100644 index 0000000..d543f74 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_interfaces.rst @@ -0,0 +1,103 @@ +=========================== +Rule ``ordered_interfaces`` +=========================== + +Orders the interfaces in an ``implements`` or ``interface extends`` clause. + +.. warning:: Using this rule is risky. + + Risky for ``implements`` when specifying both an interface and its parent + interface, because PHP doesn't break on ``parent, child`` but does on + ``child, parent``. + +Configuration +------------- + +``order`` +~~~~~~~~~ + +How the interfaces should be ordered + +Allowed values: ``'alpha'``, ``'length'`` + +Default value: ``'alpha'`` + +``direction`` +~~~~~~~~~~~~~ + +Which direction the interfaces should be ordered + +Allowed values: ``'ascend'``, ``'descend'`` + +Default value: ``'ascend'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -final class ExampleA implements Gamma, Alpha, Beta {} + +final class ExampleA implements Alpha, Beta, Gamma {} + + -interface ExampleB extends Gamma, Alpha, Beta {} + +interface ExampleB extends Alpha, Beta, Gamma {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['direction' => 'descend']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -final class ExampleA implements Gamma, Alpha, Beta {} + +final class ExampleA implements Gamma, Beta, Alpha {} + + -interface ExampleB extends Gamma, Alpha, Beta {} + +interface ExampleB extends Gamma, Beta, Alpha {} + +Example #3 +~~~~~~~~~~ + +With configuration: ``['order' => 'length']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -final class ExampleA implements MuchLonger, Short, Longer {} + +final class ExampleA implements Short, Longer, MuchLonger {} + + -interface ExampleB extends MuchLonger, Short, Longer {} + +interface ExampleB extends Short, Longer, MuchLonger {} + +Example #4 +~~~~~~~~~~ + +With configuration: ``['order' => 'length', 'direction' => 'descend']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -final class ExampleA implements MuchLonger, Short, Longer {} + +final class ExampleA implements MuchLonger, Longer, Short {} + + -interface ExampleB extends MuchLonger, Short, Longer {} + +interface ExampleB extends MuchLonger, Longer, Short {} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_traits.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_traits.rst new file mode 100644 index 0000000..764e70e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/ordered_traits.rst @@ -0,0 +1,34 @@ +======================= +Rule ``ordered_traits`` +======================= + +Trait ``use`` statements must be sorted alphabetically. + +.. warning:: Using this rule is risky. + + Risky when depending on order of the imports. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php class Foo { + -use Z; use A; } + +use A; use Z; } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``ordered_traits`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``ordered_traits`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/protected_to_private.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/protected_to_private.rst new file mode 100644 index 0000000..8146104 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/protected_to_private.rst @@ -0,0 +1,38 @@ +============================= +Rule ``protected_to_private`` +============================= + +Converts ``protected`` variables and methods to ``private`` where possible. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Sample + { + - protected $a; + + private $a; + + - protected function test() + + private function test() + { + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``protected_to_private`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``protected_to_private`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/self_accessor.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/self_accessor.rst new file mode 100644 index 0000000..c7b519b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/self_accessor.rst @@ -0,0 +1,46 @@ +====================== +Rule ``self_accessor`` +====================== + +Inside class or interface element ``self`` should be preferred to the class name +itself. + +.. warning:: Using this rule is risky. + + Risky when using dynamic calls like get_called_class() or late static + binding. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Sample + { + const BAZ = 1; + - const BAR = Sample::BAZ; + + const BAR = self::BAZ; + + public function getBar() + { + - return Sample::BAR; + + return self::BAR; + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``self_accessor`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``self_accessor`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/self_static_accessor.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/self_static_accessor.rst new file mode 100644 index 0000000..bff0ff3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/self_static_accessor.rst @@ -0,0 +1,83 @@ +============================= +Rule ``self_static_accessor`` +============================= + +Inside a ``final`` class or anonymous class ``self`` should be preferred to +``static``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Sample + { + private static $A = 1; + + public function getBar() + { + - return static::class.static::test().static::$A; + + return self::class.self::test().self::$A; + } + + private static function test() + { + return 'test'; + } + } + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Foo + { + public function bar() + { + - return new static(); + + return new self(); + } + } + +Example #3 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Foo + { + public function isBar() + { + - return $foo instanceof static; + + return $foo instanceof self; + } + } + +Example #4 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = new class() { + public function getBar() + { + - return static::class; + + return self::class; + } + }; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/single_class_element_per_statement.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/single_class_element_per_statement.rst new file mode 100644 index 0000000..896534f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/single_class_element_per_statement.rst @@ -0,0 +1,79 @@ +=========================================== +Rule ``single_class_element_per_statement`` +=========================================== + +There MUST NOT be more than one property or constant declared per statement. + +Configuration +------------- + +``elements`` +~~~~~~~~~~~~ + +List of strings which element should be modified. + +Allowed values: a subset of ``['const', 'property']`` + +Default value: ``['const', 'property']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Example + { + - const FOO_1 = 1, FOO_2 = 2; + - private static $bar1 = array(1,2,3), $bar2 = [1,2,3]; + + const FOO_1 = 1; + + const FOO_2 = 2; + + private static $bar1 = array(1,2,3); + + private static $bar2 = [1,2,3]; + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['elements' => ['property']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Example + { + const FOO_1 = 1, FOO_2 = 2; + - private static $bar1 = array(1,2,3), $bar2 = [1,2,3]; + + private static $bar1 = array(1,2,3); + + private static $bar2 = [1,2,3]; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``single_class_element_per_statement`` rule with the config below: + + ``['elements' => ['property']]`` + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``single_class_element_per_statement`` rule with the config below: + + ``['elements' => ['property']]`` + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``single_class_element_per_statement`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``single_class_element_per_statement`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/single_trait_insert_per_statement.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/single_trait_insert_per_statement.rst new file mode 100644 index 0000000..dbda024 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/single_trait_insert_per_statement.rst @@ -0,0 +1,36 @@ +========================================== +Rule ``single_trait_insert_per_statement`` +========================================== + +Each trait ``use`` must be done as single statement. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Example + { + - use Foo, Bar; + + use Foo;use Bar; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``single_trait_insert_per_statement`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``single_trait_insert_per_statement`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``single_trait_insert_per_statement`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/visibility_required.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/visibility_required.rst new file mode 100644 index 0000000..3214206 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_notation/visibility_required.rst @@ -0,0 +1,100 @@ +============================ +Rule ``visibility_required`` +============================ + +Visibility MUST be declared on all properties and methods; ``abstract`` and +``final`` MUST be declared before the visibility; ``static`` MUST be declared +after the visibility. + +Configuration +------------- + +``elements`` +~~~~~~~~~~~~ + +The structural elements to fix (PHP >= 7.1 required for ``const``). + +Allowed values: a subset of ``['property', 'method', 'const']`` + +Default value: ``['property', 'method']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Sample + { + - var $a; + - static protected $var_foo2; + + public $a; + + protected static $var_foo2; + + - function A() + + public function A() + { + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['elements' => ['const']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Sample + { + - const SAMPLE = 1; + + public const SAMPLE = 1; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP71Migration + Using the `@PHP71Migration <./../../ruleSets/PHP71Migration.rst>`_ rule set will enable the ``visibility_required`` rule with the config below: + + ``['elements' => ['const', 'method', 'property']]`` + +@PHP73Migration + Using the `@PHP73Migration <./../../ruleSets/PHP73Migration.rst>`_ rule set will enable the ``visibility_required`` rule with the config below: + + ``['elements' => ['const', 'method', 'property']]`` + +@PHP74Migration + Using the `@PHP74Migration <./../../ruleSets/PHP74Migration.rst>`_ rule set will enable the ``visibility_required`` rule with the config below: + + ``['elements' => ['const', 'method', 'property']]`` + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``visibility_required`` rule with the config below: + + ``['elements' => ['const', 'method', 'property']]`` + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``visibility_required`` rule with the config below: + + ``['elements' => ['const', 'method', 'property']]`` + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``visibility_required`` rule with the default config. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``visibility_required`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``visibility_required`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/class_usage/date_time_immutable.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_usage/date_time_immutable.rst new file mode 100644 index 0000000..ae31f94 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/class_usage/date_time_immutable.rst @@ -0,0 +1,24 @@ +============================ +Rule ``date_time_immutable`` +============================ + +Class ``DateTimeImmutable`` should be used instead of ``DateTime``. + +.. warning:: Using this rule is risky. + + Risky when the code relies on modifying ``DateTime`` objects or if any of the + ``date_create*`` functions are overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -new DateTime(); + +new DateTimeImmutable(); diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/comment_to_phpdoc.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/comment_to_phpdoc.rst new file mode 100644 index 0000000..b8bd243 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/comment_to_phpdoc.rst @@ -0,0 +1,62 @@ +========================== +Rule ``comment_to_phpdoc`` +========================== + +Comments with annotation should be docblock when used on structural elements. + +.. warning:: Using this rule is risky. + + Risky as new docblocks might mean more, e.g. a Doctrine entity might have a + new column in database. + +Configuration +------------- + +``ignored_tags`` +~~~~~~~~~~~~~~~~ + +List of ignored tags + +Allowed types: ``array`` + +Default value: ``[]`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + -<?php /* header */ $x = true; /* @var bool $isFoo */ $isFoo = true; + +<?php /* header */ $x = true; /** @var bool $isFoo */ $isFoo = true; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['ignored_tags' => ['todo']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + // @todo do something later + $foo = 1; + + -// @var int $a + +/** @var int $a */ + $a = foo(); + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``comment_to_phpdoc`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/hash_to_slash_comment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/hash_to_slash_comment.rst new file mode 100644 index 0000000..92dc41b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/hash_to_slash_comment.rst @@ -0,0 +1,22 @@ +============================== +Rule ``hash_to_slash_comment`` +============================== + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``single_line_comment_style`` instead. + +Single line comments should use double slashes ``//`` and not hash ``#``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php # comment + +<?php // comment diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/header_comment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/header_comment.rst new file mode 100644 index 0000000..d679ee4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/header_comment.rst @@ -0,0 +1,129 @@ +======================= +Rule ``header_comment`` +======================= + +Add, replace or remove header comment. + +Configuration +------------- + +``header`` +~~~~~~~~~~ + +Proper header content. + +Allowed types: ``string`` + +This option is required. + +``comment_type`` +~~~~~~~~~~~~~~~~ + +Comment syntax type. + +.. note:: The previous name of this option was ``commentType`` but it is now deprecated and will be removed on next major version. + +Allowed values: ``'comment'``, ``'PHPDoc'`` + +Default value: ``'comment'`` + +``location`` +~~~~~~~~~~~~ + +The location of the inserted header. + +Allowed values: ``'after_declare_strict'``, ``'after_open'`` + +Default value: ``'after_declare_strict'`` + +``separate`` +~~~~~~~~~~~~ + +Whether the header should be separated from the file content with a new line. + +Allowed values: ``'both'``, ``'bottom'``, ``'none'``, ``'top'`` + +Default value: ``'both'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +With configuration: ``['header' => 'Made with love.']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + declare(strict_types=1); + + +/* + + * Made with love. + + */ + + + namespace A\B; + + echo 1; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['header' => 'Made with love.', 'comment_type' => 'PHPDoc', 'location' => 'after_open', 'separate' => 'bottom']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + +/** + + * Made with love. + + */ + + + declare(strict_types=1); + + namespace A\B; + + echo 1; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['header' => 'Made with love.', 'comment_type' => 'comment', 'location' => 'after_declare_strict']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + declare(strict_types=1); + + +/* + + * Made with love. + + */ + + + namespace A\B; + + echo 1; + +Example #4 +~~~~~~~~~~ + +With configuration: ``['header' => '']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + declare(strict_types=1); + + -/* + - * Comment is not wanted here. + - */ + - + namespace A\B; + + echo 1; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/multiline_comment_opening_closing.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/multiline_comment_opening_closing.rst new file mode 100644 index 0000000..d4641ca --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/multiline_comment_opening_closing.rst @@ -0,0 +1,43 @@ +========================================== +Rule ``multiline_comment_opening_closing`` +========================================== + +DocBlocks must start with two asterisks, multiline comments must start with a +single asterisk, after the opening slash. Both must end with a single asterisk +before the closing slash. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + -/****** + +/* + * Multiline comment with arbitrary asterisks count + - ******/ + + */ + + -/**\ + +/*\ + * Multiline comment that seems a DocBlock + */ + + /** + * DocBlock with arbitrary asterisk count at the end + - **/ + + */ + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``multiline_comment_opening_closing`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/no_empty_comment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/no_empty_comment.rst new file mode 100644 index 0000000..0dffd40 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/no_empty_comment.rst @@ -0,0 +1,34 @@ +========================= +Rule ``no_empty_comment`` +========================= + +There should not be any empty comments. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -// + -# + -/* */ + + + + + + + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_empty_comment`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_empty_comment`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/no_trailing_whitespace_in_comment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/no_trailing_whitespace_in_comment.rst new file mode 100644 index 0000000..df3c8bf --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/no_trailing_whitespace_in_comment.rst @@ -0,0 +1,38 @@ +========================================== +Rule ``no_trailing_whitespace_in_comment`` +========================================== + +There MUST be no trailing spaces inside comment or PHPDoc. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -// This is + -// a comment. + +// This is + +// a comment. + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``no_trailing_whitespace_in_comment`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``no_trailing_whitespace_in_comment`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_trailing_whitespace_in_comment`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_trailing_whitespace_in_comment`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/single_line_comment_style.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/single_line_comment_style.rst new file mode 100644 index 0000000..93176b0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/comment/single_line_comment_style.rst @@ -0,0 +1,96 @@ +================================== +Rule ``single_line_comment_style`` +================================== + +Single-line comments and multi-line comments with only one line of actual +content should use the ``//`` syntax. + +Configuration +------------- + +``comment_types`` +~~~~~~~~~~~~~~~~~ + +List of comment types to fix + +Allowed values: a subset of ``['asterisk', 'hash']`` + +Default value: ``['asterisk', 'hash']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -/* asterisk comment */ + +// asterisk comment + $a = 1; + + -# hash comment + +// hash comment + $b = 2; + + /* + * multi-line + * comment + */ + $c = 3; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['comment_types' => ['asterisk']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -/* first comment */ + +// first comment + $a = 1; + + -/* + - * second comment + - */ + +// second comment + $b = 2; + + /* + * third + * comment + */ + $c = 3; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['comment_types' => ['hash']]``. + +.. code-block:: diff + + --- Original + +++ New + -<?php # comment + +<?php // comment + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``single_line_comment_style`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``single_line_comment_style`` rule with the config below: + + ``['comment_types' => ['hash']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/constant_notation/native_constant_invocation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/constant_notation/native_constant_invocation.rst new file mode 100644 index 0000000..82f88de --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/constant_notation/native_constant_invocation.rst @@ -0,0 +1,143 @@ +=================================== +Rule ``native_constant_invocation`` +=================================== + +Add leading ``\`` before constant invocation of internal constant to speed up +resolving. Constant name match is case-sensitive, except for ``null``, ``false`` +and ``true``. + +.. warning:: Using this rule is risky. + + Risky when any of the constants are namespaced or overridden. + +Configuration +------------- + +``fix_built_in`` +~~~~~~~~~~~~~~~~ + +Whether to fix constants returned by ``get_defined_constants``. User constants +are not accounted in this list and must be specified in the include one. + +Allowed types: ``bool`` + +Default value: ``true`` + +``include`` +~~~~~~~~~~~ + +List of additional constants to fix. + +Allowed types: ``array`` + +Default value: ``[]`` + +``exclude`` +~~~~~~~~~~~ + +List of constants to ignore. + +Allowed types: ``array`` + +Default value: ``['null', 'false', 'true']`` + +``scope`` +~~~~~~~~~ + +Only fix constant invocations that are made within a namespace or fix all. + +Allowed values: ``'all'``, ``'namespaced'`` + +Default value: ``'all'`` + +``strict`` +~~~~~~~~~~ + +Whether leading ``\`` of constant invocation not meant to have it should be +removed. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + -<?php var_dump(PHP_VERSION, M_PI, MY_CUSTOM_PI); + +<?php var_dump(\PHP_VERSION, \M_PI, MY_CUSTOM_PI); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['scope' => 'namespaced']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace space1 { + - echo PHP_VERSION; + + echo \PHP_VERSION; + } + namespace { + echo M_PI; + } + +Example #3 +~~~~~~~~~~ + +With configuration: ``['include' => ['MY_CUSTOM_PI']]``. + +.. code-block:: diff + + --- Original + +++ New + -<?php var_dump(PHP_VERSION, M_PI, MY_CUSTOM_PI); + +<?php var_dump(\PHP_VERSION, \M_PI, \MY_CUSTOM_PI); + +Example #4 +~~~~~~~~~~ + +With configuration: ``['fix_built_in' => false, 'include' => ['MY_CUSTOM_PI']]``. + +.. code-block:: diff + + --- Original + +++ New + -<?php var_dump(PHP_VERSION, M_PI, MY_CUSTOM_PI); + +<?php var_dump(PHP_VERSION, M_PI, \MY_CUSTOM_PI); + +Example #5 +~~~~~~~~~~ + +With configuration: ``['exclude' => ['M_PI']]``. + +.. code-block:: diff + + --- Original + +++ New + -<?php var_dump(PHP_VERSION, M_PI, MY_CUSTOM_PI); + +<?php var_dump(\PHP_VERSION, M_PI, MY_CUSTOM_PI); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``native_constant_invocation`` rule with the config below: + + ``['fix_built_in' => false, 'include' => ['DIRECTORY_SEPARATOR', 'PHP_INT_SIZE', 'PHP_SAPI', 'PHP_VERSION_ID'], 'scope' => 'namespaced', 'strict' => true]`` + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``native_constant_invocation`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/elseif.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/elseif.rst new file mode 100644 index 0000000..6be6120 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/elseif.rst @@ -0,0 +1,39 @@ +=============== +Rule ``elseif`` +=============== + +The keyword ``elseif`` should be used instead of ``else if`` so that all control +keywords look like single words. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + if ($a) { + -} else if ($b) { + +} elseif ($b) { + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``elseif`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``elseif`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``elseif`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``elseif`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/include.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/include.rst new file mode 100644 index 0000000..e5e7c01 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/include.rst @@ -0,0 +1,37 @@ +================ +Rule ``include`` +================ + +Include/Require and file path should be divided with a single space. File path +should not be placed under brackets. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -require ("sample1.php"); + -require_once "sample2.php"; + -include "sample3.php"; + -include_once("sample4.php"); + +require "sample1.php"; + +require_once "sample2.php"; + +include "sample3.php"; + +include_once "sample4.php"; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``include`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``include`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_alternative_syntax.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_alternative_syntax.rst new file mode 100644 index 0000000..f91a698 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_alternative_syntax.rst @@ -0,0 +1,63 @@ +============================== +Rule ``no_alternative_syntax`` +============================== + +Replace control structure alternative syntax to use braces. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -if(true):echo 't';else:echo 'f';endif; + +if(true) { echo 't';} else { echo 'f';} + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -while(true):echo 'red';endwhile; + +while(true) { echo 'red';} + +Example #3 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -for(;;):echo 'xc';endfor; + +for(;;) { echo 'xc';} + +Example #4 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -foreach(array('a') as $item):echo 'xc';endforeach; + +foreach(array('a') as $item) { echo 'xc';} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_alternative_syntax`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_alternative_syntax`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_break_comment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_break_comment.rst new file mode 100644 index 0000000..ed2c131 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_break_comment.rst @@ -0,0 +1,84 @@ +========================= +Rule ``no_break_comment`` +========================= + +There must be a comment when fall-through is intentional in a non-empty case +body. + +Description +----------- + +Adds a "no break" comment before fall-through cases, and removes it if there is +no fall-through. + +Configuration +------------- + +``comment_text`` +~~~~~~~~~~~~~~~~ + +The text to use in the added comment and to detect it. + +Allowed types: ``string`` + +Default value: ``'no break'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + switch ($foo) { + case 1: + foo(); + + // no break + case 2: + bar(); + - // no break + break; + case 3: + baz(); + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['comment_text' => 'some comment']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + switch ($foo) { + case 1: + foo(); + + // some comment + case 2: + foo(); + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``no_break_comment`` rule with the default config. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``no_break_comment`` rule with the default config. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_break_comment`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_break_comment`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_superfluous_elseif.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_superfluous_elseif.rst new file mode 100644 index 0000000..68c2aff --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_superfluous_elseif.rst @@ -0,0 +1,32 @@ +============================== +Rule ``no_superfluous_elseif`` +============================== + +Replaces superfluous ``elseif`` with ``if``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + if ($a) { + return 1; + -} elseif ($b) { + +} + +if ($b) { + return 2; + } + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_superfluous_elseif`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_trailing_comma_in_list_call.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_trailing_comma_in_list_call.rst new file mode 100644 index 0000000..1b97438 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_trailing_comma_in_list_call.rst @@ -0,0 +1,30 @@ +======================================= +Rule ``no_trailing_comma_in_list_call`` +======================================= + +Remove trailing commas in list function calls. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -list($a, $b,) = foo(); + +list($a, $b) = foo(); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_trailing_comma_in_list_call`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_trailing_comma_in_list_call`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_unneeded_control_parentheses.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_unneeded_control_parentheses.rst new file mode 100644 index 0000000..e7c9a7e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_unneeded_control_parentheses.rst @@ -0,0 +1,83 @@ +======================================== +Rule ``no_unneeded_control_parentheses`` +======================================== + +Removes unneeded parentheses around control statements. + +Configuration +------------- + +``statements`` +~~~~~~~~~~~~~~ + +List of control statements to fix. + +Allowed types: ``array`` + +Default value: ``['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -while ($x) { while ($y) { break (2); } } + -clone($a); + -while ($y) { continue (2); } + -echo("foo"); + -print("foo"); + -return (1 + 2); + -switch ($a) { case($x); } + -yield(2); + +while ($x) { while ($y) { break 2; } } + +clone $a; + +while ($y) { continue 2; } + +echo "foo"; + +print "foo"; + +return 1 + 2; + +switch ($a) { case $x; } + +yield 2; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['statements' => ['break', 'continue']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -while ($x) { while ($y) { break (2); } } + +while ($x) { while ($y) { break 2; } } + clone($a); + -while ($y) { continue (2); } + +while ($y) { continue 2; } + echo("foo"); + print("foo"); + return (1 + 2); + switch ($a) { case($x); } + yield(2); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_unneeded_control_parentheses`` rule with the config below: + + ``['statements' => ['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield', 'yield_from']]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_unneeded_control_parentheses`` rule with the config below: + + ``['statements' => ['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield', 'yield_from']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_unneeded_curly_braces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_unneeded_curly_braces.rst new file mode 100644 index 0000000..ca18736 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_unneeded_curly_braces.rst @@ -0,0 +1,75 @@ +================================= +Rule ``no_unneeded_curly_braces`` +================================= + +Removes unneeded curly braces that are superfluous and aren't part of a control +structure's body. + +Configuration +------------- + +``namespaces`` +~~~~~~~~~~~~~~ + +Remove unneeded curly braces from bracketed namespaces. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + -<?php { + +<?php + echo 1; + -} + + + + switch ($b) { + - case 1: { + + case 1: + break; + - } + + + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['namespaces' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -namespace Foo { + +namespace Foo; + function Bar(){} + -} + + + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_unneeded_curly_braces`` rule with the config below: + + ``['namespaces' => true]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_unneeded_curly_braces`` rule with the config below: + + ``['namespaces' => true]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_useless_else.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_useless_else.rst new file mode 100644 index 0000000..de4770b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/no_useless_else.rst @@ -0,0 +1,32 @@ +======================== +Rule ``no_useless_else`` +======================== + +There should not be useless ``else`` cases. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + if ($a) { + return 1; + -} else { + +} + return 2; + -} + + + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_useless_else`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/simplified_if_return.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/simplified_if_return.rst new file mode 100644 index 0000000..a7783fa --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/simplified_if_return.rst @@ -0,0 +1,20 @@ +============================= +Rule ``simplified_if_return`` +============================= + +Simplify ``if`` control structures that return the boolean result of their +condition. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -if ($foo) { return true; } return false; + +return (bool) ($foo) ; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_case_semicolon_to_colon.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_case_semicolon_to_colon.rst new file mode 100644 index 0000000..d1fc8ed --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_case_semicolon_to_colon.rst @@ -0,0 +1,42 @@ +======================================= +Rule ``switch_case_semicolon_to_colon`` +======================================= + +A case should be followed by a colon and not a semicolon. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + switch ($a) { + - case 1; + + case 1: + break; + - default; + + default: + break; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``switch_case_semicolon_to_colon`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``switch_case_semicolon_to_colon`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``switch_case_semicolon_to_colon`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``switch_case_semicolon_to_colon`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_case_space.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_case_space.rst new file mode 100644 index 0000000..245f2a6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_case_space.rst @@ -0,0 +1,42 @@ +========================== +Rule ``switch_case_space`` +========================== + +Removes extra spaces between colon and case value. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + switch($a) { + - case 1 : + + case 1: + break; + - default : + + default: + return 2; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``switch_case_space`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``switch_case_space`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``switch_case_space`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``switch_case_space`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_continue_to_break.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_continue_to_break.rst new file mode 100644 index 0000000..10bf3e4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/switch_continue_to_break.rst @@ -0,0 +1,58 @@ +================================= +Rule ``switch_continue_to_break`` +================================= + +Switch case must not be ended with ``continue`` but with ``break``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + switch ($foo) { + case 1: + - continue; + + break; + } + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + switch ($foo) { + case 1: + while($bar) { + do { + - continue 3; + + break 3; + } while(false); + + if ($foo + 1 > 3) { + continue; + } + + - continue 2; + + break 2; + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``switch_continue_to_break`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``switch_continue_to_break`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/trailing_comma_in_multiline.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/trailing_comma_in_multiline.rst new file mode 100644 index 0000000..ca12d7d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/trailing_comma_in_multiline.rst @@ -0,0 +1,125 @@ +==================================== +Rule ``trailing_comma_in_multiline`` +==================================== + +Multi-line arrays, arguments list and parameters list must have a trailing +comma. + +Configuration +------------- + +``after_heredoc`` +~~~~~~~~~~~~~~~~~ + +Whether a trailing comma should also be placed after heredoc end. + +Allowed types: ``bool`` + +Default value: ``false`` + +``elements`` +~~~~~~~~~~~~ + +Where to fix multiline trailing comma (PHP >= 7.3 required for ``arguments``, +PHP >= 8.0 for ``parameters``). + +Allowed values: a subset of ``['arrays', 'arguments', 'parameters']`` + +Default value: ``['arrays']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + array( + 1, + - 2 + + 2, + ); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['after_heredoc' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $x = [ + 'foo', + <<<EOD + bar + - EOD + + EOD, + ]; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['elements' => ['arguments']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + foo( + 1, + - 2 + + 2, + ); + +Example #4 +~~~~~~~~~~ + +With configuration: ``['elements' => ['parameters']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + function foo( + $x, + - $y + + $y, + ) + { + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP73Migration + Using the `@PHP73Migration <./../../ruleSets/PHP73Migration.rst>`_ rule set will enable the ``trailing_comma_in_multiline`` rule with the config below: + + ``['after_heredoc' => true]`` + +@PHP74Migration + Using the `@PHP74Migration <./../../ruleSets/PHP74Migration.rst>`_ rule set will enable the ``trailing_comma_in_multiline`` rule with the config below: + + ``['after_heredoc' => true]`` + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``trailing_comma_in_multiline`` rule with the config below: + + ``['after_heredoc' => true]`` + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``trailing_comma_in_multiline`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``trailing_comma_in_multiline`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/yoda_style.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/yoda_style.rst new file mode 100644 index 0000000..c7ffb7f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/control_structure/yoda_style.rst @@ -0,0 +1,121 @@ +=================== +Rule ``yoda_style`` +=================== + +Write conditions in Yoda style (``true``), non-Yoda style (``['equal' => false, +'identical' => false, 'less_and_greater' => false]``) or ignore those conditions +(``null``) based on configuration. + +Configuration +------------- + +``equal`` +~~~~~~~~~ + +Style for equal (``==``, ``!=``) statements. + +Allowed types: ``bool``, ``null`` + +Default value: ``true`` + +``identical`` +~~~~~~~~~~~~~ + +Style for identical (``===``, ``!==``) statements. + +Allowed types: ``bool``, ``null`` + +Default value: ``true`` + +``less_and_greater`` +~~~~~~~~~~~~~~~~~~~~ + +Style for less and greater than (``<``, ``<=``, ``>``, ``>=``) statements. + +Allowed types: ``bool``, ``null`` + +Default value: ``null`` + +``always_move_variable`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether variables should always be on non assignable side when applying Yoda +style. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + - if ($a === null) { + + if (null === $a) { + echo "null"; + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['equal' => true, 'identical' => false, 'less_and_greater' => null]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + - $b = $c != 1; // equal + - $a = 1 === $b; // identical + + $b = 1 != $c; // equal + + $a = $b === 1; // identical + $c = $c > 3; // less than + +Example #3 +~~~~~~~~~~ + +With configuration: ``['always_move_variable' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -return $foo === count($bar); + +return count($bar) === $foo; + +Example #4 +~~~~~~~~~~ + +With configuration: ``['equal' => false, 'identical' => false, 'less_and_greater' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + // Enforce non-Yoda style. + - if (null === $a) { + + if ($a === null) { + echo "null"; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``yoda_style`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``yoda_style`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_array_assignment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_array_assignment.rst new file mode 100644 index 0000000..999dc8b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_array_assignment.rst @@ -0,0 +1,71 @@ +============================================= +Rule ``doctrine_annotation_array_assignment`` +============================================= + +Doctrine annotations must use configured operator for assignment in arrays. + +Configuration +------------- + +``ignored_tags`` +~~~~~~~~~~~~~~~~ + +List of tags that must not be treated as Doctrine Annotations. + +Allowed types: ``array`` + +Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'fix', 'FIXME', 'fixme', 'override']`` + +``operator`` +~~~~~~~~~~~~ + +The operator to use. + +Allowed values: ``':'``, ``'='`` + +Default value: ``'='`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @Foo({bar : "baz"}) + + * @Foo({bar = "baz"}) + */ + class Bar {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['operator' => ':']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @Foo({bar = "baz"}) + + * @Foo({bar : "baz"}) + */ + class Bar {} + +Rule sets +--------- + +The rule is part of the following rule set: + +@DoctrineAnnotation + Using the `@DoctrineAnnotation <./../../ruleSets/DoctrineAnnotation.rst>`_ rule set will enable the ``doctrine_annotation_array_assignment`` rule with the config below: + + ``['operator' => ':']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_braces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_braces.rst new file mode 100644 index 0000000..8852b77 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_braces.rst @@ -0,0 +1,69 @@ +=================================== +Rule ``doctrine_annotation_braces`` +=================================== + +Doctrine annotations without arguments must use the configured syntax. + +Configuration +------------- + +``ignored_tags`` +~~~~~~~~~~~~~~~~ + +List of tags that must not be treated as Doctrine Annotations. + +Allowed types: ``array`` + +Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'fix', 'FIXME', 'fixme', 'override']`` + +``syntax`` +~~~~~~~~~~ + +Whether to add or remove braces. + +Allowed values: ``'with_braces'``, ``'without_braces'`` + +Default value: ``'without_braces'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @Foo() + + * @Foo + */ + class Bar {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['syntax' => 'with_braces']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @Foo + + * @Foo() + */ + class Bar {} + +Rule sets +--------- + +The rule is part of the following rule set: + +@DoctrineAnnotation + Using the `@DoctrineAnnotation <./../../ruleSets/DoctrineAnnotation.rst>`_ rule set will enable the ``doctrine_annotation_braces`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_indentation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_indentation.rst new file mode 100644 index 0000000..62f8d32 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_indentation.rst @@ -0,0 +1,75 @@ +======================================== +Rule ``doctrine_annotation_indentation`` +======================================== + +Doctrine annotations must be indented with four spaces. + +Configuration +------------- + +``ignored_tags`` +~~~~~~~~~~~~~~~~ + +List of tags that must not be treated as Doctrine Annotations. + +Allowed types: ``array`` + +Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'fix', 'FIXME', 'fixme', 'override']`` + +``indent_mixed_lines`` +~~~~~~~~~~~~~~~~~~~~~~ + +Whether to indent lines that have content before closing parenthesis. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @Foo( + - * foo="foo" + - * ) + + * @Foo( + + * foo="foo" + + * ) + */ + class Bar {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['indent_mixed_lines' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @Foo({@Bar, + - * @Baz}) + + * @Foo({@Bar, + + * @Baz}) + */ + class Bar {} + +Rule sets +--------- + +The rule is part of the following rule set: + +@DoctrineAnnotation + Using the `@DoctrineAnnotation <./../../ruleSets/DoctrineAnnotation.rst>`_ rule set will enable the ``doctrine_annotation_indentation`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_spaces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_spaces.rst new file mode 100644 index 0000000..046a4c3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/doctrine_annotation/doctrine_annotation_spaces.rst @@ -0,0 +1,178 @@ +=================================== +Rule ``doctrine_annotation_spaces`` +=================================== + +Fixes spaces in Doctrine annotations. + +Description +----------- + +There must not be any space around parentheses; commas must be preceded by no +space and followed by one space; there must be no space around named arguments +assignment operator; there must be one space around array assignment operator. + +Configuration +------------- + +``ignored_tags`` +~~~~~~~~~~~~~~~~ + +List of tags that must not be treated as Doctrine Annotations. + +Allowed types: ``array`` + +Default value: ``['abstract', 'access', 'code', 'deprec', 'encode', 'exception', 'final', 'ingroup', 'inheritdoc', 'inheritDoc', 'magic', 'name', 'toc', 'tutorial', 'private', 'static', 'staticvar', 'staticVar', 'throw', 'api', 'author', 'category', 'copyright', 'deprecated', 'example', 'filesource', 'global', 'ignore', 'internal', 'license', 'link', 'method', 'package', 'param', 'property', 'property-read', 'property-write', 'return', 'see', 'since', 'source', 'subpackage', 'throws', 'todo', 'TODO', 'usedBy', 'uses', 'var', 'version', 'after', 'afterClass', 'backupGlobals', 'backupStaticAttributes', 'before', 'beforeClass', 'codeCoverageIgnore', 'codeCoverageIgnoreStart', 'codeCoverageIgnoreEnd', 'covers', 'coversDefaultClass', 'coversNothing', 'dataProvider', 'depends', 'expectedException', 'expectedExceptionCode', 'expectedExceptionMessage', 'expectedExceptionMessageRegExp', 'group', 'large', 'medium', 'preserveGlobalState', 'requires', 'runTestsInSeparateProcesses', 'runInSeparateProcess', 'small', 'test', 'testdox', 'ticket', 'uses', 'SuppressWarnings', 'noinspection', 'package_version', 'enduml', 'startuml', 'psalm', 'phpstan', 'fix', 'FIXME', 'fixme', 'override']`` + +``around_parentheses`` +~~~~~~~~~~~~~~~~~~~~~~ + +Whether to fix spaces around parentheses. + +Allowed types: ``bool`` + +Default value: ``true`` + +``around_commas`` +~~~~~~~~~~~~~~~~~ + +Whether to fix spaces around commas. + +Allowed types: ``bool`` + +Default value: ``true`` + +``around_argument_assignments`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: This option is deprecated and will be removed on next major version. Use options ``before_argument_assignments`` and ``after_argument_assignments`` +instead. + +Whether to fix spaces around argument assignment operator. + +Allowed types: ``bool`` + +Default value: ``true`` + +``before_argument_assignments`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to add, remove or ignore spaces before argument assignment operator. + +Allowed types: ``null``, ``bool`` + +Default value: ``false`` + +``after_argument_assignments`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to add, remove or ignore spaces after argument assignment operator. + +Allowed types: ``null``, ``bool`` + +Default value: ``false`` + +``around_array_assignments`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: This option is deprecated and will be removed on next major version. Use options ``before_array_assignments_equals``, +``after_array_assignments_equals``, ``before_array_assignments_colon`` and +``after_array_assignments_colon`` instead. + +Whether to fix spaces around array assignment operators. + +Allowed types: ``bool`` + +Default value: ``true`` + +``before_array_assignments_equals`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to add, remove or ignore spaces before array ``=`` assignment operator. + +Allowed types: ``null``, ``bool`` + +Default value: ``true`` + +``after_array_assignments_equals`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to add, remove or ignore spaces after array assignment ``=`` operator. + +Allowed types: ``null``, ``bool`` + +Default value: ``true`` + +``before_array_assignments_colon`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to add, remove or ignore spaces before array ``:`` assignment operator. + +Allowed types: ``null``, ``bool`` + +Default value: ``true`` + +``after_array_assignments_colon`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to add, remove or ignore spaces after array assignment ``:`` operator. + +Allowed types: ``null``, ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @Foo ( ) + + * @Foo() + */ + class Bar {} + + /** + - * @Foo("bar" ,"baz") + + * @Foo("bar", "baz") + */ + class Bar2 {} + + /** + - * @Foo(foo = "foo", bar = {"foo":"foo", "bar"="bar"}) + + * @Foo(foo="foo", bar={"foo" : "foo", "bar" = "bar"}) + */ + class Bar3 {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['after_array_assignments_equals' => false, 'before_array_assignments_equals' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @Foo(foo = "foo", bar = {"foo":"foo", "bar"="bar"}) + + * @Foo(foo="foo", bar={"foo" : "foo", "bar"="bar"}) + */ + class Bar {} + +Rule sets +--------- + +The rule is part of the following rule set: + +@DoctrineAnnotation + Using the `@DoctrineAnnotation <./../../ruleSets/DoctrineAnnotation.rst>`_ rule set will enable the ``doctrine_annotation_spaces`` rule with the config below: + + ``['before_array_assignments_colon' => false]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/combine_nested_dirname.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/combine_nested_dirname.rst new file mode 100644 index 0000000..5a811b0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/combine_nested_dirname.rst @@ -0,0 +1,47 @@ +=============================== +Rule ``combine_nested_dirname`` +=============================== + +Replace multiple nested calls of ``dirname`` by only one call with second +``$level`` parameter. Requires PHP >= 7.0. + +.. warning:: Using this rule is risky. + + Risky when the function ``dirname`` is overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -dirname(dirname(dirname($path))); + +dirname($path, 3); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP70Migration:risky + Using the `@PHP70Migration:risky <./../../ruleSets/PHP70MigrationRisky.rst>`_ rule set will enable the ``combine_nested_dirname`` rule. + +@PHP71Migration:risky + Using the `@PHP71Migration:risky <./../../ruleSets/PHP71MigrationRisky.rst>`_ rule set will enable the ``combine_nested_dirname`` rule. + +@PHP74Migration:risky + Using the `@PHP74Migration:risky <./../../ruleSets/PHP74MigrationRisky.rst>`_ rule set will enable the ``combine_nested_dirname`` rule. + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``combine_nested_dirname`` rule. + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``combine_nested_dirname`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``combine_nested_dirname`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/fopen_flag_order.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/fopen_flag_order.rst new file mode 100644 index 0000000..a282421 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/fopen_flag_order.rst @@ -0,0 +1,34 @@ +========================= +Rule ``fopen_flag_order`` +========================= + +Order the flags in ``fopen`` calls, ``b`` and ``t`` must be last. + +.. warning:: Using this rule is risky. + + Risky when the function ``fopen`` is overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = fopen($foo, 'br+'); + +$a = fopen($foo, 'r+b'); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``fopen_flag_order`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``fopen_flag_order`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/fopen_flags.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/fopen_flags.rst new file mode 100644 index 0000000..988e4b9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/fopen_flags.rst @@ -0,0 +1,66 @@ +==================== +Rule ``fopen_flags`` +==================== + +The flags in ``fopen`` calls must omit ``t``, and ``b`` must be omitted or +included consistently. + +.. warning:: Using this rule is risky. + + Risky when the function ``fopen`` is overridden. + +Configuration +------------- + +``b_mode`` +~~~~~~~~~~ + +The ``b`` flag must be used (``true``) or omitted (``false``). + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = fopen($foo, 'rwt'); + +$a = fopen($foo, 'rwb'); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['b_mode' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = fopen($foo, 'rwt'); + +$a = fopen($foo, 'rw'); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``fopen_flags`` rule with the config below: + + ``['b_mode' => false]`` + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``fopen_flags`` rule with the config below: + + ``['b_mode' => false]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/function_declaration.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/function_declaration.rst new file mode 100644 index 0000000..98d1a7e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/function_declaration.rst @@ -0,0 +1,89 @@ +============================= +Rule ``function_declaration`` +============================= + +Spaces should be properly placed in a function declaration. + +Configuration +------------- + +``closure_function_spacing`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Spacing to use before open parenthesis for closures. + +Allowed values: ``'none'``, ``'one'`` + +Default value: ``'one'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + class Foo + { + - public static function bar ( $baz , $foo ) + + public static function bar($baz , $foo) + { + return false; + } + } + + -function foo ($bar, $baz) + +function foo($bar, $baz) + { + return false; + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['closure_function_spacing' => 'none']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$f = function () {}; + +$f = function() {}; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['closure_function_spacing' => 'none']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$f = fn () => null; + +$f = fn() => null; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``function_declaration`` rule with the default config. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``function_declaration`` rule with the default config. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``function_declaration`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``function_declaration`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/function_typehint_space.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/function_typehint_space.rst new file mode 100644 index 0000000..2bb4557 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/function_typehint_space.rst @@ -0,0 +1,43 @@ +================================ +Rule ``function_typehint_space`` +================================ + +Ensure single space between function's argument and its typehint. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample(array$a) + +function sample(array $a) + {} + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample(array $a) + +function sample(array $a) + {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``function_typehint_space`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``function_typehint_space`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/implode_call.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/implode_call.rst new file mode 100644 index 0000000..9fc49f2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/implode_call.rst @@ -0,0 +1,51 @@ +===================== +Rule ``implode_call`` +===================== + +Function ``implode`` must be called with 2 arguments in the documented order. + +.. warning:: Using this rule is risky. + + Risky when the function ``implode`` is overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -implode($pieces, ''); + +implode('', $pieces); + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -implode($pieces); + +implode('', $pieces); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP74Migration:risky + Using the `@PHP74Migration:risky <./../../ruleSets/PHP74MigrationRisky.rst>`_ rule set will enable the ``implode_call`` rule. + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``implode_call`` rule. + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``implode_call`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``implode_call`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/lambda_not_used_import.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/lambda_not_used_import.rst new file mode 100644 index 0000000..60d37b1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/lambda_not_used_import.rst @@ -0,0 +1,30 @@ +=============================== +Rule ``lambda_not_used_import`` +=============================== + +Lambda must not import variables it doesn't use. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$foo = function() use ($bar) {}; + +$foo = function() {}; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``lambda_not_used_import`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``lambda_not_used_import`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/method_argument_space.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/method_argument_space.rst new file mode 100644 index 0000000..0e25c04 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/method_argument_space.rst @@ -0,0 +1,254 @@ +============================== +Rule ``method_argument_space`` +============================== + +In method arguments and method call, there MUST NOT be a space before each comma +and there MUST be one space after each comma. Argument lists MAY be split across +multiple lines, where each subsequent line is indented once. When doing so, the +first item in the list MUST be on the next line, and there MUST be only one +argument per line. + +Configuration +------------- + +``keep_multiple_spaces_after_comma`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether keep multiple spaces after comma. + +Allowed types: ``bool`` + +Default value: ``false`` + +``ensure_fully_multiline`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: This option is deprecated and will be removed on next major version. Use option ``on_multiline`` instead. + +ensure every argument of a multiline argument list is on its own line + +Allowed types: ``bool`` + +Default value: ``false`` + +``on_multiline`` +~~~~~~~~~~~~~~~~ + +Defines how to handle function arguments lists that contain newlines. + +Allowed values: ``'ensure_fully_multiline'``, ``'ensure_single_line'``, ``'ignore'`` + +Default value: ``'ignore'`` + +``after_heredoc`` +~~~~~~~~~~~~~~~~~ + +Whether the whitespace between heredoc end and comma should be removed. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample($a=10,$b=20,$c=30) {} + -sample(1, 2); + +function sample($a=10, $b=20, $c=30) {} + +sample(1, 2); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['keep_multiple_spaces_after_comma' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample($a=10,$b=20,$c=30) {} + -sample(1, 2); + +function sample($a=10, $b=20, $c=30) {} + +sample(1, 2); + +Example #3 +~~~~~~~~~~ + +With configuration: ``['keep_multiple_spaces_after_comma' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample($a=10,$b=20,$c=30) {} + +function sample($a=10, $b=20, $c=30) {} + sample(1, 2); + +Example #4 +~~~~~~~~~~ + +With configuration: ``['on_multiline' => 'ensure_fully_multiline']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample($a=10, + - $b=20,$c=30) {} + -sample(1, + - 2); + +function sample( + + $a=10, + + $b=20, + + $c=30 + +) {} + +sample( + + 1, + + 2 + +); + +Example #5 +~~~~~~~~~~ + +With configuration: ``['on_multiline' => 'ensure_single_line']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample( + - $a=10, + - $b=20, + - $c=30 + -) {} + -sample( + - 1, + - 2 + -); + +function sample($a=10, $b=20, $c=30) {} + +sample(1, 2); + +Example #6 +~~~~~~~~~~ + +With configuration: ``['on_multiline' => 'ensure_fully_multiline', 'keep_multiple_spaces_after_comma' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample($a=10, + - $b=20,$c=30) {} + -sample(1, + - 2); + +function sample( + + $a=10, + + $b=20, + + $c=30 + +) {} + +sample( + + 1, + + 2 + +); + sample('foo', 'foobarbaz', 'baz'); + sample('foobar', 'bar', 'baz'); + +Example #7 +~~~~~~~~~~ + +With configuration: ``['on_multiline' => 'ensure_fully_multiline', 'keep_multiple_spaces_after_comma' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample($a=10, + - $b=20,$c=30) {} + -sample(1, + - 2); + -sample('foo', 'foobarbaz', 'baz'); + -sample('foobar', 'bar', 'baz'); + +function sample( + + $a=10, + + $b=20, + + $c=30 + +) {} + +sample( + + 1, + + 2 + +); + +sample('foo', 'foobarbaz', 'baz'); + +sample('foobar', 'bar', 'baz'); + +Example #8 +~~~~~~~~~~ + +With configuration: ``['after_heredoc' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + sample( + <<<EOD + foo + - EOD + - , + + EOD, + 'bar' + ); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP73Migration + Using the `@PHP73Migration <./../../ruleSets/PHP73Migration.rst>`_ rule set will enable the ``method_argument_space`` rule with the config below: + + ``['after_heredoc' => true]`` + +@PHP74Migration + Using the `@PHP74Migration <./../../ruleSets/PHP74Migration.rst>`_ rule set will enable the ``method_argument_space`` rule with the config below: + + ``['after_heredoc' => true]`` + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``method_argument_space`` rule with the config below: + + ``['after_heredoc' => true]`` + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``method_argument_space`` rule with the config below: + + ``['on_multiline' => 'ensure_fully_multiline']`` + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``method_argument_space`` rule with the config below: + + ``['on_multiline' => 'ensure_fully_multiline']`` + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``method_argument_space`` rule with the config below: + + ``['on_multiline' => 'ensure_fully_multiline']`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``method_argument_space`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/native_function_invocation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/native_function_invocation.rst new file mode 100644 index 0000000..c236c0c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/native_function_invocation.rst @@ -0,0 +1,205 @@ +=================================== +Rule ``native_function_invocation`` +=================================== + +Add leading ``\`` before function invocation to speed up resolving. + +.. warning:: Using this rule is risky. + + Risky when any of the functions are overridden. + +Configuration +------------- + +``exclude`` +~~~~~~~~~~~ + +List of functions to ignore. + +Allowed types: ``array`` + +Default value: ``[]`` + +``include`` +~~~~~~~~~~~ + +List of function names or sets to fix. Defined sets are ``@internal`` (all +native functions), ``@all`` (all global functions) and ``@compiler_optimized`` +(functions that are specially optimized by Zend). + +Allowed types: ``array`` + +Default value: ``['@internal']`` + +``scope`` +~~~~~~~~~ + +Only fix function calls that are made within a namespace or fix all. + +Allowed values: ``'all'``, ``'namespaced'`` + +Default value: ``'all'`` + +``strict`` +~~~~~~~~~~ + +Whether leading ``\`` of function call not meant to have it should be removed. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + function baz($options) + { + - if (!array_key_exists("foo", $options)) { + + if (!\array_key_exists("foo", $options)) { + throw new \InvalidArgumentException(); + } + + - return json_encode($options); + + return \json_encode($options); + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['exclude' => ['json_encode']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + function baz($options) + { + - if (!array_key_exists("foo", $options)) { + + if (!\array_key_exists("foo", $options)) { + throw new \InvalidArgumentException(); + } + + return json_encode($options); + } + +Example #3 +~~~~~~~~~~ + +With configuration: ``['scope' => 'all']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace space1 { + - echo count([1]); + + echo \count([1]); + } + namespace { + - echo count([1]); + + echo \count([1]); + } + +Example #4 +~~~~~~~~~~ + +With configuration: ``['scope' => 'namespaced']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace space1 { + - echo count([1]); + + echo \count([1]); + } + namespace { + echo count([1]); + } + +Example #5 +~~~~~~~~~~ + +With configuration: ``['include' => ['myGlobalFunction']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -myGlobalFunction(); + +\myGlobalFunction(); + count(); + +Example #6 +~~~~~~~~~~ + +With configuration: ``['include' => ['@all']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -myGlobalFunction(); + -count(); + +\myGlobalFunction(); + +\count(); + +Example #7 +~~~~~~~~~~ + +With configuration: ``['include' => ['@internal']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + myGlobalFunction(); + -count(); + +\count(); + +Example #8 +~~~~~~~~~~ + +With configuration: ``['include' => ['@compiler_optimized']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $a .= str_repeat($a, 4); + -$c = get_class($d); + +$c = \get_class($d); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``native_function_invocation`` rule with the config below: + + ``['include' => ['@compiler_optimized'], 'scope' => 'namespaced', 'strict' => true]`` + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``native_function_invocation`` rule with the config below: + + ``['include' => ['@compiler_optimized'], 'scope' => 'namespaced', 'strict' => true]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_spaces_after_function_name.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_spaces_after_function_name.rst new file mode 100644 index 0000000..7f0bab3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_spaces_after_function_name.rst @@ -0,0 +1,43 @@ +====================================== +Rule ``no_spaces_after_function_name`` +====================================== + +When making a method or function call, there MUST NOT be a space between the +method or function name and the opening parenthesis. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -require ('sample.php'); + -echo (test (3)); + -exit (1); + -$func (); + +require('sample.php'); + +echo(test(3)); + +exit(1); + +$func(); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``no_spaces_after_function_name`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``no_spaces_after_function_name`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_spaces_after_function_name`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_spaces_after_function_name`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_unreachable_default_argument_value.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_unreachable_default_argument_value.rst new file mode 100644 index 0000000..f153f4c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_unreachable_default_argument_value.rst @@ -0,0 +1,40 @@ +============================================== +Rule ``no_unreachable_default_argument_value`` +============================================== + +In function arguments there must not be arguments with default values before +non-default ones. + +.. warning:: Using this rule is risky. + + Modifies the signature of functions; therefore risky when using systems (such + as some Symfony components) that rely on those (for example through + reflection). + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -function example($foo = "two words", $bar) {} + +function example($foo, $bar) {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``no_unreachable_default_argument_value`` rule. + +@PSR12:risky + Using the `@PSR12:risky <./../../ruleSets/PSR12Risky.rst>`_ rule set will enable the ``no_unreachable_default_argument_value`` rule. + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``no_unreachable_default_argument_value`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_useless_sprintf.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_useless_sprintf.rst new file mode 100644 index 0000000..d254000 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/no_useless_sprintf.rst @@ -0,0 +1,34 @@ +=========================== +Rule ``no_useless_sprintf`` +=========================== + +There must be no ``sprintf`` calls with only the first argument. + +.. warning:: Using this rule is risky. + + Risky when if the ``sprintf`` function is overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$foo = sprintf('bar'); + +$foo = 'bar'; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``no_useless_sprintf`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``no_useless_sprintf`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/nullable_type_declaration_for_default_null_value.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/nullable_type_declaration_for_default_null_value.rst new file mode 100644 index 0000000..2256a96 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/nullable_type_declaration_for_default_null_value.rst @@ -0,0 +1,55 @@ +========================================================= +Rule ``nullable_type_declaration_for_default_null_value`` +========================================================= + +Adds or removes ``?`` before type declarations for parameters with a default +``null`` value. + +Description +----------- + +Rule is applied only in a PHP 7.1+ environment. + +Configuration +------------- + +``use_nullable_type_declaration`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to add or remove ``?`` before type declarations for parameters with a +default ``null`` value. + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample(string $str = null) + +function sample(?string $str = null) + {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['use_nullable_type_declaration' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample(?string $str = null) + +function sample(string $str = null) + {} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_param_type.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_param_type.rst new file mode 100644 index 0000000..aca1691 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_param_type.rst @@ -0,0 +1,78 @@ +============================= +Rule ``phpdoc_to_param_type`` +============================= + +EXPERIMENTAL: Takes ``@param`` annotations of non-mixed types and adjusts +accordingly the function signature. Requires PHP >= 7.0. + +.. warning:: Using this rule is risky. + + This rule is EXPERIMENTAL and [1] is not covered with backward compatibility + promise. [2] ``@param`` annotation is mandatory for the fixer to make + changes, signatures of methods without it (no docblock, inheritdocs) will not + be fixed. [3] Manual actions are required if inherited signatures are not + properly documented. + +Configuration +------------- + +``scalar_types`` +~~~~~~~~~~~~~~~~ + +Fix also scalar types; may have unexpected behaviour due to PHP bad type +coercion system. + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + /** @param string $bar */ + -function my_foo($bar) + +function my_foo(string $bar) + {} + +Example #2 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + /** @param string|null $bar */ + -function my_foo($bar) + +function my_foo(?string $bar) + {} + +Example #3 +~~~~~~~~~~ + +With configuration: ``['scalar_types' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** @param Foo $foo */ + -function foo($foo) {} + +function foo(Foo $foo) {} + /** @param string $foo */ + function bar($foo) {} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_property_type.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_property_type.rst new file mode 100644 index 0000000..0f0b953 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_property_type.rst @@ -0,0 +1,67 @@ +================================ +Rule ``phpdoc_to_property_type`` +================================ + +EXPERIMENTAL: Takes ``@var`` annotation of non-mixed types and adjusts +accordingly the property signature. Requires PHP >= 7.4. + +.. warning:: Using this rule is risky. + + This rule is EXPERIMENTAL and [1] is not covered with backward compatibility + promise. [2] ``@var`` annotation is mandatory for the fixer to make changes, + signatures of properties without it (no docblock) will not be fixed. [3] + Manual actions might be required for newly typed properties that are read + before initialization. + +Configuration +------------- + +``scalar_types`` +~~~~~~~~~~~~~~~~ + +Fix also scalar types; may have unexpected behaviour due to PHP bad type +coercion system. + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo { + /** @var int */ + - private $foo; + + private int $foo; + /** @var \Traversable */ + - private $bar; + + private \Traversable $bar; + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['scalar_types' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo { + /** @var int */ + private $foo; + /** @var \Traversable */ + - private $bar; + + private \Traversable $bar; + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_return_type.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_return_type.rst new file mode 100644 index 0000000..d3bc97f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/phpdoc_to_return_type.rst @@ -0,0 +1,114 @@ +============================== +Rule ``phpdoc_to_return_type`` +============================== + +EXPERIMENTAL: Takes ``@return`` annotation of non-mixed types and adjusts +accordingly the function signature. Requires PHP >= 7.0. + +.. warning:: Using this rule is risky. + + This rule is EXPERIMENTAL and [1] is not covered with backward compatibility + promise. [2] ``@return`` annotation is mandatory for the fixer to make + changes, signatures of methods without it (no docblock, inheritdocs) will not + be fixed. [3] Manual actions are required if inherited signatures are not + properly documented. + +Configuration +------------- + +``scalar_types`` +~~~~~~~~~~~~~~~~ + +Fix also scalar types; may have unexpected behaviour due to PHP bad type +coercion system. + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + /** @return \My\Bar */ + -function my_foo() + +function my_foo(): \My\Bar + {} + +Example #2 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + /** @return void */ + -function my_foo() + +function my_foo(): void + {} + +Example #3 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + /** @return object */ + -function my_foo() + +function my_foo(): object + {} + +Example #4 +~~~~~~~~~~ + +With configuration: ``['scalar_types' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** @return Foo */ + -function foo() {} + +function foo(): Foo {} + /** @return string */ + function bar() {} + +Example #5 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Foo { + /** + * @return static + */ + - public function create($prototype) { + + public function create($prototype): static { + return new static($prototype); + } + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/regular_callable_call.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/regular_callable_call.rst new file mode 100644 index 0000000..f23e856 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/regular_callable_call.rst @@ -0,0 +1,46 @@ +============================== +Rule ``regular_callable_call`` +============================== + +Callables must be called without using ``call_user_func*`` when possible. + +.. warning:: Using this rule is risky. + + Risky when the ``call_user_func`` or ``call_user_func_array`` function is + overridden or when are used in constructions that should be avoided, like + ``call_user_func_array('foo', ['bar' => 'baz'])`` or ``call_user_func($foo, + $foo = 'bar')``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + - call_user_func("var_dump", 1, 2); + + var_dump(1, 2); + + - call_user_func("Bar\Baz::d", 1, 2); + + Bar\Baz::d(1, 2); + + - call_user_func_array($callback, [1, 2]); + + $callback(...[1, 2]); + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -call_user_func(function ($a, $b) { var_dump($a, $b); }, 1, 2); + +(function ($a, $b) { var_dump($a, $b); })(1, 2); + + -call_user_func(static function ($a, $b) { var_dump($a, $b); }, 1, 2); + +(static function ($a, $b) { var_dump($a, $b); })(1, 2); diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/return_type_declaration.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/return_type_declaration.rst new file mode 100644 index 0000000..edad00a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/return_type_declaration.rst @@ -0,0 +1,79 @@ +================================ +Rule ``return_type_declaration`` +================================ + +There should be one or no space before colon, and one space after it in return +type declarations, according to configuration. + +Description +----------- + +Rule is applied only in a PHP 7+ environment. + +Configuration +------------- + +``space_before`` +~~~~~~~~~~~~~~~~ + +Spacing to apply before colon. + +Allowed values: ``'none'``, ``'one'`` + +Default value: ``'none'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function foo(int $a):string {}; + +function foo(int $a): string {}; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['space_before' => 'none']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function foo(int $a):string {}; + +function foo(int $a): string {}; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['space_before' => 'one']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -function foo(int $a):string {}; + +function foo(int $a) : string {}; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``return_type_declaration`` rule with the default config. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``return_type_declaration`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``return_type_declaration`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/single_line_throw.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/single_line_throw.rst new file mode 100644 index 0000000..0294333 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/single_line_throw.rst @@ -0,0 +1,30 @@ +========================== +Rule ``single_line_throw`` +========================== + +Throwing exception must be done in single line. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -throw new Exception( + - 'Error.', + - 500 + -); + +throw new Exception('Error.', 500); + +Rule sets +--------- + +The rule is part of the following rule set: + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``single_line_throw`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/static_lambda.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/static_lambda.rst new file mode 100644 index 0000000..5e2d9e2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/static_lambda.rst @@ -0,0 +1,25 @@ +====================== +Rule ``static_lambda`` +====================== + +Lambdas not (indirect) referencing ``$this`` must be declared ``static``. + +.. warning:: Using this rule is risky. + + Risky when using ``->bindTo`` on lambdas without referencing to ``$this``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = function () use ($b) + +$a = static function () use ($b) + { echo $b; + }; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/use_arrow_functions.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/use_arrow_functions.rst new file mode 100644 index 0000000..24f7000 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/use_arrow_functions.rst @@ -0,0 +1,37 @@ +============================ +Rule ``use_arrow_functions`` +============================ + +Anonymous functions with one-liner return statement must use arrow functions. + +.. warning:: Using this rule is risky. + + Risky when using ``isset()`` on outside variables that are not imported with + ``use ()``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -foo(function ($a) use ($b) { + - return $a + $b; + -}); + +foo(fn ($a) => $a + $b); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP74Migration:risky + Using the `@PHP74Migration:risky <./../../ruleSets/PHP74MigrationRisky.rst>`_ rule set will enable the ``use_arrow_functions`` rule. + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``use_arrow_functions`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/void_return.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/void_return.rst new file mode 100644 index 0000000..d03181b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/function_notation/void_return.rst @@ -0,0 +1,38 @@ +==================== +Rule ``void_return`` +==================== + +Add ``void`` return type to functions with missing or empty return statements, +but priority is given to ``@return`` annotations. Requires PHP >= 7.1. + +.. warning:: Using this rule is risky. + + Modifies the signature of functions. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -function foo($a) {}; + +function foo($a): void {}; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP71Migration:risky + Using the `@PHP71Migration:risky <./../../ruleSets/PHP71MigrationRisky.rst>`_ rule set will enable the ``void_return`` rule. + +@PHP74Migration:risky + Using the `@PHP74Migration:risky <./../../ruleSets/PHP74MigrationRisky.rst>`_ rule set will enable the ``void_return`` rule. + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``void_return`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/import/fully_qualified_strict_types.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/fully_qualified_strict_types.rst new file mode 100644 index 0000000..721007b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/fully_qualified_strict_types.rst @@ -0,0 +1,59 @@ +===================================== +Rule ``fully_qualified_strict_types`` +===================================== + +Transforms imported FQCN parameters and return types in function arguments to +short version. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + use Foo\Bar; + + class SomeClass + { + - public function doSomething(\Foo\Bar $foo) + + public function doSomething(Bar $foo) + { + } + } + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + use Foo\Bar; + use Foo\Bar\Baz; + + class SomeClass + { + - public function doSomething(\Foo\Bar $foo): \Foo\Bar\Baz + + public function doSomething(Bar $foo): Baz + { + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``fully_qualified_strict_types`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``fully_qualified_strict_types`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/import/global_namespace_import.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/global_namespace_import.rst new file mode 100644 index 0000000..6c64c75 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/global_namespace_import.rst @@ -0,0 +1,108 @@ +================================ +Rule ``global_namespace_import`` +================================ + +Imports or fully qualifies global classes/functions/constants. + +Configuration +------------- + +``import_constants`` +~~~~~~~~~~~~~~~~~~~~ + +Whether to import, not import or ignore global constants. + +Allowed values: ``false``, ``null``, ``true`` + +Default value: ``null`` + +``import_functions`` +~~~~~~~~~~~~~~~~~~~~ + +Whether to import, not import or ignore global functions. + +Allowed values: ``false``, ``null``, ``true`` + +Default value: ``null`` + +``import_classes`` +~~~~~~~~~~~~~~~~~~ + +Whether to import, not import or ignore global classes. + +Allowed values: ``false``, ``null``, ``true`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + namespace Foo; + +use DateTimeImmutable; + + -$d = new \DateTimeImmutable(); + +$d = new DateTimeImmutable(); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['import_classes' => true, 'import_constants' => true, 'import_functions' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + namespace Foo; + +use DateTimeImmutable; + +use function count; + +use const M_PI; + + -if (\count($x)) { + - /** @var \DateTimeImmutable $d */ + - $d = new \DateTimeImmutable(); + - $p = \M_PI; + +if (count($x)) { + + /** @var DateTimeImmutable $d */ + + $d = new DateTimeImmutable(); + + $p = M_PI; + } + +Example #3 +~~~~~~~~~~ + +With configuration: ``['import_classes' => false, 'import_constants' => false, 'import_functions' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + namespace Foo; + + use DateTimeImmutable; + use function count; + use const M_PI; + + -if (count($x)) { + - /** @var DateTimeImmutable $d */ + - $d = new DateTimeImmutable(); + - $p = M_PI; + +if (\count($x)) { + + /** @var \DateTimeImmutable $d */ + + $d = new \DateTimeImmutable(); + + $p = \M_PI; + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/import/group_import.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/group_import.rst new file mode 100644 index 0000000..6b51170 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/group_import.rst @@ -0,0 +1,20 @@ +===================== +Rule ``group_import`` +===================== + +There MUST be group use for the same namespaces. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -use Foo\Bar; + -use Foo\Baz; + +use Foo\{Bar, Baz}; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/import/no_leading_import_slash.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/no_leading_import_slash.rst new file mode 100644 index 0000000..be594c0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/no_leading_import_slash.rst @@ -0,0 +1,34 @@ +================================ +Rule ``no_leading_import_slash`` +================================ + +Remove leading slashes in ``use`` clauses. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace Foo; + -use \Bar; + +use Bar; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``no_leading_import_slash`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_leading_import_slash`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_leading_import_slash`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/import/no_unused_imports.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/no_unused_imports.rst new file mode 100644 index 0000000..bdf3fdf --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/no_unused_imports.rst @@ -0,0 +1,32 @@ +========================== +Rule ``no_unused_imports`` +========================== + +Unused ``use`` statements must be removed. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + use \DateTime; + -use \Exception; + + new DateTime(); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_unused_imports`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_unused_imports`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/import/ordered_imports.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/ordered_imports.rst new file mode 100644 index 0000000..5a4c20a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/ordered_imports.rst @@ -0,0 +1,166 @@ +======================== +Rule ``ordered_imports`` +======================== + +Ordering ``use`` statements. + +Configuration +------------- + +``sort_algorithm`` +~~~~~~~~~~~~~~~~~~ + +whether the statements should be sorted alphabetically or by length, or not +sorted + +.. note:: The previous name of this option was ``sortAlgorithm`` but it is now deprecated and will be removed on next major version. + +Allowed values: ``'alpha'``, ``'length'``, ``'none'`` + +Default value: ``'alpha'`` + +``imports_order`` +~~~~~~~~~~~~~~~~~ + +Defines the order of import types. + +.. note:: The previous name of this option was ``importsOrder`` but it is now deprecated and will be removed on next major version. + +Allowed types: ``array``, ``null`` + +Default value: ``null`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -use Z; use A; + +use A; use Z; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['sort_algorithm' => 'length']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + +use Bar; + +use Acme; + +use Bar1; + use Acme\Bar; + -use Bar1; + -use Acme; + -use Bar; + +Example #3 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + +use AAA; + +use const AAB; + use function AAC; + -use const AAB; + -use AAA; + +Example #4 +~~~~~~~~~~ + +With configuration: ``['sort_algorithm' => 'length', 'imports_order' => ['const', 'class', 'function']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + +use const BBB; + use const AAAA; + -use const BBB; + + +use AAC; + use Bar; + -use AAC; + use Acme; + + +use function DDD; + use function CCC\AA; + -use function DDD; + +Example #5 +~~~~~~~~~~ + +With configuration: ``['sort_algorithm' => 'alpha', 'imports_order' => ['const', 'class', 'function']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + +use const AAAA; + use const BBB; + -use const AAAA; + + +use AAC; + use Acme; + -use AAC; + use Bar; + + +use function CCC\AA; + use function DDD; + -use function CCC\AA; + +Example #6 +~~~~~~~~~~ + +With configuration: ``['sort_algorithm' => 'none', 'imports_order' => ['const', 'class', 'function']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + use const BBB; + use const AAAA; + + -use function DDD; + -use function CCC\AA; + - + use Acme; + use AAC; + + + use Bar; + +use function DDD; + +use function CCC\AA; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``ordered_imports`` rule with the config below: + + ``['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'none']`` + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``ordered_imports`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``ordered_imports`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/import/single_import_per_statement.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/single_import_per_statement.rst new file mode 100644 index 0000000..0114373 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/single_import_per_statement.rst @@ -0,0 +1,38 @@ +==================================== +Rule ``single_import_per_statement`` +==================================== + +There MUST be one use keyword per declaration. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -use Foo, Sample, Sample\Sample as Sample2; + +use Foo; + +use Sample; + +use Sample\Sample as Sample2; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``single_import_per_statement`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``single_import_per_statement`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``single_import_per_statement`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``single_import_per_statement`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/import/single_line_after_imports.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/single_line_after_imports.rst new file mode 100644 index 0000000..f9d8ca3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/import/single_line_after_imports.rst @@ -0,0 +1,61 @@ +================================== +Rule ``single_line_after_imports`` +================================== + +Each namespace use MUST go on its own line and there MUST be one blank line +after the use statements block. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace Foo; + + use Bar; + use Baz; + + + final class Example + { + } + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace Foo; + + use Bar; + use Baz; + + - + final class Example + { + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``single_line_after_imports`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``single_line_after_imports`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``single_line_after_imports`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``single_line_after_imports`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/index.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/index.rst new file mode 100644 index 0000000..6a4929e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/index.rst @@ -0,0 +1,595 @@ +======================= +List of Available Rules +======================= + +Alias +----- + +- `array_push <./alias/array_push.rst>`_ *(risky)* + Converts simple usages of ``array_push($x, $y);`` to ``$x[] = $y;``. +- `backtick_to_shell_exec <./alias/backtick_to_shell_exec.rst>`_ + Converts backtick operators to ``shell_exec`` calls. +- `ereg_to_preg <./alias/ereg_to_preg.rst>`_ *(risky)* + Replace deprecated ``ereg`` regular expression functions with ``preg``. +- `mb_str_functions <./alias/mb_str_functions.rst>`_ *(risky)* + Replace non multibyte-safe functions with corresponding mb function. +- `no_alias_functions <./alias/no_alias_functions.rst>`_ *(risky)* + Master functions shall be used instead of aliases. +- `no_alias_language_construct_call <./alias/no_alias_language_construct_call.rst>`_ + Master language constructs shall be used instead of aliases. +- `no_mixed_echo_print <./alias/no_mixed_echo_print.rst>`_ + Either language construct ``print`` or ``echo`` should be used. +- `pow_to_exponentiation <./alias/pow_to_exponentiation.rst>`_ *(risky)* + Converts ``pow`` to the ``**`` operator. +- `random_api_migration <./alias/random_api_migration.rst>`_ *(risky)* + Replaces ``rand``, ``srand``, ``getrandmax`` functions calls with their ``mt_*`` analogs or ``random_int``. +- `set_type_to_cast <./alias/set_type_to_cast.rst>`_ *(risky)* + Cast shall be used, not ``settype``. + +Array Notation +-------------- + +- `array_syntax <./array_notation/array_syntax.rst>`_ + PHP arrays should be declared using the configured syntax. +- `no_multiline_whitespace_around_double_arrow <./array_notation/no_multiline_whitespace_around_double_arrow.rst>`_ + Operator ``=>`` should not be surrounded by multi-line whitespaces. +- `no_trailing_comma_in_singleline_array <./array_notation/no_trailing_comma_in_singleline_array.rst>`_ + PHP single-line arrays should not have trailing comma. +- `no_whitespace_before_comma_in_array <./array_notation/no_whitespace_before_comma_in_array.rst>`_ + In array declaration, there MUST NOT be a whitespace before each comma. +- `normalize_index_brace <./array_notation/normalize_index_brace.rst>`_ + Array index should always be written by using square braces. +- `trailing_comma_in_multiline_array <./array_notation/trailing_comma_in_multiline_array.rst>`_ *(deprecated)* + PHP multi-line arrays should have a trailing comma. +- `trim_array_spaces <./array_notation/trim_array_spaces.rst>`_ + Arrays should be formatted like function/method arguments, without leading or trailing single line space. +- `whitespace_after_comma_in_array <./array_notation/whitespace_after_comma_in_array.rst>`_ + In array declaration, there MUST be a whitespace after each comma. + +Basic +----- + +- `braces <./basic/braces.rst>`_ + The body of each structure MUST be enclosed by braces. Braces should be properly placed. Body of braces should be properly indented. +- `encoding <./basic/encoding.rst>`_ + PHP code MUST use only UTF-8 without BOM (remove BOM). +- `non_printable_character <./basic/non_printable_character.rst>`_ *(risky)* + Remove Zero-width space (ZWSP), Non-breaking space (NBSP) and other invisible unicode symbols. +- `psr0 <./basic/psr0.rst>`_ *(deprecated, risky)* + Classes must be in a path that matches their namespace, be at least one namespace deep and the class name should match the file name. +- `psr4 <./basic/psr4.rst>`_ *(deprecated, risky)* + Class names should match the file name. +- `psr_autoloading <./basic/psr_autoloading.rst>`_ *(risky)* + Classes must be in a path that matches their namespace, be at least one namespace deep and the class name should match the file name. + +Casing +------ + +- `constant_case <./casing/constant_case.rst>`_ + The PHP constants ``true``, ``false``, and ``null`` MUST be written using the correct casing. +- `lowercase_constants <./casing/lowercase_constants.rst>`_ *(deprecated)* + The PHP constants ``true``, ``false``, and ``null`` MUST be in lower case. +- `lowercase_keywords <./casing/lowercase_keywords.rst>`_ + PHP keywords MUST be in lower case. +- `lowercase_static_reference <./casing/lowercase_static_reference.rst>`_ + Class static references ``self``, ``static`` and ``parent`` MUST be in lower case. +- `magic_constant_casing <./casing/magic_constant_casing.rst>`_ + Magic constants should be referred to using the correct casing. +- `magic_method_casing <./casing/magic_method_casing.rst>`_ + Magic method definitions and calls must be using the correct casing. +- `native_function_casing <./casing/native_function_casing.rst>`_ + Function defined by PHP should be called using the correct casing. +- `native_function_type_declaration_casing <./casing/native_function_type_declaration_casing.rst>`_ + Native type hints for functions should use the correct case. + +Cast Notation +------------- + +- `cast_spaces <./cast_notation/cast_spaces.rst>`_ + A single space or none should be between cast and variable. +- `lowercase_cast <./cast_notation/lowercase_cast.rst>`_ + Cast should be written in lower case. +- `modernize_types_casting <./cast_notation/modernize_types_casting.rst>`_ *(risky)* + Replaces ``intval``, ``floatval``, ``doubleval``, ``strval`` and ``boolval`` function calls with according type casting operator. +- `no_short_bool_cast <./cast_notation/no_short_bool_cast.rst>`_ + Short cast ``bool`` using double exclamation mark should not be used. +- `no_unset_cast <./cast_notation/no_unset_cast.rst>`_ + Variables must be set ``null`` instead of using ``(unset)`` casting. +- `short_scalar_cast <./cast_notation/short_scalar_cast.rst>`_ + Cast ``(boolean)`` and ``(integer)`` should be written as ``(bool)`` and ``(int)``, ``(double)`` and ``(real)`` as ``(float)``, ``(binary)`` as ``(string)``. + +Class Notation +-------------- + +- `class_attributes_separation <./class_notation/class_attributes_separation.rst>`_ + Class, trait and interface elements must be separated with one or none blank line. +- `class_definition <./class_notation/class_definition.rst>`_ + Whitespace around the keywords of a class, trait or interfaces definition should be one space. +- `final_class <./class_notation/final_class.rst>`_ *(risky)* + All classes must be final, except abstract ones and Doctrine entities. +- `final_internal_class <./class_notation/final_internal_class.rst>`_ *(risky)* + Internal classes should be ``final``. +- `final_public_method_for_abstract_class <./class_notation/final_public_method_for_abstract_class.rst>`_ *(risky)* + All ``public`` methods of ``abstract`` classes should be ``final``. +- `final_static_access <./class_notation/final_static_access.rst>`_ *(deprecated)* + Converts ``static`` access to ``self`` access in ``final`` classes. +- `method_separation <./class_notation/method_separation.rst>`_ *(deprecated)* + Methods must be separated with one blank line. +- `no_blank_lines_after_class_opening <./class_notation/no_blank_lines_after_class_opening.rst>`_ + There should be no empty lines after class opening brace. +- `no_null_property_initialization <./class_notation/no_null_property_initialization.rst>`_ + Properties MUST not be explicitly initialized with ``null`` except when they have a type declaration (PHP 7.4). +- `no_php4_constructor <./class_notation/no_php4_constructor.rst>`_ *(risky)* + Convert PHP4-style constructors to ``__construct``. +- `no_unneeded_final_method <./class_notation/no_unneeded_final_method.rst>`_ *(risky)* + A ``final`` class must not have ``final`` methods and ``private`` methods must not be ``final``. +- `ordered_class_elements <./class_notation/ordered_class_elements.rst>`_ + Orders the elements of classes/interfaces/traits. +- `ordered_interfaces <./class_notation/ordered_interfaces.rst>`_ *(risky)* + Orders the interfaces in an ``implements`` or ``interface extends`` clause. +- `ordered_traits <./class_notation/ordered_traits.rst>`_ *(risky)* + Trait ``use`` statements must be sorted alphabetically. +- `protected_to_private <./class_notation/protected_to_private.rst>`_ + Converts ``protected`` variables and methods to ``private`` where possible. +- `self_accessor <./class_notation/self_accessor.rst>`_ *(risky)* + Inside class or interface element ``self`` should be preferred to the class name itself. +- `self_static_accessor <./class_notation/self_static_accessor.rst>`_ + Inside a ``final`` class or anonymous class ``self`` should be preferred to ``static``. +- `single_class_element_per_statement <./class_notation/single_class_element_per_statement.rst>`_ + There MUST NOT be more than one property or constant declared per statement. +- `single_trait_insert_per_statement <./class_notation/single_trait_insert_per_statement.rst>`_ + Each trait ``use`` must be done as single statement. +- `visibility_required <./class_notation/visibility_required.rst>`_ + Visibility MUST be declared on all properties and methods; ``abstract`` and ``final`` MUST be declared before the visibility; ``static`` MUST be declared after the visibility. + +Class Usage +----------- + +- `date_time_immutable <./class_usage/date_time_immutable.rst>`_ *(risky)* + Class ``DateTimeImmutable`` should be used instead of ``DateTime``. + +Comment +------- + +- `comment_to_phpdoc <./comment/comment_to_phpdoc.rst>`_ *(risky)* + Comments with annotation should be docblock when used on structural elements. +- `hash_to_slash_comment <./comment/hash_to_slash_comment.rst>`_ *(deprecated)* + Single line comments should use double slashes ``//`` and not hash ``#``. +- `header_comment <./comment/header_comment.rst>`_ + Add, replace or remove header comment. +- `multiline_comment_opening_closing <./comment/multiline_comment_opening_closing.rst>`_ + DocBlocks must start with two asterisks, multiline comments must start with a single asterisk, after the opening slash. Both must end with a single asterisk before the closing slash. +- `no_empty_comment <./comment/no_empty_comment.rst>`_ + There should not be any empty comments. +- `no_trailing_whitespace_in_comment <./comment/no_trailing_whitespace_in_comment.rst>`_ + There MUST be no trailing spaces inside comment or PHPDoc. +- `single_line_comment_style <./comment/single_line_comment_style.rst>`_ + Single-line comments and multi-line comments with only one line of actual content should use the ``//`` syntax. + +Constant Notation +----------------- + +- `native_constant_invocation <./constant_notation/native_constant_invocation.rst>`_ *(risky)* + Add leading ``\`` before constant invocation of internal constant to speed up resolving. Constant name match is case-sensitive, except for ``null``, ``false`` and ``true``. + +Control Structure +----------------- + +- `elseif <./control_structure/elseif.rst>`_ + The keyword ``elseif`` should be used instead of ``else if`` so that all control keywords look like single words. +- `include <./control_structure/include.rst>`_ + Include/Require and file path should be divided with a single space. File path should not be placed under brackets. +- `no_alternative_syntax <./control_structure/no_alternative_syntax.rst>`_ + Replace control structure alternative syntax to use braces. +- `no_break_comment <./control_structure/no_break_comment.rst>`_ + There must be a comment when fall-through is intentional in a non-empty case body. +- `no_superfluous_elseif <./control_structure/no_superfluous_elseif.rst>`_ + Replaces superfluous ``elseif`` with ``if``. +- `no_trailing_comma_in_list_call <./control_structure/no_trailing_comma_in_list_call.rst>`_ + Remove trailing commas in list function calls. +- `no_unneeded_control_parentheses <./control_structure/no_unneeded_control_parentheses.rst>`_ + Removes unneeded parentheses around control statements. +- `no_unneeded_curly_braces <./control_structure/no_unneeded_curly_braces.rst>`_ + Removes unneeded curly braces that are superfluous and aren't part of a control structure's body. +- `no_useless_else <./control_structure/no_useless_else.rst>`_ + There should not be useless ``else`` cases. +- `simplified_if_return <./control_structure/simplified_if_return.rst>`_ + Simplify ``if`` control structures that return the boolean result of their condition. +- `switch_case_semicolon_to_colon <./control_structure/switch_case_semicolon_to_colon.rst>`_ + A case should be followed by a colon and not a semicolon. +- `switch_case_space <./control_structure/switch_case_space.rst>`_ + Removes extra spaces between colon and case value. +- `switch_continue_to_break <./control_structure/switch_continue_to_break.rst>`_ + Switch case must not be ended with ``continue`` but with ``break``. +- `trailing_comma_in_multiline <./control_structure/trailing_comma_in_multiline.rst>`_ + Multi-line arrays, arguments list and parameters list must have a trailing comma. +- `yoda_style <./control_structure/yoda_style.rst>`_ + Write conditions in Yoda style (``true``), non-Yoda style (``['equal' => false, 'identical' => false, 'less_and_greater' => false]``) or ignore those conditions (``null``) based on configuration. + +Doctrine Annotation +------------------- + +- `doctrine_annotation_array_assignment <./doctrine_annotation/doctrine_annotation_array_assignment.rst>`_ + Doctrine annotations must use configured operator for assignment in arrays. +- `doctrine_annotation_braces <./doctrine_annotation/doctrine_annotation_braces.rst>`_ + Doctrine annotations without arguments must use the configured syntax. +- `doctrine_annotation_indentation <./doctrine_annotation/doctrine_annotation_indentation.rst>`_ + Doctrine annotations must be indented with four spaces. +- `doctrine_annotation_spaces <./doctrine_annotation/doctrine_annotation_spaces.rst>`_ + Fixes spaces in Doctrine annotations. + +Function Notation +----------------- + +- `combine_nested_dirname <./function_notation/combine_nested_dirname.rst>`_ *(risky)* + Replace multiple nested calls of ``dirname`` by only one call with second ``$level`` parameter. Requires PHP >= 7.0. +- `fopen_flag_order <./function_notation/fopen_flag_order.rst>`_ *(risky)* + Order the flags in ``fopen`` calls, ``b`` and ``t`` must be last. +- `fopen_flags <./function_notation/fopen_flags.rst>`_ *(risky)* + The flags in ``fopen`` calls must omit ``t``, and ``b`` must be omitted or included consistently. +- `function_declaration <./function_notation/function_declaration.rst>`_ + Spaces should be properly placed in a function declaration. +- `function_typehint_space <./function_notation/function_typehint_space.rst>`_ + Ensure single space between function's argument and its typehint. +- `implode_call <./function_notation/implode_call.rst>`_ *(risky)* + Function ``implode`` must be called with 2 arguments in the documented order. +- `lambda_not_used_import <./function_notation/lambda_not_used_import.rst>`_ + Lambda must not import variables it doesn't use. +- `method_argument_space <./function_notation/method_argument_space.rst>`_ + In method arguments and method call, there MUST NOT be a space before each comma and there MUST be one space after each comma. Argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line. +- `native_function_invocation <./function_notation/native_function_invocation.rst>`_ *(risky)* + Add leading ``\`` before function invocation to speed up resolving. +- `no_spaces_after_function_name <./function_notation/no_spaces_after_function_name.rst>`_ + When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis. +- `no_unreachable_default_argument_value <./function_notation/no_unreachable_default_argument_value.rst>`_ *(risky)* + In function arguments there must not be arguments with default values before non-default ones. +- `no_useless_sprintf <./function_notation/no_useless_sprintf.rst>`_ *(risky)* + There must be no ``sprintf`` calls with only the first argument. +- `nullable_type_declaration_for_default_null_value <./function_notation/nullable_type_declaration_for_default_null_value.rst>`_ + Adds or removes ``?`` before type declarations for parameters with a default ``null`` value. +- `phpdoc_to_param_type <./function_notation/phpdoc_to_param_type.rst>`_ *(risky)* + EXPERIMENTAL: Takes ``@param`` annotations of non-mixed types and adjusts accordingly the function signature. Requires PHP >= 7.0. +- `phpdoc_to_property_type <./function_notation/phpdoc_to_property_type.rst>`_ *(risky)* + EXPERIMENTAL: Takes ``@var`` annotation of non-mixed types and adjusts accordingly the property signature. Requires PHP >= 7.4. +- `phpdoc_to_return_type <./function_notation/phpdoc_to_return_type.rst>`_ *(risky)* + EXPERIMENTAL: Takes ``@return`` annotation of non-mixed types and adjusts accordingly the function signature. Requires PHP >= 7.0. +- `regular_callable_call <./function_notation/regular_callable_call.rst>`_ *(risky)* + Callables must be called without using ``call_user_func*`` when possible. +- `return_type_declaration <./function_notation/return_type_declaration.rst>`_ + There should be one or no space before colon, and one space after it in return type declarations, according to configuration. +- `single_line_throw <./function_notation/single_line_throw.rst>`_ + Throwing exception must be done in single line. +- `static_lambda <./function_notation/static_lambda.rst>`_ *(risky)* + Lambdas not (indirect) referencing ``$this`` must be declared ``static``. +- `use_arrow_functions <./function_notation/use_arrow_functions.rst>`_ *(risky)* + Anonymous functions with one-liner return statement must use arrow functions. +- `void_return <./function_notation/void_return.rst>`_ *(risky)* + Add ``void`` return type to functions with missing or empty return statements, but priority is given to ``@return`` annotations. Requires PHP >= 7.1. + +Import +------ + +- `fully_qualified_strict_types <./import/fully_qualified_strict_types.rst>`_ + Transforms imported FQCN parameters and return types in function arguments to short version. +- `global_namespace_import <./import/global_namespace_import.rst>`_ + Imports or fully qualifies global classes/functions/constants. +- `group_import <./import/group_import.rst>`_ + There MUST be group use for the same namespaces. +- `no_leading_import_slash <./import/no_leading_import_slash.rst>`_ + Remove leading slashes in ``use`` clauses. +- `no_unused_imports <./import/no_unused_imports.rst>`_ + Unused ``use`` statements must be removed. +- `ordered_imports <./import/ordered_imports.rst>`_ + Ordering ``use`` statements. +- `single_import_per_statement <./import/single_import_per_statement.rst>`_ + There MUST be one use keyword per declaration. +- `single_line_after_imports <./import/single_line_after_imports.rst>`_ + Each namespace use MUST go on its own line and there MUST be one blank line after the use statements block. + +Language Construct +------------------ + +- `class_keyword_remove <./language_construct/class_keyword_remove.rst>`_ + Converts ``::class`` keywords to FQCN strings. +- `combine_consecutive_issets <./language_construct/combine_consecutive_issets.rst>`_ + Using ``isset($var) &&`` multiple times should be done in one call. +- `combine_consecutive_unsets <./language_construct/combine_consecutive_unsets.rst>`_ + Calling ``unset`` on multiple items should be done in one call. +- `declare_equal_normalize <./language_construct/declare_equal_normalize.rst>`_ + Equal sign in declare statement should be surrounded by spaces or not following configuration. +- `dir_constant <./language_construct/dir_constant.rst>`_ *(risky)* + Replaces ``dirname(__FILE__)`` expression with equivalent ``__DIR__`` constant. +- `error_suppression <./language_construct/error_suppression.rst>`_ *(risky)* + Error control operator should be added to deprecation notices and/or removed from other cases. +- `explicit_indirect_variable <./language_construct/explicit_indirect_variable.rst>`_ + Add curly braces to indirect variables to make them clear to understand. Requires PHP >= 7.0. +- `function_to_constant <./language_construct/function_to_constant.rst>`_ *(risky)* + Replace core functions calls returning constants with the constants. +- `is_null <./language_construct/is_null.rst>`_ *(risky)* + Replaces ``is_null($var)`` expression with ``null === $var``. +- `no_unset_on_property <./language_construct/no_unset_on_property.rst>`_ *(risky)* + Properties should be set to ``null`` instead of using ``unset``. +- `silenced_deprecation_error <./language_construct/silenced_deprecation_error.rst>`_ *(deprecated, risky)* + Ensures deprecation notices are silenced. +- `single_space_after_construct <./language_construct/single_space_after_construct.rst>`_ + Ensures a single space after language constructs. + +List Notation +------------- + +- `list_syntax <./list_notation/list_syntax.rst>`_ + List (``array`` destructuring) assignment should be declared using the configured syntax. Requires PHP >= 7.1. + +Namespace Notation +------------------ + +- `blank_line_after_namespace <./namespace_notation/blank_line_after_namespace.rst>`_ + There MUST be one blank line after the namespace declaration. +- `clean_namespace <./namespace_notation/clean_namespace.rst>`_ + Namespace must not contain spacing, comments or PHPDoc. +- `no_blank_lines_before_namespace <./namespace_notation/no_blank_lines_before_namespace.rst>`_ + There should be no blank lines before a namespace declaration. +- `no_leading_namespace_whitespace <./namespace_notation/no_leading_namespace_whitespace.rst>`_ + The namespace declaration line shouldn't contain leading whitespace. +- `single_blank_line_before_namespace <./namespace_notation/single_blank_line_before_namespace.rst>`_ + There should be exactly one blank line before a namespace declaration. + +Naming +------ + +- `no_homoglyph_names <./naming/no_homoglyph_names.rst>`_ *(risky)* + Replace accidental usage of homoglyphs (non ascii characters) in names. + +Operator +-------- + +- `binary_operator_spaces <./operator/binary_operator_spaces.rst>`_ + Binary operators should be surrounded by space as configured. +- `concat_space <./operator/concat_space.rst>`_ + Concatenation should be spaced according configuration. +- `increment_style <./operator/increment_style.rst>`_ + Pre- or post-increment and decrement operators should be used if possible. +- `logical_operators <./operator/logical_operators.rst>`_ *(risky)* + Use ``&&`` and ``||`` logical operators instead of ``and`` and ``or``. +- `new_with_braces <./operator/new_with_braces.rst>`_ + All instances created with new keyword must be followed by braces. +- `not_operator_with_space <./operator/not_operator_with_space.rst>`_ + Logical NOT operators (``!``) should have leading and trailing whitespaces. +- `not_operator_with_successor_space <./operator/not_operator_with_successor_space.rst>`_ + Logical NOT operators (``!``) should have one trailing whitespace. +- `object_operator_without_whitespace <./operator/object_operator_without_whitespace.rst>`_ + There should not be space before or after object operators ``->`` and ``?->``. +- `operator_linebreak <./operator/operator_linebreak.rst>`_ + Operators - when multiline - must always be at the beginning or at the end of the line. +- `pre_increment <./operator/pre_increment.rst>`_ *(deprecated)* + Pre incrementation/decrementation should be used if possible. +- `standardize_increment <./operator/standardize_increment.rst>`_ + Increment and decrement operators should be used if possible. +- `standardize_not_equals <./operator/standardize_not_equals.rst>`_ + Replace all ``<>`` with ``!=``. +- `ternary_operator_spaces <./operator/ternary_operator_spaces.rst>`_ + Standardize spaces around ternary operator. +- `ternary_to_elvis_operator <./operator/ternary_to_elvis_operator.rst>`_ *(risky)* + Use the Elvis operator ``?:`` where possible. +- `ternary_to_null_coalescing <./operator/ternary_to_null_coalescing.rst>`_ + Use ``null`` coalescing operator ``??`` where possible. Requires PHP >= 7.0. +- `unary_operator_spaces <./operator/unary_operator_spaces.rst>`_ + Unary operators should be placed adjacent to their operands. + +PHP Tag +------- + +- `blank_line_after_opening_tag <./php_tag/blank_line_after_opening_tag.rst>`_ + Ensure there is no code on the same line as the PHP open tag and it is followed by a blank line. +- `echo_tag_syntax <./php_tag/echo_tag_syntax.rst>`_ + Replaces short-echo ``<?=`` with long format ``<?php echo``/``<?php print`` syntax, or vice-versa. +- `full_opening_tag <./php_tag/full_opening_tag.rst>`_ + PHP code must use the long ``<?php`` tags or short-echo ``<?=`` tags and not other tag variations. +- `linebreak_after_opening_tag <./php_tag/linebreak_after_opening_tag.rst>`_ + Ensure there is no code on the same line as the PHP open tag. +- `no_closing_tag <./php_tag/no_closing_tag.rst>`_ + The closing ``?>`` tag MUST be omitted from files containing only PHP. +- `no_short_echo_tag <./php_tag/no_short_echo_tag.rst>`_ *(deprecated)* + Replaces short-echo ``<?=`` with long format ``<?php echo`` syntax. + +PHPUnit +------- + +- `php_unit_construct <./php_unit/php_unit_construct.rst>`_ *(risky)* + PHPUnit assertion method calls like ``->assertSame(true, $foo)`` should be written with dedicated method like ``->assertTrue($foo)``. +- `php_unit_dedicate_assert <./php_unit/php_unit_dedicate_assert.rst>`_ *(risky)* + PHPUnit assertions like ``assertInternalType``, ``assertFileExists``, should be used over ``assertTrue``. +- `php_unit_dedicate_assert_internal_type <./php_unit/php_unit_dedicate_assert_internal_type.rst>`_ *(risky)* + PHPUnit assertions like ``assertIsArray`` should be used over ``assertInternalType``. +- `php_unit_expectation <./php_unit/php_unit_expectation.rst>`_ *(risky)* + Usages of ``->setExpectedException*`` methods MUST be replaced by ``->expectException*`` methods. +- `php_unit_fqcn_annotation <./php_unit/php_unit_fqcn_annotation.rst>`_ + PHPUnit annotations should be a FQCNs including a root namespace. +- `php_unit_internal_class <./php_unit/php_unit_internal_class.rst>`_ + All PHPUnit test classes should be marked as internal. +- `php_unit_method_casing <./php_unit/php_unit_method_casing.rst>`_ + Enforce camel (or snake) case for PHPUnit test methods, following configuration. +- `php_unit_mock <./php_unit/php_unit_mock.rst>`_ *(risky)* + Usages of ``->getMock`` and ``->getMockWithoutInvokingTheOriginalConstructor`` methods MUST be replaced by ``->createMock`` or ``->createPartialMock`` methods. +- `php_unit_mock_short_will_return <./php_unit/php_unit_mock_short_will_return.rst>`_ *(risky)* + Usage of PHPUnit's mock e.g. ``->will($this->returnValue(..))`` must be replaced by its shorter equivalent such as ``->willReturn(...)``. +- `php_unit_namespaced <./php_unit/php_unit_namespaced.rst>`_ *(risky)* + PHPUnit classes MUST be used in namespaced version, e.g. ``\PHPUnit\Framework\TestCase`` instead of ``\PHPUnit_Framework_TestCase``. +- `php_unit_no_expectation_annotation <./php_unit/php_unit_no_expectation_annotation.rst>`_ *(risky)* + Usages of ``@expectedException*`` annotations MUST be replaced by ``->setExpectedException*`` methods. +- `php_unit_ordered_covers <./php_unit/php_unit_ordered_covers.rst>`_ *(deprecated)* + Order ``@covers`` annotation of PHPUnit tests. +- `php_unit_set_up_tear_down_visibility <./php_unit/php_unit_set_up_tear_down_visibility.rst>`_ *(risky)* + Changes the visibility of the ``setUp()`` and ``tearDown()`` functions of PHPUnit to ``protected``, to match the PHPUnit TestCase. +- `php_unit_size_class <./php_unit/php_unit_size_class.rst>`_ + All PHPUnit test cases should have ``@small``, ``@medium`` or ``@large`` annotation to enable run time limits. +- `php_unit_strict <./php_unit/php_unit_strict.rst>`_ *(risky)* + PHPUnit methods like ``assertSame`` should be used instead of ``assertEquals``. +- `php_unit_test_annotation <./php_unit/php_unit_test_annotation.rst>`_ *(risky)* + Adds or removes @test annotations from tests, following configuration. +- `php_unit_test_case_static_method_calls <./php_unit/php_unit_test_case_static_method_calls.rst>`_ *(risky)* + Calls to ``PHPUnit\Framework\TestCase`` static methods must all be of the same type, either ``$this->``, ``self::`` or ``static::``. +- `php_unit_test_class_requires_covers <./php_unit/php_unit_test_class_requires_covers.rst>`_ + Adds a default ``@coversNothing`` annotation to PHPUnit test classes that have no ``@covers*`` annotation. + +PHPDoc +------ + +- `align_multiline_comment <./phpdoc/align_multiline_comment.rst>`_ + Each line of multi-line DocComments must have an asterisk [PSR-5] and must be aligned with the first one. +- `general_phpdoc_annotation_remove <./phpdoc/general_phpdoc_annotation_remove.rst>`_ + Configured annotations should be omitted from PHPDoc. +- `general_phpdoc_tag_rename <./phpdoc/general_phpdoc_tag_rename.rst>`_ + Renames PHPDoc tags. +- `no_blank_lines_after_phpdoc <./phpdoc/no_blank_lines_after_phpdoc.rst>`_ + There should not be blank lines between docblock and the documented element. +- `no_empty_phpdoc <./phpdoc/no_empty_phpdoc.rst>`_ + There should not be empty PHPDoc blocks. +- `no_superfluous_phpdoc_tags <./phpdoc/no_superfluous_phpdoc_tags.rst>`_ + Removes ``@param``, ``@return`` and ``@var`` tags that don't provide any useful information. +- `phpdoc_add_missing_param_annotation <./phpdoc/phpdoc_add_missing_param_annotation.rst>`_ + PHPDoc should contain ``@param`` for all params. +- `phpdoc_align <./phpdoc/phpdoc_align.rst>`_ + All items of the given phpdoc tags must be either left-aligned or (by default) aligned vertically. +- `phpdoc_annotation_without_dot <./phpdoc/phpdoc_annotation_without_dot.rst>`_ + PHPDoc annotation descriptions should not be a sentence. +- `phpdoc_indent <./phpdoc/phpdoc_indent.rst>`_ + Docblocks should have the same indentation as the documented subject. +- `phpdoc_inline_tag <./phpdoc/phpdoc_inline_tag.rst>`_ *(deprecated)* + Fix PHPDoc inline tags, make ``@inheritdoc`` always inline. +- `phpdoc_inline_tag_normalizer <./phpdoc/phpdoc_inline_tag_normalizer.rst>`_ + Fixes PHPDoc inline tags. +- `phpdoc_line_span <./phpdoc/phpdoc_line_span.rst>`_ + Changes doc blocks from single to multi line, or reversed. Works for class constants, properties and methods only. +- `phpdoc_no_access <./phpdoc/phpdoc_no_access.rst>`_ + ``@access`` annotations should be omitted from PHPDoc. +- `phpdoc_no_alias_tag <./phpdoc/phpdoc_no_alias_tag.rst>`_ + No alias PHPDoc tags should be used. +- `phpdoc_no_empty_return <./phpdoc/phpdoc_no_empty_return.rst>`_ + ``@return void`` and ``@return null`` annotations should be omitted from PHPDoc. +- `phpdoc_no_package <./phpdoc/phpdoc_no_package.rst>`_ + ``@package`` and ``@subpackage`` annotations should be omitted from PHPDoc. +- `phpdoc_no_useless_inheritdoc <./phpdoc/phpdoc_no_useless_inheritdoc.rst>`_ + Classy that does not inherit must not have ``@inheritdoc`` tags. +- `phpdoc_order_by_value <./phpdoc/phpdoc_order_by_value.rst>`_ + Order phpdoc tags by value. +- `phpdoc_order <./phpdoc/phpdoc_order.rst>`_ + Annotations in PHPDoc should be ordered so that ``@param`` annotations come first, then ``@throws`` annotations, then ``@return`` annotations. +- `phpdoc_return_self_reference <./phpdoc/phpdoc_return_self_reference.rst>`_ + The type of ``@return`` annotations of methods returning a reference to itself must the configured one. +- `phpdoc_scalar <./phpdoc/phpdoc_scalar.rst>`_ + Scalar types should always be written in the same form. ``int`` not ``integer``, ``bool`` not ``boolean``, ``float`` not ``real`` or ``double``. +- `phpdoc_separation <./phpdoc/phpdoc_separation.rst>`_ + Annotations in PHPDoc should be grouped together so that annotations of the same type immediately follow each other, and annotations of a different type are separated by a single blank line. +- `phpdoc_single_line_var_spacing <./phpdoc/phpdoc_single_line_var_spacing.rst>`_ + Single line ``@var`` PHPDoc should have proper spacing. +- `phpdoc_summary <./phpdoc/phpdoc_summary.rst>`_ + PHPDoc summary should end in either a full stop, exclamation mark, or question mark. +- `phpdoc_tag_casing <./phpdoc/phpdoc_tag_casing.rst>`_ + Fixes casing of PHPDoc tags. +- `phpdoc_tag_type <./phpdoc/phpdoc_tag_type.rst>`_ + Forces PHPDoc tags to be either regular annotations or inline. +- `phpdoc_to_comment <./phpdoc/phpdoc_to_comment.rst>`_ + Docblocks should only be used on structural elements. +- `phpdoc_trim_consecutive_blank_line_separation <./phpdoc/phpdoc_trim_consecutive_blank_line_separation.rst>`_ + Removes extra blank lines after summary and after description in PHPDoc. +- `phpdoc_trim <./phpdoc/phpdoc_trim.rst>`_ + PHPDoc should start and end with content, excluding the very first and last line of the docblocks. +- `phpdoc_types <./phpdoc/phpdoc_types.rst>`_ + The correct case must be used for standard PHP types in PHPDoc. +- `phpdoc_types_order <./phpdoc/phpdoc_types_order.rst>`_ + Sorts PHPDoc types. +- `phpdoc_var_annotation_correct_order <./phpdoc/phpdoc_var_annotation_correct_order.rst>`_ + ``@var`` and ``@type`` annotations must have type and name in the correct order. +- `phpdoc_var_without_name <./phpdoc/phpdoc_var_without_name.rst>`_ + ``@var`` and ``@type`` annotations of classy properties should not contain the name. + +Return Notation +--------------- + +- `blank_line_before_return <./return_notation/blank_line_before_return.rst>`_ *(deprecated)* + An empty line feed should precede a return statement. +- `no_useless_return <./return_notation/no_useless_return.rst>`_ + There should not be an empty ``return`` statement at the end of a function. +- `return_assignment <./return_notation/return_assignment.rst>`_ + Local, dynamic and directly referenced variables should not be assigned and directly returned by a function or method. +- `simplified_null_return <./return_notation/simplified_null_return.rst>`_ + A return statement wishing to return ``void`` should not return ``null``. + +Semicolon +--------- + +- `multiline_whitespace_before_semicolons <./semicolon/multiline_whitespace_before_semicolons.rst>`_ + Forbid multi-line whitespace before the closing semicolon or move the semicolon to the new line for chained calls. +- `no_empty_statement <./semicolon/no_empty_statement.rst>`_ + Remove useless (semicolon) statements. +- `no_multiline_whitespace_before_semicolons <./semicolon/no_multiline_whitespace_before_semicolons.rst>`_ *(deprecated)* + Multi-line whitespace before closing semicolon are prohibited. +- `no_singleline_whitespace_before_semicolons <./semicolon/no_singleline_whitespace_before_semicolons.rst>`_ + Single-line whitespace before closing semicolon are prohibited. +- `semicolon_after_instruction <./semicolon/semicolon_after_instruction.rst>`_ + Instructions must be terminated with a semicolon. +- `space_after_semicolon <./semicolon/space_after_semicolon.rst>`_ + Fix whitespace after a semicolon. + +Strict +------ + +- `declare_strict_types <./strict/declare_strict_types.rst>`_ *(risky)* + Force strict types declaration in all files. Requires PHP >= 7.0. +- `strict_comparison <./strict/strict_comparison.rst>`_ *(risky)* + Comparisons should be strict. +- `strict_param <./strict/strict_param.rst>`_ *(risky)* + Functions should be used with ``$strict`` param set to ``true``. + +String Notation +--------------- + +- `escape_implicit_backslashes <./string_notation/escape_implicit_backslashes.rst>`_ + Escape implicit backslashes in strings and heredocs to ease the understanding of which are special chars interpreted by PHP and which not. +- `explicit_string_variable <./string_notation/explicit_string_variable.rst>`_ + Converts implicit variables into explicit ones in double-quoted strings or heredoc syntax. +- `heredoc_to_nowdoc <./string_notation/heredoc_to_nowdoc.rst>`_ + Convert ``heredoc`` to ``nowdoc`` where possible. +- `no_binary_string <./string_notation/no_binary_string.rst>`_ + There should not be a binary flag before strings. +- `no_trailing_whitespace_in_string <./string_notation/no_trailing_whitespace_in_string.rst>`_ *(risky)* + There must be no trailing whitespace in strings. +- `simple_to_complex_string_variable <./string_notation/simple_to_complex_string_variable.rst>`_ + Converts explicit variables in double-quoted strings and heredoc syntax from simple to complex format (``${`` to ``{$``). +- `single_quote <./string_notation/single_quote.rst>`_ + Convert double quotes to single quotes for simple strings. +- `string_line_ending <./string_notation/string_line_ending.rst>`_ *(risky)* + All multi-line strings must use correct line ending. + +Whitespace +---------- + +- `array_indentation <./whitespace/array_indentation.rst>`_ + Each element of an array must be indented exactly once. +- `blank_line_before_statement <./whitespace/blank_line_before_statement.rst>`_ + An empty line feed must precede any configured statement. +- `compact_nullable_typehint <./whitespace/compact_nullable_typehint.rst>`_ + Remove extra spaces in a nullable typehint. +- `heredoc_indentation <./whitespace/heredoc_indentation.rst>`_ + Heredoc/nowdoc content must be properly indented. Requires PHP >= 7.3. +- `indentation_type <./whitespace/indentation_type.rst>`_ + Code MUST use configured indentation type. +- `line_ending <./whitespace/line_ending.rst>`_ + All PHP files must use same line ending. +- `method_chaining_indentation <./whitespace/method_chaining_indentation.rst>`_ + Method chaining MUST be properly indented. Method chaining with different levels of indentation is not supported. +- `no_extra_blank_lines <./whitespace/no_extra_blank_lines.rst>`_ + Removes extra blank lines and/or blank lines following configuration. +- `no_extra_consecutive_blank_lines <./whitespace/no_extra_consecutive_blank_lines.rst>`_ *(deprecated)* + Removes extra blank lines and/or blank lines following configuration. +- `no_spaces_around_offset <./whitespace/no_spaces_around_offset.rst>`_ + There MUST NOT be spaces around offset braces. +- `no_spaces_inside_parenthesis <./whitespace/no_spaces_inside_parenthesis.rst>`_ + There MUST NOT be a space after the opening parenthesis. There MUST NOT be a space before the closing parenthesis. +- `no_trailing_whitespace <./whitespace/no_trailing_whitespace.rst>`_ + Remove trailing whitespace at the end of non-blank lines. +- `no_whitespace_in_blank_line <./whitespace/no_whitespace_in_blank_line.rst>`_ + Remove trailing whitespace at the end of blank lines. +- `single_blank_line_at_eof <./whitespace/single_blank_line_at_eof.rst>`_ + A PHP file without end tag must always end with a single empty line feed. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/class_keyword_remove.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/class_keyword_remove.rst new file mode 100644 index 0000000..efcb8b6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/class_keyword_remove.rst @@ -0,0 +1,22 @@ +============================= +Rule ``class_keyword_remove`` +============================= + +Converts ``::class`` keywords to FQCN strings. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + use Foo\Bar\Baz; + + -$className = Baz::class; + +$className = 'Foo\Bar\Baz'; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/combine_consecutive_issets.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/combine_consecutive_issets.rst new file mode 100644 index 0000000..e298a8d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/combine_consecutive_issets.rst @@ -0,0 +1,27 @@ +=================================== +Rule ``combine_consecutive_issets`` +=================================== + +Using ``isset($var) &&`` multiple times should be done in one call. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = isset($a) && isset($b); + +$a = isset($a, $b) ; + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``combine_consecutive_issets`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/combine_consecutive_unsets.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/combine_consecutive_unsets.rst new file mode 100644 index 0000000..d819dad --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/combine_consecutive_unsets.rst @@ -0,0 +1,27 @@ +=================================== +Rule ``combine_consecutive_unsets`` +=================================== + +Calling ``unset`` on multiple items should be done in one call. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -unset($a); unset($b); + +unset($a, $b); + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``combine_consecutive_unsets`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/declare_equal_normalize.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/declare_equal_normalize.rst new file mode 100644 index 0000000..9883f83 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/declare_equal_normalize.rst @@ -0,0 +1,61 @@ +================================ +Rule ``declare_equal_normalize`` +================================ + +Equal sign in declare statement should be surrounded by spaces or not following +configuration. + +Configuration +------------- + +``space`` +~~~~~~~~~ + +Spacing to apply around the equal sign. + +Allowed values: ``'none'``, ``'single'`` + +Default value: ``'none'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -declare(ticks = 1); + +declare(ticks=1); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['space' => 'single']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -declare(ticks=1); + +declare(ticks = 1); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``declare_equal_normalize`` rule with the default config. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``declare_equal_normalize`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``declare_equal_normalize`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/dir_constant.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/dir_constant.rst new file mode 100644 index 0000000..522340b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/dir_constant.rst @@ -0,0 +1,34 @@ +===================== +Rule ``dir_constant`` +===================== + +Replaces ``dirname(__FILE__)`` expression with equivalent ``__DIR__`` constant. + +.. warning:: Using this rule is risky. + + Risky when the function ``dirname`` is overridden. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = dirname(__FILE__); + +$a = __DIR__; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``dir_constant`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``dir_constant`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/error_suppression.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/error_suppression.rst new file mode 100644 index 0000000..dfb2510 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/error_suppression.rst @@ -0,0 +1,97 @@ +========================== +Rule ``error_suppression`` +========================== + +Error control operator should be added to deprecation notices and/or removed +from other cases. + +.. warning:: Using this rule is risky. + + Risky because adding/removing ``@`` might cause changes to code behaviour or + if ``trigger_error`` function is overridden. + +Configuration +------------- + +``mute_deprecation_error`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to add ``@`` in deprecation notices. + +Allowed types: ``bool`` + +Default value: ``true`` + +``noise_remaining_usages`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to remove ``@`` in remaining usages. + +Allowed types: ``bool`` + +Default value: ``false`` + +``noise_remaining_usages_exclude`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +List of global functions to exclude from removing ``@`` + +Allowed types: ``array`` + +Default value: ``[]`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -trigger_error('Warning.', E_USER_DEPRECATED); + +@trigger_error('Warning.', E_USER_DEPRECATED); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['noise_remaining_usages' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -@mkdir($dir); + -@unlink($path); + +mkdir($dir); + +unlink($path); + +Example #3 +~~~~~~~~~~ + +With configuration: ``['noise_remaining_usages' => true, 'noise_remaining_usages_exclude' => ['unlink']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -@mkdir($dir); + +mkdir($dir); + @unlink($path); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``error_suppression`` rule with the default config. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``error_suppression`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/explicit_indirect_variable.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/explicit_indirect_variable.rst new file mode 100644 index 0000000..e07165f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/explicit_indirect_variable.rst @@ -0,0 +1,34 @@ +=================================== +Rule ``explicit_indirect_variable`` +=================================== + +Add curly braces to indirect variables to make them clear to understand. +Requires PHP >= 7.0. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -echo $$foo; + -echo $$foo['bar']; + -echo $foo->$bar['baz']; + -echo $foo->$callback($baz); + +echo ${$foo}; + +echo ${$foo}['bar']; + +echo $foo->{$bar}['baz']; + +echo $foo->{$callback}($baz); + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``explicit_indirect_variable`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/function_to_constant.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/function_to_constant.rst new file mode 100644 index 0000000..a0fa77f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/function_to_constant.rst @@ -0,0 +1,90 @@ +============================= +Rule ``function_to_constant`` +============================= + +Replace core functions calls returning constants with the constants. + +.. warning:: Using this rule is risky. + + Risky when any of the configured functions to replace are overridden. + +Configuration +------------- + +``functions`` +~~~~~~~~~~~~~ + +List of function names to fix. + +Allowed values: a subset of ``['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']`` + +Default value: ``['get_class', 'php_sapi_name', 'phpversion', 'pi']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -echo phpversion(); + -echo pi(); + -echo php_sapi_name(); + +echo PHP_VERSION; + +echo M_PI; + +echo PHP_SAPI; + class Foo + { + public function Bar() + { + - echo get_class(); + + echo __CLASS__; + echo get_called_class(); + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['functions' => ['get_called_class', 'get_class_this', 'phpversion']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -echo phpversion(); + +echo PHP_VERSION; + echo pi(); + class Foo + { + public function Bar() + { + echo get_class(); + - get_class($this); + - echo get_called_class(); + + static::class; + + echo static::class; + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``function_to_constant`` rule with the config below: + + ``['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']]`` + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``function_to_constant`` rule with the config below: + + ``['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/is_null.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/is_null.rst new file mode 100644 index 0000000..3566b5f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/is_null.rst @@ -0,0 +1,50 @@ +================ +Rule ``is_null`` +================ + +Replaces ``is_null($var)`` expression with ``null === $var``. + +.. warning:: Using this rule is risky. + + Risky when the function ``is_null`` is overridden. + +Configuration +------------- + +``use_yoda_style`` +~~~~~~~~~~~~~~~~~~ + +.. warning:: This option is deprecated and will be removed on next major version. Use ``yoda_style`` fixer instead. + +Whether Yoda style conditions should be used. + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = is_null($b); + +$a = null === $b; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``is_null`` rule with the default config. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``is_null`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/no_unset_on_property.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/no_unset_on_property.rst new file mode 100644 index 0000000..20c8046 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/no_unset_on_property.rst @@ -0,0 +1,35 @@ +============================= +Rule ``no_unset_on_property`` +============================= + +Properties should be set to ``null`` instead of using ``unset``. + +.. warning:: Using this rule is risky. + + Risky when relying on attributes to be removed using ``unset`` rather than be + set to ``null``. Changing variables to ``null`` instead of unsetting means + these still show up when looping over class variables and reference + properties remain unbroken. With PHP 7.4, this rule might introduce ``null`` + assignments to properties whose type declaration does not allow it. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -unset($this->a); + +$this->a = null; + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``no_unset_on_property`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/silenced_deprecation_error.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/silenced_deprecation_error.rst new file mode 100644 index 0000000..34edd25 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/silenced_deprecation_error.rst @@ -0,0 +1,27 @@ +=================================== +Rule ``silenced_deprecation_error`` +=================================== + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``error_suppression`` instead. + +Ensures deprecation notices are silenced. + +.. warning:: Using this rule is risky. + + Silencing of deprecation errors might cause changes to code behaviour. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -trigger_error('Warning.', E_USER_DEPRECATED); + +@trigger_error('Warning.', E_USER_DEPRECATED); diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/single_space_after_construct.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/single_space_after_construct.rst new file mode 100644 index 0000000..3b937ed --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/language_construct/single_space_after_construct.rst @@ -0,0 +1,73 @@ +===================================== +Rule ``single_space_after_construct`` +===================================== + +Ensures a single space after language constructs. + +Configuration +------------- + +``constructs`` +~~~~~~~~~~~~~~ + +List of constructs which must be followed by a single space. + +Allowed values: a subset of ``['abstract', 'as', 'attribute', 'break', 'case', 'catch', 'class', 'clone', 'comment', 'const', 'const_import', 'continue', 'do', 'echo', 'else', 'elseif', 'extends', 'final', 'finally', 'for', 'foreach', 'function', 'function_import', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'match', 'named_argument', 'namespace', 'new', 'open_tag_with_echo', 'php_doc', 'php_open', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'throw', 'trait', 'try', 'use', 'use_lambda', 'use_trait', 'var', 'while', 'yield', 'yield_from']`` + +Default value: ``['abstract', 'as', 'attribute', 'break', 'case', 'catch', 'class', 'clone', 'comment', 'const', 'const_import', 'continue', 'do', 'echo', 'else', 'elseif', 'extends', 'final', 'finally', 'for', 'foreach', 'function', 'function_import', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'match', 'named_argument', 'namespace', 'new', 'open_tag_with_echo', 'php_doc', 'php_open', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'throw', 'trait', 'try', 'use', 'use_lambda', 'use_trait', 'var', 'while', 'yield', 'yield_from']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -throw new \Exception(); + +throw new \Exception(); + +Example #2 +~~~~~~~~~~ + +With configuration: ``['constructs' => ['echo']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -echo "Hello!"; + +echo "Hello!"; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['constructs' => ['yield_from']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -yield from baz(); + +yield from baz(); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``single_space_after_construct`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``single_space_after_construct`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/list_notation/list_syntax.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/list_notation/list_syntax.rst new file mode 100644 index 0000000..fb4bc01 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/list_notation/list_syntax.rst @@ -0,0 +1,72 @@ +==================== +Rule ``list_syntax`` +==================== + +List (``array`` destructuring) assignment should be declared using the +configured syntax. Requires PHP >= 7.1. + +Configuration +------------- + +``syntax`` +~~~~~~~~~~ + +Whether to use the ``long`` or ``short`` ``list`` syntax. + +Allowed values: ``'long'``, ``'short'`` + +Default value: ``'long'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -[$sample] = $array; + +list($sample) = $array; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['syntax' => 'short']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -list($sample) = $array; + +[$sample] = $array; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP71Migration + Using the `@PHP71Migration <./../../ruleSets/PHP71Migration.rst>`_ rule set will enable the ``list_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@PHP73Migration + Using the `@PHP73Migration <./../../ruleSets/PHP73Migration.rst>`_ rule set will enable the ``list_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@PHP74Migration + Using the `@PHP74Migration <./../../ruleSets/PHP74Migration.rst>`_ rule set will enable the ``list_syntax`` rule with the config below: + + ``['syntax' => 'short']`` + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``list_syntax`` rule with the config below: + + ``['syntax' => 'short']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/blank_line_after_namespace.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/blank_line_after_namespace.rst new file mode 100644 index 0000000..44a729d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/blank_line_after_namespace.rst @@ -0,0 +1,50 @@ +=================================== +Rule ``blank_line_after_namespace`` +=================================== + +There MUST be one blank line after the namespace declaration. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace Sample\Sample; + + - + $a; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + namespace Sample\Sample; + + + Class Test{} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``blank_line_after_namespace`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``blank_line_after_namespace`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``blank_line_after_namespace`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``blank_line_after_namespace`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/clean_namespace.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/clean_namespace.rst new file mode 100644 index 0000000..255444d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/clean_namespace.rst @@ -0,0 +1,44 @@ +======================== +Rule ``clean_namespace`` +======================== + +Namespace must not contain spacing, comments or PHPDoc. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -namespace Foo \ Bar; + +namespace Foo\Bar; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -echo foo /* comment */ \ bar(); + +echo foo\bar(); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``clean_namespace`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``clean_namespace`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``clean_namespace`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/no_blank_lines_before_namespace.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/no_blank_lines_before_namespace.rst new file mode 100644 index 0000000..92230b8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/no_blank_lines_before_namespace.rst @@ -0,0 +1,21 @@ +======================================== +Rule ``no_blank_lines_before_namespace`` +======================================== + +There should be no blank lines before a namespace declaration. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + - + - + - + namespace Example; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/no_leading_namespace_whitespace.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/no_leading_namespace_whitespace.rst new file mode 100644 index 0000000..b33471f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/no_leading_namespace_whitespace.rst @@ -0,0 +1,32 @@ +======================================== +Rule ``no_leading_namespace_whitespace`` +======================================== + +The namespace declaration line shouldn't contain leading whitespace. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + - namespace Test8a; + - namespace Test8b; + +namespace Test8a; + +namespace Test8b; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_leading_namespace_whitespace`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_leading_namespace_whitespace`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/single_blank_line_before_namespace.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/single_blank_line_before_namespace.rst new file mode 100644 index 0000000..25288a7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/namespace_notation/single_blank_line_before_namespace.rst @@ -0,0 +1,46 @@ +=========================================== +Rule ``single_blank_line_before_namespace`` +=========================================== + +There should be exactly one blank line before a namespace declaration. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php namespace A {} + +<?php + + + +namespace A {} + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + - + namespace A{} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``single_blank_line_before_namespace`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``single_blank_line_before_namespace`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``single_blank_line_before_namespace`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/naming/no_homoglyph_names.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/naming/no_homoglyph_names.rst new file mode 100644 index 0000000..7aa83c7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/naming/no_homoglyph_names.rst @@ -0,0 +1,34 @@ +=========================== +Rule ``no_homoglyph_names`` +=========================== + +Replace accidental usage of homoglyphs (non ascii characters) in names. + +.. warning:: Using this rule is risky. + + Renames classes and cannot rename the files. You might have string references + to renamed code (``$$name``). + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $nаmе = 'wrong "a" character'; + +<?php $name = 'wrong "a" character'; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``no_homoglyph_names`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``no_homoglyph_names`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/binary_operator_spaces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/binary_operator_spaces.rst new file mode 100644 index 0000000..d7c3873 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/binary_operator_spaces.rst @@ -0,0 +1,210 @@ +=============================== +Rule ``binary_operator_spaces`` +=============================== + +Binary operators should be surrounded by space as configured. + +Configuration +------------- + +``default`` +~~~~~~~~~~~ + +Default fix strategy. + +Allowed values: ``'align'``, ``'align_single_space'``, ``'align_single_space_minimal'``, ``'no_space'``, ``'single_space'``, ``null`` + +Default value: ``'single_space'`` + +``operators`` +~~~~~~~~~~~~~ + +Dictionary of ``binary operator`` => ``fix strategy`` values that differ from +the default strategy. + +Allowed types: ``array`` + +Default value: ``[]`` + +``align_double_arrow`` +~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: This option is deprecated and will be removed on next major version. Use options ``operators`` and ``default`` instead. + +Whether to apply, remove or ignore double arrows alignment. + +Allowed values: ``false``, ``null``, ``true`` + +Default value: ``false`` + +``align_equals`` +~~~~~~~~~~~~~~~~ + +.. warning:: This option is deprecated and will be removed on next major version. Use options ``operators`` and ``default`` instead. + +Whether to apply, remove or ignore equals alignment. + +Allowed values: ``false``, ``null``, ``true`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a= 1 + $b^ $d !== $e or $f; + +$a = 1 + $b ^ $d !== $e or $f; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['operators' => ['=' => 'align', 'xor' => null]]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $aa= 1; + -$b=2; + +$b =2; + + $c = $d xor $e; + -$f -= 1; + +$f -= 1; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['operators' => ['+=' => 'align_single_space']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = $b +=$c; + -$d = $ee+=$f; + +$a = $b += $c; + +$d = $ee += $f; + + -$g = $b +=$c; + -$h = $ee+=$f; + +$g = $b += $c; + +$h = $ee += $f; + +Example #4 +~~~~~~~~~~ + +With configuration: ``['operators' => ['===' => 'align_single_space_minimal']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = $b===$c; + -$d = $f === $g; + -$h = $i=== $j; + +$a = $b === $c; + +$d = $f === $g; + +$h = $i === $j; + +Example #5 +~~~~~~~~~~ + +With configuration: ``['operators' => ['|' => 'no_space']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$foo = \json_encode($bar, JSON_PRESERVE_ZERO_FRACTION | JSON_PRETTY_PRINT); + +$foo = \json_encode($bar, JSON_PRESERVE_ZERO_FRACTION|JSON_PRETTY_PRINT); + +Example #6 +~~~~~~~~~~ + +With configuration: ``['operators' => ['=>' => 'single_space']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $array = [ + - "foo" => 1, + - "baaaaaaaaaaar" => 11, + + "foo" => 1, + + "baaaaaaaaaaar" => 11, + ]; + +Example #7 +~~~~~~~~~~ + +With configuration: ``['operators' => ['=>' => 'align']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $array = [ + - "foo" => 12, + + "foo" => 12, + "baaaaaaaaaaar" => 13, + ]; + +Example #8 +~~~~~~~~~~ + +With configuration: ``['operators' => ['=>' => 'align_single_space']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $array = [ + - "foo" => 12, + + "foo" => 12, + "baaaaaaaaaaar" => 13, + ]; + +Example #9 +~~~~~~~~~~ + +With configuration: ``['operators' => ['=>' => 'align_single_space_minimal']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $array = [ + - "foo" => 12, + - "baaaaaaaaaaar" => 13, + + "foo" => 12, + + "baaaaaaaaaaar" => 13, + ]; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``binary_operator_spaces`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``binary_operator_spaces`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/concat_space.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/concat_space.rst new file mode 100644 index 0000000..590f0e9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/concat_space.rst @@ -0,0 +1,70 @@ +===================== +Rule ``concat_space`` +===================== + +Concatenation should be spaced according configuration. + +Configuration +------------- + +``spacing`` +~~~~~~~~~~~ + +Spacing to apply around concatenation operator. + +Allowed values: ``'none'``, ``'one'`` + +Default value: ``'none'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$foo = 'bar' . 3 . 'baz'.'qux'; + +$foo = 'bar'. 3 .'baz'.'qux'; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['spacing' => 'none']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$foo = 'bar' . 3 . 'baz'.'qux'; + +$foo = 'bar'. 3 .'baz'.'qux'; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['spacing' => 'one']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$foo = 'bar' . 3 . 'baz'.'qux'; + +$foo = 'bar' . 3 . 'baz' . 'qux'; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``concat_space`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``concat_space`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/increment_style.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/increment_style.rst new file mode 100644 index 0000000..da63644 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/increment_style.rst @@ -0,0 +1,61 @@ +======================== +Rule ``increment_style`` +======================== + +Pre- or post-increment and decrement operators should be used if possible. + +Configuration +------------- + +``style`` +~~~~~~~~~ + +Whether to use pre- or post-increment and decrement operators. + +Allowed values: ``'post'``, ``'pre'`` + +Default value: ``'pre'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a++; + -$b--; + +++$a; + +--$b; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['style' => 'post']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -++$a; + ---$b; + +$a++; + +$b--; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``increment_style`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``increment_style`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/logical_operators.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/logical_operators.rst new file mode 100644 index 0000000..4838d25 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/logical_operators.rst @@ -0,0 +1,37 @@ +========================== +Rule ``logical_operators`` +========================== + +Use ``&&`` and ``||`` logical operators instead of ``and`` and ``or``. + +.. warning:: Using this rule is risky. + + Risky, because you must double-check if using and/or with lower precedence + was intentional. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + -if ($a == "foo" and ($b == "bar" or $c == "baz")) { + +if ($a == "foo" && ($b == "bar" || $c == "baz")) { + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``logical_operators`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``logical_operators`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/new_with_braces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/new_with_braces.rst new file mode 100644 index 0000000..491c366 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/new_with_braces.rst @@ -0,0 +1,32 @@ +======================== +Rule ``new_with_braces`` +======================== + +All instances created with new keyword must be followed by braces. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $x = new X; + +<?php $x = new X(); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``new_with_braces`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``new_with_braces`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``new_with_braces`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/not_operator_with_space.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/not_operator_with_space.rst new file mode 100644 index 0000000..e33458f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/not_operator_with_space.rst @@ -0,0 +1,22 @@ +================================ +Rule ``not_operator_with_space`` +================================ + +Logical NOT operators (``!``) should have leading and trailing whitespaces. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + -if (!$bar) { + +if ( ! $bar) { + echo "Help!"; + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/not_operator_with_successor_space.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/not_operator_with_successor_space.rst new file mode 100644 index 0000000..02c2495 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/not_operator_with_successor_space.rst @@ -0,0 +1,22 @@ +========================================== +Rule ``not_operator_with_successor_space`` +========================================== + +Logical NOT operators (``!``) should have one trailing whitespace. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + -if (!$bar) { + +if (! $bar) { + echo "Help!"; + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/object_operator_without_whitespace.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/object_operator_without_whitespace.rst new file mode 100644 index 0000000..e8e9762 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/object_operator_without_whitespace.rst @@ -0,0 +1,29 @@ +=========================================== +Rule ``object_operator_without_whitespace`` +=========================================== + +There should not be space before or after object operators ``->`` and ``?->``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $a -> b; + +<?php $a->b; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``object_operator_without_whitespace`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``object_operator_without_whitespace`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/operator_linebreak.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/operator_linebreak.rst new file mode 100644 index 0000000..408ec6f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/operator_linebreak.rst @@ -0,0 +1,74 @@ +=========================== +Rule ``operator_linebreak`` +=========================== + +Operators - when multiline - must always be at the beginning or at the end of +the line. + +Configuration +------------- + +``only_booleans`` +~~~~~~~~~~~~~~~~~ + +whether to limit operators to only boolean ones + +Allowed types: ``bool`` + +Default value: ``false`` + +``position`` +~~~~~~~~~~~~ + +whether to place operators at the beginning or at the end of the line + +Allowed values: ``'beginning'``, ``'end'`` + +Default value: ``'beginning'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + function foo() { + - return $bar || + - $baz; + + return $bar + + || $baz; + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['position' => 'end']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + function foo() { + - return $bar + - || $baz; + + return $bar || + + $baz; + } + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``operator_linebreak`` rule with the config below: + + ``['only_booleans' => true]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/pre_increment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/pre_increment.rst new file mode 100644 index 0000000..2d4ec38 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/pre_increment.rst @@ -0,0 +1,25 @@ +====================== +Rule ``pre_increment`` +====================== + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``increment_style`` instead. + +Pre incrementation/decrementation should be used if possible. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a++; + -$b--; + +++$a; + +--$b; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/standardize_increment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/standardize_increment.rst new file mode 100644 index 0000000..176d9f5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/standardize_increment.rst @@ -0,0 +1,41 @@ +============================== +Rule ``standardize_increment`` +============================== + +Increment and decrement operators should be used if possible. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$i += 1; + +++$i; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$i -= 1; + +--$i; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``standardize_increment`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``standardize_increment`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/standardize_not_equals.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/standardize_not_equals.rst new file mode 100644 index 0000000..329941c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/standardize_not_equals.rst @@ -0,0 +1,30 @@ +=============================== +Rule ``standardize_not_equals`` +=============================== + +Replace all ``<>`` with ``!=``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = $b <> $c; + +$a = $b != $c; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``standardize_not_equals`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``standardize_not_equals`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_operator_spaces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_operator_spaces.rst new file mode 100644 index 0000000..cbc2c1f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_operator_spaces.rst @@ -0,0 +1,32 @@ +================================ +Rule ``ternary_operator_spaces`` +================================ + +Standardize spaces around ternary operator. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $a = $a ?1 :0; + +<?php $a = $a ? 1 : 0; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``ternary_operator_spaces`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``ternary_operator_spaces`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``ternary_operator_spaces`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_to_elvis_operator.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_to_elvis_operator.rst new file mode 100644 index 0000000..b99d005 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_to_elvis_operator.rst @@ -0,0 +1,44 @@ +================================== +Rule ``ternary_to_elvis_operator`` +================================== + +Use the Elvis operator ``?:`` where possible. + +.. warning:: Using this rule is risky. + + Risky when relying on functions called on both sides of the ``?`` operator. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$foo = $foo ? $foo : 1; + +$foo = $foo ? : 1; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $foo = $bar[a()] ? $bar[a()] : 1; # "risky" sample, "a()" only gets called once after fixing + +<?php $foo = $bar[a()] ? : 1; # "risky" sample, "a()" only gets called once after fixing + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``ternary_to_elvis_operator`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``ternary_to_elvis_operator`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_to_null_coalescing.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_to_null_coalescing.rst new file mode 100644 index 0000000..38d4f6c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/ternary_to_null_coalescing.rst @@ -0,0 +1,39 @@ +=================================== +Rule ``ternary_to_null_coalescing`` +=================================== + +Use ``null`` coalescing operator ``??`` where possible. Requires PHP >= 7.0. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$sample = isset($a) ? $a : $b; + +$sample = $a ?? $b; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP70Migration + Using the `@PHP70Migration <./../../ruleSets/PHP70Migration.rst>`_ rule set will enable the ``ternary_to_null_coalescing`` rule. + +@PHP71Migration + Using the `@PHP71Migration <./../../ruleSets/PHP71Migration.rst>`_ rule set will enable the ``ternary_to_null_coalescing`` rule. + +@PHP73Migration + Using the `@PHP73Migration <./../../ruleSets/PHP73Migration.rst>`_ rule set will enable the ``ternary_to_null_coalescing`` rule. + +@PHP74Migration + Using the `@PHP74Migration <./../../ruleSets/PHP74Migration.rst>`_ rule set will enable the ``ternary_to_null_coalescing`` rule. + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``ternary_to_null_coalescing`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/unary_operator_spaces.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/unary_operator_spaces.rst new file mode 100644 index 0000000..e477bd3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/operator/unary_operator_spaces.rst @@ -0,0 +1,38 @@ +============================== +Rule ``unary_operator_spaces`` +============================== + +Unary operators should be placed adjacent to their operands. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$sample ++; + --- $sample; + -$sample = ! ! $a; + -$sample = ~ $c; + -function & foo(){} + +$sample++; + +--$sample; + +$sample = !!$a; + +$sample = ~$c; + +function &foo(){} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``unary_operator_spaces`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``unary_operator_spaces`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/blank_line_after_opening_tag.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/blank_line_after_opening_tag.rst new file mode 100644 index 0000000..1f539ff --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/blank_line_after_opening_tag.rst @@ -0,0 +1,36 @@ +===================================== +Rule ``blank_line_after_opening_tag`` +===================================== + +Ensure there is no code on the same line as the PHP open tag and it is followed +by a blank line. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $a = 1; + +<?php + + + +$a = 1; + $b = 1; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``blank_line_after_opening_tag`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``blank_line_after_opening_tag`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``blank_line_after_opening_tag`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/echo_tag_syntax.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/echo_tag_syntax.rst new file mode 100644 index 0000000..47d8a3f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/echo_tag_syntax.rst @@ -0,0 +1,128 @@ +======================== +Rule ``echo_tag_syntax`` +======================== + +Replaces short-echo ``<?=`` with long format ``<?php echo``/``<?php print`` +syntax, or vice-versa. + +Configuration +------------- + +``format`` +~~~~~~~~~~ + +The desired language construct. + +Allowed values: ``'long'``, ``'short'`` + +Default value: ``'long'`` + +``long_function`` +~~~~~~~~~~~~~~~~~ + +The function to be used to expand the short echo tags + +Allowed values: ``'echo'``, ``'print'`` + +Default value: ``'echo'`` + +``shorten_simple_statements_only`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Render short-echo tags only in case of simple code + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + -<?=1?> + +<?php echo 1?> + <?php print '2' . '3'; ?> + <?php /* comment */ echo '2' . '3'; ?> + <?php print '2' . '3'; someFunction(); ?> + +Example #2 +~~~~~~~~~~ + +With configuration: ``['format' => 'long']``. + +.. code-block:: diff + + --- Original + +++ New + -<?=1?> + +<?php echo 1?> + <?php print '2' . '3'; ?> + <?php /* comment */ echo '2' . '3'; ?> + <?php print '2' . '3'; someFunction(); ?> + +Example #3 +~~~~~~~~~~ + +With configuration: ``['format' => 'long', 'long_function' => 'print']``. + +.. code-block:: diff + + --- Original + +++ New + -<?=1?> + +<?php print 1?> + <?php print '2' . '3'; ?> + <?php /* comment */ echo '2' . '3'; ?> + <?php print '2' . '3'; someFunction(); ?> + +Example #4 +~~~~~~~~~~ + +With configuration: ``['format' => 'short']``. + +.. code-block:: diff + + --- Original + +++ New + <?=1?> + -<?php print '2' . '3'; ?> + -<?php /* comment */ echo '2' . '3'; ?> + +<?= '2' . '3'; ?> + +<?=/* comment */ '2' . '3'; ?> + <?php print '2' . '3'; someFunction(); ?> + +Example #5 +~~~~~~~~~~ + +With configuration: ``['format' => 'short', 'shorten_simple_statements_only' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?=1?> + -<?php print '2' . '3'; ?> + -<?php /* comment */ echo '2' . '3'; ?> + -<?php print '2' . '3'; someFunction(); ?> + +<?= '2' . '3'; ?> + +<?=/* comment */ '2' . '3'; ?> + +<?= '2' . '3'; someFunction(); ?> + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``echo_tag_syntax`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``echo_tag_syntax`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/full_opening_tag.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/full_opening_tag.rst new file mode 100644 index 0000000..57198dd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/full_opening_tag.rst @@ -0,0 +1,41 @@ +========================= +Rule ``full_opening_tag`` +========================= + +PHP code must use the long ``<?php`` tags or short-echo ``<?=`` tags and not +other tag variations. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<? + +<?php + + echo "Hello!"; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR1 + Using the `@PSR1 <./../../ruleSets/PSR1.rst>`_ rule set will enable the ``full_opening_tag`` rule. + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``full_opening_tag`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``full_opening_tag`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``full_opening_tag`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``full_opening_tag`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/linebreak_after_opening_tag.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/linebreak_after_opening_tag.rst new file mode 100644 index 0000000..0c84893 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/linebreak_after_opening_tag.rst @@ -0,0 +1,31 @@ +==================================== +Rule ``linebreak_after_opening_tag`` +==================================== + +Ensure there is no code on the same line as the PHP open tag. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $a = 1; + +<?php + +$a = 1; + $b = 3; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``linebreak_after_opening_tag`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``linebreak_after_opening_tag`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/no_closing_tag.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/no_closing_tag.rst new file mode 100644 index 0000000..7fd7d64 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/no_closing_tag.rst @@ -0,0 +1,40 @@ +======================= +Rule ``no_closing_tag`` +======================= + +The closing ``?>`` tag MUST be omitted from files containing only PHP. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Sample + { + -} + -?> + +} + \ No newline at end of file + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``no_closing_tag`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``no_closing_tag`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_closing_tag`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_closing_tag`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/no_short_echo_tag.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/no_short_echo_tag.rst new file mode 100644 index 0000000..637707d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_tag/no_short_echo_tag.rst @@ -0,0 +1,22 @@ +========================== +Rule ``no_short_echo_tag`` +========================== + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``echo_tag_syntax`` instead. + +Replaces short-echo ``<?=`` with long format ``<?php echo`` syntax. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?= "foo"; + +<?php echo "foo"; diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_construct.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_construct.rst new file mode 100644 index 0000000..877ce5c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_construct.rst @@ -0,0 +1,80 @@ +=========================== +Rule ``php_unit_construct`` +=========================== + +PHPUnit assertion method calls like ``->assertSame(true, $foo)`` should be +written with dedicated method like ``->assertTrue($foo)``. + +.. warning:: Using this rule is risky. + + Fixer could be risky if one is overriding PHPUnit's native methods. + +Configuration +------------- + +``assertions`` +~~~~~~~~~~~~~~ + +List of assertion methods to fix. + +Allowed values: a subset of ``['assertSame', 'assertEquals', 'assertNotEquals', 'assertNotSame']`` + +Default value: ``['assertEquals', 'assertSame', 'assertNotEquals', 'assertNotSame']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class FooTest extends \PHPUnit_Framework_TestCase { + public function testSomething() { + - $this->assertEquals(false, $b); + - $this->assertSame(true, $a); + - $this->assertNotEquals(null, $c); + - $this->assertNotSame(null, $d); + + $this->assertFalse($b); + + $this->assertTrue($a); + + $this->assertNotNull($c); + + $this->assertNotNull($d); + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['assertions' => ['assertSame', 'assertNotSame']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class FooTest extends \PHPUnit_Framework_TestCase { + public function testSomething() { + $this->assertEquals(false, $b); + - $this->assertSame(true, $a); + + $this->assertTrue($a); + $this->assertNotEquals(null, $c); + - $this->assertNotSame(null, $d); + + $this->assertNotNull($d); + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``php_unit_construct`` rule with the default config. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``php_unit_construct`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_dedicate_assert.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_dedicate_assert.rst new file mode 100644 index 0000000..214afc5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_dedicate_assert.rst @@ -0,0 +1,147 @@ +================================= +Rule ``php_unit_dedicate_assert`` +================================= + +PHPUnit assertions like ``assertInternalType``, ``assertFileExists``, should be +used over ``assertTrue``. + +.. warning:: Using this rule is risky. + + Fixer could be risky if one is overriding PHPUnit's native methods. + +Configuration +------------- + +``functions`` +~~~~~~~~~~~~~ + +.. warning:: This option is deprecated and will be removed on next major version. Use option ``target`` instead. + +List of assertions to fix (overrides ``target``). + +Allowed values: a subset of ``['array_key_exists', 'empty', 'file_exists', 'is_array', 'is_bool', 'is_callable', 'is_double', 'is_float', 'is_infinite', 'is_int', 'is_integer', 'is_long', 'is_nan', 'is_null', 'is_numeric', 'is_object', 'is_real', 'is_resource', 'is_scalar', 'is_string']``, ``null`` + +Default value: ``null`` + +``target`` +~~~~~~~~~~ + +Target version of PHPUnit. + +Allowed values: ``'3.0'``, ``'3.5'``, ``'5.0'``, ``'5.6'``, ``'newest'`` + +Default value: ``'5.0'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testSomeTest() + { + - $this->assertTrue(is_float( $a), "my message"); + - $this->assertTrue(is_nan($a)); + + $this->assertInternalType('float', $a, "my message"); + + $this->assertNan($a); + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['target' => '5.6']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testSomeTest() + { + - $this->assertTrue(is_dir($a)); + - $this->assertTrue(is_writable($a)); + - $this->assertTrue(is_readable($a)); + + $this->assertDirectoryExists($a); + + $this->assertIsWritable($a); + + $this->assertIsReadable($a); + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHPUnit30Migration:risky + Using the `@PHPUnit30Migration:risky <./../../ruleSets/PHPUnit30MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the config below: + + ``['target' => '3.0']`` + +@PHPUnit32Migration:risky + Using the `@PHPUnit32Migration:risky <./../../ruleSets/PHPUnit32MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the config below: + + ``['target' => '3.0']`` + +@PHPUnit35Migration:risky + Using the `@PHPUnit35Migration:risky <./../../ruleSets/PHPUnit35MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the config below: + + ``['target' => '3.5']`` + +@PHPUnit43Migration:risky + Using the `@PHPUnit43Migration:risky <./../../ruleSets/PHPUnit43MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the config below: + + ``['target' => '3.5']`` + +@PHPUnit48Migration:risky + Using the `@PHPUnit48Migration:risky <./../../ruleSets/PHPUnit48MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the config below: + + ``['target' => '3.5']`` + +@PHPUnit50Migration:risky + Using the `@PHPUnit50Migration:risky <./../../ruleSets/PHPUnit50MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the default config. + +@PHPUnit52Migration:risky + Using the `@PHPUnit52Migration:risky <./../../ruleSets/PHPUnit52MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the default config. + +@PHPUnit54Migration:risky + Using the `@PHPUnit54Migration:risky <./../../ruleSets/PHPUnit54MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the default config. + +@PHPUnit55Migration:risky + Using the `@PHPUnit55Migration:risky <./../../ruleSets/PHPUnit55MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the default config. + +@PHPUnit56Migration:risky + Using the `@PHPUnit56Migration:risky <./../../ruleSets/PHPUnit56MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the config below: + + ``['target' => '5.6']`` + +@PHPUnit57Migration:risky + Using the `@PHPUnit57Migration:risky <./../../ruleSets/PHPUnit57MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the config below: + + ``['target' => '5.6']`` + +@PHPUnit60Migration:risky + Using the `@PHPUnit60Migration:risky <./../../ruleSets/PHPUnit60MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the config below: + + ``['target' => '5.6']`` + +@PHPUnit75Migration:risky + Using the `@PHPUnit75Migration:risky <./../../ruleSets/PHPUnit75MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the config below: + + ``['target' => '5.6']`` + +@PHPUnit84Migration:risky + Using the `@PHPUnit84Migration:risky <./../../ruleSets/PHPUnit84MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert`` rule with the config below: + + ``['target' => '5.6']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_dedicate_assert_internal_type.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_dedicate_assert_internal_type.rst new file mode 100644 index 0000000..d2a11b7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_dedicate_assert_internal_type.rst @@ -0,0 +1,83 @@ +=============================================== +Rule ``php_unit_dedicate_assert_internal_type`` +=============================================== + +PHPUnit assertions like ``assertIsArray`` should be used over +``assertInternalType``. + +.. warning:: Using this rule is risky. + + Risky when PHPUnit methods are overridden or when project has PHPUnit + incompatibilities. + +Configuration +------------- + +``target`` +~~~~~~~~~~ + +Target version of PHPUnit. + +Allowed values: ``'7.5'``, ``'newest'`` + +Default value: ``'newest'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit\Framework\TestCase + { + public function testMe() + { + - $this->assertInternalType("array", $var); + - $this->assertInternalType("boolean", $var); + + $this->assertIsArray($var); + + $this->assertIsBool($var); + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['target' => '7.5']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit\Framework\TestCase + { + public function testMe() + { + - $this->assertInternalType("array", $var); + - $this->assertInternalType("boolean", $var); + + $this->assertIsArray($var); + + $this->assertIsBool($var); + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHPUnit75Migration:risky + Using the `@PHPUnit75Migration:risky <./../../ruleSets/PHPUnit75MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert_internal_type`` rule with the config below: + + ``['target' => '7.5']`` + +@PHPUnit84Migration:risky + Using the `@PHPUnit84Migration:risky <./../../ruleSets/PHPUnit84MigrationRisky.rst>`_ rule set will enable the ``php_unit_dedicate_assert_internal_type`` rule with the config below: + + ``['target' => '7.5']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_expectation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_expectation.rst new file mode 100644 index 0000000..573e8e5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_expectation.rst @@ -0,0 +1,190 @@ +============================= +Rule ``php_unit_expectation`` +============================= + +Usages of ``->setExpectedException*`` methods MUST be replaced by +``->expectException*`` methods. + +.. warning:: Using this rule is risky. + + Risky when PHPUnit classes are overridden or not accessible, or when project + has PHPUnit incompatibilities. + +Configuration +------------- + +``target`` +~~~~~~~~~~ + +Target version of PHPUnit. + +Allowed values: ``'5.2'``, ``'5.6'``, ``'8.4'``, ``'newest'`` + +Default value: ``'newest'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testFoo() + { + - $this->setExpectedException("RuntimeException", "Msg", 123); + + $this->expectException("RuntimeException"); + + $this->expectExceptionMessage("Msg"); + + $this->expectExceptionCode(123); + foo(); + } + + public function testBar() + { + - $this->setExpectedExceptionRegExp("RuntimeException", "/Msg.*/", 123); + + $this->expectException("RuntimeException"); + + $this->expectExceptionMessageMatches("/Msg.*/"); + + $this->expectExceptionCode(123); + bar(); + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['target' => '8.4']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testFoo() + { + - $this->setExpectedException("RuntimeException", null, 123); + + $this->expectException("RuntimeException"); + + $this->expectExceptionCode(123); + foo(); + } + + public function testBar() + { + - $this->setExpectedExceptionRegExp("RuntimeException", "/Msg.*/", 123); + + $this->expectException("RuntimeException"); + + $this->expectExceptionMessageMatches("/Msg.*/"); + + $this->expectExceptionCode(123); + bar(); + } + } + +Example #3 +~~~~~~~~~~ + +With configuration: ``['target' => '5.6']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testFoo() + { + - $this->setExpectedException("RuntimeException", null, 123); + + $this->expectException("RuntimeException"); + + $this->expectExceptionCode(123); + foo(); + } + + public function testBar() + { + - $this->setExpectedExceptionRegExp("RuntimeException", "/Msg.*/", 123); + + $this->expectException("RuntimeException"); + + $this->expectExceptionMessageRegExp("/Msg.*/"); + + $this->expectExceptionCode(123); + bar(); + } + } + +Example #4 +~~~~~~~~~~ + +With configuration: ``['target' => '5.2']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testFoo() + { + - $this->setExpectedException("RuntimeException", "Msg", 123); + + $this->expectException("RuntimeException"); + + $this->expectExceptionMessage("Msg"); + + $this->expectExceptionCode(123); + foo(); + } + + public function testBar() + { + $this->setExpectedExceptionRegExp("RuntimeException", "/Msg.*/", 123); + bar(); + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHPUnit52Migration:risky + Using the `@PHPUnit52Migration:risky <./../../ruleSets/PHPUnit52MigrationRisky.rst>`_ rule set will enable the ``php_unit_expectation`` rule with the config below: + + ``['target' => '5.2']`` + +@PHPUnit54Migration:risky + Using the `@PHPUnit54Migration:risky <./../../ruleSets/PHPUnit54MigrationRisky.rst>`_ rule set will enable the ``php_unit_expectation`` rule with the config below: + + ``['target' => '5.2']`` + +@PHPUnit55Migration:risky + Using the `@PHPUnit55Migration:risky <./../../ruleSets/PHPUnit55MigrationRisky.rst>`_ rule set will enable the ``php_unit_expectation`` rule with the config below: + + ``['target' => '5.2']`` + +@PHPUnit56Migration:risky + Using the `@PHPUnit56Migration:risky <./../../ruleSets/PHPUnit56MigrationRisky.rst>`_ rule set will enable the ``php_unit_expectation`` rule with the config below: + + ``['target' => '5.6']`` + +@PHPUnit57Migration:risky + Using the `@PHPUnit57Migration:risky <./../../ruleSets/PHPUnit57MigrationRisky.rst>`_ rule set will enable the ``php_unit_expectation`` rule with the config below: + + ``['target' => '5.6']`` + +@PHPUnit60Migration:risky + Using the `@PHPUnit60Migration:risky <./../../ruleSets/PHPUnit60MigrationRisky.rst>`_ rule set will enable the ``php_unit_expectation`` rule with the config below: + + ``['target' => '5.6']`` + +@PHPUnit75Migration:risky + Using the `@PHPUnit75Migration:risky <./../../ruleSets/PHPUnit75MigrationRisky.rst>`_ rule set will enable the ``php_unit_expectation`` rule with the config below: + + ``['target' => '5.6']`` + +@PHPUnit84Migration:risky + Using the `@PHPUnit84Migration:risky <./../../ruleSets/PHPUnit84MigrationRisky.rst>`_ rule set will enable the ``php_unit_expectation`` rule with the config below: + + ``['target' => '8.4']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_fqcn_annotation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_fqcn_annotation.rst new file mode 100644 index 0000000..7cd2a14 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_fqcn_annotation.rst @@ -0,0 +1,44 @@ +================================= +Rule ``php_unit_fqcn_annotation`` +================================= + +PHPUnit annotations should be a FQCNs including a root namespace. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + /** + - * @expectedException InvalidArgumentException + - * @covers Project\NameSpace\Something + - * @coversDefaultClass Project\Default + - * @uses Project\Test\Util + + * @expectedException \InvalidArgumentException + + * @covers \Project\NameSpace\Something + + * @coversDefaultClass \Project\Default + + * @uses \Project\Test\Util + */ + public function testSomeTest() + { + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``php_unit_fqcn_annotation`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``php_unit_fqcn_annotation`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_internal_class.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_internal_class.rst new file mode 100644 index 0000000..61acc24 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_internal_class.rst @@ -0,0 +1,60 @@ +================================ +Rule ``php_unit_internal_class`` +================================ + +All PHPUnit test classes should be marked as internal. + +Configuration +------------- + +``types`` +~~~~~~~~~ + +What types of classes to mark as internal + +Allowed values: a subset of ``['normal', 'final', 'abstract']`` + +Default value: ``['normal', 'final']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + +/** + + * @internal + + */ + class MyTest extends TestCase {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['types' => ['final']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class MyTest extends TestCase {} + +/** + + * @internal + + */ + final class FinalTest extends TestCase {} + abstract class AbstractTest extends TestCase {} + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``php_unit_internal_class`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_method_casing.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_method_casing.rst new file mode 100644 index 0000000..edfbc40 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_method_casing.rst @@ -0,0 +1,63 @@ +=============================== +Rule ``php_unit_method_casing`` +=============================== + +Enforce camel (or snake) case for PHPUnit test methods, following configuration. + +Configuration +------------- + +``case`` +~~~~~~~~ + +Apply camel or snake case to test methods + +Allowed values: ``'camel_case'``, ``'snake_case'`` + +Default value: ``'camel_case'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + class MyTest extends \PhpUnit\FrameWork\TestCase + { + - public function test_my_code() {} + + public function testMyCode() {} + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['case' => 'snake_case']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class MyTest extends \PhpUnit\FrameWork\TestCase + { + - public function testMyCode() {} + + public function test_my_code() {} + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``php_unit_method_casing`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``php_unit_method_casing`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_mock.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_mock.rst new file mode 100644 index 0000000..81e5eb2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_mock.rst @@ -0,0 +1,110 @@ +====================== +Rule ``php_unit_mock`` +====================== + +Usages of ``->getMock`` and ``->getMockWithoutInvokingTheOriginalConstructor`` +methods MUST be replaced by ``->createMock`` or ``->createPartialMock`` methods. + +.. warning:: Using this rule is risky. + + Risky when PHPUnit classes are overridden or not accessible, or when project + has PHPUnit incompatibilities. + +Configuration +------------- + +``target`` +~~~~~~~~~~ + +Target version of PHPUnit. + +Allowed values: ``'5.4'``, ``'5.5'``, ``'newest'`` + +Default value: ``'newest'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testFoo() + { + - $mock = $this->getMockWithoutInvokingTheOriginalConstructor("Foo"); + - $mock1 = $this->getMock("Foo"); + - $mock1 = $this->getMock("Bar", ["aaa"]); + + $mock = $this->createMock("Foo"); + + $mock1 = $this->createMock("Foo"); + + $mock1 = $this->createPartialMock("Bar", ["aaa"]); + $mock1 = $this->getMock("Baz", ["aaa"], ["argument"]); // version with more than 2 params is not supported + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['target' => '5.4']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testFoo() + { + - $mock1 = $this->getMock("Foo"); + + $mock1 = $this->createMock("Foo"); + $mock1 = $this->getMock("Bar", ["aaa"]); // version with multiple params is not supported + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHPUnit54Migration:risky + Using the `@PHPUnit54Migration:risky <./../../ruleSets/PHPUnit54MigrationRisky.rst>`_ rule set will enable the ``php_unit_mock`` rule with the config below: + + ``['target' => '5.4']`` + +@PHPUnit55Migration:risky + Using the `@PHPUnit55Migration:risky <./../../ruleSets/PHPUnit55MigrationRisky.rst>`_ rule set will enable the ``php_unit_mock`` rule with the config below: + + ``['target' => '5.5']`` + +@PHPUnit56Migration:risky + Using the `@PHPUnit56Migration:risky <./../../ruleSets/PHPUnit56MigrationRisky.rst>`_ rule set will enable the ``php_unit_mock`` rule with the config below: + + ``['target' => '5.5']`` + +@PHPUnit57Migration:risky + Using the `@PHPUnit57Migration:risky <./../../ruleSets/PHPUnit57MigrationRisky.rst>`_ rule set will enable the ``php_unit_mock`` rule with the config below: + + ``['target' => '5.5']`` + +@PHPUnit60Migration:risky + Using the `@PHPUnit60Migration:risky <./../../ruleSets/PHPUnit60MigrationRisky.rst>`_ rule set will enable the ``php_unit_mock`` rule with the config below: + + ``['target' => '5.5']`` + +@PHPUnit75Migration:risky + Using the `@PHPUnit75Migration:risky <./../../ruleSets/PHPUnit75MigrationRisky.rst>`_ rule set will enable the ``php_unit_mock`` rule with the config below: + + ``['target' => '5.5']`` + +@PHPUnit84Migration:risky + Using the `@PHPUnit84Migration:risky <./../../ruleSets/PHPUnit84MigrationRisky.rst>`_ rule set will enable the ``php_unit_mock`` rule with the config below: + + ``['target' => '5.5']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_mock_short_will_return.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_mock_short_will_return.rst new file mode 100644 index 0000000..219d14a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_mock_short_will_return.rst @@ -0,0 +1,51 @@ +======================================== +Rule ``php_unit_mock_short_will_return`` +======================================== + +Usage of PHPUnit's mock e.g. ``->will($this->returnValue(..))`` must be replaced +by its shorter equivalent such as ``->willReturn(...)``. + +.. warning:: Using this rule is risky. + + Risky when PHPUnit classes are overridden or not accessible, or when project + has PHPUnit incompatibilities. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testSomeTest() + { + $someMock = $this->createMock(Some::class); + - $someMock->method("some")->will($this->returnSelf()); + - $someMock->method("some")->will($this->returnValue("example")); + - $someMock->method("some")->will($this->returnArgument(2)); + - $someMock->method("some")->will($this->returnCallback("str_rot13")); + - $someMock->method("some")->will($this->returnValueMap(["a","b","c"])); + + $someMock->method("some")->willReturnSelf(); + + $someMock->method("some")->willReturn("example"); + + $someMock->method("some")->willReturnArgument(2); + + $someMock->method("some")->willReturnCallback("str_rot13"); + + $someMock->method("some")->willReturnMap(["a","b","c"]); + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``php_unit_mock_short_will_return`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``php_unit_mock_short_will_return`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_namespaced.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_namespaced.rst new file mode 100644 index 0000000..c4ad4aa --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_namespaced.rst @@ -0,0 +1,133 @@ +============================ +Rule ``php_unit_namespaced`` +============================ + +PHPUnit classes MUST be used in namespaced version, e.g. +``\PHPUnit\Framework\TestCase`` instead of ``\PHPUnit_Framework_TestCase``. + +Description +----------- + +PHPUnit v6 has finally fully switched to namespaces. +You could start preparing the upgrade by switching from non-namespaced TestCase +to namespaced one. +Forward compatibility layer (``\PHPUnit\Framework\TestCase`` class) was +backported to PHPUnit v4.8.35 and PHPUnit v5.4.0. +Extended forward compatibility layer (``PHPUnit\Framework\Assert``, +``PHPUnit\Framework\BaseTestListener``, ``PHPUnit\Framework\TestListener`` +classes) was introduced in v5.7.0. + + +.. warning:: Using this rule is risky. + + Risky when PHPUnit classes are overridden or not accessible, or when project + has PHPUnit incompatibilities. + +Configuration +------------- + +``target`` +~~~~~~~~~~ + +Target version of PHPUnit. + +Allowed values: ``'4.8'``, ``'5.7'``, ``'6.0'``, ``'newest'`` + +Default value: ``'newest'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -final class MyTest extends \PHPUnit_Framework_TestCase + +final class MyTest extends \PHPUnit\Framework\TestCase + { + public function testSomething() + { + - PHPUnit_Framework_Assert::assertTrue(true); + + PHPUnit\Framework\Assert::assertTrue(true); + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['target' => '4.8']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -final class MyTest extends \PHPUnit_Framework_TestCase + +final class MyTest extends \PHPUnit\Framework\TestCase + { + public function testSomething() + { + PHPUnit_Framework_Assert::assertTrue(true); + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHPUnit48Migration:risky + Using the `@PHPUnit48Migration:risky <./../../ruleSets/PHPUnit48MigrationRisky.rst>`_ rule set will enable the ``php_unit_namespaced`` rule with the config below: + + ``['target' => '4.8']`` + +@PHPUnit50Migration:risky + Using the `@PHPUnit50Migration:risky <./../../ruleSets/PHPUnit50MigrationRisky.rst>`_ rule set will enable the ``php_unit_namespaced`` rule with the config below: + + ``['target' => '4.8']`` + +@PHPUnit52Migration:risky + Using the `@PHPUnit52Migration:risky <./../../ruleSets/PHPUnit52MigrationRisky.rst>`_ rule set will enable the ``php_unit_namespaced`` rule with the config below: + + ``['target' => '4.8']`` + +@PHPUnit54Migration:risky + Using the `@PHPUnit54Migration:risky <./../../ruleSets/PHPUnit54MigrationRisky.rst>`_ rule set will enable the ``php_unit_namespaced`` rule with the config below: + + ``['target' => '4.8']`` + +@PHPUnit55Migration:risky + Using the `@PHPUnit55Migration:risky <./../../ruleSets/PHPUnit55MigrationRisky.rst>`_ rule set will enable the ``php_unit_namespaced`` rule with the config below: + + ``['target' => '4.8']`` + +@PHPUnit56Migration:risky + Using the `@PHPUnit56Migration:risky <./../../ruleSets/PHPUnit56MigrationRisky.rst>`_ rule set will enable the ``php_unit_namespaced`` rule with the config below: + + ``['target' => '4.8']`` + +@PHPUnit57Migration:risky + Using the `@PHPUnit57Migration:risky <./../../ruleSets/PHPUnit57MigrationRisky.rst>`_ rule set will enable the ``php_unit_namespaced`` rule with the config below: + + ``['target' => '5.7']`` + +@PHPUnit60Migration:risky + Using the `@PHPUnit60Migration:risky <./../../ruleSets/PHPUnit60MigrationRisky.rst>`_ rule set will enable the ``php_unit_namespaced`` rule with the config below: + + ``['target' => '6.0']`` + +@PHPUnit75Migration:risky + Using the `@PHPUnit75Migration:risky <./../../ruleSets/PHPUnit75MigrationRisky.rst>`_ rule set will enable the ``php_unit_namespaced`` rule with the config below: + + ``['target' => '6.0']`` + +@PHPUnit84Migration:risky + Using the `@PHPUnit84Migration:risky <./../../ruleSets/PHPUnit84MigrationRisky.rst>`_ rule set will enable the ``php_unit_namespaced`` rule with the config below: + + ``['target' => '6.0']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_no_expectation_annotation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_no_expectation_annotation.rst new file mode 100644 index 0000000..efe5eab --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_no_expectation_annotation.rst @@ -0,0 +1,163 @@ +=========================================== +Rule ``php_unit_no_expectation_annotation`` +=========================================== + +Usages of ``@expectedException*`` annotations MUST be replaced by +``->setExpectedException*`` methods. + +.. warning:: Using this rule is risky. + + Risky when PHPUnit classes are overridden or not accessible, or when project + has PHPUnit incompatibilities. + +Configuration +------------- + +``target`` +~~~~~~~~~~ + +Target version of PHPUnit. + +Allowed values: ``'3.2'``, ``'4.3'``, ``'newest'`` + +Default value: ``'newest'`` + +``use_class_const`` +~~~~~~~~~~~~~~~~~~~ + +Use ::class notation. + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + /** + - * @expectedException FooException + - * @expectedExceptionMessageRegExp /foo.*$/ + - * @expectedExceptionCode 123 + */ + function testAaa() + { + + $this->setExpectedExceptionRegExp(\FooException::class, '/foo.*$/', 123); + + + aaa(); + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['target' => '3.2']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + /** + - * @expectedException FooException + - * @expectedExceptionCode 123 + */ + function testBbb() + { + + $this->setExpectedException(\FooException::class, null, 123); + + + bbb(); + } + + /** + * @expectedException FooException + * @expectedExceptionMessageRegExp /foo.*$/ + */ + function testCcc() + { + ccc(); + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHPUnit32Migration:risky + Using the `@PHPUnit32Migration:risky <./../../ruleSets/PHPUnit32MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '3.2']`` + +@PHPUnit35Migration:risky + Using the `@PHPUnit35Migration:risky <./../../ruleSets/PHPUnit35MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '3.2']`` + +@PHPUnit43Migration:risky + Using the `@PHPUnit43Migration:risky <./../../ruleSets/PHPUnit43MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` + +@PHPUnit48Migration:risky + Using the `@PHPUnit48Migration:risky <./../../ruleSets/PHPUnit48MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` + +@PHPUnit50Migration:risky + Using the `@PHPUnit50Migration:risky <./../../ruleSets/PHPUnit50MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` + +@PHPUnit52Migration:risky + Using the `@PHPUnit52Migration:risky <./../../ruleSets/PHPUnit52MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` + +@PHPUnit54Migration:risky + Using the `@PHPUnit54Migration:risky <./../../ruleSets/PHPUnit54MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` + +@PHPUnit55Migration:risky + Using the `@PHPUnit55Migration:risky <./../../ruleSets/PHPUnit55MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` + +@PHPUnit56Migration:risky + Using the `@PHPUnit56Migration:risky <./../../ruleSets/PHPUnit56MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` + +@PHPUnit57Migration:risky + Using the `@PHPUnit57Migration:risky <./../../ruleSets/PHPUnit57MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` + +@PHPUnit60Migration:risky + Using the `@PHPUnit60Migration:risky <./../../ruleSets/PHPUnit60MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` + +@PHPUnit75Migration:risky + Using the `@PHPUnit75Migration:risky <./../../ruleSets/PHPUnit75MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` + +@PHPUnit84Migration:risky + Using the `@PHPUnit84Migration:risky <./../../ruleSets/PHPUnit84MigrationRisky.rst>`_ rule set will enable the ``php_unit_no_expectation_annotation`` rule with the config below: + + ``['target' => '4.3']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_ordered_covers.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_ordered_covers.rst new file mode 100644 index 0000000..27f20e9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_ordered_covers.rst @@ -0,0 +1,28 @@ +================================ +Rule ``php_unit_ordered_covers`` +================================ + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``phpdoc_order_by_value`` instead. + +Order ``@covers`` annotation of PHPUnit tests. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + + * @covers Bar + * @covers Foo + - * @covers Bar + */ + final class MyTest extends \PHPUnit_Framework_TestCase + {} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_set_up_tear_down_visibility.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_set_up_tear_down_visibility.rst new file mode 100644 index 0000000..3c645d1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_set_up_tear_down_visibility.rst @@ -0,0 +1,49 @@ +============================================= +Rule ``php_unit_set_up_tear_down_visibility`` +============================================= + +Changes the visibility of the ``setUp()`` and ``tearDown()`` functions of +PHPUnit to ``protected``, to match the PHPUnit TestCase. + +.. warning:: Using this rule is risky. + + This fixer may change functions named ``setUp()`` or ``tearDown()`` outside + of PHPUnit tests, when a class is wrongly seen as a PHPUnit test. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + private $hello; + - public function setUp() + + protected function setUp() + { + $this->hello = "hello"; + } + + - public function tearDown() + + protected function tearDown() + { + $this->hello = null; + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``php_unit_set_up_tear_down_visibility`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``php_unit_set_up_tear_down_visibility`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_size_class.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_size_class.rst new file mode 100644 index 0000000..682d466 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_size_class.rst @@ -0,0 +1,57 @@ +============================ +Rule ``php_unit_size_class`` +============================ + +All PHPUnit test cases should have ``@small``, ``@medium`` or ``@large`` +annotation to enable run time limits. + +Description +----------- + +The special groups [small, medium, large] provides a way to identify tests that +are taking long to be executed. + +Configuration +------------- + +``group`` +~~~~~~~~~ + +Define a specific group to be used in case no group is already in use + +Allowed values: ``'large'``, ``'medium'``, ``'small'`` + +Default value: ``'small'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + +/** + + * @small + + */ + class MyTest extends TestCase {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['group' => 'medium']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + +/** + + * @medium + + */ + class MyTest extends TestCase {} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_strict.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_strict.rst new file mode 100644 index 0000000..3908c9d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_strict.rst @@ -0,0 +1,80 @@ +======================== +Rule ``php_unit_strict`` +======================== + +PHPUnit methods like ``assertSame`` should be used instead of ``assertEquals``. + +.. warning:: Using this rule is risky. + + Risky when any of the functions are overridden or when testing object + equality. + +Configuration +------------- + +``assertions`` +~~~~~~~~~~~~~~ + +List of assertion methods to fix. + +Allowed values: a subset of ``['assertAttributeEquals', 'assertAttributeNotEquals', 'assertEquals', 'assertNotEquals']`` + +Default value: ``['assertAttributeEquals', 'assertAttributeNotEquals', 'assertEquals', 'assertNotEquals']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testSomeTest() + { + - $this->assertAttributeEquals(a(), b()); + - $this->assertAttributeNotEquals(a(), b()); + - $this->assertEquals(a(), b()); + - $this->assertNotEquals(a(), b()); + + $this->assertAttributeSame(a(), b()); + + $this->assertAttributeNotSame(a(), b()); + + $this->assertSame(a(), b()); + + $this->assertNotSame(a(), b()); + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['assertions' => ['assertEquals']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testSomeTest() + { + $this->assertAttributeEquals(a(), b()); + $this->assertAttributeNotEquals(a(), b()); + - $this->assertEquals(a(), b()); + + $this->assertSame(a(), b()); + $this->assertNotEquals(a(), b()); + } + } + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``php_unit_strict`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_annotation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_annotation.rst new file mode 100644 index 0000000..f46959d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_annotation.rst @@ -0,0 +1,84 @@ +================================= +Rule ``php_unit_test_annotation`` +================================= + +Adds or removes @test annotations from tests, following configuration. + +.. warning:: Using this rule is risky. + + This fixer may change the name of your tests, and could cause incompatibility + with abstract classes or interfaces. + +Configuration +------------- + +``style`` +~~~~~~~~~ + +Whether to use the @test annotation or not. + +Allowed values: ``'annotation'``, ``'prefix'`` + +Default value: ``'prefix'`` + +``case`` +~~~~~~~~ + +.. warning:: This option is deprecated and will be removed on next major version. Use ``php_unit_method_casing`` fixer instead. + +Whether to camel or snake case when adding the test prefix + +Allowed values: ``'camel'``, ``'snake'`` + +Default value: ``'camel'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Test extends \PhpUnit\FrameWork\TestCase + { + /** + - * @test + + * + */ + - public function itDoesSomething() {} } + + public function testItDoesSomething() {} } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['style' => 'annotation']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Test extends \PhpUnit\FrameWork\TestCase + { + -public function testItDoesSomething() {}} + +/** + + * @test + + */ + +public function itDoesSomething() {}} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``php_unit_test_annotation`` rule with the default config. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``php_unit_test_annotation`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_case_static_method_calls.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_case_static_method_calls.rst new file mode 100644 index 0000000..aced0e5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_case_static_method_calls.rst @@ -0,0 +1,88 @@ +=============================================== +Rule ``php_unit_test_case_static_method_calls`` +=============================================== + +Calls to ``PHPUnit\Framework\TestCase`` static methods must all be of the same +type, either ``$this->``, ``self::`` or ``static::``. + +.. warning:: Using this rule is risky. + + Risky when PHPUnit methods are overridden or not accessible, or when project + has PHPUnit incompatibilities. + +Configuration +------------- + +``call_type`` +~~~~~~~~~~~~~ + +The call type to use for referring to PHPUnit methods. + +Allowed values: ``'self'``, ``'static'``, ``'this'`` + +Default value: ``'static'`` + +``methods`` +~~~~~~~~~~~ + +Dictionary of ``method`` => ``call_type`` values that differ from the default +strategy. + +Allowed types: ``array`` + +Default value: ``[]`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testMe() + { + - $this->assertSame(1, 2); + - self::assertSame(1, 2); + + static::assertSame(1, 2); + + static::assertSame(1, 2); + static::assertSame(1, 2); + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['call_type' => 'this']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testMe() + { + $this->assertSame(1, 2); + - self::assertSame(1, 2); + - static::assertSame(1, 2); + + $this->assertSame(1, 2); + + $this->assertSame(1, 2); + } + } + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``php_unit_test_case_static_method_calls`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_class_requires_covers.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_class_requires_covers.rst new file mode 100644 index 0000000..a303a91 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/php_unit/php_unit_test_class_requires_covers.rst @@ -0,0 +1,37 @@ +============================================ +Rule ``php_unit_test_class_requires_covers`` +============================================ + +Adds a default ``@coversNothing`` annotation to PHPUnit test classes that have +no ``@covers*`` annotation. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + + +/** + + * @coversNothing + + */ + final class MyTest extends \PHPUnit_Framework_TestCase + { + public function testSomeTest() + { + $this->assertSame(a(), b()); + } + } + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``php_unit_test_class_requires_covers`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/align_multiline_comment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/align_multiline_comment.rst new file mode 100644 index 0000000..e612747 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/align_multiline_comment.rst @@ -0,0 +1,85 @@ +================================ +Rule ``align_multiline_comment`` +================================ + +Each line of multi-line DocComments must have an asterisk [PSR-5] and must be +aligned with the first one. + +Configuration +------------- + +``comment_type`` +~~~~~~~~~~~~~~~~ + +Whether to fix PHPDoc comments only (``phpdocs_only``), any multi-line comment +whose lines all start with an asterisk (``phpdocs_like``) or any multi-line +comment (``all_multiline``). + +Allowed values: ``'all_multiline'``, ``'phpdocs_like'``, ``'phpdocs_only'`` + +Default value: ``'phpdocs_only'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * This is a DOC Comment + -with a line not prefixed with asterisk + - + - */ + + * This is a DOC Comment + + * with a line not prefixed with asterisk + + * + + */ + +Example #2 +~~~~~~~~~~ + +With configuration: ``['comment_type' => 'phpdocs_like']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /* + - * This is a doc-like multiline comment + -*/ + + * This is a doc-like multiline comment + + */ + +Example #3 +~~~~~~~~~~ + +With configuration: ``['comment_type' => 'all_multiline']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /* + - * This is a doc-like multiline comment + + * This is a doc-like multiline comment + with a line not prefixed with asterisk + + - */ + + */ + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``align_multiline_comment`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/general_phpdoc_annotation_remove.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/general_phpdoc_annotation_remove.rst new file mode 100644 index 0000000..38c2697 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/general_phpdoc_annotation_remove.rst @@ -0,0 +1,54 @@ +========================================= +Rule ``general_phpdoc_annotation_remove`` +========================================= + +Configured annotations should be omitted from PHPDoc. + +Configuration +------------- + +``annotations`` +~~~~~~~~~~~~~~~ + +List of annotations to remove, e.g. ``["author"]``. + +Allowed types: ``array`` + +Default value: ``[]`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +With configuration: ``['annotations' => ['author']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @internal + - * @author John Doe + */ + function foo() {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['annotations' => ['package', 'subpackage']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @author John Doe + - * @package ACME API + - * @subpackage Authorization + * @version 1.0 + */ + function foo() {} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/general_phpdoc_tag_rename.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/general_phpdoc_tag_rename.rst new file mode 100644 index 0000000..33c3098 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/general_phpdoc_tag_rename.rst @@ -0,0 +1,127 @@ +================================== +Rule ``general_phpdoc_tag_rename`` +================================== + +Renames PHPDoc tags. + +Configuration +------------- + +``fix_annotation`` +~~~~~~~~~~~~~~~~~~ + +Whether annotation tags should be fixed. + +Allowed types: ``bool`` + +Default value: ``true`` + +``fix_inline`` +~~~~~~~~~~~~~~ + +Whether inline tags should be fixed. + +Allowed types: ``bool`` + +Default value: ``true`` + +``replacements`` +~~~~~~~~~~~~~~~~ + +A map of tags to replace. + +Allowed types: ``array`` + +Default value: ``[]`` + +``case_sensitive`` +~~~~~~~~~~~~~~~~~~ + +Whether tags should be replaced only if they have exact same casing. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +With configuration: ``['replacements' => ['inheritDocs' => 'inheritDoc']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @inheritDocs + - * {@inheritdocs} + + * @inheritDoc + + * {@inheritDoc} + */ + +Example #2 +~~~~~~~~~~ + +With configuration: ``['replacements' => ['inheritDocs' => 'inheritDoc'], 'fix_annotation' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @inheritDocs + - * {@inheritdocs} + + * {@inheritDoc} + */ + +Example #3 +~~~~~~~~~~ + +With configuration: ``['replacements' => ['inheritDocs' => 'inheritDoc'], 'fix_inline' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @inheritDocs + + * @inheritDoc + * {@inheritdocs} + */ + +Example #4 +~~~~~~~~~~ + +With configuration: ``['replacements' => ['inheritDocs' => 'inheritDoc'], 'case_sensitive' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @inheritDocs + + * @inheritDoc + * {@inheritdocs} + */ + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``general_phpdoc_tag_rename`` rule with the config below: + + ``['replacements' => ['inheritDocs' => 'inheritDoc']]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``general_phpdoc_tag_rename`` rule with the config below: + + ``['replacements' => ['inheritDocs' => 'inheritDoc']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_blank_lines_after_phpdoc.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_blank_lines_after_phpdoc.rst new file mode 100644 index 0000000..ec2efb5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_blank_lines_after_phpdoc.rst @@ -0,0 +1,35 @@ +==================================== +Rule ``no_blank_lines_after_phpdoc`` +==================================== + +There should not be blank lines between docblock and the documented element. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + /** + * This is the bar class. + */ + - + - + class Bar {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_blank_lines_after_phpdoc`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_blank_lines_after_phpdoc`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_empty_phpdoc.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_empty_phpdoc.rst new file mode 100644 index 0000000..6708544 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_empty_phpdoc.rst @@ -0,0 +1,29 @@ +======================== +Rule ``no_empty_phpdoc`` +======================== + +There should not be empty PHPDoc blocks. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php /** */ + +<?php + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_empty_phpdoc`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_empty_phpdoc`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_superfluous_phpdoc_tags.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_superfluous_phpdoc_tags.rst new file mode 100644 index 0000000..771067c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/no_superfluous_phpdoc_tags.rst @@ -0,0 +1,149 @@ +=================================== +Rule ``no_superfluous_phpdoc_tags`` +=================================== + +Removes ``@param``, ``@return`` and ``@var`` tags that don't provide any useful +information. + +Configuration +------------- + +``allow_mixed`` +~~~~~~~~~~~~~~~ + +Whether type ``mixed`` without description is allowed (``true``) or considered +superfluous (``false``) + +Allowed types: ``bool`` + +Default value: ``false`` + +``remove_inheritdoc`` +~~~~~~~~~~~~~~~~~~~~~ + +Remove ``@inheritDoc`` tags + +Allowed types: ``bool`` + +Default value: ``false`` + +``allow_unused_params`` +~~~~~~~~~~~~~~~~~~~~~~~ + +Whether ``param`` annotation without actual signature is allowed (``true``) or +considered superfluous (``false``) + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo { + /** + - * @param Bar $bar + - * @param mixed $baz + */ + public function doFoo(Bar $bar, $baz) {} + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['allow_mixed' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo { + /** + - * @param Bar $bar + * @param mixed $baz + */ + public function doFoo(Bar $bar, $baz) {} + } + +Example #3 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo { + /** + - * @param Bar $bar + - * @param mixed $baz + * + - * @return Baz + */ + public function doFoo(Bar $bar, $baz): Baz {} + } + +Example #4 +~~~~~~~~~~ + +With configuration: ``['remove_inheritdoc' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo { + /** + - * @inheritDoc + + * + */ + public function doFoo(Bar $bar, $baz) {} + } + +Example #5 +~~~~~~~~~~ + +With configuration: ``['allow_unused_params' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo { + /** + - * @param Bar $bar + - * @param mixed $baz + * @param string|int|null $qux + */ + public function doFoo(Bar $bar, $baz /*, $qux = null */) {} + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_superfluous_phpdoc_tags`` rule with the config below: + + ``['allow_mixed' => true, 'allow_unused_params' => true]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_superfluous_phpdoc_tags`` rule with the config below: + + ``['allow_mixed' => true, 'allow_unused_params' => true]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_add_missing_param_annotation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_add_missing_param_annotation.rst new file mode 100644 index 0000000..5205350 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_add_missing_param_annotation.rst @@ -0,0 +1,83 @@ +============================================ +Rule ``phpdoc_add_missing_param_annotation`` +============================================ + +PHPDoc should contain ``@param`` for all params. + +Configuration +------------- + +``only_untyped`` +~~~~~~~~~~~~~~~~ + +Whether to add missing ``@param`` annotations for untyped parameters only. + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @param int $bar + + * @param mixed $baz + * + * @return void + */ + function f9(string $foo, $bar, $baz) {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['only_untyped' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @param int $bar + + * @param mixed $baz + * + * @return void + */ + function f9(string $foo, $bar, $baz) {} + +Example #3 +~~~~~~~~~~ + +With configuration: ``['only_untyped' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @param int $bar + + * @param string $foo + + * @param mixed $baz + * + * @return void + */ + function f9(string $foo, $bar, $baz) {} + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_add_missing_param_annotation`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_align.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_align.rst new file mode 100644 index 0000000..e0d2fe7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_align.rst @@ -0,0 +1,114 @@ +===================== +Rule ``phpdoc_align`` +===================== + +All items of the given phpdoc tags must be either left-aligned or (by default) +aligned vertically. + +Configuration +------------- + +``tags`` +~~~~~~~~ + +The tags that should be aligned. + +Allowed values: a subset of ``['param', 'property', 'property-read', 'property-write', 'return', 'throws', 'type', 'var', 'method']`` + +Default value: ``['param', 'return', 'throws', 'type', 'var']`` + +``align`` +~~~~~~~~~ + +Align comments + +Allowed values: ``'left'``, ``'vertical'`` + +Default value: ``'vertical'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param EngineInterface $templating + - * @param string $format + - * @param int $code an HTTP response status code + - * @param bool $debug + - * @param mixed &$reference a parameter passed by reference + + * @param EngineInterface $templating + + * @param string $format + + * @param int $code an HTTP response status code + + * @param bool $debug + + * @param mixed &$reference a parameter passed by reference + */ + +Example #2 +~~~~~~~~~~ + +With configuration: ``['align' => 'vertical']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param EngineInterface $templating + - * @param string $format + - * @param int $code an HTTP response status code + - * @param bool $debug + - * @param mixed &$reference a parameter passed by reference + + * @param EngineInterface $templating + + * @param string $format + + * @param int $code an HTTP response status code + + * @param bool $debug + + * @param mixed &$reference a parameter passed by reference + */ + +Example #3 +~~~~~~~~~~ + +With configuration: ``['align' => 'left']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param EngineInterface $templating + - * @param string $format + - * @param int $code an HTTP response status code + - * @param bool $debug + - * @param mixed &$reference a parameter passed by reference + + * @param EngineInterface $templating + + * @param string $format + + * @param int $code an HTTP response status code + + * @param bool $debug + + * @param mixed &$reference a parameter passed by reference + */ + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_align`` rule with the config below: + + ``['tags' => ['method', 'param', 'property', 'return', 'throws', 'type', 'var']]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_align`` rule with the config below: + + ``['tags' => ['method', 'param', 'property', 'return', 'throws', 'type', 'var']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_annotation_without_dot.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_annotation_without_dot.rst new file mode 100644 index 0000000..f677ed3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_annotation_without_dot.rst @@ -0,0 +1,33 @@ +====================================== +Rule ``phpdoc_annotation_without_dot`` +====================================== + +PHPDoc annotation descriptions should not be a sentence. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param string $bar Some string. + + * @param string $bar some string + */ + function foo ($bar) {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_annotation_without_dot`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_annotation_without_dot`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_indent.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_indent.rst new file mode 100644 index 0000000..e037beb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_indent.rst @@ -0,0 +1,38 @@ +====================== +Rule ``phpdoc_indent`` +====================== + +Docblocks should have the same indentation as the documented subject. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class DocBlocks + { + -/** + - * Test constants + - */ + + /** + + * Test constants + + */ + const INDENT = 1; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_indent`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_indent`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_inline_tag.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_inline_tag.rst new file mode 100644 index 0000000..c6b57aa --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_inline_tag.rst @@ -0,0 +1,32 @@ +========================== +Rule ``phpdoc_inline_tag`` +========================== + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``general_phpdoc_tag_rename``, + ``phpdoc_inline_tag_normalizer`` and ``phpdoc_tag_type`` instead. + +Fix PHPDoc inline tags, make ``@inheritdoc`` always inline. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @{TUTORIAL} + - * {{ @link }} + - * {@examples} + - * @inheritdocs + + * {@TUTORIAL} + + * {@link} + + * {@example} + + * {@inheritdoc} + */ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_inline_tag_normalizer.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_inline_tag_normalizer.rst new file mode 100644 index 0000000..64811d2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_inline_tag_normalizer.rst @@ -0,0 +1,66 @@ +===================================== +Rule ``phpdoc_inline_tag_normalizer`` +===================================== + +Fixes PHPDoc inline tags. + +Configuration +------------- + +``tags`` +~~~~~~~~ + +The list of tags to normalize + +Allowed types: ``array`` + +Default value: ``['example', 'id', 'internal', 'inheritdoc', 'inheritdocs', 'link', 'source', 'toc', 'tutorial']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @{TUTORIAL} + - * {{ @link }} + + * {@TUTORIAL} + + * {@link} + * @inheritDoc + */ + +Example #2 +~~~~~~~~~~ + +With configuration: ``['tags' => ['TUTORIAL']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @{TUTORIAL} + + * {@TUTORIAL} + * {{ @link }} + * @inheritDoc + */ + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_inline_tag_normalizer`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_inline_tag_normalizer`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_line_span.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_line_span.rst new file mode 100644 index 0000000..2552e5e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_line_span.rst @@ -0,0 +1,77 @@ +========================= +Rule ``phpdoc_line_span`` +========================= + +Changes doc blocks from single to multi line, or reversed. Works for class +constants, properties and methods only. + +Configuration +------------- + +``const`` +~~~~~~~~~ + +Whether const blocks should be single or multi line + +Allowed values: ``'multi'``, ``'single'`` + +Default value: ``'multi'`` + +``property`` +~~~~~~~~~~~~ + +Whether property doc blocks should be single or multi line + +Allowed values: ``'multi'``, ``'single'`` + +Default value: ``'multi'`` + +``method`` +~~~~~~~~~~ + +Whether method doc blocks should be single or multi line + +Allowed values: ``'multi'``, ``'single'`` + +Default value: ``'multi'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + class Foo{ + - /** @var bool */ + + /** + + * @var bool + + */ + public $var; + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['property' => 'single']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + class Foo{ + - /** + - * @var bool + - */ + + /** @var bool */ + public $var; + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_access.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_access.rst new file mode 100644 index 0000000..d2fb19a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_access.rst @@ -0,0 +1,36 @@ +========================= +Rule ``phpdoc_no_access`` +========================= + +``@access`` annotations should be omitted from PHPDoc. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Foo + { + /** + * @internal + - * @access private + */ + private $bar; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_no_access`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_no_access`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_alias_tag.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_alias_tag.rst new file mode 100644 index 0000000..0326e05 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_alias_tag.rst @@ -0,0 +1,74 @@ +============================ +Rule ``phpdoc_no_alias_tag`` +============================ + +No alias PHPDoc tags should be used. + +Configuration +------------- + +``replacements`` +~~~~~~~~~~~~~~~~ + +Mapping between replaced annotations with new ones. + +Allowed types: ``array`` + +Default value: ``['property-read' => 'property', 'property-write' => 'property', 'type' => 'var', 'link' => 'see']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @property string $foo + - * @property-read string $bar + + * @property string $bar + * + - * @link baz + + * @see baz + */ + final class Example + { + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['replacements' => ['link' => 'website']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @property string $foo + * @property-read string $bar + * + - * @link baz + + * @website baz + */ + final class Example + { + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_no_alias_tag`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_no_alias_tag`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_empty_return.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_empty_return.rst new file mode 100644 index 0000000..45bc4fc --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_empty_return.rst @@ -0,0 +1,42 @@ +=============================== +Rule ``phpdoc_no_empty_return`` +=============================== + +``@return void`` and ``@return null`` annotations should be omitted from PHPDoc. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @return null + */ + function foo() {} + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @return void + */ + function foo() {} + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_no_empty_return`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_package.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_package.rst new file mode 100644 index 0000000..4b46665 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_package.rst @@ -0,0 +1,36 @@ +========================== +Rule ``phpdoc_no_package`` +========================== + +``@package`` and ``@subpackage`` annotations should be omitted from PHPDoc. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @internal + - * @package Foo + - * subpackage Bar + */ + class Baz + { + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_no_package`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_no_package`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_useless_inheritdoc.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_useless_inheritdoc.rst new file mode 100644 index 0000000..b0e8591 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_no_useless_inheritdoc.rst @@ -0,0 +1,52 @@ +===================================== +Rule ``phpdoc_no_useless_inheritdoc`` +===================================== + +Classy that does not inherit must not have ``@inheritdoc`` tags. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -/** {@inheritdoc} */ + +/** */ + class Sample + { + } + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + class Sample + { + /** + - * @inheritdoc + + * + */ + public function Test() + { + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_no_useless_inheritdoc`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_no_useless_inheritdoc`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_order.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_order.rst new file mode 100644 index 0000000..4086b44 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_order.rst @@ -0,0 +1,37 @@ +===================== +Rule ``phpdoc_order`` +===================== + +Annotations in PHPDoc should be ordered so that ``@param`` annotations come +first, then ``@throws`` annotations, then ``@return`` annotations. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * Hello there! + * + - * @throws Exception|RuntimeException foo + * @custom Test! + - * @return int Return the number of changes. + * @param string $foo + * @param bool $bar Bar + + * @throws Exception|RuntimeException foo + + * @return int Return the number of changes. + */ + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_order`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_order_by_value.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_order_by_value.rst new file mode 100644 index 0000000..d19d835 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_order_by_value.rst @@ -0,0 +1,64 @@ +============================== +Rule ``phpdoc_order_by_value`` +============================== + +Order phpdoc tags by value. + +Configuration +------------- + +``annotations`` +~~~~~~~~~~~~~~~ + +List of annotations to order, e.g. ``["covers"]``. + +Allowed values: a subset of ``['author', 'covers', 'coversNothing', 'dataProvider', 'depends', 'group', 'internal', 'method', 'property', 'property-read', 'property-write', 'requires', 'throws', 'uses']`` + +Default value: ``['covers']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + + * @covers Bar + * @covers Foo + - * @covers Bar + */ + final class MyTest extends \PHPUnit_Framework_TestCase + {} + +Example #2 +~~~~~~~~~~ + +With configuration: ``['annotations' => ['author']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + + * @author Alice + * @author Bob + - * @author Alice + */ + final class MyTest extends \PHPUnit_Framework_TestCase + {} + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_order_by_value`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_return_self_reference.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_return_self_reference.rst new file mode 100644 index 0000000..6c08225 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_return_self_reference.rst @@ -0,0 +1,93 @@ +===================================== +Rule ``phpdoc_return_self_reference`` +===================================== + +The type of ``@return`` annotations of methods returning a reference to itself +must the configured one. + +Configuration +------------- + +``replacements`` +~~~~~~~~~~~~~~~~ + +Mapping between replaced return types with new ones. + +Allowed types: ``array`` + +Default value: ``['this' => '$this', '@this' => '$this', '$self' => 'self', '@self' => 'self', '$static' => 'static', '@static' => 'static']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Sample + { + /** + - * @return this + + * @return $this + */ + public function test1() + { + return $this; + } + + /** + - * @return $self + + * @return self + */ + public function test2() + { + return $this; + } + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['replacements' => ['this' => 'self']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + class Sample + { + /** + - * @return this + + * @return self + */ + public function test1() + { + return $this; + } + + /** + * @return $self + */ + public function test2() + { + return $this; + } + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_return_self_reference`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_return_self_reference`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_scalar.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_scalar.rst new file mode 100644 index 0000000..9ddf11b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_scalar.rst @@ -0,0 +1,79 @@ +====================== +Rule ``phpdoc_scalar`` +====================== + +Scalar types should always be written in the same form. ``int`` not ``integer``, +``bool`` not ``boolean``, ``float`` not ``real`` or ``double``. + +Configuration +------------- + +``types`` +~~~~~~~~~ + +A list of types to fix. + +Allowed values: a subset of ``['boolean', 'callback', 'double', 'integer', 'real', 'str']`` + +Default value: ``['boolean', 'double', 'integer', 'real', 'str']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param integer $a + - * @param boolean $b + - * @param real $c + + * @param int $a + + * @param bool $b + + * @param float $c + * + - * @return double + + * @return float + */ + function sample($a, $b, $c) + { + return sample2($a, $b, $c); + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['types' => ['boolean']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @param integer $a + - * @param boolean $b + + * @param bool $b + * @param real $c + */ + function sample($a, $b, $c) + { + return sample2($a, $b, $c); + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_scalar`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_scalar`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_separation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_separation.rst new file mode 100644 index 0000000..3771866 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_separation.rst @@ -0,0 +1,43 @@ +========================== +Rule ``phpdoc_separation`` +========================== + +Annotations in PHPDoc should be grouped together so that annotations of the same +type immediately follow each other, and annotations of a different type are +separated by a single blank line. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * Description. + + * + * @param string $foo + + * @param bool $bar Bar + * + + * @throws Exception|RuntimeException + * + - * @param bool $bar Bar + - * @throws Exception|RuntimeException + * @return bool + */ + function fnc($foo, $bar) {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_separation`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_separation`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_single_line_var_spacing.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_single_line_var_spacing.rst new file mode 100644 index 0000000..e9744a2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_single_line_var_spacing.rst @@ -0,0 +1,30 @@ +======================================= +Rule ``phpdoc_single_line_var_spacing`` +======================================= + +Single line ``@var`` PHPDoc should have proper spacing. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php /**@var MyClass $a */ + +<?php /** @var MyClass $a */ + $a = test(); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_single_line_var_spacing`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_single_line_var_spacing`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_summary.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_summary.rst new file mode 100644 index 0000000..829d8f9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_summary.rst @@ -0,0 +1,34 @@ +======================= +Rule ``phpdoc_summary`` +======================= + +PHPDoc summary should end in either a full stop, exclamation mark, or question +mark. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * Foo function is great + + * Foo function is great. + */ + function foo () {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_summary`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_summary`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_tag_casing.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_tag_casing.rst new file mode 100644 index 0000000..46109ac --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_tag_casing.rst @@ -0,0 +1,51 @@ +========================== +Rule ``phpdoc_tag_casing`` +========================== + +Fixes casing of PHPDoc tags. + +Configuration +------------- + +``tags`` +~~~~~~~~ + +List of tags to fix with their expected casing. + +Allowed types: ``array`` + +Default value: ``['inheritDoc']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @inheritdoc + + * @inheritDoc + */ + +Example #2 +~~~~~~~~~~ + +With configuration: ``['tags' => ['foo']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * @inheritdoc + - * @Foo + + * @foo + */ diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_tag_type.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_tag_type.rst new file mode 100644 index 0000000..75cd7dc --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_tag_type.rst @@ -0,0 +1,65 @@ +======================== +Rule ``phpdoc_tag_type`` +======================== + +Forces PHPDoc tags to be either regular annotations or inline. + +Configuration +------------- + +``tags`` +~~~~~~~~ + +The list of tags to fix + +Allowed types: ``array`` + +Default value: ``['api' => 'annotation', 'author' => 'annotation', 'copyright' => 'annotation', 'deprecated' => 'annotation', 'example' => 'annotation', 'global' => 'annotation', 'inheritDoc' => 'annotation', 'internal' => 'annotation', 'license' => 'annotation', 'method' => 'annotation', 'package' => 'annotation', 'param' => 'annotation', 'property' => 'annotation', 'return' => 'annotation', 'see' => 'annotation', 'since' => 'annotation', 'throws' => 'annotation', 'todo' => 'annotation', 'uses' => 'annotation', 'var' => 'annotation', 'version' => 'annotation']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * {@api} + + * @api + */ + +Example #2 +~~~~~~~~~~ + +With configuration: ``['tags' => ['inheritdoc' => 'inline']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @inheritdoc + + * {@inheritdoc} + */ + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_tag_type`` rule with the config below: + + ``['tags' => ['inheritDoc' => 'inline']]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_tag_type`` rule with the config below: + + ``['tags' => ['inheritDoc' => 'inline']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_to_comment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_to_comment.rst new file mode 100644 index 0000000..17d1bef --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_to_comment.rst @@ -0,0 +1,35 @@ +========================== +Rule ``phpdoc_to_comment`` +========================== + +Docblocks should only be used on structural elements. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + $first = true;// needed because by default first docblock is never fixed. + + -/** This should not be a docblock */ + +/* This should not be a docblock */ + foreach($connections as $key => $sqlite) { + $sqlite->open($path); + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_to_comment`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_to_comment`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_trim.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_trim.rst new file mode 100644 index 0000000..3f1c649 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_trim.rst @@ -0,0 +1,36 @@ +==================== +Rule ``phpdoc_trim`` +==================== + +PHPDoc should start and end with content, excluding the very first and last line +of the docblocks. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * + * Foo must be final class. + - * + - * + */ + final class Foo {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_trim`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_trim`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_trim_consecutive_blank_line_separation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_trim_consecutive_blank_line_separation.rst new file mode 100644 index 0000000..2203197 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_trim_consecutive_blank_line_separation.rst @@ -0,0 +1,44 @@ +====================================================== +Rule ``phpdoc_trim_consecutive_blank_line_separation`` +====================================================== + +Removes extra blank lines after summary and after description in PHPDoc. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + * Summary. + * + - * + * Description that contain 4 lines, + * + * + * while 2 of them are blank! + * + - * + * @param string $foo + - * + * + * @dataProvider provideFixCases + */ + function fnc($foo) {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_trim_consecutive_blank_line_separation`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_trim_consecutive_blank_line_separation`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_types.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_types.rst new file mode 100644 index 0000000..4c4ca21 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_types.rst @@ -0,0 +1,66 @@ +===================== +Rule ``phpdoc_types`` +===================== + +The correct case must be used for standard PHP types in PHPDoc. + +Configuration +------------- + +``groups`` +~~~~~~~~~~ + +Type groups to fix. + +Allowed values: a subset of ``['simple', 'alias', 'meta']`` + +Default value: ``['simple', 'alias', 'meta']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param STRING|String[] $bar + + * @param string|string[] $bar + * + - * @return inT[] + + * @return int[] + */ + +Example #2 +~~~~~~~~~~ + +With configuration: ``['groups' => ['simple', 'alias']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param BOOL $foo + + * @param bool $foo + * + * @return MIXED + */ + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_types`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_types`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_types_order.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_types_order.rst new file mode 100644 index 0000000..07e630d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_types_order.rst @@ -0,0 +1,117 @@ +=========================== +Rule ``phpdoc_types_order`` +=========================== + +Sorts PHPDoc types. + +Configuration +------------- + +``sort_algorithm`` +~~~~~~~~~~~~~~~~~~ + +The sorting algorithm to apply. + +Allowed values: ``'alpha'``, ``'none'`` + +Default value: ``'alpha'`` + +``null_adjustment`` +~~~~~~~~~~~~~~~~~~~ + +Forces the position of ``null`` (overrides ``sort_algorithm``). + +Allowed values: ``'always_first'``, ``'always_last'``, ``'none'`` + +Default value: ``'always_first'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param string|null $bar + + * @param null|string $bar + */ + +Example #2 +~~~~~~~~~~ + +With configuration: ``['null_adjustment' => 'always_last']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param null|string $bar + + * @param string|null $bar + */ + +Example #3 +~~~~~~~~~~ + +With configuration: ``['sort_algorithm' => 'alpha']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param null|string|int|\Foo $bar + + * @param null|\Foo|int|string $bar + */ + +Example #4 +~~~~~~~~~~ + +With configuration: ``['sort_algorithm' => 'alpha', 'null_adjustment' => 'always_last']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param null|string|int|\Foo $bar + + * @param \Foo|int|string|null $bar + */ + +Example #5 +~~~~~~~~~~ + +With configuration: ``['sort_algorithm' => 'alpha', 'null_adjustment' => 'none']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + /** + - * @param null|string|int|\Foo $bar + + * @param \Foo|int|null|string $bar + */ + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_types_order`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_types_order`` rule with the config below: + + ``['null_adjustment' => 'always_last', 'sort_algorithm' => 'none']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_var_annotation_correct_order.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_var_annotation_correct_order.rst new file mode 100644 index 0000000..05b11b1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_var_annotation_correct_order.rst @@ -0,0 +1,28 @@ +============================================ +Rule ``phpdoc_var_annotation_correct_order`` +============================================ + +``@var`` and ``@type`` annotations must have type and name in the correct order. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -/** @var $foo int */ + +/** @var int $foo */ + $foo = 2 + 2; + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_var_annotation_correct_order`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_var_without_name.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_var_without_name.rst new file mode 100644 index 0000000..9c9ab7c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/phpdoc/phpdoc_var_without_name.rst @@ -0,0 +1,43 @@ +================================ +Rule ``phpdoc_var_without_name`` +================================ + +``@var`` and ``@type`` annotations of classy properties should not contain the +name. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + final class Foo + { + /** + - * @var int $bar + + * @var int + */ + public $bar; + + /** + - * @type $baz float + + * @type float + */ + public $baz; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``phpdoc_var_without_name`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``phpdoc_var_without_name`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/blank_line_before_return.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/blank_line_before_return.rst new file mode 100644 index 0000000..bdfe12a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/blank_line_before_return.rst @@ -0,0 +1,27 @@ +================================= +Rule ``blank_line_before_return`` +================================= + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``blank_line_before_statement`` instead. + +An empty line feed should precede a return statement. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + function A() + { + echo 1; + + + return 1; + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/no_useless_return.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/no_useless_return.rst new file mode 100644 index 0000000..3b23e3d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/no_useless_return.rst @@ -0,0 +1,32 @@ +========================== +Rule ``no_useless_return`` +========================== + +There should not be an empty ``return`` statement at the end of a function. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + function example($b) { + if ($b) { + return; + } + - return; + + + } + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_useless_return`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/return_assignment.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/return_assignment.rst new file mode 100644 index 0000000..900cdaf --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/return_assignment.rst @@ -0,0 +1,31 @@ +========================== +Rule ``return_assignment`` +========================== + +Local, dynamic and directly referenced variables should not be assigned and +directly returned by a function or method. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + function a() { + - $a = 1; + - return $a; + + return 1; + } + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``return_assignment`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/simplified_null_return.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/simplified_null_return.rst new file mode 100644 index 0000000..5022681 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/return_notation/simplified_null_return.rst @@ -0,0 +1,33 @@ +=============================== +Rule ``simplified_null_return`` +=============================== + +A return statement wishing to return ``void`` should not return ``null``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php return null; + +<?php return; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -function foo() { return null; } + +function foo() { return; } + function bar(): int { return null; } + function baz(): ?int { return null; } + -function xyz(): void { return null; } + +function xyz(): void { return; } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/multiline_whitespace_before_semicolons.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/multiline_whitespace_before_semicolons.rst new file mode 100644 index 0000000..657b3d8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/multiline_whitespace_before_semicolons.rst @@ -0,0 +1,65 @@ +=============================================== +Rule ``multiline_whitespace_before_semicolons`` +=============================================== + +Forbid multi-line whitespace before the closing semicolon or move the semicolon +to the new line for chained calls. + +Configuration +------------- + +``strategy`` +~~~~~~~~~~~~ + +Forbid multi-line whitespace or move the semicolon to the new line for chained +calls. + +Allowed values: ``'new_line_for_chained_calls'``, ``'no_multi_line'`` + +Default value: ``'no_multi_line'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + function foo () { + - return 1 + 2 + - ; + + return 1 + 2; + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['strategy' => 'new_line_for_chained_calls']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $this->method1() + ->method2() + - ->method(3); + + ->method(3) + +; + ?> + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``multiline_whitespace_before_semicolons`` rule with the config below: + + ``['strategy' => 'new_line_for_chained_calls']`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_empty_statement.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_empty_statement.rst new file mode 100644 index 0000000..8b725d5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_empty_statement.rst @@ -0,0 +1,51 @@ +=========================== +Rule ``no_empty_statement`` +=========================== + +Remove useless (semicolon) statements. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $a = 1;; + +<?php $a = 1; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php echo 1;2; + +<?php echo 1; + +Example #3 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php while(foo()){ + - continue 1; + + continue ; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_empty_statement`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_empty_statement`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_multiline_whitespace_before_semicolons.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_multiline_whitespace_before_semicolons.rst new file mode 100644 index 0000000..54fce50 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_multiline_whitespace_before_semicolons.rst @@ -0,0 +1,26 @@ +================================================== +Rule ``no_multiline_whitespace_before_semicolons`` +================================================== + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``multiline_whitespace_before_semicolons`` instead. + +Multi-line whitespace before closing semicolon are prohibited. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + function foo () { + - return 1 + 2 + - ; + + return 1 + 2; + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_singleline_whitespace_before_semicolons.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_singleline_whitespace_before_semicolons.rst new file mode 100644 index 0000000..b96d39d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/no_singleline_whitespace_before_semicolons.rst @@ -0,0 +1,29 @@ +=================================================== +Rule ``no_singleline_whitespace_before_semicolons`` +=================================================== + +Single-line whitespace before closing semicolon are prohibited. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $this->foo() ; + +<?php $this->foo(); + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_singleline_whitespace_before_semicolons`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_singleline_whitespace_before_semicolons`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/semicolon_after_instruction.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/semicolon_after_instruction.rst new file mode 100644 index 0000000..68f8bc5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/semicolon_after_instruction.rst @@ -0,0 +1,29 @@ +==================================== +Rule ``semicolon_after_instruction`` +==================================== + +Instructions must be terminated with a semicolon. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php echo 1 ?> + +<?php echo 1; ?> + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``semicolon_after_instruction`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``semicolon_after_instruction`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/space_after_semicolon.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/space_after_semicolon.rst new file mode 100644 index 0000000..ce02afc --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/semicolon/space_after_semicolon.rst @@ -0,0 +1,67 @@ +============================== +Rule ``space_after_semicolon`` +============================== + +Fix whitespace after a semicolon. + +Configuration +------------- + +``remove_in_empty_for_expressions`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether spaces should be removed for empty ``for`` expressions. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + - sample(); $test = 1; + - sample();$test = 2; + - for ( ;;++$sample) { + + sample(); $test = 1; + + sample(); $test = 2; + + for ( ; ; ++$sample) { + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['remove_in_empty_for_expressions' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -for ($i = 0; ; ++$i) { + +for ($i = 0;; ++$i) { + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``space_after_semicolon`` rule with the config below: + + ``['remove_in_empty_for_expressions' => true]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``space_after_semicolon`` rule with the config below: + + ``['remove_in_empty_for_expressions' => true]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/strict/declare_strict_types.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/strict/declare_strict_types.rst new file mode 100644 index 0000000..7b3660b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/strict/declare_strict_types.rst @@ -0,0 +1,40 @@ +============================= +Rule ``declare_strict_types`` +============================= + +Force strict types declaration in all files. Requires PHP >= 7.0. + +.. warning:: Using this rule is risky. + + Forcing strict types will stop non strict code from working. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php + +<?php declare(strict_types=1); + \ No newline at end of file + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP70Migration:risky + Using the `@PHP70Migration:risky <./../../ruleSets/PHP70MigrationRisky.rst>`_ rule set will enable the ``declare_strict_types`` rule. + +@PHP71Migration:risky + Using the `@PHP71Migration:risky <./../../ruleSets/PHP71MigrationRisky.rst>`_ rule set will enable the ``declare_strict_types`` rule. + +@PHP74Migration:risky + Using the `@PHP74Migration:risky <./../../ruleSets/PHP74MigrationRisky.rst>`_ rule set will enable the ``declare_strict_types`` rule. + +@PHP80Migration:risky + Using the `@PHP80Migration:risky <./../../ruleSets/PHP80MigrationRisky.rst>`_ rule set will enable the ``declare_strict_types`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/strict/strict_comparison.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/strict/strict_comparison.rst new file mode 100644 index 0000000..d899ca3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/strict/strict_comparison.rst @@ -0,0 +1,31 @@ +========================== +Rule ``strict_comparison`` +========================== + +Comparisons should be strict. + +.. warning:: Using this rule is risky. + + Changing comparisons to strict might change code behavior. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = 1== $b; + +$a = 1=== $b; + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``strict_comparison`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/strict/strict_param.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/strict/strict_param.rst new file mode 100644 index 0000000..bd827f6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/strict/strict_param.rst @@ -0,0 +1,45 @@ +===================== +Rule ``strict_param`` +===================== + +Functions should be used with ``$strict`` param set to ``true``. + +Description +----------- + +The functions "array_keys", "array_search", "base64_decode", "in_array" and +"mb_detect_encoding" should be used with $strict param. + +.. warning:: Using this rule is risky. + + Risky when the fixed function is overridden or if the code relies on + non-strict usage. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = array_keys($b); + -$a = array_search($b, $c); + -$a = base64_decode($b); + -$a = in_array($b, $c); + -$a = mb_detect_encoding($b, $c); + +$a = array_search($b, $c, true); + +$a = base64_decode($b, true); + +$a = in_array($b, $c, true); + +$a = mb_detect_encoding($b, $c, true); + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``strict_param`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/escape_implicit_backslashes.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/escape_implicit_backslashes.rst new file mode 100644 index 0000000..bb6d237 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/escape_implicit_backslashes.rst @@ -0,0 +1,145 @@ +==================================== +Rule ``escape_implicit_backslashes`` +==================================== + +Escape implicit backslashes in strings and heredocs to ease the understanding of +which are special chars interpreted by PHP and which not. + +Description +----------- + +In PHP double-quoted strings and heredocs some chars like ``n``, ``$`` or ``u`` +have special meanings if preceded by a backslash (and some are special only if +followed by other special chars), while a backslash preceding other chars are +interpreted like a plain backslash. The precise list of those special chars is +hard to remember and to identify quickly: this fixer escapes backslashes that do +not start a special interpretation with the char after them. +It is possible to fix also single-quoted strings: in this case there is no +special chars apart from single-quote and backslash itself, so the fixer simply +ensure that all backslashes are escaped. Both single and double backslashes are +allowed in single-quoted strings, so the purpose in this context is mainly to +have a uniformed way to have them written all over the codebase. + +Configuration +------------- + +``single_quoted`` +~~~~~~~~~~~~~~~~~ + +Whether to fix single-quoted strings. + +Allowed types: ``bool`` + +Default value: ``false`` + +``double_quoted`` +~~~~~~~~~~~~~~~~~ + +Whether to fix double-quoted strings. + +Allowed types: ``bool`` + +Default value: ``true`` + +``heredoc_syntax`` +~~~~~~~~~~~~~~~~~~ + +Whether to fix heredoc syntax. + +Allowed types: ``bool`` + +Default value: ``true`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $singleQuoted = 'String with \" and My\Prefix\\'; + + -$doubleQuoted = "Interpret my \n but not my \a"; + +$doubleQuoted = "Interpret my \n but not my \\a"; + + $hereDoc = <<<HEREDOC + -Interpret my \100 but not my \999 + +Interpret my \100 but not my \\999 + HEREDOC; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['single_quoted' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -$singleQuoted = 'String with \" and My\Prefix\\'; + +$singleQuoted = 'String with \\" and My\\Prefix\\'; + + -$doubleQuoted = "Interpret my \n but not my \a"; + +$doubleQuoted = "Interpret my \n but not my \\a"; + + $hereDoc = <<<HEREDOC + -Interpret my \100 but not my \999 + +Interpret my \100 but not my \\999 + HEREDOC; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['double_quoted' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $singleQuoted = 'String with \" and My\Prefix\\'; + + $doubleQuoted = "Interpret my \n but not my \a"; + + $hereDoc = <<<HEREDOC + -Interpret my \100 but not my \999 + +Interpret my \100 but not my \\999 + HEREDOC; + +Example #4 +~~~~~~~~~~ + +With configuration: ``['heredoc_syntax' => false]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $singleQuoted = 'String with \" and My\Prefix\\'; + + -$doubleQuoted = "Interpret my \n but not my \a"; + +$doubleQuoted = "Interpret my \n but not my \\a"; + + $hereDoc = <<<HEREDOC + Interpret my \100 but not my \999 + HEREDOC; + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``escape_implicit_backslashes`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/explicit_string_variable.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/explicit_string_variable.rst new file mode 100644 index 0000000..467ad66 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/explicit_string_variable.rst @@ -0,0 +1,47 @@ +================================= +Rule ``explicit_string_variable`` +================================= + +Converts implicit variables into explicit ones in double-quoted strings or +heredoc syntax. + +Description +----------- + +The reasoning behind this rule is the following: +- When there are two valid ways of doing the same thing, using both is +confusing, there should be a coding standard to follow +- PHP manual marks ``"$var"`` syntax as implicit and ``"${var}"`` syntax as +explicit: explicit code should always be preferred +- Explicit syntax allows word concatenation inside strings, e.g. +``"${var}IsAVar"``, implicit doesn't +- Explicit syntax is easier to detect for IDE/editors and therefore has +colors/highlight with higher contrast, which is easier to read +Backtick operator is skipped because it is harder to handle; you can use +``backtick_to_shell_exec`` fixer to normalize backticks to strings + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = "My name is $name !"; + -$b = "I live in $state->country !"; + -$c = "I have $farm[0] chickens !"; + +$a = "My name is ${name} !"; + +$b = "I live in {$state->country} !"; + +$c = "I have {$farm[0]} chickens !"; + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``explicit_string_variable`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/heredoc_to_nowdoc.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/heredoc_to_nowdoc.rst new file mode 100644 index 0000000..94bece6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/heredoc_to_nowdoc.rst @@ -0,0 +1,28 @@ +========================== +Rule ``heredoc_to_nowdoc`` +========================== + +Convert ``heredoc`` to ``nowdoc`` where possible. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $a = <<<"TEST" + +<?php $a = <<<'TEST' + Foo + TEST; + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``heredoc_to_nowdoc`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/no_binary_string.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/no_binary_string.rst new file mode 100644 index 0000000..5d1c78d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/no_binary_string.rst @@ -0,0 +1,41 @@ +========================= +Rule ``no_binary_string`` +========================= + +There should not be a binary flag before strings. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $a = b'foo'; + +<?php $a = 'foo'; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $a = b<<<EOT + +<?php $a = <<<EOT + foo + EOT; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_binary_string`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_binary_string`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/no_trailing_whitespace_in_string.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/no_trailing_whitespace_in_string.rst new file mode 100644 index 0000000..0fbda43 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/no_trailing_whitespace_in_string.rst @@ -0,0 +1,40 @@ +========================================= +Rule ``no_trailing_whitespace_in_string`` +========================================= + +There must be no trailing whitespace in strings. + +.. warning:: Using this rule is risky. + + Changing the whitespaces in strings might affect string comparisons and + outputs. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $a = ' + - foo + +<?php $a = ' + + foo + '; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12:risky + Using the `@PSR12:risky <./../../ruleSets/PSR12Risky.rst>`_ rule set will enable the ``no_trailing_whitespace_in_string`` rule. + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``no_trailing_whitespace_in_string`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``no_trailing_whitespace_in_string`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/simple_to_complex_string_variable.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/simple_to_complex_string_variable.rst new file mode 100644 index 0000000..b2f61f5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/simple_to_complex_string_variable.rst @@ -0,0 +1,49 @@ +========================================== +Rule ``simple_to_complex_string_variable`` +========================================== + +Converts explicit variables in double-quoted strings and heredoc syntax from +simple to complex format (``${`` to ``{$``). + +Description +----------- + +Doesn't touch implicit variables. Works together nicely with +``explicit_string_variable``. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + $name = 'World'; + -echo "Hello ${name}!"; + +echo "Hello {$name}!"; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + $name = 'World'; + echo <<<TEST + -Hello ${name}! + +Hello {$name}! + TEST; + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``simple_to_complex_string_variable`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/single_quote.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/single_quote.rst new file mode 100644 index 0000000..0597952 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/single_quote.rst @@ -0,0 +1,62 @@ +===================== +Rule ``single_quote`` +===================== + +Convert double quotes to single quotes for simple strings. + +Configuration +------------- + +``strings_containing_single_quote_chars`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Whether to fix double-quoted strings that contains single-quotes. + +Allowed types: ``bool`` + +Default value: ``false`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -$a = "sample"; + +$a = 'sample'; + $b = "sample with 'single-quotes'"; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['strings_containing_single_quote_chars' => true]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + -$a = "sample"; + -$b = "sample with 'single-quotes'"; + +$a = 'sample'; + +$b = 'sample with \'single-quotes\''; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``single_quote`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``single_quote`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/string_line_ending.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/string_line_ending.rst new file mode 100644 index 0000000..5f9c7fb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/string_notation/string_line_ending.rst @@ -0,0 +1,38 @@ +=========================== +Rule ``string_line_ending`` +=========================== + +All multi-line strings must use correct line ending. + +.. warning:: Using this rule is risky. + + Changing the line endings of multi-line strings might affect string + comparisons and outputs. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + -<?php $a = 'my^M + +<?php $a = 'my + multi + -line^M + +line + string';^M + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer:risky + Using the `@PhpCsFixer:risky <./../../ruleSets/PhpCsFixerRisky.rst>`_ rule set will enable the ``string_line_ending`` rule. + +@Symfony:risky + Using the `@Symfony:risky <./../../ruleSets/SymfonyRisky.rst>`_ rule set will enable the ``string_line_ending`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/array_indentation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/array_indentation.rst new file mode 100644 index 0000000..12e521b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/array_indentation.rst @@ -0,0 +1,33 @@ +========================== +Rule ``array_indentation`` +========================== + +Each element of an array must be indented exactly once. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + $foo = [ + - 'bar' => [ + - 'baz' => true, + - ], + + 'bar' => [ + + 'baz' => true, + + ], + ]; + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``array_indentation`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/blank_line_before_statement.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/blank_line_before_statement.rst new file mode 100644 index 0000000..b21ef19 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/blank_line_before_statement.rst @@ -0,0 +1,243 @@ +==================================== +Rule ``blank_line_before_statement`` +==================================== + +An empty line feed must precede any configured statement. + +Configuration +------------- + +``statements`` +~~~~~~~~~~~~~~ + +List of statements which must be preceded by an empty line. + +Allowed values: a subset of ``['break', 'case', 'continue', 'declare', 'default', 'die', 'do', 'exit', 'for', 'foreach', 'goto', 'if', 'include', 'include_once', 'require', 'require_once', 'return', 'switch', 'throw', 'try', 'while', 'yield', 'yield_from']`` + +Default value: ``['break', 'continue', 'declare', 'return', 'throw', 'try']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + function A() { + echo 1; + + + return 1; + } + +Example #2 +~~~~~~~~~~ + +With configuration: ``['statements' => ['break']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + switch ($foo) { + case 42: + $bar->process(); + + + break; + case 44: + break; + } + +Example #3 +~~~~~~~~~~ + +With configuration: ``['statements' => ['continue']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + foreach ($foo as $bar) { + if ($bar->isTired()) { + $bar->sleep(); + + + continue; + } + } + +Example #4 +~~~~~~~~~~ + +With configuration: ``['statements' => ['do']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $i = 0; + + + do { + echo $i; + } while ($i > 0); + +Example #5 +~~~~~~~~~~ + +With configuration: ``['statements' => ['exit']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + if ($foo === false) { + exit(0); + } else { + $bar = 9000; + + + exit(1); + } + +Example #6 +~~~~~~~~~~ + +With configuration: ``['statements' => ['goto']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + a: + + if ($foo === false) { + goto a; + } else { + $bar = 9000; + + + goto b; + } + +Example #7 +~~~~~~~~~~ + +With configuration: ``['statements' => ['if']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = 9000; + + + if (true) { + $foo = $bar; + } + +Example #8 +~~~~~~~~~~ + +With configuration: ``['statements' => ['return']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + if (true) { + $foo = $bar; + + + return; + } + +Example #9 +~~~~~~~~~~ + +With configuration: ``['statements' => ['switch']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = 9000; + + + switch ($a) { + case 42: + break; + } + +Example #10 +~~~~~~~~~~~ + +With configuration: ``['statements' => ['throw']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + if (null === $a) { + $foo->bar(); + + + throw new \UnexpectedValueException("A cannot be null."); + } + +Example #11 +~~~~~~~~~~~ + +With configuration: ``['statements' => ['try']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = 9000; + + + try { + $foo->bar(); + } catch (\Exception $exception) { + $a = -1; + } + +Example #12 +~~~~~~~~~~~ + +With configuration: ``['statements' => ['yield']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + if (true) { + $foo = $bar; + + + yield $foo; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``blank_line_before_statement`` rule with the config below: + + ``['statements' => ['break', 'case', 'continue', 'declare', 'default', 'exit', 'goto', 'include', 'include_once', 'require', 'require_once', 'return', 'switch', 'throw', 'try']]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``blank_line_before_statement`` rule with the config below: + + ``['statements' => ['return']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/compact_nullable_typehint.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/compact_nullable_typehint.rst new file mode 100644 index 0000000..219d76c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/compact_nullable_typehint.rst @@ -0,0 +1,39 @@ +================================== +Rule ``compact_nullable_typehint`` +================================== + +Remove extra spaces in a nullable typehint. + +Description +----------- + +Rule is applied only in a PHP 7.1+ environment. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -function sample(? string $str): ? string + +function sample(?string $str): ?string + {} + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``compact_nullable_typehint`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``compact_nullable_typehint`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``compact_nullable_typehint`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/heredoc_indentation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/heredoc_indentation.rst new file mode 100644 index 0000000..27f3f2f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/heredoc_indentation.rst @@ -0,0 +1,89 @@ +============================ +Rule ``heredoc_indentation`` +============================ + +Heredoc/nowdoc content must be properly indented. Requires PHP >= 7.3. + +Configuration +------------- + +``indentation`` +~~~~~~~~~~~~~~~ + +Whether the indentation should be the same as in the start token line or one +level more. + +Allowed values: ``'same_as_start'``, ``'start_plus_one'`` + +Default value: ``'start_plus_one'`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = <<<EOD + -abc + - def + -EOD; + + abc + + def + + EOD; + +Example #2 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = <<<'EOD' + -abc + - def + -EOD; + + abc + + def + + EOD; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['indentation' => 'same_as_start']``. + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = <<<'EOD' + -abc + - def + -EOD; + + abc + + def + + EOD; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PHP73Migration + Using the `@PHP73Migration <./../../ruleSets/PHP73Migration.rst>`_ rule set will enable the ``heredoc_indentation`` rule with the default config. + +@PHP74Migration + Using the `@PHP74Migration <./../../ruleSets/PHP74Migration.rst>`_ rule set will enable the ``heredoc_indentation`` rule with the default config. + +@PHP80Migration + Using the `@PHP80Migration <./../../ruleSets/PHP80Migration.rst>`_ rule set will enable the ``heredoc_indentation`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/indentation_type.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/indentation_type.rst new file mode 100644 index 0000000..edf02cd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/indentation_type.rst @@ -0,0 +1,39 @@ +========================= +Rule ``indentation_type`` +========================= + +Code MUST use configured indentation type. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + + if (true) { + - echo 'Hello!'; + + echo 'Hello!'; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``indentation_type`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``indentation_type`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``indentation_type`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``indentation_type`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/line_ending.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/line_ending.rst new file mode 100644 index 0000000..0215d82 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/line_ending.rst @@ -0,0 +1,41 @@ +==================== +Rule ``line_ending`` +==================== + +All PHP files must use same line ending. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php $b = " $a ^M + - 123"; $a = <<<TEST^M + -AAAAA ^M + - |^M + + 123"; $a = <<<TEST + +AAAAA + + | + TEST; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``line_ending`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``line_ending`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``line_ending`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``line_ending`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/method_chaining_indentation.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/method_chaining_indentation.rst new file mode 100644 index 0000000..c9a0ef7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/method_chaining_indentation.rst @@ -0,0 +1,29 @@ +==================================== +Rule ``method_chaining_indentation`` +==================================== + +Method chaining MUST be properly indented. Method chaining with different levels +of indentation is not supported. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + $user->setEmail('voff.web@gmail.com') + - ->setPassword('233434'); + + ->setPassword('233434'); + +Rule sets +--------- + +The rule is part of the following rule set: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``method_chaining_indentation`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_extra_blank_lines.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_extra_blank_lines.rst new file mode 100644 index 0000000..948c611 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_extra_blank_lines.rst @@ -0,0 +1,248 @@ +============================= +Rule ``no_extra_blank_lines`` +============================= + +Removes extra blank lines and/or blank lines following configuration. + +Configuration +------------- + +``tokens`` +~~~~~~~~~~ + +List of tokens to fix. + +Allowed values: a subset of ``['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use', 'useTrait', 'use_trait']`` + +Default value: ``['extra']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $foo = array("foo"); + + - + $bar = "bar"; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['break']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + switch ($foo) { + case 41: + echo "foo"; + break; + - + case 42: + break; + } + +Example #3 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['continue']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + for ($i = 0; $i < 9000; ++$i) { + if (true) { + continue; + - + } + } + +Example #4 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['curly_brace_block']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + for ($i = 0; $i < 9000; ++$i) { + - + echo $i; + - + } + +Example #5 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['extra']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $foo = array("foo"); + + - + $bar = "bar"; + +Example #6 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['parenthesis_brace_block']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $foo = array( + - + "foo" + - + ); + +Example #7 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['return']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + function foo($bar) + { + return $bar; + - + } + +Example #8 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['square_brace_block']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $foo = [ + - + "foo" + - + ]; + +Example #9 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['throw']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + function foo($bar) + { + throw new \Exception("Hello!"); + - + } + +Example #10 +~~~~~~~~~~~ + +With configuration: ``['tokens' => ['use']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + namespace Foo; + + use Bar\Baz; + - + use Baz\Bar; + + class Bar + { + } + +Example #11 +~~~~~~~~~~~ + +With configuration: ``['tokens' => ['use_trait']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + class Foo + { + use Bar; + - + use Baz; + } + +Example #12 +~~~~~~~~~~~ + +With configuration: ``['tokens' => ['switch', 'case', 'default']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + switch($a) { + - + case 1: + - + default: + - + echo 3; + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_extra_blank_lines`` rule with the config below: + + ``['tokens' => ['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait']]`` + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_extra_blank_lines`` rule with the config below: + + ``['tokens' => ['case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait']]`` diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_extra_consecutive_blank_lines.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_extra_consecutive_blank_lines.rst new file mode 100644 index 0000000..d6e0f12 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_extra_consecutive_blank_lines.rst @@ -0,0 +1,237 @@ +========================================= +Rule ``no_extra_consecutive_blank_lines`` +========================================= + +.. warning:: This rule is deprecated and will be removed on next major version. + + You should use ``no_extra_blank_lines`` instead. + +Removes extra blank lines and/or blank lines following configuration. + +Configuration +------------- + +``tokens`` +~~~~~~~~~~ + +List of tokens to fix. + +Allowed values: a subset of ``['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use', 'useTrait', 'use_trait']`` + +Default value: ``['extra']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $foo = array("foo"); + + - + $bar = "bar"; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['break']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + switch ($foo) { + case 41: + echo "foo"; + break; + - + case 42: + break; + } + +Example #3 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['continue']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + for ($i = 0; $i < 9000; ++$i) { + if (true) { + continue; + - + } + } + +Example #4 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['curly_brace_block']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + for ($i = 0; $i < 9000; ++$i) { + - + echo $i; + - + } + +Example #5 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['extra']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $foo = array("foo"); + + - + $bar = "bar"; + +Example #6 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['parenthesis_brace_block']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $foo = array( + - + "foo" + - + ); + +Example #7 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['return']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + function foo($bar) + { + return $bar; + - + } + +Example #8 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['square_brace_block']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + $foo = [ + - + "foo" + - + ]; + +Example #9 +~~~~~~~~~~ + +With configuration: ``['tokens' => ['throw']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + function foo($bar) + { + throw new \Exception("Hello!"); + - + } + +Example #10 +~~~~~~~~~~~ + +With configuration: ``['tokens' => ['use']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + namespace Foo; + + use Bar\Baz; + - + use Baz\Bar; + + class Bar + { + } + +Example #11 +~~~~~~~~~~~ + +With configuration: ``['tokens' => ['use_trait']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + + class Foo + { + use Bar; + - + use Baz; + } + +Example #12 +~~~~~~~~~~~ + +With configuration: ``['tokens' => ['switch', 'case', 'default']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + switch($a) { + - + case 1: + - + default: + - + echo 3; + } diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_spaces_around_offset.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_spaces_around_offset.rst new file mode 100644 index 0000000..6cc8461 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_spaces_around_offset.rst @@ -0,0 +1,70 @@ +================================ +Rule ``no_spaces_around_offset`` +================================ + +There MUST NOT be spaces around offset braces. + +Configuration +------------- + +``positions`` +~~~~~~~~~~~~~ + +Whether spacing should be fixed inside and/or outside the offset braces. + +Allowed values: a subset of ``['inside', 'outside']`` + +Default value: ``['inside', 'outside']`` + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +*Default* configuration. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$sample = $b [ 'a' ] [ 'b' ]; + +$sample = $b['a']['b']; + +Example #2 +~~~~~~~~~~ + +With configuration: ``['positions' => ['inside']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$sample = $b [ 'a' ] [ 'b' ]; + +$sample = $b ['a'] ['b']; + +Example #3 +~~~~~~~~~~ + +With configuration: ``['positions' => ['outside']]``. + +.. code-block:: diff + + --- Original + +++ New + <?php + -$sample = $b [ 'a' ] [ 'b' ]; + +$sample = $b[ 'a' ][ 'b' ]; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_spaces_around_offset`` rule with the default config. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_spaces_around_offset`` rule with the default config. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_spaces_inside_parenthesis.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_spaces_inside_parenthesis.rst new file mode 100644 index 0000000..10adfe5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_spaces_inside_parenthesis.rst @@ -0,0 +1,53 @@ +===================================== +Rule ``no_spaces_inside_parenthesis`` +===================================== + +There MUST NOT be a space after the opening parenthesis. There MUST NOT be a +space before the closing parenthesis. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -if ( $a ) { + - foo( ); + +if ($a) { + + foo(); + } + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -function foo( $bar, $baz ) + +function foo($bar, $baz) + { + } + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``no_spaces_inside_parenthesis`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``no_spaces_inside_parenthesis`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_spaces_inside_parenthesis`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_spaces_inside_parenthesis`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_trailing_whitespace.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_trailing_whitespace.rst new file mode 100644 index 0000000..cc06fa4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_trailing_whitespace.rst @@ -0,0 +1,36 @@ +=============================== +Rule ``no_trailing_whitespace`` +=============================== + +Remove trailing whitespace at the end of non-blank lines. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = 1; + +$a = 1; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``no_trailing_whitespace`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``no_trailing_whitespace`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_trailing_whitespace`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_trailing_whitespace`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_whitespace_in_blank_line.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_whitespace_in_blank_line.rst new file mode 100644 index 0000000..43346be --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/no_whitespace_in_blank_line.rst @@ -0,0 +1,34 @@ +==================================== +Rule ``no_whitespace_in_blank_line`` +==================================== + +Remove trailing whitespace at the end of blank lines. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + - + + + $a = 1; + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``no_whitespace_in_blank_line`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``no_whitespace_in_blank_line`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``no_whitespace_in_blank_line`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/single_blank_line_at_eof.rst b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/single_blank_line_at_eof.rst new file mode 100644 index 0000000..070781a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/rules/whitespace/single_blank_line_at_eof.rst @@ -0,0 +1,48 @@ +================================= +Rule ``single_blank_line_at_eof`` +================================= + +A PHP file without end tag must always end with a single empty line feed. + +Examples +-------- + +Example #1 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + -$a = 1; + \ No newline at end of file + +$a = 1; + +Example #2 +~~~~~~~~~~ + +.. code-block:: diff + + --- Original + +++ New + <?php + $a = 1; + - + +Rule sets +--------- + +The rule is part of the following rule sets: + +@PSR12 + Using the `@PSR12 <./../../ruleSets/PSR12.rst>`_ rule set will enable the ``single_blank_line_at_eof`` rule. + +@PSR2 + Using the `@PSR2 <./../../ruleSets/PSR2.rst>`_ rule set will enable the ``single_blank_line_at_eof`` rule. + +@PhpCsFixer + Using the `@PhpCsFixer <./../../ruleSets/PhpCsFixer.rst>`_ rule set will enable the ``single_blank_line_at_eof`` rule. + +@Symfony + Using the `@Symfony <./../../ruleSets/Symfony.rst>`_ rule set will enable the ``single_blank_line_at_eof`` rule. diff --git a/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/checkstyle.xsd b/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/checkstyle.xsd new file mode 100644 index 0000000..02249fa --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/checkstyle.xsd @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright 2016 LinkedIn Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--> +<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:element name="checkstyle" type="checkstyleType"/> + <xs:complexType name="fileType"> + <xs:sequence> + <xs:element type="errorType" name="error" maxOccurs="unbounded" minOccurs="0"/> + </xs:sequence> + <xs:attribute type="xs:string" name="name" use="optional"/> + </xs:complexType> + <xs:complexType name="errorType"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:string" name="line" use="optional"/> + <xs:attribute type="xs:string" name="severity" use="optional"/> + <xs:attribute type="xs:string" name="message" use="optional"/> + <xs:attribute type="xs:string" name="source" use="optional"/> + <xs:attribute type="xs:string" name="column" use="optional"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + <xs:complexType name="checkstyleType"> + <xs:sequence> + <xs:element type="fileType" name="file" maxOccurs="unbounded" minOccurs="0"/> + </xs:sequence> + <xs:attribute type="xs:string" name="version"/> + </xs:complexType> +</xs:schema> \ No newline at end of file diff --git a/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/junit-10.xsd b/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/junit-10.xsd new file mode 100644 index 0000000..1f41ea3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/junit-10.xsd @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- +The MIT License (MIT) + +Copyright (c) 2014, Gregory Boissinot + +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. +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + <xs:element name="failure"> + <xs:complexType mixed="true"> + <xs:attribute name="type" type="xs:string" use="optional"/> + <xs:attribute name="message" type="xs:string" use="optional"/> + </xs:complexType> + </xs:element> + + <xs:element name="error"> + <xs:complexType mixed="true"> + <xs:attribute name="type" type="xs:string" use="optional"/> + <xs:attribute name="message" type="xs:string" use="optional"/> + </xs:complexType> + </xs:element> + + <xs:element name="skipped"> + <xs:complexType mixed="true"> + <xs:attribute name="type" type="xs:string" use="optional"/> + <xs:attribute name="message" type="xs:string" use="optional"/> + </xs:complexType> + </xs:element> + + <xs:element name="properties"> + <xs:complexType> + <xs:sequence> + <xs:element ref="property" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + </xs:element> + + <xs:element name="property"> + <xs:complexType> + <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="value" type="xs:string" use="required"/> + </xs:complexType> + </xs:element> + + <xs:element name="system-err" type="xs:string"/> + <xs:element name="system-out" type="xs:string"/> + + <xs:element name="testcase"> + <xs:complexType> + <xs:sequence> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element ref="skipped"/> + <xs:element ref="error"/> + <xs:element ref="failure"/> + <xs:element ref="system-out"/> + <xs:element ref="system-err"/> + </xs:choice> + </xs:sequence> + <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="assertions" type="xs:string" use="optional"/> + <xs:attribute name="time" type="xs:string" use="optional"/> + <xs:attribute name="timestamp" type="xs:string" use="optional"/> + <xs:attribute name="classname" type="xs:string" use="optional"/> + <xs:attribute name="status" type="xs:string" use="optional"/> + <xs:attribute name="class" type="xs:string" use="optional"/> + <xs:attribute name="file" type="xs:string" use="optional"/> + <xs:attribute name="line" type="xs:string" use="optional"/> + <xs:attribute name="log" type="xs:string" use="optional"/> + <xs:attribute name="group" type="xs:string" use="optional"/> + <xs:attribute name="url" type="xs:string" use="optional"/> + </xs:complexType> + </xs:element> + + <xs:element name="testsuite"> + <xs:complexType> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element ref="testsuite"/> + <xs:element ref="properties"/> + <xs:element ref="testcase"/> + <xs:element ref="system-out"/> + <xs:element ref="system-err"/> + </xs:choice> + <xs:attribute name="name" type="xs:string" use="optional"/> + <xs:attribute name="tests" type="xs:string" use="required"/> + <xs:attribute name="failures" type="xs:string" use="optional"/> + <xs:attribute name="errors" type="xs:string" use="optional"/> + <xs:attribute name="time" type="xs:string" use="optional"/> + <xs:attribute name="disabled" type="xs:string" use="optional"/> + <xs:attribute name="skipped" type="xs:string" use="optional"/> + <xs:attribute name="skips" type="xs:string" use="optional"/> + <xs:attribute name="timestamp" type="xs:string" use="optional"/> + <xs:attribute name="hostname" type="xs:string" use="optional"/> + <xs:attribute name="id" type="xs:string" use="optional"/> + <xs:attribute name="package" type="xs:string" use="optional"/> + <xs:attribute name="assertions" type="xs:string" use="optional"/> + <xs:attribute name="file" type="xs:string" use="optional"/> + <xs:attribute name="skip" type="xs:string" use="optional"/> + <xs:attribute name="log" type="xs:string" use="optional"/> + <xs:attribute name="url" type="xs:string" use="optional"/> + </xs:complexType> + </xs:element> + + <xs:element name="testsuites"> + <xs:complexType> + <xs:sequence> + <xs:element ref="testsuite" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="name" type="xs:string" use="optional"/> + <xs:attribute name="time" type="xs:string" use="optional"/> + <xs:attribute name="tests" type="xs:string" use="optional"/> + <xs:attribute name="failures" type="xs:string" use="optional"/> + <xs:attribute name="disabled" type="xs:string" use="optional"/> + <xs:attribute name="errors" type="xs:string" use="optional"/> + </xs:complexType> + </xs:element> + +</xs:schema> diff --git a/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/schema.json b/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/schema.json new file mode 100644 index 0000000..15db1e4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/schema.json @@ -0,0 +1,47 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "files": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "appliedFixers": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string" + } + } + }, + "required": [ + "name" + ] + } + }, + "time": { + "type": "object", + "properties": { + "total": { + "type": "number" + } + }, + "required": [ + "total" + ] + }, + "memory": { + "type": "number" + } + }, + "required": [ + "files", + "time", + "memory" + ] +} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/xml.xsd b/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/xml.xsd new file mode 100644 index 0000000..c7159a3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/schemas/fix/xml.xsd @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + <xs:element name="applied_fixer"> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:string" name="name"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + + <xs:element name="applied_fixers"> + <xs:complexType> + <xs:sequence> + <xs:element ref="applied_fixer" maxOccurs="unbounded" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + </xs:element> + + <xs:element name="diff" type="xs:string"/> + + <xs:element name="file"> + <xs:complexType> + <xs:sequence> + <xs:element ref="applied_fixers" maxOccurs="1" minOccurs="0"/> + <xs:element ref="diff" maxOccurs="1" minOccurs="0"/> + </xs:sequence> + <xs:attribute type="xs:byte" name="id" use="optional"/> + <xs:attribute type="xs:string" name="name" use="optional"/> + </xs:complexType> + </xs:element> + + <xs:element name="total"> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:float" name="value"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + + <xs:element name="files"> + <xs:complexType> + <xs:sequence> + <xs:element ref="file" maxOccurs="unbounded" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + </xs:element> + + <xs:element name="time"> + <xs:complexType> + <xs:sequence> + <xs:element ref="total"/> + </xs:sequence> + <xs:attribute type="xs:string" name="unit"/> + </xs:complexType> + </xs:element> + + <xs:element name="memory"> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:float" name="value"/> + <xs:attribute type="xs:string" name="unit"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + + <xs:element name="report"> + <xs:complexType> + <xs:sequence> + <xs:element ref="files"/> + <xs:element ref="time" maxOccurs="1" minOccurs="0"/> + <xs:element ref="memory" maxOccurs="1" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + </xs:element> + +</xs:schema> \ No newline at end of file diff --git a/vendor/friendsofphp/php-cs-fixer/doc/schemas/list-sets/schema.json b/vendor/friendsofphp/php-cs-fixer/doc/schemas/list-sets/schema.json new file mode 100644 index 0000000..8869c8f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/schemas/list-sets/schema.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "sets": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "isRisky": { + "type": "boolean" + }, + "name": { + "type": "string" + } + }, + "required": [ + "description", + "isRisky", + "name" + ] + } + } + }, + "required": [ + "sets" + ] +} diff --git a/vendor/friendsofphp/php-cs-fixer/doc/usage.rst b/vendor/friendsofphp/php-cs-fixer/doc/usage.rst new file mode 100644 index 0000000..a43f2c8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/doc/usage.rst @@ -0,0 +1,244 @@ +===== +Usage +===== + +The ``fix`` command +------------------- + +The ``fix`` command tries to fix as much coding standards +problems as possible on a given file or files in a given directory and its subdirectories: + +.. code-block:: console + + $ php php-cs-fixer.phar fix /path/to/dir + $ php php-cs-fixer.phar fix /path/to/file + +By default ``--path-mode`` is set to ``override``, which means, that if you specify the path to a file or a directory via +command arguments, then the paths provided to a ``Finder`` in config file will be ignored. You can also use ``--path-mode=intersection``, +which will use the intersection of the paths from the config file and from the argument: + +.. code-block:: console + + $ php php-cs-fixer.phar fix --path-mode=intersection /path/to/dir + +The ``--format`` option for the output format. Supported formats are ``txt`` (default one), ``json``, ``xml``, ``checkstyle``, ``junit`` and ``gitlab``. + +NOTE: the output for the following formats are generated in accordance with schemas + +* ``checkstyle`` follows the common `"checkstyle" XML schema </doc/schemas/fix/checkstyle.xsd>`_ +* ``json`` follows the `own JSON schema </doc/schemas/fix/schema.json>`_ +* ``junit`` follows the `JUnit XML schema from Jenkins </doc/schemas/fix/junit-10.xsd>`_ +* ``xml`` follows the `own XML schema </doc/schemas/fix/xml.xsd>`_ + +The ``--quiet`` Do not output any message. + +The ``--verbose`` option will show the applied rules. When using the ``txt`` format it will also display progress notifications. + +NOTE: if there is an error like "errors reported during linting after fixing", you can use this to be even more verbose for debugging purpose + +* ``-v``: verbose +* ``-vv``: very verbose +* ``-vvv``: debug + +The ``--rules`` option limits the rules to apply to the +project: + +.. code-block:: console + + $ php php-cs-fixer.phar fix /path/to/project --rules=@PSR2 + +By default the ``PSR1`` and ``PSR2`` rules are used. If the ``--rules`` option is used rules from config files are ignored. + +The ``--rules`` option lets you choose the exact rules to apply (the rule names must be separated by a comma): + +.. code-block:: console + + $ php php-cs-fixer.phar fix /path/to/dir --rules=line_ending,full_opening_tag,indentation_type + +You can also exclude the rules you don't want by placing a dash in front of the rule name, if this is more convenient, +using ``-name_of_fixer``: + +.. code-block:: console + + $ php php-cs-fixer.phar fix /path/to/dir --rules=-full_opening_tag,-indentation_type + +When using combinations of exact and exclude rules, applying exact rules along with above excluded results: + +.. code-block:: console + + $ php php-cs-fixer.phar fix /path/to/project --rules=@Symfony,-@PSR1,-blank_line_before_statement,strict_comparison + +Complete configuration for rules can be supplied using a ``json`` formatted string. + +.. code-block:: console + + $ php php-cs-fixer.phar fix /path/to/project --rules='{"concat_space": {"spacing": "none"}}' + +The ``--dry-run`` flag will run the fixer without making changes to your files. + +The ``--diff`` flag can be used to let the fixer output all the changes it makes. + +The ``--diff-format`` option allows to specify in which format the fixer should output the changes it makes: + +* ``udiff``: unified diff format; +* ``sbd``: Sebastianbergmann/diff format (default when using ``--diff`` without specifying ``diff-format``). + +The ``--allow-risky`` option (pass ``yes`` or ``no``) allows you to set whether risky rules may run. Default value is taken from config file. +A rule is considered risky if it could change code behaviour. By default no risky rules are run. + +The ``--stop-on-violation`` flag stops the execution upon first file that needs to be fixed. + +The ``--show-progress`` option allows you to choose the way process progress is rendered: + +* ``none``: disables progress output; +* ``run-in``: [deprecated] simple single-line progress output; +* ``estimating``: [deprecated] multiline progress output with number of files and percentage on each line. Note that with this option, the files list is evaluated before processing to get the total number of files and then kept in memory to avoid using the file iterator twice. This has an impact on memory usage so using this option is not recommended on very large projects; +* ``estimating-max``: [deprecated] same as ``dots``; +* ``dots``: same as ``estimating`` but using all terminal columns instead of default 80. + +If the option is not provided, it defaults to ``run-in`` unless a config file that disables output is used, in which case it defaults to ``none``. This option has no effect if the verbosity of the command is less than ``verbose``. + +.. code-block:: console + + $ php php-cs-fixer.phar fix --verbose --show-progress=estimating + +The command can also read from standard input, in which case it won't +automatically fix anything: + +.. code-block:: console + + $ cat foo.php | php php-cs-fixer.phar fix --diff - + +Finally, if you don't need BC kept on CLI level, you might use `PHP_CS_FIXER_FUTURE_MODE` to start using options that +would be default in next MAJOR release (unified differ, estimating, full-width progress indicator): + +.. code-block:: console + + $ PHP_CS_FIXER_FUTURE_MODE=1 php php-cs-fixer.phar fix -v --diff + +The ``--dry-run`` option displays the files that need to be +fixed but without actually modifying them: + +.. code-block:: console + + $ php php-cs-fixer.phar fix /path/to/code --dry-run + +By using ``--using-cache`` option with ``yes`` or ``no`` you can set if the caching +mechanism should be used. + +The ``list-files`` command +-------------------------- + +The ``list-files`` command will list all files which need fixing. + +.. code-block:: console + + $ php php-cs-fixer.phar list-files + +The ``--config`` option can be used, like in the ``fix`` command, to tell from which path a config file should be loaded. + +.. code-block:: console + + $ php php-cs-fixer.phar list-files --config=.php-cs-fixer.dist.php + +The output is build in a form that its easy to use in combination with ``xargs`` command in a linux pipe. +This can be useful e.g. in situations where the caching mechanism might not be available (CI, Docker) and distribute +fixing across several processes might speedup the process. + +Note: You need to pass the config to the ``fix`` command, in order to make it work with several files being passed by ``list-files``. + +.. code-block:: console + + $ php php-cs-fixer.phar list-files --config=.php-cs-fixer.dist.php | xargs -n 10 -P 8 php php-cs-fixer.phar fix --config=.php-cs-fixer.dist.php --path-mode intersection -v + +* ``-n`` defines how many files a single subprocess process +* ``-P`` defines how many subprocesses the shell is allowed to spawn for parallel processing (usually similar to the number of CPUs your system has) + + +Rule descriptions +----------------- + +Use the following command to quickly understand what a rule will do to your code: + +.. code-block:: console + + $ php php-cs-fixer.phar describe align_multiline_comment + +To visualize all the rules that belong to a ruleset: + +.. code-block:: console + + $ php php-cs-fixer.phar describe @PSR2 + +Caching +------- + +The caching mechanism is enabled by default. This will speed up further runs by +fixing only files that were modified since the last run. The tool will fix all +files if the tool version has changed or the list of rules has changed. +Cache is supported only for tool downloaded as phar file or installed via +composer. + +Cache can be disabled via ``--using-cache`` option or config file: + +.. code-block:: php + + <?php + + $config = new PhpCsFixer\Config(); + return $config->setUsingCache(false); + +Cache file can be specified via ``--cache-file`` option or config file: + +.. code-block:: php + + <?php + + $config = new PhpCsFixer\Config(); + return $config->setCacheFile(__DIR__.'/.php_cs.cache'); + +Using PHP CS Fixer on CI +------------------------ + +Require ``friendsofphp/php-cs-fixer`` as a ``dev`` dependency: + +.. code-block:: console + + $ ./composer.phar require --dev friendsofphp/php-cs-fixer + +Then, add the following command to your CI: + +.. code-block:: console + + $ IFS=' + $ ' + $ CHANGED_FILES=$(git diff --name-only --diff-filter=ACMRTUXB "${COMMIT_RANGE}") + $ if ! echo "${CHANGED_FILES}" | grep -qE "^(\\.php-cs-fixer(\\.dist)?\\.php|composer\\.lock)$"; then EXTRA_ARGS=$(printf -- '--path-mode=intersection\n--\n%s' "${CHANGED_FILES}"); else EXTRA_ARGS=''; fi + $ vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --dry-run --stop-on-violation --using-cache=no ${EXTRA_ARGS} + +Where ``$COMMIT_RANGE`` is your range of commits, e.g. ``$TRAVIS_COMMIT_RANGE`` or ``HEAD~..HEAD``. + +Environment options +------------------- + +The ``PHP_CS_FIXER_IGNORE_ENV`` environment variable can be used to ignore any environment requirements. +This includes requirements like missing PHP extensions, unsupported PHP versions or by using HHVM. + +NOTE: Execution may be unstable when used. + +.. code-block:: console + + $ PHP_CS_FIXER_IGNORE_ENV=1 php php-cs-fixer.phar fix /path/to/dir + +Exit code +--------- + +Exit code of the ``fix`` command is built using following bit flags: + +* 0 - OK. +* 1 - General error (or PHP minimal requirement not matched). +* 4 - Some files have invalid syntax (only in dry-run mode). +* 8 - Some files need fixing (only in dry-run mode). +* 16 - Configuration error of the application. +* 32 - Configuration error of a Fixer. +* 64 - Exception raised within the application. diff --git a/vendor/friendsofphp/php-cs-fixer/logo.md b/vendor/friendsofphp/php-cs-fixer/logo.md new file mode 100644 index 0000000..b08e6a8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/logo.md @@ -0,0 +1,3 @@ +The logo is © 2010-2014 Sensio Labs. + +Original resolution can be found at https://github.com/PHP-CS-Fixer/logo . diff --git a/vendor/friendsofphp/php-cs-fixer/logo.png b/vendor/friendsofphp/php-cs-fixer/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0ee90a821322b4bbb293cb466fd717f8a2ef44df GIT binary patch literal 18627 zcmd2?Wm6nouwL99f(Ccj;6XxQae}+E$l~s<!8N!AcUxS8dvJHR;BJ@qR^9(_YwFBQ z&4-zmr~5po`%HwAf)pAu5i$S(K$8YaD1Tg6KgJLu{Kq-yb1W(V02OTc?VFPHw{PV3 zj&>kRYcl|VKHeu@7}zUH(r=(s$e4`mis>?>l*JtWlg|q8rxL|1a-~43?h~9mQ35W$ zR1aixbI^FMr(a70K|>7l1>oS|qU;=x{r(GAyU*QzHP-E()a@ML*D<DAZ$hHPGYX{H z7N>1vgf*CoW`Dx$kL#23QNT^SAThYVxV&W@sBfQq<@Zd^90ufw3XMAVQm&I{uQxbP zJojO#C*f{8ZF2;%0$+w)miBlj;KE*oxQq)_uKTcz^ZpJv64&SFVJl)u;i>)h_8Tw@ zx&CAh(KQ?Qy21~2Tpr<EutcW{_|7aA3?NiXQVI<rs3c;bRc;`=zrYaijo0ODkuluW z6oq4?9>jP<=xXD+PQ<ZQrbl<~T)Z1Z#9W0V;#qn7+ITjAgy{}n)sWJqi~#y7T@7hC z#KK&MXRXpnZ%5Gm2Y^v*H3i1t<{nKR1l)5y6*2$yL%FGF>EO9{cmfoZmhYn3+apGO zqW4<cS<^e~c=ak;+Q6_xbNsE^Tz2*07I<S>DG9*)e@AXdapK1lBzvHi69B+U_1}PU zFBEYF0LTH-5@M?E%cmV~nbaB{tS{{cnPtbT!ZV2)_55HwETBIC3l%<$$+517mWbFo zXp5*AocVa_6^+%%u?ahXe;OH{5?#S8inLcT?f{~jym2mbUO$gLRuVQUHg{EDUMrRA znx9ZzP<7Loo0;@lN0bQ1q!15A#G?Fvbz|nAuYzd=xj?b=>VU%j3~NpMht~gUEY<AH z?>^`KOh;vk@Fya^5#B|lotFtwFcVaJWO&slac7)(BvI%K$o_k5kKaq|`_p?S#J5V- zxlKZoe`?(@KKB>YjWnfaXA-A0bvU9S2ms)crF>&2Xo7C`sm$TRTKj^f?tA|iBC&lU zL&(M}$3;^}O^F;|Db|h-@O#X5Yj2_BWT2AJgkQhhUx+W=W;32vME+FGjk@#BXhtyB zD#^Y^PTc)hJ19-eAGEJ%IiB-YTy1bJiHuJnPF$n<LI*pwAZOW`9>4(t!Sf=1qSZOX zXD1iEDaUN)R&GYbQV6(je~sqwf95s{Chs&S8emH1{8yDUnuDvnT7pUi4`QFBA?;mg z-J>-bkRN-Be!qd7m{WyBVj7{ZzczyL{0*QY6tSt$?VD7Q$#qRr2RuPl%#vT=n|yzB z1$DF0{8j9D{%ltiZjVJ7ya2ZI6h=z0^UvLg9^BE$05L0&>rtux41VyS2u9~96Kjm) ziQw<jq`qjwZWW}|4MwEsLv^6RdQ}_yd5~m;N)*b0XxLC?0nn!i9^#p+tg?o><-5p- z#Xx2;CJ=;b-_x^eQI`mg#DwZT_uf3yA-GX2vb@bGLINoS9p0j@mO}2pADPQ^EvX{0 zGS7k{qC6v&XIh%_sV0e&42$(o`rw)0Ew}~W`rk{2>gp<1WIv`mMOx}(mP}cgw}Ik< zi8V?Bi?uqXM1#O(VAqO7@UPAT8xdKoEy@b5)vGiEp43A(N2C+HHiS0BS!$$i7@1OD zi?fYC6(^Frfg=M>xU3C*<>%&{JLYMqc>jH`uX5p4ARbplOyXQaeRXjvLsB<_$O8bP z#q83P@lXW|FH;+rn*<+Jtzc?*L5yLzB0uanPaR&X<^T00aimqQ2G>Z+t-VN7Yyc5V z9e(IDMqqA><iOVKs)Gs<#%>re?)eZ70I+>Nt)_{%I1n#mxpXI?Ls46-3Pa1{*fr+d zRJsshr;-YE<q#DbjN1MCbe6P>{#H7Vf%Tt!J<)!b6qNaH*bxg1ObW2MbY|NTdC;kZ z_;)lE;opXbP-o@EvWdNR`o{)6kOwzAh?ZkNLPWlYv+}e5gRoh@$*r}YEPR32gFDn? zLBM)aK#IFgB;N3~-+oKuzL3{6ynPUw$cLXHL4seOr(nasvJ`03C1E+Pa6NI->P`;g ze1kjv7u|~~y2hlX(F8aAsgc;@$HZFySd-7|$wsu?2qGA!$!~ulA^;rGSFXmafLJ*b z*e<o1AAlR9u*Ao|vl$q*gbKx6qp+hA0;PS)mnw3zSM3M(tjxL&w+9nQH2eE2GH{X7 zQ4pPQRn66KaAAjbPh=C2k}-Tk?p8J??UDPoeHF>-A15n7!o&4%X3TDCS>z){_yk3L zC~8x(a^U+dpwBKrRVUaIIz3~5J9G24XoBF%Ap!<xF0?gd?zAp)zW18DVX|1eUY_gP zfa^LV6~Y31;Rs^;FPqqu5S!q`cBu7Z=WlIo7S$bL9wm|M3dH%7ce}cbI(W8DYcBli zRe4ryyeO9xMl&So=GDAD;km|7d;AsNXG8vki8TgsUH?rh4#sTq-8cCJ^)3rc#vcKI ztK;RTqaZwZF<MmkzZO%PE_N+w$f*Dfu=;m@KD%$mf2*;n_H{?-X7=|%^^Q$DH?${` z6H%0?hRc&ePVnK7b4e2-{(!)v-8`ZYMzBV?X5b%*9VN*KP;|UF9tRS&d?3KYToIKE z4}TDuH8o&O5MHT@kI&h;0`?-vPzY|50z?WO2R)Sx_^OyIPcFj<HKNm<!c7IPWy@vy zz+~n^^I2;wEz*tDG&>hHwdQk)Mh(Xa{3R?_D>kxXEG`G<iJ{(rsDaGZRREt%42D#? z``cc|B^mEm#Ek{O4-A+rfId{d0sx6pGn8D0A(syRW+0%ThkV=9kAn9DQP*B)@ScU3 zH{xbA`}{z@RZ=l9z1ZSfhUfsLkbQgbU?|~Zv*_2nn#bugJ`V1P_$fkvdIlsx<swmC zC?q6mH1QDtc7hR-e@SNn7_m$WmCZ3-g3r!j@Zjq_L%6R&dMzI;4|wjlZ^kKbnFqRR zG`$(*L_`>ApMPki-e2qEB=XPaLX^t7n9$xCvn^5<)>Orx;lvc|d|vimT|zhq{IEby zOhVTiLBJ6Ub>H`qD4xXlZ)r46Su|VwqL#9oG{h?I&dq^LRh^h#7@4A_O5);J)KD_8 z7|_3Wp-5ryhJi$)0{{sssg{()(jQY}@zR7_LOf>NPZ1X!W;Cdn0T7I_AN8N=co-oW zyIimr`6$m0J*})lSF<?HpufT7qVqtBzqtZ=R-fC5R?+S&Q1ut^Bn19596GPw{YhZB zuQU*%m9EZ}2%85XX1j0-atCn0NF1&}U~mRwzAfVQQ9~M(EiQ1j)DHlfyw{8wVy!r; z2D9J6&4>p$azo=1H~M(8@WUEgsl+GCLEnNm2ec#k$%$cryVo_-mQiOSiwQQ<C6pFF zO-{hMxBT$`V6O+)pVH3x{sV^rxM}h=G%!~Yx%8>PD6~DkwI@*WTW$?ZA%g~hKq5Fh zOOV6C8&RP&Ds*ai+(&yEjz#rh+z@`_&t{kD#Yxv)Z4M9RpYMFt<Vb|jRovSQJ)*LY z^1pK%E}c$1S($Yryzz~XxFzrY*})DTlo=(Kh@xBv`f(Gu1=eD8<BQ(7-f4Xgj<oMI zLdNt{pe{q?1%0=%3E^)vEP>JJ?V*76bUXVqc1Tdh#dRAhj%E&==_RD(9^WGFHTy%0 zxsH;HA4LMx`A-p%iG=r8-|3jpbFYQAxoJNxux)x$<v#U(dLo56ka8o$oi#GA_@43* ziWr@E)~0`6-J_ycSOEa9W2iqlCTTN>OTP2pdwAKSOsiG5e`+$TT<RV0LQYUGq5G`T zQ(F5oO<@`II|SYGb?Ni@zAUTq1iztW<g@IX<>ppoJoDnl{#EVym^3CZltiQ-*(gE! z+iD#h3Xq%P3P{kCwn9_uTgJYrFm5i^s0(G<`JcaBUR!OpT&7CzE9qe>VN7U$Osy<^ zv40}73mTqDe%RzI)&wPXMo4aTL2K(5tBrU3Nr>G+4Ov%}MS2EDL)`gquV>fhs>lc` zDecd!6fV|3c*pYwYI}^h=g^mcm&O30?@=-m9~i+{OI4v3H9R%C=;~8$X}HT&thtjs z@TBFSt4>HWDw-a;xixti;^5m;j&#EzQU9Ke^L^7EW3-=LBKW`HQH=WS9oIhuyN}QL zaGsP#aA)&etqJ}$wXB{8;m4%vvSb1xqMohkWX!D*ssC*y6&JNo3*$e5q<dOL^OrsO z&!0+tC_{>c?m%0H(MHFvFBPm9bWz=TzCJUSB_Znq;L4Rl`Fw)#BQw3ndQFS7_*NWT z=j2YRdvO(=3v)^0BB91*>v!P7`$0GC-$d(uVNvPqtpWZifcH$*`R9iDu72&<Ngg`z zu0)X^K$1Bi&*yn-#r3zOt?l1-wcB(;rV1>9e<XuQI|Ll0T9FIXl&c=0IwH>;*YlIU zv&gV9p%7O(?de7U&StEvnSPnx0a@zOw^47~P)uk&ou*zVy(m(lzo>+>xN-}m^4N{( z@mr#N-21dFV9;B_ffvqypqXjjt0$w9et=`x74*Gv>!Jgs8*PZpGxuAj1|h+}N5mat zKEJ`}#{Qa<8`Z3WiLm~pLiM|3OpaGhS~AfBjYk5kKoiCUudS?3l<5`NW8ibY;cf7r z*%ZEEdxjtKj!8VJNHRhk97igl-Q#?6de6@J>`hIfp1zI07*u#Lp5~3&Eh7UXcD#ZX zb%g&F^`a;8hm?teGeYf!73fFU$HvGWTTW~V^vf6MDOVr!Z5Mo!U@yL4J4V(S2N}L) zb;`fOce~Zz1>wzQsv{Gvev>$#OD8i0k)Z--#2ftpu7y7@wNK?wlxlRYUtkYI!yy97 zM1;(Jh8GlQucYJuFuGp0a_ZjRUaPVGGe_Go{0P@nSd_cW{O+DSwtM{Di<I|d<rjFy zI`q;^_*4WjZ$faT7MQxt%cyTBmE>#0u{Bg{W0!uMb)^;^Bp{k1k+b9!G+=}Jg0XRb zPCayh^v9)$;p%_iP2Qdoyvi(J-f24``s~L#-uxRPQl^D~9<%%nOm_O*)1~cJ2Z9+p zT&}|dm{`2~S_~p>+bxI96ZLRFUs<kc6OzWEZw*MKr(swQ45mGH{B6}hx>Td|&IxBT z+n&~Lm-`VJat&zmx%+Ji?b8<y_bPMD**o@&Va7XIuY%NQW1~;|+w)iNjj%g#Fv@Ly zLxME5px}>6Rd&w@Orc6KR7^y1_HI~tRAcD5C#qQ$+6bafEV6DS(3=Ldt?~RX%&7%{ zE@F{t<<#&F^zMI{w*5)G#YtH!rFE&~SPQSo1n80uZIylQ1kL}s7P6QOyAyu!RkHe4 z(NhtByasQkO(4t>JUvU@a1exu8Q3jHPKk&-Bw4wS1)~aQkGQFm>Jc7ZWqjc!Is~Ic z&Rx$!DB=n^_zz3-{w*Eb$z-qBIYhn=+rOt9wk4p)d|9ws=79mXo)oInPS(?>y>7zp z*(hf%f8`7}DtTBbc6n{!xpw*jU}{E_{WT>p#YGVVF<}v*prA$nqRIzD`+tM|Dk+NG zoe^G=2o-7dv~W=j+ohiN5OM!@CQtG~YqX@xRC?I(zd&u%NHX&mcbQTt$&an}1H320 z&Rf~J^cKD6z;UOCe`YT@PTzab$hRowrl8ui`!52hfOpogND<Qy4iEZpnAl3teE^gI zq60=i8LYL*Us8aip|+!;F?4PUJrq<oH-Xf`F;6U_n`=UOr4L;U3Hki`q^y}MVxbkt zly9z#KlKA0%h%-Fmb#bw29i~FpTl82oBm1q+N0cUTz>}kc8}el>c13WYzCg;2Ld-A z*6AEhG`@z7^l{Kb1F?Z%QA7Z6p0si%<ls#lz`@<^MfgBfd8_o1U?<^v6lAyV*6z-; zVB3eo>BLQ>T}t%P#$6H8x1NbQ1n<Zf1Ob#kbl#D65qP1VXaFmRhZ`YPE`p*^c{R6n z__^9|-&bEkL_({1U=g*E!_$WuMa8ZcKIQ*7p)<{deTW=uCf!6gsE3``w?xMbfm6>i zy&a_7O@9{6cpmp+=W0p*qei_;YdP@ua7eA|wM9!HNa;&g-8KNC@5+E@e1s}A`JHoR zhFnJ!_~%Iv|69MZ7%+FLtldK{dcH0Tv<LMo^|7tuF)=+JaJ|s&{!23m&5$ZY@LHxZ z$rDm;i*h#j{O<)La_jvkmTWpT>|(XxtG29ZIs&4ntOBVoyg~~iQ<`lRj1O_AiiBk& zAdQ|p-ZENRFd6$J<o(t`8mzY5x6t8%w|YCD^ZPd2BL2#Dn}^54<&8yQbRL|)t!S0s z%NE!dmx79wiVKs<_0)9Yf)m5YR)D$q1ho?2uO?h3e7mHmL$rmWmZylMZ<FtlX;T!7 zg<5iGpL_b^rSgP{RZMUmdYZaoWNP_SXRDGN-sRt+s<o|sU4yMwj-ds*Bw3+0iQubD z#lzrXxv~u_#_KYHTk4AA%WI7!dpjy;2dbkNjP-WO(?iG<(B{(D6LyyHs&qP=>vTW{ zhpUJ-_QrE8AQ#j|{pAa9C*fD_fw0h;`!L?$+KgKXzdDGhsk1u|&`H|QL2<dutEDyN zIR|{wC3j3P5`Cy@WQStVo%2s*-WzQH&FZufjo68apDyls?)>)mPwM}^WkgA|(%g+X z0r73=#RJKMgX4&P5-eACS58oJ)j)xmW0Z|h6TkIh!jkx1d?E2Wj7d)`p(yajgjS7p z|82HR99}xmba4+GBpOXX1|~K6J5Kg6UHK7u;%yS(Fr`torb1ks^-Ec*FgDv=`NrA2 z@uSRDK0pA_KiEGGSpru6t0v|Zag#r+kt>L(KLUxKp+}s1Kpsni>Oo#2H}oeYvzQzP zPE0UNn*dNUxE=U=O(Wwq`h)1C$TrMSte4KawI>bpd%Wb{tX(}9SZYb&Qe&AYWL%}F zYvESRwxsane?X?=XVMUcEdWf$g@a>1Vur|&p`rvX_!bSCrEI5glcTS$%d>-!1s)Y& z0AA71Rw5Abx17TpmA6^&ur+Z9N!wd;(hSOsBMeJ}(_?)UBCjw%2MPf(n~TH)mN`^~ zLNo<XCYek?-XzN|;FFFPZ0Tqi$HOx$@#l~()@Dh0D}pSpKIaXDE_=F<L|8*4p~En| z%p*cPqLD?^p+vt#RX9~<y0u<)yD{Z#g&9cBOT_9UPPqYNNkp%xu0)Vif)_c@9SxSy zDG9oQCeaDcaVa(V!%^;J7@igpKF@t5A<_7$Zd@%@<yB$y!H0k4lc)TT4bt;dKW!PO z0^hKvG0*Z0$JtE%8EU=jJ!o?(3PE;6%3RG<aR;kb$(qf*H0_QA7Ha5#PZv}n-bwO_ zobIbR8#U#g$Ox(u%@ENBxS>Xpd|~2(jC<0?&YRnB+9!6k^Q)XfzxS~!+;Hf|wB+V6 zlvG$KsOvgl3@d-6W(Mmq@|gY<FNYLKOux91cxLEQ5ozoH0zji+W1P1>%{}2Be5G6^ zQiJSa+d!n73bvQ}32DY3{GMISV8?n+&)`&xwze@T1lbB48MFP9WqR&~#}wrM)MxQm zFOtihP10Xze!*B&_K`tT{z8Td1={MaL9bkCOg!*SfdB<+=fgj>4xz+@X(V)zjx6A0 zqyUG1^>}r+lg&kXx|>oVwgU7Xd4=lXh!(hU(7~FGFw^Xt{Ax*{qMlCM2TC2dC~Xp& zo-b46YHP#F7=%g|pQZcA18I%aP-nC+UaEK?IN%8Da=EI#ic5<SYHN?N7&OAWu_38K zOI@QvL9#2o15Ar}-aizDDE*ViR!RT<!C>X-GUw~2+VII8p9mK1Z~Op45OJ>xgV#yt z?r|`w(|2hQ<GwW9DL&FPsRQZep{G*FSFGZz&RjGz_IKLP=yE*xCey3gjfb1>GGh^Y zpNK(vP<i{ih@buUn?*~dNfMxs)_nopr#HA|{mK^6bVQ|w@^C2e3d}c|7PdIIdpgmX znAxhe*zuY}-q}*E*IDk{-gG({GOo0U&6Ie8bI&DmB<C~~SJZf^x1^=BOg<Z3(PD4j zgOaKKm0;#P)IKgPb}+7a(WZJClo3(#Y6JaI$v$^s`cDY9Dt8Xf?aox^X?IG{tg{oV zB}3+90S-9adX!?$DzPL>#$P2~5kOw8tj!k84VECEf1*n^+JoE;9><_no$J&2Tc~}d z42%bgrE@%V#yT3oXP?dEBC(W(z&q@hYXuqRU5J^mNWqG_OKhjyv{s&b-y(eFs2yW# zzfN(sLW{5b3|-}{(<Z{!SXl{Z24#JcnM?Rdhzj&KAP>IiaWTU-EThqO*wjMh(<H0v z2{(7dl=)Mo`h(?HcRCnvbJe*4fO%Wv+AD#2K&R51rlnCG+KnBJ#C5lX!rJ*nW^ju_ zmWJpPW8d!m@5`9an>T7wIge;Va-1auu}wFSMMh!6CGL3XqWd(WLj`a}u^^0v^s(YE zJISkptA@fvvESr?O^qLO3j*e9v-XrGfstOXf7`hj<6yZ@EXNViGKEm0n<nCl$he^S z9+x$>zvtZw-nmD{S&9X++<3pHXS4OGe3;Vwr!&)!mc4zAtBAq#6G!BolOAuf?&`wj z4z0;<==94v0jA(wLvCHYcD|uJIp<w5!z6R_P1SOq`wk1Ap7ekb2^OpQs~+MQqG?zG ziz3H&uTd0(*EJVGR%YR+jRlO9V!AL_{YT|Cv^tjW-Pe+5vqV%YX}<rQfo_c0%4VM2 zcK8E+Tq!5-Oii4xjufiQO1YjzQkBmRYe@zEhU9BP3GhG}%_Htq!a{K<{W+v3Ib|?X zwgm^PPDi$j8ca8JUpVKsfxg>i<a@2#bz|wP+eV$wM%IQeoA>$SAa*I(P5*Hk2gSS5 z713QkK_RQyR8a4V*)3;}alKA$vVN2SlT|ro$_&3_upnvjpmhZHi>dsGGmGZuiWT4j za1a(Tw9Z(m2o991%G~X=+Re{N2M$)e6$^A<YhbT9cePo)ZTbw8AsL#}{{9mucJ+<4 z#t$#mkv#oMm#z~wFXefaUr_)eIozoITxHtj`k9Gk66+f#(oA{ES7WoQ_dzy%R!Zzz zLtNFhC|r4!>UCGKU|X$9BkBZ9Wic?BLLuszC#HBqI5MQ~LYqr5yo5a2L8r)W27f#4 zbhmG+qdHsY=7Cu2#0G#Z#vCI`KFT_=4@III4Acy?ZcnY>)1}S&IdoT%n#Dw+I~rYN zjFdqx1nN-pzqi<b4(^u4ny32V6vxghCn{O<6-B@X%ea&oi0GcosN05o_AI8;t_?yS z_t2mqnvgMjV^2GOB=Y`ZE`|QCY_!;hJeEaXLLP;we-OWyWIq3#?bW3UpCVRwo$ky? zxl+btB)ALK*gAfqPSAr<ssH9xjC5!+`RKuv{L0m&yNZUbcl#xl1p!NJ1Yxcy8Jk;F zlsN+mtEaa7LKk7&Ui|R9^!vt$_y_{pOlt<A@Lt50V(mN(EG!sEp^bu&{!Ty1DqPLZ z|CSY#?dz9DEodiQJi%30ndDq<V^tOUCqz0-RpXr*D;nkyCeCEiqlw+b05ti=PR=aa zggS09Uv!infh3A)e8dd+h#oO7v2H<jhL)pf>lYRwiarN_1fjO4Q2;goh`6+xBThP+ z?#}b3|I9`z+|D*XHDmA<Ekv+TWlxtXOEbt6OqX@6Dxn)KVLCN%P1#O{gw?QLI@q7; z7T--nJu44;bzI0LMhlFiz!pjuK`At(PB3I=EX4L+KoN=&_YX#u8yyHDhh^|@3h>|x zPoReV5myD5Z<s%^dYU+Jf}kSYNaAtYiB{}^meRg{psYU9lD_=?ta%#0rTYvU+d^dF zGD@T@q?9_qQLH^mR6?Tj-LVu^hu#GRt3|9)P56LASDZ?enj#6xG8F(b=ZN*ua<kQ^ zmat(~yLN+>D1^^DPDZ%(A=>?vw@_M`2)9zFGKkUM$jwFb>+yT@DmW_K-dtgA`SlL0 z(W74Iyw6RV|M`|FibM-TOjuQs9sP^!T?beiNF#R*kDbrXw$v;}9>^(=$N&XeOm=kI zG&cEbtWp|i!y`T%XWU5rWg$X}JmLD9MNE7p*-hAWFnW!thB?LTIERUmZsJEB<hKQr zUK2}XuE}qz{TW5!G$Jx$E~|5=IkIdOwY{m|=a|ZA*D@f$@Uj<NL#G`5j+FQi4D}Gk z(A3y50#*_p3=-5hQH;sAX8}{_pW2=E791=(NfqlWbz&b~qHb*(sP2pyk*i*}@u+Oo za__ADHJAhFqgj55#zNqH)iFz>jTUdu?rw1FQJ3xF!{+OK=YmsaWU}SgH4*!saSh$a zd<3?(7Y~(TRT-1y>CS<B;pJkzXFSGF7$YO8MA6#de=x@TXn#FFce`$W&z1ZYZ^)kS z|C2_PdeaNtdm-S?*+f~P`JI~W0==|wM*0;}x<2n6pt5Ms`U!|Q>2%g|(7KjNvV3E_ zt!tlO;uLOOeBz>uM^m9*zP(TU?zHwzr1N~OzMjj@$+}Gk%wj#*V*Jjf*zvg8Ssc6J z-s{%saLZHO{Fbiq(kDGy=N^(hI`D-mz6#k4T{h42;Oz623?~pvGw*9d*`2rW=qQjH z04+2bG*6oA!Y5yzLi~xEU*+$5RlnDg^Yg;V37;m@m*o>45i53jwXcasTJI~9e!Xpe zsbrexCXbIvvS#_2PT8^oQi%7~i8kwBKt+S39(+DC(Y!CSW3#)}kDXmp_d;5ws<|%g zN!c#!Hc4qd6ua@!I*qS$VPCIKHsp)BzNX|vDEsL}k$LCW3w>?q6mq?>gSwe}{^96u ztYG4a7D%|!gKoIJ%*-q4yP{w^Un%7PLXKT?VH&_74RC$cK37lYB2CRO3H%1B+=9*q zIpul0s#;s7Zk%o0zH|*$udugXkARV>C1e-I{&p4D+f4aQs{bjyj<VLIfo>E!_sD+O z@A9*m!HE^Vq6<8<Vy|fR(no|kdmbMs7yCwb<neERM+&`TZ(_yv*?~6Eq1tze$3&t* zcP1esJQ#B%Eo&K6bd}>8iQ@;IPt6-@7Cc+Jo|BNyG87~Mf)CF#b^!Q;SN>}AW_0B1 zXV36iZCawzZxGp`U{yV~%J0D#38nmNSLnx<3d?Cf_sjBr3g|s)G`I;%^KNn@DuZX{ z()4XC%M=(Lp10LBEL2;SeMN)ncI)zZg~ND#SZAYCDLv~vhqUuD&<HJ9-rOAQ+bgoA z$-P~8ZM-zG0SiHF1SH;mQk|p2dya3MW71H7tdk~1TtyOg;YsOlgd6?`or&S9PCoPW zvq+@*>sLaVp>lCWZ~%L2VzFMfbaUk|>Q=b33*%J8<AnQSM$pq0>|=si%3I4;Mvip# z3W&q^s-rY&RI4)b!-Zob-_L*7N8dz7>HObb0B7^IUsujql*RI20M3(oZtYV)`y1IL zeoB@@q4Stk%F}0(kok2TwBSE>F8B=EG+DpSD8AlRqkk451#@x#T?FA5DYx{n++#ko z@$4KWQqOg$o`@|>S5<9M;5xO3iD|`f2i_f4nFMKtt^3gr%)8^~A4N!jWkXto6-u-M z(r2r#>rcIY!DN=4t*8(X#~2ZI=%hHDEw?D<*K{+cC5-aW{UUCF2TW_LK$KhTefgb- z<l^f1S&?tGR@l8OugMu*?r+|@ynLMx&SRr9UpDdI@9NK)Kbc3H_3aHY;7#wvQ;`i- zu3W+OtP4hKUO|QO$z0p|jvX=cheh$k7Mv`i9Uxlm1RlgUP1z|o+%fk+KYuZh_0K&< z5n}ozCFQ25y;6v~JUMUq%io57W};CkfNylTQMXVBY3b97$U`=Mpyw0(o0Fq)dzlv7 z!yZFHaLKqT3dRh%_!M^~Sq=%QXNF3p?!?%9d@q9E*^0sAw5-o0js@Fzr0zoA_QP;F z<ou4tX>Eh%;XGl)9krVoOPlDiA&yy9m9fAYd&1SqW~!IgbmrYc^HYIp^uZtb3}WdC zqiG~0GXls070`@)Wh%tF6GfS!w^SWlvo(iKJ;2|&aqwUQFA>`&ov>Wy3xNBJfK~fu z8UDsEU{N(O88OR4XPA9gz!Uuje%GNfB6g)pV_LFaW&6;5JBy2kWY<w)an4H**{bIb zTE+@D%W(CWt4GzE77^J~aN60Mn9$5)l<M)GgfVJ#`nftzU2P@~=YvLBt{ejDq!aX{ zSu{!XDK<m=m?=d;;Q6zKW!gHqy;DXKa;+(Lk=X}d5=W+<A>3{CGVI^Ebuw(8bNqDX zQapeh;W6R9(XUlu%f#Sk>6X*DlKg&%;HGPTecyGDq0@Apy54TKa{dW9q?mE9ZY8xG z4R#AKPH;GhQ1zHTn2=^NX3YWflOQ9JNV?zMI^ns?<(2pCVl&`1jb>aMBxZY*?oMki zuxD&w^sqT-lJ)ABHM9>ZFtV)}jp4Sk)Nu-&y>$LG!Vbki#0tORLJ=$~umIKD5IFBq z%U74>!4Bq|8_BGnIR!Jo_B1dTIAsBgW-dtZvrouVfD|ipK@tLMs?VaA5ovSS2Yxh2 zNCyR$3=^Dnm3@|VB-bWOzl-m_-u9{Yva@|A`}`PW1$m0^xh4KLWLo!by>d6xX!A=8 z43C9QLi8tlP3L&tRJO}ch27IQiX)?@nqKKvtZ@7Ey7NiV?_F}RcCVC#&ee$Xx85_| zP8zzhI;yL~e%(mla1Qs3UXH@PKx8N$N|~KEhB{}oCMOPNwJ!mvK(Nh7^Kuzz_|cr| zX}6=;YC}&*BT-Hx(OnTMRJHP?Ju#(%DnzALwlr;Pjh8duQe~q5^^?7l!10l_V49Gg zBIB|rg%D<T;@7%kMKT`0`~>`TmJO|08-HSXo|TOnqMTfm9%-ajU>e%SePgmr|2=qq z0p#@g+miJ^FY(e9pGm<l{QM?^I2;phrkD*C<rtaf^v0+fh;XsuQ~_Gqd=2+OA03C@ zMwN=4+@)XSKy2g)IfP)<d~TjA+9vHI^~>2`*h>>-M*TfwHL~?eMG?*#7!{_B<VojZ zM6?Ml6WX*9@F(Q9htH%5OX#WUsM#jJmD6o%BoL9z(t!mtL(Y5g!v{tKJ0&Tj^mr)j zCJwt-dLJIdRL&y}w1Y=#e#@bgFR$z4x4YMFeBN80cy0KC)P!7Q+7@|cmRQZsMOB_W za-C!uTE_^i+qYe)HQ3_2g9ILKYYK6I2?pYW5W*M*-E1w=On(#7dx=`46Nmdp^(>}1 z3*4{0jVsE<Ml<h!!N0V=uaI%|#u`J%qKH3(MKZ#ZihXSjB}r7@-oS2ApvxWspeC6Y zZSkXHFQJ>Zdcrs<BY>OzyHWMH!q8>{ld!9Ha&<F9lCaf<B2=qj(k56<1+Kye6Ui|% zt?;tXx_{Ee9UV$AlVTuiFbD<4q#I%7el^WaAKEXjdC@{)dUO;%ksozpL2uIK!m{!H z&3eq9Mj%YcwRm=;S1p!w@xl$y44UxD{$MTZuBUyP-q!;z?DD^BQ!<{7>V7&H%@1Z* z#8%{OB^6b<9~RjebXt(aAg0~6*-=rPgEq{?pi8ak00rh@7(Up4++~O^?FN(y>6YTd z;;{Gr;GQ}nDHDYk)<K|1d7KmxkQbtI;P9Z+bm^u)dr)%`YO13u|6KkBA5`E^7)zA` z6rIatj<z>xt`@g=)t<b=78lMkXmS9>JFUhnS4tpJ6%QlNp^d6m6^;$NvU-~6T=u=i z{4!{MTRDl|4nSqJ{&`^^<)M+xsFv}wkns!ZT_Y_NClxJ$pfZtH9jPO2FPPb>!DTmK z#n;Trl)g6gx(`@zX8N8Yf<Mi-4aOJ~t)s%A9Kll{eWEV#l+=!>re{)@*=xg+1u3zN z=WDa(XLra!R4d8P6Q@oezA1$w<*5##Ea|rWu&G=)ek}-Lg8gG9rOI9L&{fs-V%9Y^ zC1O#%iDFL!zG$5N*P_brfL^lVh-X`hGCLpAIQqTieZtO<x#+O><hgaAX>azhsv(la zQgYsuo`Y=^daS#rw|5cZWU^xj&jF7UCF@9}mB?X)LXwJS@0{4K0I7M-%jj}~OYNsT z;ivY54>NuY*w6^&foFe7U!o5l!wZe|UcJ{UH~r@%PW1cIIfm=e@GaxKl?TH_zE%^a z;sC3VVT%H6zs_rVGC6xCu_J8&yfrQIn~{2QGr08VhN&+yONdg~Nza+fgK~%|S&`{F zTc%kSDinO``{rSMPD3rB{=AM7oa8YYH>5)($VueoNOYn?ltoMRo4^4nHGy47C^Vqc zmU{aWqNtl3RTV*)Ec7#2f>_R?01Z6{_4*>n&D+BGLBcV<ITL_Y2;U@PyYK0zm_Fak z&C=|O2ckqW(;nVlyuA19KU$DxdgMtMhz(IyU``9=tQ@$R36&ns!~LG_$C&zwzz1)F zeQTe=8r9d79hezq-ugD#osIwY^MF6iBzFBa&8jx367s{Ysg<<cLOa{#V>x5w^05F; zAwq#{-bGM(d4+IZ%>wsI=sZ<+o`q}xFb)Iz4Fdy71Fg-HtJU2Oy4IQ-AL(O&LRH9+ zysDOK$4Ku_7!7|PWK+|&ux6)+xVp;`ipSy$Hf6wAs2)b@=hrT(B%(%aX;H3Jo?z8F zK7P+yooo+3mRN_n5c<G$WZvQ}uq;Sp$P~T3!bt&Rl9vpL+h#z;;C#9LpjT4J<FpUw z{^h&F%|mer=e=F~ZdtF5FBGeb&8N2ggQSttYtgl3pH96(DuBIA2rL4v{>*Bbd|G@U zriQ<<<P-wP8fwMF0*$~>E;ed&JBye+?4BwQFlXfm={r8g1%Y_l@AGnMM+?dN6D-+Y zTFSUg_$@VK;)jwVV9nv(zG`w-#A*!2yfqTyw<Vb&6{`lDbNx&-i7=JACoM&_Me>^) z@7G=<8CPj;Q3qXnSg}{@^JC7^WBw2uFm|Km%xY?#liAqaDt_z!U>0Knk}|@bTXnyD zSkq3NIl893I5;mT7o68K1NfhrZ(b4#g(tuB1PBby+R${($N(2PntiODH(t#^S(YEY zArmnGJ2eHElT-N{80`#PGq0pV$6^0??LcYt$IWIo%eBE?1>he{Jn6dOGzDINa#JYG zHy(DDMN+hU*aSmVS}50f9_}yyp`ZhM9aUa4?n>Q{aSHQ%x?l%=lanWC$4rTAAyHNi z@U^C)Nk(7vtG|AhTEL4DpK;Z;l}DBz*NVgY8lRa`bZcU!jUY6*E+qK%MyJAsj++Tk zrMe%BaHspIlfmlIbHSh*`b#OlFdQ;_9vSa!!>|h7cx{EzqZwrw8E-9?VB5U=NHw{7 zXNR#^xCE{+4c-6sZJGr8%a63I03(8MH)ms4(-KKO{mn1Nh<TvaFM3yVFK`*8elPoW z?TQRLviN$hWxXt}U2$d`_tjM~pW6xqT&@~5&EK20vtGkYTK*wX#Xm+)|9vCl3yHws ze34hDWEpoS8hgtOu*FT7pRe#UM%Vdy?Nc)js;0rdg2htvUTB$hIt2qhqnsL-C8$0p zWC_1dH@$AJJU8j{Y3uN@erIMDMbr-TK6~>WnHax)zFbn}cS)gNl9`K6Y0(EqhF9<) zQPe)Goj(N8**;m3MhSx`8A{BUafxWv50AyTdaKnp)tQEF(F{R{?(#~|bBGWcLo*t5 zH=EVh+wGghs$##3A;F%C#I)6e{mwztjeW8S5>IC`|E!BlFw<`-1FbB+%MuxoZIqcO zsp5@I>&BR?hzhCjlS-%F8=>)<tWsSeW1H*w!pUa(9*;%UayS;Ndr3UAH^+9xEl5(B zH-QBEIGEE!M8V~54R_Qu7H?3hiPYmEtSfG8?_HqF*2E#LY#trT0|^JBm+YmGbZ*VT zplBYqrOX&=M*kTqcY8L~WAwo9y$PPpcWO=0;B9|{-~K$>&S@lMp`Y_JKLs9-tl{zX zVxVS5HIL9j$a!lj>DK_&PMoR}I2f*Q@<M-1Y~=(n?F@#_@aoo7Q0!a&`JyoDCw0bm z;5{5MsNp;@uI^HQT+W<gs_jzoL*;jZzd-=bi`VjwrBbHI`WY^A2RV9^9QHAj8f;#x zwkxZet}2&(9WGi;I+8G1C;A43%6It=P?bjpmuO?$akvpJX_UDjS=>l!t!zCpNGi6| z#cF5?3iOX)^>R4ot>=nUdalZ&WpRU9YHvPNdI`j}F!O^~o3-UryQg?}`ItVZlkvt% z0iob}hwlnT!-0>3tMMUcld^lZs$@!m(iZX3JrBtsl$K?mBYzYbnWXQGWNM4=Y3CD! zUO~}tL+>5wPH&^8!lcRuV{vciS6+&=qPV)N?(2*J-^(HlzFd~j@^u1l*ZI2kP8K=( zLfabv=~5^8a;FP*vV&xkPZU12t=spP>+5I(cp(&2gNPsPNFUGd-8IK0`6;Rr4%QU2 zMM5=hnvWjsI+uNnW1i$bbEN3cVJ${&_4Sy*#NR+*<`|mwQzDANoyt8TMQtG4X#WsI zQ?MhsY}ILB=!bb)>lXK%4L@i%|CtyRMPZt(rL*kT#8+54K1M&Na>POY9Ce^B-=s}w zxN%|(f-$`EA!A$$(P%&CjXyda_}e*Hd*5@u!*l*fKY!j#p#2=DygjV*7Oh*{Du$SV z+sd=uvX0<gY_<A4-u3K+J+kzepYu?d-6LOrd;c%loa^ppXzsG=Hs}7#v05kdMf$7- zADeH`5C&E&(iTTF{g3Z^%|J-d`W8g*aDGpcPeBfeK@mHCwDX^9S>c&3gI1q46m#=G z2`uB)sKS4TYrex8U-TX4pv+P|BU~08|G_kr%E(rp*?%cnU1|>n4^m9CmM;Hj1tm9e z@~uyKfgOxZ*;7XD$~1Mc=u06Ab*{YrOUa>I>=AY6EgYa2%gU*GOS-GqAaY7n>$T`_ zv1>89ihfF1tZ<IPuYc3w!0@nhFZig~b-0Rq=t3@oO<(uC6cEDOi_bf36el+ayiUku z2e8fVUOPt)w?uG4UCQUCp3nb;Pg)hPZt>4S-K{Y{`=)ETiF=(ay0KLk|N5J$DG?MU z&g`C2GXF0!&8hQXPbqSHPI?qp9`ifRT!4GkvxsM-uDjRdfDKix=`w%x!-6AHOX>(j zw)5HxZ2{DFr4oPYJZr<>C*j~Y<|rEyFoDwOvr_rVE6ec`nW106C{>IN8-z0k;(8Xb z_{Hn;f(a@fhzFW;_--RE)?fCm@fxp~Ep)TuUmn`LBQcoSJjpAy;^?~C$dP(IRaUrE zxYo^Xh50@_mHR%OVWieJV*td71Uh^dM8-%x>NMJt-Bbr-Is$@)Bu5t6q870zw*tKr zee8t6eqJ3p&=6|FIlP#3VLE)w7Rk>f2ogJnmIqirv>05*WK8|yh!>ruHukf^u$N*u zkxC1dTgNlp3wtc|2Y$H=p0uPK<gnByWPkfJ#pzo#v)FkWHsASB-Sv`l9%ArnQC8ms zozJo1gtP4C)q`2V(}12yv3#E^j2~n2Tf3@z<d$k`D(JFT(dgO?zZYujQt&+V&bpgH zj1XCQUcfk{3~B%7B$Rz@Si|oy_G``MpHa!)g;AEtBH7;OjZF>NYM8%BH9x=sW1=Re z=s24}Kp1v0*t94pWO{|z&9pF5STE?m<1H{-abjl@t>R@n)O$&sCSluY6N7caFpB%0 z@RG@dPGyCGJY0_XVZw@TcFVp6zwK&pxx4$)yf?WU*>11vr-klXI2l&7ny^w9s*UGD z%|8P6vTR}XW%j=7rAMNQ356Vn9S6yHzLKKMbBBb&NQ-tg%}7q3G{_K5T2xAr4E3nj z$vQ5NT!MaQ2bXThZEf}K*{|8W_n)jC_zMg)VZ@EK>rB6a3#hpB{1Ywf&FOSV#VaZM z0l|gzkTk_^FuMtY<}+cn_6z2moGfU~Gf<jaIDtp4oMlT0nj|lZ!>k{Jf$8gUi|gQG zyiYaB(z|H_Vked&$*^m+m$%`)Sr|@Q4C6j;i!jy3icQt9!k&<a!nn*WN$HBrybTi% zmqzey8>{f+te?+b_}yw`2<Iox_VlVMZDIiinj!972;lkastn%eQrv_V^s(hVrAL&U zV^bcP;m~Z42Rfm_w*aGlZB9iX(5A>SaXM=4JOw4JLFEW~5jL1<?4h8+ct$+!V}EkQ zui1lP2ySR7BK}kVkD?Zllz+{FDPtt@BlKR`IQM$I3S+Qhw#+$RLTmA43U0UZbet`9 zoO18{&Mh+x#$HU?lfuNHy`^n#OK=I?GKO`|9o5>>nfB2tOty)EH6u)3-yocAxu@d1 zzk48|HhZQOVUZ<8_PDX@uEb~uW`QSU48e9_$ZECZlVnpYsbG>$lgonX!}W4~V%Eg$ zVWGCyXK^C9gg>+iW|glEtoTove;(lH*Wu?q>3B5z4eyA3$CPHU5%Xn=+%9BKTy-76 zt@U2ZGSoH{1z$r-2P{OwU#&|%v*i1q4IE5>+4ii$peFvdQEQgQeA9OUDM*hntb58f z;`cE8%1aWbOe|l!5X*TFtuELKGkCDQ)NR{2#KExB|B%T!HG&#;&})8!33Ucb*#pqM zjKAz+oUJ$V<Z3q5#5CBTH&HiV+Imo+&manG?{g)8_L@>8sb7DeouN-t;K7+PB9wJ> z>__d_GtfJ1Z9dgt{0|!1k5MHy<>-`8<$g&EpO$YYSTJaRw=4{1UqlmV$^CT0=Fv4C zLFv_q#z2F;WWCcmFYQ+LZ7xxu04qnq#dW+PlbAAfSl5O)QG=y8EA7%o-)x`p%uA<d z6)6rX5UxA_?;`PjHzy4iYaqD}(EyTVDqSIWQ5vvK0pjL(_?JheSL$c2>XYGnV<g$o zJ%&P}MO*rb^IYt&#}J>1)MWFZ8B_ivZ6=C2#|@3YXNy%ouVxQXX7oCWJDF1PJ6<|f z-~x<j62%ztuJbMbRT>XsPSaC6u3=QK_-+k}=kzx*MO^Jh;6Ef!Ujs|DENODSR6JBF zr`40^K@JKUbk1(e_wX$?d^mb1YwrS0aC*Yf_dR5JY-s9Y3$8jaTq{>DoCP+x3gt%O z0B6q^!itDA9W=PMG<}+-_ui#RHG2gCSvd-cc<VRjSBtU<Gxxe%UbfSfNeyYhh?baW z4~?9IuB5x5x-Y$TqT+$V7`n2U*(VVgWIupv>?%hc{SjLS7@t=cHkJhKa~+gGi(ES= zr+*&Q{zPQ~@9f?X%xHd67l<6_Wy03vK>T94xE#K@xIXMuypF?GO&+sq50AZ${KN>* znux(LP$S@fW5kOjJJRpEjaipp!O*%afa&i2Gb5vM{6jaQtg^^tk3Yl{eQ5UIUGnbt zZ1rxzc01;@E4JsQd%xr1m1;jPm)$<F$&qy|Ckv0%x;Rtq<M*OlzAR3(IPUIjV(Q&6 z+Qf-#cjO*rMm-ieJ!nku0>_{7Z%w*GR+9=eUc9~r+Lu?#2Pwffl`+{Jq#9rC6k}cp zHJK>jqMBXKX{tS64L)Wc7=NEhs)Z_|kcg?(vBSTizhl>Ow3~Le>2Q`}u8`%v>Gx>= zbM7)-8K(A_Sa2{;vM+A&6-=~RfTxJ~B69wnYB=UaL@|r+s>4Ka-D~c2m`cPX-71mW z!~t>Y5Q2Hf8oJE-d;L^O1}P7>S=&J5XuoQf9DX~3n;`vEnPV`WKV{-8O|r$2d*ODe z7F9e$@V359<*#5)I?ZR+pyUMX#&hCOyz5|9RR0jw<r-uCk8r%PS^m1ati}+0p;3a} z5CtL0$z!|Sb7#(hxU4$aC^w#@6{yi_>YSHy3tO%~-=4gc{C<b7|LwI|)me$JuaTV! zjQZ^L^xfC!SSFz^tf1kzXkEN1;k+eISv;L~`cXf%C}KEqkVrk9JVe!;*Kw^Qm54uJ zdzLSi5F{i#-DS3r1h@zA5h+)MaIXJS#z!nItMEbi>rhJl;#jBxW})6>E0Fk*S>bxs zDFgJmk`ih~t>%C^;L#cxrQ*|(!b0TIV&nb43^xLfYq)F`d0a_!gNXQEJZxj?nW@`? zQ-k-<UarfGlX9mwjQv?-tyJ_7BkU1Cy#K+n;YOG$c97tGcigA!&U;sOu3*l%v*W?; zl+Pt8k$i7ACiZ1CfH6r*VaRhCSQ6)GET&U_<;^z@bibO>#37ivbl>weiK1t@so}1l zA-s)<_g!XeG`TZ2IX&_~L(?z>Rw(PHQtd}u1ddb!9qDV&;72`F;>;5W%9^gqa4aum z@dS;TRF*6MZICllc#07|T2A(z&y46-Y1pePH%z77K0*aCnNf4`pT1rS|JA1Ivc;LV zS%T_~+B)QlHQDZ?sJY9NlQs96kG5I$ahUtr??$Y?oh^6Yy@)J-lH$-oorF+Xj*3=D zo$52=W)q_MM>v_YYTEPISuI-qA>CX)x!Xysc@7<}Vzxlnk!%AJy*222<J7Y5^2@Ud z=B^_&C^(~c0~ah(=)>0E*(nNEL|_uhcQnF&CTqoSGk9=JErPSu;Bat6{3y^9yBP#Z zaE5G;;ob>5voVH9(=$!11qq(LMeEQSM@S%xVu0lVBox|=)+u=wl`FwYtU=`!Fn`3n z9E!E;u#aMp)kTy#R&STnJYVZsC33UP@+(crJih?dKe)~)XlpUij$pC<R@mo+w^YXC z6PF3y4+6mmt5QI>-E3_Dp*XOh?I~{J9&ttnR*R(K2MZpD=PtnbGg2IY^O4or^)?{Q z!FfZ4fd2tiG-|>nqt<tjl`UJ&3-)H7shiOMM3r|rxeiaZsN5zqvOjccVZk@OM-4=# zj0C87DME0DeDGHpm!cslS&|IJo%2ckKb5)lES1<Tzv^wl0e3>_tM8k{1-N7smed7C z<jH3ej4J`1XgWW#vw9vbds7LCL-n%JxF_$~g#}d0gGTdypF>kmTYfl}zSmzBSzOQ% z8d)WgK-d$}77`c}Aa+x=5#`(nBOceIO)M9E%=1Y(x=6sQlP!6x$>{S1_KFs824)xu zB$7G~WENidqM@ayjt#%5CP1p52s9s2dDI=)vcMZ^Rz4UCoJ3*ZpK5yS8vQNxS@ol? z(7Vczghhu<oh&YZA2$hcGX@!>{+7D?&Bp;<tR1MA{@ukD8D|h<KGYmYZ)W@~s~_n8 z6=BjvOoCvwlQ`5;i~$Z?>@H$n_XL6PLZ5yoI1MPAa(c*LA~$N#moXa2C-iAmL7ZJ| ztnPdvJ*?JJLuOd*>CeuWA#t03ZUQHrdvVA7!+iWJobo9dosjfFxbVa7-g~!bA&*J0 zSL46s1>WXMM4$mJ?7T`zN<TZx?(=+JeKE$zzKg`(K@J|y;Nw&7Q%9^Sm4Jgq`*Jh( zBS~{+uIyl3N(+Gk9#~!`)Z-C&iel+9hf1x-Y<!G`KP*>iC0RVW>>q88-MUFwS_%s9 zNsd~9C4yO6tYsvuOogWfE0X*6586r^zOGQ-4)0xDMvE?dRj$r>`==Bqtco#;#BJu0 zbd84{cxg)Hl;{?LSSx`HlhO3sZ|BQHHp)V+(XYsol%F+BG<`VI?BIv&h34Jp-{IPw zzFeWjXuSfg!4>L}Gi**H{l$UpxK;<N%nhO7$6rYtIMnQ11^z!+6rAA;Q5sgAHe#?V zopa_C1_jE6lFdz6_pIWoKAR5<B@M>dG#`d62q}KcRZY!Lt4#!1g0SmxsMsqAlv{+R zTNL^dEP*sS=P1TN8VXZrb)gtJbBzn#F{ve1IC*22`ZP8Bek5%~#7Z$`^)dHjqcbnU zVr}1mxcvO>;k15%80KHr0L`?e#0nl5R7;?d2FMX|*D$I_$1?a>J58`?#lV&$&)X;v zi6miu2>C?XT*b4bLg%NQuC9%Q)O-A`stv#Mpy&SMe}sUKf~_i34U-u?4VGe|QEKhu zy)QjgnpO}5!QdHF+dsDlH;NJ-1ra2#9G!7FJEH)p3xX`L6foXcFJC|2w&mRaWmxBh zY-L$%2@<N8b)O0v#$<#Bs<1jEOa!Q**|XgjiKqk|CBLi@(j6|vS=Oaf1mKz1^7S7j z-DPSFX||iWmEsnt`kVF06a?nojQP()wnBA@+1f7(jqmax7-wAJ{}X`+e)x5eMOmBn z1QJzcSO<iZTrCxzPk?1u@k0Z<uK2>h);)WLlzfWyTD!z+{H)A$8H@_EA6KS?T`uNv z>U`JLG9{@E$H{7vZaJZWHJ54fY^mreQ^vGgjRBlmw7Cz5?j>&j`Y`+OeK#0{NI{}A zYX%EcA;hHXR5uckkjf~gI{W@>!zEXJ&-Wa2a_CTh*WlLSC7dKnnUpOzl(G_4keFtz zJCzd9o}JfPIT#m-000KNNkl<ZlaOuSbnTjwX9MZZN~nlzHP2%rQ<PTfi(aMp8j@<8 zkVcwBy`6cz0sspX!0{>XKxPlV>jp$)4Hg0nhSoafyUu`AMk$uc-QBl!_kS3M<s5$W zp4U62nceFzdGU2ikZqxW^`c}0K*~&2g^C~5ZfUcW1lDe+@7b!>3}`h?ww03SyeFM{ zj)`z4y^za$4+Lhfy1__w{18HZ+pm;*wNu>#qMamU2N9WI$VH}KFQ9()R4^Z&=YTc9 zqB&550LO?YpGtRhKP;pnhxb1EPVGAb%CN=;c3l3CJ?pm~TZC+M3N!AMz4S>)HshU7 zxaF~z3W6YbDZ4Ziv*Ky{3^*mu)Y|LWC@MW;#6BCR=RBL9%m$>Dbc|H~HoGwPhssK1 zg)(Nyw2p!C7()|lzk`EDusN_!0g&@mZqAfbFu*=M$7zr;P&$AazH3)6m>D~<K}zYG zR^muJ)p3^*i%<1#+_6stWjO7Ut?lkqiH?m=7AKx|0FFt?rd=(@0L(lGH|Ocz)Muqr zWG$`XPLF*=oY}DZ!Q$|tUvs8UzDj$}ZV(L;iR~a#wT{MunI!?5nF$QhaF{HjdRlvM z90y<uN7Q_2n8#wt^bx}}OJF3m?{qOpT(IkkJIq+zJ;fJ9J6R`-zN2`$e}YJjX>AWm zDXeN~CJkU@kz+rr=~Qb0XPR()inYaJ-`J<x*3Q4neXj8{2?=L*qE~y)78y^KgjA0+ zLxc7I-`=^zMpcDz{QsRZw=+|xGtf{N1yLkKYK)@cVRT`9EEKIFA>zu%!U(d^jTkqs zT)=`vV~8;|2+>4c)CEyV06}6<tUP=~Kp=%uTc99VpmgRw&iT8TnWTw@sHJ7l@3)!B zy_1`Bzcc^)|IWGR-VdHW1?O@Qrs$a`SpZo8*o0ac@4uXUC8dmN4p+%B2S~(mRL*#p z6s<MgHkH~l<)+y?X3e|*XsRLOFB1p+4PjjNdyvVCK)wO^R1nzI*%Mu*8*iQ8RXyaT zEPJHSf4lE;zZvZ@FO_cm({0!680(s&@B7cK5p%bQJa2;Z9b)Wc5z|z0IarbgWaY*D zq|o~m09%>e9DWau@F*i>KMo)I4Hy5g5HTeHD@5e1H6{=vC2P%)H711E{=t&pw`kc4 zKi22?>$W!@gviD?iqj{L|Gq4aT>HYM@2V4NN;&>ao&UH4u<Ll|XFn#1Z?qP9KqiSX zE%clMVY7&|2uw4?%z$7vfB<AnFek)Bh}eqe9OylgFo8%4B9aE=X%XxYksc$40&|{_ zLk2iC9%8E|x<3i!sI_Kxkg~0;Jo)Xk_s1TiAsCq(7PQ5ol!rVJ0L+pu15iXv1TlRS z>>^#e_il-INgK(RKzs<`OzjvRF}!zhj@}s4CxVZRpk06t0$Tun2SLAq+yZdcw)WNI z(jVoa@>u{KV#L|N&h(XsT@`h>tINy<i(>#sdUtQ=78ns&@kuPPa|lww1Y>Ngh};8% z7J3q38Y0JpNCC)@aie!0^nMdyUM5{n+l#M{I0gUZy4Cif7hV|`hr8?XmF(Q`+WUp3 z>~oFThMV^t=t)-{PSZ*q!_^;M-+r3S2AL@olnrcFAgvHi1272BqY$1WI5YGo*Iyhu zH}UYn?j?(szTHtL8I1*yomOnhwXb^i)#=wyc=FBnwk%xR(Rm!e5P)cy_*8(JQr3a< z-MhGSYA`-V&oqD>;djIN4;V)u7w0{?vp9F*{&Ld0oeWQh<uD|DR~=kfYhud)DD<AZ zFm=uPtzVzJQ0{J?n41Hj2%rEU3!tHz{pbZ*Q_A{a&I60s)A>d3w7HMCktZhN93c5H zj4oJf&Rpf@4lglPLgh`g<&E19oVxS2>B}7<BIqMgt~#7ohf~4T9n%*)cFCDNdgdX_ zhhccarevT_noLw`1tit<5i8%>)H7_KqJq0Nq46{5m`!5W?MrU39-FAWq+_`MPGD(n zkD}NR+}pN%jn{}MD!4J?=gq5x@N-M0Fd?~BBciC_#*l1dHcPTK3Zv60Bfn@w6cyZ9 z2GyXDByMsXCwqM2`!ym;4V^R@1ESa!qbR!0lWQJ+X0@(SRMg?FAhnyy0f0sTxr0ag z?u(=N$cD{(_Exvo%0emXaLOozCe;|G0ZahU(h%6@hLn9``_BFA-del4h{~#sK>#5t zOQsxZB~X?B9acjyYQYV6xJ)6RNw-WY46OU)s~-l=mxfST*-<M_uPZq8PorGHw9*<Q uR>Z(L$Ev{GFrg`mq9}@@D2k$thCczopJM@zawSXv0000<MNUMnLSTZ|`Kd|( literal 0 HcmV?d00001 diff --git a/vendor/friendsofphp/php-cs-fixer/php-cs-fixer b/vendor/friendsofphp/php-cs-fixer/php-cs-fixer index 28b0b09..6bd3f20 100755 --- a/vendor/friendsofphp/php-cs-fixer/php-cs-fixer +++ b/vendor/friendsofphp/php-cs-fixer/php-cs-fixer @@ -2,43 +2,116 @@ <?php /* - * This file is part of the PHP CS utility. + * This file is part of PHP CS Fixer. * * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> * * This source file is subject to the MIT license that is bundled * with this source code in the file LICENSE. */ -/** - * @author Fabien Potencier <fabien@symfony.com> - * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> - */ +if (getenv('PHP_CS_FIXER_FUTURE_MODE')) { + error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED); +} if (defined('HHVM_VERSION_ID')) { - if (HHVM_VERSION_ID < 30900) { - fwrite(STDERR, "HHVM needs to be a minimum version of HHVM 3.9.0\n"); + fwrite(STDERR, "HHVM is not supported.\n"); + + if (getenv('PHP_CS_FIXER_IGNORE_ENV')) { + fwrite(STDERR, "Ignoring environment requirements because `PHP_CS_FIXER_IGNORE_ENV` is set. Execution may be unstable.\n"); + } else { + exit(1); + } +} elseif ( + !defined('PHP_VERSION_ID') + || \PHP_VERSION_ID === 80000 + || \PHP_VERSION_ID < 50600 + || \PHP_VERSION_ID >= 80100 +) { + fwrite(STDERR, "PHP needs to be a minimum version of PHP 5.6.0 and maximum version of PHP 8.0.*.\n"); + fwrite(STDERR, 'Current PHP version: '.PHP_VERSION.".\n"); + + if (defined('PHP_VERSION_ID') && \PHP_VERSION_ID === 80000) { + fwrite(STDERR, "PHP CS Fixer is not able run on PHP 8.0.0 due to bug in PHP tokenizer (https://bugs.php.net/bug.php?id=80462).\n"); + fwrite(STDERR, "Update PHP version to unblock execution.\n"); + + exit(1); + } + + if (getenv('PHP_CS_FIXER_IGNORE_ENV')) { + fwrite(STDERR, "Ignoring environment requirements because `PHP_CS_FIXER_IGNORE_ENV` is set. Execution may be unstable.\n"); + } else { + fwrite(STDERR, "To ignore this requirement please set `PHP_CS_FIXER_IGNORE_ENV`.\n"); + fwrite(STDERR, "If you use PHP version higher than supported, you may experience code modified in a wrong way.\n"); + fwrite(STDERR, "Please report such cases at https://github.com/FriendsOfPHP/PHP-CS-Fixer .\n"); + exit(1); } -} elseif (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50306 || PHP_VERSION_ID >= 70200) { - fwrite(STDERR, "PHP needs to be a minimum version of PHP 5.3.6 and maximum version of PHP 7.1.*\n"); - exit(1); } -set_error_handler(function ($severity, $message, $file, $line) { +foreach (['json', 'tokenizer'] as $extension) { + if (!extension_loaded($extension)) { + fwrite(STDERR, sprintf("PHP extension ext-%s is missing from your system. Install or enable it.\n", $extension)); + + if (getenv('PHP_CS_FIXER_IGNORE_ENV')) { + fwrite(STDERR, "Ignoring environment requirements because `PHP_CS_FIXER_IGNORE_ENV` is set. Execution may be unstable.\n"); + } else { + exit(1); + } + } +} +unset($extension); + +set_error_handler(static function ($severity, $message, $file, $line) { if ($severity & error_reporting()) { throw new ErrorException($message, 0, $severity, $file, $line); } }); -// installed via composer? -if (file_exists($a = __DIR__.'/../../autoload.php')) { - require_once $a; -} else { - require_once __DIR__.'/vendor/autoload.php'; +$require = true; +if (class_exists('Phar')) { + // Maybe this file is used as phar-stub? Let's try! + try { + Phar::mapPhar('php-cs-fixer.phar'); + + require_once 'phar://php-cs-fixer.phar/vendor/autoload.php'; + $require = false; + } catch (PharException $e) { + } } -use Symfony\CS\Console\Application; +if ($require) { + // OK, it's not, let give Composer autoloader a try! + $possibleFiles = [__DIR__.'/../../autoload.php', __DIR__.'/../autoload.php', __DIR__.'/vendor/autoload.php']; + $file = null; + foreach ($possibleFiles as $possibleFile) { + if (file_exists($possibleFile)) { + $file = $possibleFile; + + break; + } + } + + if (null === $file) { + throw new RuntimeException('Unable to locate autoload.php file.'); + } + + require_once $file; + + unset($possibleFiles, $possibleFile, $file); +} +unset($require); + +use Composer\XdebugHandler\XdebugHandler; +use PhpCsFixer\Console\Application; + +// Restart if xdebug is loaded, unless the environment variable PHP_CS_FIXER_ALLOW_XDEBUG is set. +$xdebug = new XdebugHandler('PHP_CS_FIXER', '--ansi'); +$xdebug->check(); +unset($xdebug); $application = new Application(); $application->run(); + +__HALT_COMPILER(); diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractAlignFixer.php b/vendor/friendsofphp/php-cs-fixer/src/AbstractAlignFixerHelper.php similarity index 52% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractAlignFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/AbstractAlignFixerHelper.php index 4a79f24..a24881e 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractAlignFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/AbstractAlignFixerHelper.php @@ -10,14 +10,18 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS; +namespace PhpCsFixer; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\Tokens; /** * @author Carlos Cirello <carlos.cirello.nl@gmail.com> + * + * @internal + * + * @deprecated */ -abstract class AbstractAlignFixer extends AbstractFixer +abstract class AbstractAlignFixerHelper { /** * @const Placeholder used as anchor for right alignment. @@ -25,18 +29,48 @@ abstract class AbstractAlignFixer extends AbstractFixer const ALIGNABLE_PLACEHOLDER = "\x2 ALIGNABLE%d \x3"; /** - * Look for group of placeholders, and provide vertical alignment. + * Keep track of the deepest level ever achieved while + * parsing the code. Used later to replace alignment + * placeholders with spaces. + * + * @var int + */ + protected $deepestLevel = 0; + + public function fix(Tokens $tokens) + { + // This fixer works partially on Tokens and partially on string representation of code. + // During the process of fixing internal state of single Token may be affected by injecting ALIGNABLE_PLACEHOLDER to its content. + // The placeholder will be resolved by `replacePlaceholder` method by removing placeholder or changing it into spaces. + // That way of fixing the code causes disturbances in marking Token as changed - if code is perfectly valid then placeholder + // still be injected and removed, which will cause the `changed` flag to be set. + // To handle that unwanted behavior we work on clone of Tokens collection and then override original collection with fixed collection. + $tokensClone = clone $tokens; + + $this->injectAlignmentPlaceholders($tokensClone, 0, \count($tokens)); + $content = $this->replacePlaceholder($tokensClone); + + $tokens->setCode($content); + } + + /** + * Inject into the text placeholders of candidates of vertical alignment. * - * @param Tokens $tokens - * @param int $deepestLevel + * @param int $startAt + * @param int $endAt + */ + abstract protected function injectAlignmentPlaceholders(Tokens $tokens, $startAt, $endAt); + + /** + * Look for group of placeholders, and provide vertical alignment. * * @return string */ - protected function replacePlaceholder(Tokens $tokens, $deepestLevel) + protected function replacePlaceholder(Tokens $tokens) { $tmpCode = $tokens->generateCode(); - for ($j = 0; $j <= $deepestLevel; ++$j) { + for ($j = 0; $j <= $this->deepestLevel; ++$j) { $placeholder = sprintf(self::ALIGNABLE_PLACEHOLDER, $j); if (false === strpos($tmpCode, $placeholder)) { @@ -44,22 +78,22 @@ protected function replacePlaceholder(Tokens $tokens, $deepestLevel) } $lines = explode("\n", $tmpCode); - $linesWithPlaceholder = array(); + $linesWithPlaceholder = []; $blockSize = 0; - $linesWithPlaceholder[$blockSize] = array(); + $linesWithPlaceholder[$blockSize] = []; foreach ($lines as $index => $line) { if (substr_count($line, $placeholder) > 0) { $linesWithPlaceholder[$blockSize][] = $index; } else { ++$blockSize; - $linesWithPlaceholder[$blockSize] = array(); + $linesWithPlaceholder[$blockSize] = []; } } foreach ($linesWithPlaceholder as $group) { - if (count($group) < 1) { + if (\count($group) < 1) { continue; } diff --git a/vendor/friendsofphp/php-cs-fixer/src/AbstractDoctrineAnnotationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/AbstractDoctrineAnnotationFixer.php new file mode 100644 index 0000000..f1ef7d5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/AbstractDoctrineAnnotationFixer.php @@ -0,0 +1,228 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Doctrine\Annotation\Tokens as DoctrineAnnotationTokens; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @internal + */ +abstract class AbstractDoctrineAnnotationFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var array + */ + private $classyElements; + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // fetch indexes one time, this is safe as we never add or remove a token during fixing + $analyzer = new TokensAnalyzer($tokens); + $this->classyElements = $analyzer->getClassyElements(); + + /** @var Token $docCommentToken */ + foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $index => $docCommentToken) { + if (!$this->nextElementAcceptsDoctrineAnnotations($tokens, $index)) { + continue; + } + + $doctrineAnnotationTokens = DoctrineAnnotationTokens::createFromDocComment( + $docCommentToken, + $this->configuration['ignored_tags'] + ); + $this->fixAnnotations($doctrineAnnotationTokens); + $tokens[$index] = new Token([T_DOC_COMMENT, $doctrineAnnotationTokens->getCode()]); + } + } + + /** + * Fixes Doctrine annotations from the given PHPDoc style comment. + */ + abstract protected function fixAnnotations(DoctrineAnnotationTokens $doctrineAnnotationTokens); + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('ignored_tags', 'List of tags that must not be treated as Doctrine Annotations.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([static function ($values) { + foreach ($values as $value) { + if (!\is_string($value)) { + return false; + } + } + + return true; + }]) + ->setDefault([ + // PHPDocumentor 1 + 'abstract', + 'access', + 'code', + 'deprec', + 'encode', + 'exception', + 'final', + 'ingroup', + 'inheritdoc', + 'inheritDoc', + 'magic', + 'name', + 'toc', + 'tutorial', + 'private', + 'static', + 'staticvar', + 'staticVar', + 'throw', + + // PHPDocumentor 2 + 'api', + 'author', + 'category', + 'copyright', + 'deprecated', + 'example', + 'filesource', + 'global', + 'ignore', + 'internal', + 'license', + 'link', + 'method', + 'package', + 'param', + 'property', + 'property-read', + 'property-write', + 'return', + 'see', + 'since', + 'source', + 'subpackage', + 'throws', + 'todo', + 'TODO', + 'usedBy', + 'uses', + 'var', + 'version', + + // PHPUnit + 'after', + 'afterClass', + 'backupGlobals', + 'backupStaticAttributes', + 'before', + 'beforeClass', + 'codeCoverageIgnore', + 'codeCoverageIgnoreStart', + 'codeCoverageIgnoreEnd', + 'covers', + 'coversDefaultClass', + 'coversNothing', + 'dataProvider', + 'depends', + 'expectedException', + 'expectedExceptionCode', + 'expectedExceptionMessage', + 'expectedExceptionMessageRegExp', + 'group', + 'large', + 'medium', + 'preserveGlobalState', + 'requires', + 'runTestsInSeparateProcesses', + 'runInSeparateProcess', + 'small', + 'test', + 'testdox', + 'ticket', + 'uses', + + // PHPCheckStyle + 'SuppressWarnings', + + // PHPStorm + 'noinspection', + + // PEAR + 'package_version', + + // PlantUML + 'enduml', + 'startuml', + + // Psalm + 'psalm', + + // PHPStan + 'phpstan', + + // other + 'fix', + 'FIXME', + 'fixme', + 'override', + ]) + ->getOption(), + ]); + } + + /** + * @param int $index + * + * @return bool + */ + private function nextElementAcceptsDoctrineAnnotations(Tokens $tokens, $index) + { + do { + $index = $tokens->getNextMeaningfulToken($index); + + if (null === $index) { + return false; + } + } while ($tokens[$index]->isGivenKind([T_ABSTRACT, T_FINAL])); + + if ($tokens[$index]->isClassy()) { + return true; + } + + while ($tokens[$index]->isGivenKind([T_PUBLIC, T_PROTECTED, T_PRIVATE, T_FINAL, T_ABSTRACT, T_NS_SEPARATOR, T_STRING, CT::T_NULLABLE_TYPE])) { + $index = $tokens->getNextMeaningfulToken($index); + } + + return isset($this->classyElements[$index]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/AbstractFixer.php b/vendor/friendsofphp/php-cs-fixer/src/AbstractFixer.php new file mode 100644 index 0000000..7ce3f48 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/AbstractFixer.php @@ -0,0 +1,217 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\ConfigurationException\InvalidForEnvFixerConfigurationException; +use PhpCsFixer\ConfigurationException\RequiredFixerConfigurationException; +use PhpCsFixer\Console\Application; +use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\DefinedFixerInterface; +use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\DeprecatedFixerOption; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; +use PhpCsFixer\FixerConfiguration\InvalidOptionsForEnvException; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Exception\ExceptionInterface; +use Symfony\Component\OptionsResolver\Exception\MissingOptionsException; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +abstract class AbstractFixer implements FixerInterface, DefinedFixerInterface +{ + /** + * @var null|array<string, mixed> + */ + protected $configuration; + + /** + * @var WhitespacesFixerConfig + */ + protected $whitespacesConfig; + + /** + * @var null|FixerConfigurationResolverInterface + */ + private $configurationDefinition; + + public function __construct() + { + if ($this instanceof ConfigurableFixerInterface) { + try { + $this->configure([]); + } catch (RequiredFixerConfigurationException $e) { + // ignore + } + } + + if ($this instanceof WhitespacesAwareFixerInterface) { + $this->whitespacesConfig = $this->getDefaultWhitespacesFixerConfig(); + } + } + + final public function fix(\SplFileInfo $file, Tokens $tokens) + { + if ($this instanceof ConfigurableFixerInterface && null === $this->configuration) { + throw new RequiredFixerConfigurationException($this->getName(), 'Configuration is required.'); + } + + if (0 < $tokens->count() && $this->isCandidate($tokens) && $this->supports($file)) { + $this->applyFix($file, $tokens); + } + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + $nameParts = explode('\\', static::class); + $name = substr(end($nameParts), 0, -\strlen('Fixer')); + + return Utils::camelCaseToUnderscore($name); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function supports(\SplFileInfo $file) + { + return true; + } + + public function configure(array $configuration = null) + { + if (!$this instanceof ConfigurationDefinitionFixerInterface) { + throw new \LogicException('Cannot configure using Abstract parent, child not implementing "PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface".'); + } + + if (null === $configuration) { + Utils::triggerDeprecation(new \InvalidArgumentException( + 'Passing NULL to set default configuration is deprecated and will not be supported in 3.0, use an empty array instead.' + )); + + $configuration = []; + } + + foreach ($this->getConfigurationDefinition()->getOptions() as $option) { + if (!$option instanceof DeprecatedFixerOption) { + continue; + } + + $name = $option->getName(); + if (\array_key_exists($name, $configuration)) { + Utils::triggerDeprecation(new \InvalidArgumentException(sprintf( + 'Option "%s" for rule "%s" is deprecated and will be removed in version %d.0. %s', + $name, + $this->getName(), + Application::getMajorVersion() + 1, + str_replace('`', '"', $option->getDeprecationMessage()) + ))); + } + } + + try { + $this->configuration = $this->getConfigurationDefinition()->resolve($configuration); + } catch (MissingOptionsException $exception) { + throw new RequiredFixerConfigurationException( + $this->getName(), + sprintf('Missing required configuration: %s', $exception->getMessage()), + $exception + ); + } catch (InvalidOptionsForEnvException $exception) { + throw new InvalidForEnvFixerConfigurationException( + $this->getName(), + sprintf('Invalid configuration for env: %s', $exception->getMessage()), + $exception + ); + } catch (ExceptionInterface $exception) { + throw new InvalidFixerConfigurationException( + $this->getName(), + sprintf('Invalid configuration: %s', $exception->getMessage()), + $exception + ); + } + } + + /** + * @return FixerConfigurationResolverInterface + */ + public function getConfigurationDefinition() + { + if (!$this instanceof ConfigurationDefinitionFixerInterface) { + throw new \LogicException('Cannot get configuration definition using Abstract parent, child not implementing "PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface".'); + } + + if (null === $this->configurationDefinition) { + $this->configurationDefinition = $this->createConfigurationDefinition(); + } + + return $this->configurationDefinition; + } + + public function setWhitespacesConfig(WhitespacesFixerConfig $config) + { + if (!$this instanceof WhitespacesAwareFixerInterface) { + throw new \LogicException('Cannot run method for class not implementing "PhpCsFixer\Fixer\WhitespacesAwareFixerInterface".'); + } + + $this->whitespacesConfig = $config; + } + + abstract protected function applyFix(\SplFileInfo $file, Tokens $tokens); + + /** + * @return FixerConfigurationResolverInterface + */ + protected function createConfigurationDefinition() + { + if (!$this instanceof ConfigurationDefinitionFixerInterface) { + throw new \LogicException('Cannot create configuration definition using Abstract parent, child not implementing "PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface".'); + } + + throw new \LogicException('Not implemented.'); + } + + private function getDefaultWhitespacesFixerConfig() + { + static $defaultWhitespacesFixerConfig = null; + + if (null === $defaultWhitespacesFixerConfig) { + $defaultWhitespacesFixerConfig = new WhitespacesFixerConfig(' ', "\n"); + } + + return $defaultWhitespacesFixerConfig; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/AbstractFopenFlagFixer.php b/vendor/friendsofphp/php-cs-fixer/src/AbstractFopenFlagFixer.php new file mode 100644 index 0000000..363a76f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/AbstractFopenFlagFixer.php @@ -0,0 +1,127 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + * + * @author SpacePossum + */ +abstract class AbstractFopenFlagFixer extends AbstractFunctionReferenceFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_STRING, T_CONSTANT_ENCAPSED_STRING]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + $index = 0; + $end = $tokens->count() - 1; + while (true) { + $candidate = $this->find('fopen', $tokens, $index, $end); + + if (null === $candidate) { + break; + } + + $index = $candidate[1]; // proceed to '(' of `fopen` + + // fetch arguments + $arguments = $argumentsAnalyzer->getArguments( + $tokens, + $index, + $candidate[2] + ); + + $argumentsCount = \count($arguments); // argument count sanity check + + if ($argumentsCount < 2 || $argumentsCount > 4) { + continue; + } + + $argumentStartIndex = array_keys($arguments)[1]; // get second argument index + + $this->fixFopenFlagToken( + $tokens, + $argumentStartIndex, + $arguments[$argumentStartIndex] + ); + } + } + + abstract protected function fixFopenFlagToken(Tokens $tokens, $argumentStartIndex, $argumentEndIndex); + + /** + * @param string $mode + * + * @return bool + */ + protected function isValidModeString($mode) + { + $modeLength = \strlen($mode); + if ($modeLength < 1 || $modeLength > 13) { // 13 === length 'r+w+a+x+c+etb' + return false; + } + + $validFlags = [ + 'a' => true, + 'b' => true, + 'c' => true, + 'e' => true, + 'r' => true, + 't' => true, + 'w' => true, + 'x' => true, + ]; + + if (!isset($validFlags[$mode[0]])) { + return false; + } + + unset($validFlags[$mode[0]]); + + for ($i = 1; $i < $modeLength; ++$i) { + if (isset($validFlags[$mode[$i]])) { + unset($validFlags[$mode[$i]]); + + continue; + } + + if ('+' !== $mode[$i] + || ( + 'a' !== $mode[$i - 1] // 'a+','c+','r+','w+','x+' + && 'c' !== $mode[$i - 1] + && 'r' !== $mode[$i - 1] + && 'w' !== $mode[$i - 1] + && 'x' !== $mode[$i - 1] + ) + ) { + return false; + } + } + + return true; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/AbstractFunctionReferenceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/AbstractFunctionReferenceFixer.php new file mode 100644 index 0000000..430e810 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/AbstractFunctionReferenceFixer.php @@ -0,0 +1,67 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + * + * @author Vladimir Reznichenko <kalessil@gmail.com> + */ +abstract class AbstractFunctionReferenceFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * Looks up Tokens sequence for suitable candidates and delivers boundaries information, + * which can be supplied by other methods in this abstract class. + * + * @param string $functionNameToSearch + * @param int $start + * @param null|int $end + * + * @return null|int[] returns $functionName, $openParenthesis, $closeParenthesis packed into array + */ + protected function find($functionNameToSearch, Tokens $tokens, $start = 0, $end = null) + { + // make interface consistent with findSequence + $end = null === $end ? $tokens->count() : $end; + + // find raw sequence which we can analyse for context + $candidateSequence = [[T_STRING, $functionNameToSearch], '(']; + $matches = $tokens->findSequence($candidateSequence, $start, $end, false); + if (null === $matches) { + // not found, simply return without further attempts + return null; + } + + // translate results for humans + list($functionName, $openParenthesis) = array_keys($matches); + + $functionsAnalyzer = new FunctionsAnalyzer(); + + if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $functionName)) { + return $this->find($functionNameToSearch, $tokens, $openParenthesis, $end); + } + + return [$functionName, $openParenthesis, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesis)]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/AbstractLinesBeforeNamespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/AbstractLinesBeforeNamespaceFixer.php new file mode 100644 index 0000000..2e0faab --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/AbstractLinesBeforeNamespaceFixer.php @@ -0,0 +1,110 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * This abstract fixer is responsible for ensuring that a certain number of + * lines prefix a namespace declaration. + * + * @author Graham Campbell <graham@alt-three.com> + * + * @internal + */ +abstract class AbstractLinesBeforeNamespaceFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * Make sure # of line breaks prefixing namespace is within given range. + * + * @param int $index + * @param int $expectedMin min. # of line breaks + * @param int $expectedMax max. # of line breaks + */ + protected function fixLinesBeforeNamespace(Tokens $tokens, $index, $expectedMin, $expectedMax) + { + // Let's determine the total numbers of new lines before the namespace + // and the opening token + $openingTokenIndex = null; + $precedingNewlines = 0; + $newlineInOpening = false; + $openingToken = null; + for ($i = 1; $i <= 2; ++$i) { + if (isset($tokens[$index - $i])) { + $token = $tokens[$index - $i]; + if ($token->isGivenKind(T_OPEN_TAG)) { + $openingToken = $token; + $openingTokenIndex = $index - $i; + $newlineInOpening = false !== strpos($token->getContent(), "\n"); + if ($newlineInOpening) { + ++$precedingNewlines; + } + + break; + } + if (false === $token->isGivenKind(T_WHITESPACE)) { + break; + } + $precedingNewlines += substr_count($token->getContent(), "\n"); + } + } + + if ($precedingNewlines >= $expectedMin && $precedingNewlines <= $expectedMax) { + return; + } + + $previousIndex = $index - 1; + $previous = $tokens[$previousIndex]; + + if (0 === $expectedMax) { + // Remove all the previous new lines + if ($previous->isWhitespace()) { + $tokens->clearAt($previousIndex); + } + // Remove new lines in opening token + if ($newlineInOpening) { + $tokens[$openingTokenIndex] = new Token([T_OPEN_TAG, rtrim($openingToken->getContent()).' ']); + } + + return; + } + + $lineEnding = $this->whitespacesConfig->getLineEnding(); + $newlinesForWhitespaceToken = $expectedMax; + if (null !== $openingToken) { + // Use the configured line ending for the PHP opening tag + $content = rtrim($openingToken->getContent()); + $newContent = $content.$lineEnding; + $tokens[$openingTokenIndex] = new Token([T_OPEN_TAG, $newContent]); + --$newlinesForWhitespaceToken; + } + if (0 === $newlinesForWhitespaceToken) { + // We have all the needed new lines in the opening tag + if ($previous->isWhitespace()) { + // Let's remove the previous token containing extra new lines + $tokens->clearAt($previousIndex); + } + + return; + } + if ($previous->isWhitespace()) { + // Fix the previous whitespace token + $tokens[$previousIndex] = new Token([T_WHITESPACE, str_repeat($lineEnding, $newlinesForWhitespaceToken).substr($previous->getContent(), strrpos($previous->getContent(), "\n") + 1)]); + } else { + // Add a new whitespace token + $tokens->insertAt($index, new Token([T_WHITESPACE, str_repeat($lineEnding, $newlinesForWhitespaceToken)])); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/AbstractNoUselessElseFixer.php b/vendor/friendsofphp/php-cs-fixer/src/AbstractNoUselessElseFixer.php new file mode 100644 index 0000000..676c970 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/AbstractNoUselessElseFixer.php @@ -0,0 +1,218 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +abstract class AbstractNoUselessElseFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getPriority() + { + // should be run before NoWhitespaceInBlankLineFixer, NoExtraBlankLinesFixer, BracesFixer and after NoEmptyStatementFixer. + return 39; + } + + /** + * @param int $index + * + * @return bool + */ + protected function isSuperfluousElse(Tokens $tokens, $index) + { + $previousBlockStart = $index; + + do { + // Check if all 'if', 'else if ' and 'elseif' blocks above this 'else' always end, + // if so this 'else' is overcomplete. + list($previousBlockStart, $previousBlockEnd) = $this->getPreviousBlock($tokens, $previousBlockStart); + + // short 'if' detection + $previous = $previousBlockEnd; + if ($tokens[$previous]->equals('}')) { + $previous = $tokens->getPrevMeaningfulToken($previous); + } + + if ( + !$tokens[$previous]->equals(';') // 'if' block doesn't end with semicolon, keep 'else' + || $tokens[$tokens->getPrevMeaningfulToken($previous)]->equals('{') // empty 'if' block, keep 'else' + ) { + return false; + } + + $candidateIndex = $tokens->getPrevTokenOfKind( + $previous, + [ + ';', + [T_BREAK], + [T_CLOSE_TAG], + [T_CONTINUE], + [T_EXIT], + [T_GOTO], + [T_IF], + [T_RETURN], + [T_THROW], + ] + ); + + if (null === $candidateIndex || $tokens[$candidateIndex]->equalsAny([';', [T_CLOSE_TAG], [T_IF]])) { + return false; + } + + if ($tokens[$candidateIndex]->equals([T_THROW])) { + $previousIndex = $tokens->getPrevMeaningfulToken($candidateIndex); + + if (!$tokens[$previousIndex]->equalsAny([';', '{'])) { + return false; + } + } + + if ($this->isInConditional($tokens, $candidateIndex, $previousBlockStart) + || $this->isInConditionWithoutBraces($tokens, $candidateIndex, $previousBlockStart) + ) { + return false; + } + + // implicit continue, i.e. delete candidate + } while (!$tokens[$previousBlockStart]->isGivenKind(T_IF)); + + return true; + } + + /** + * Return the first and last token index of the previous block. + * + * [0] First is either T_IF, T_ELSE or T_ELSEIF + * [1] Last is either '}' or ';' / T_CLOSE_TAG for short notation blocks + * + * @param int $index T_IF, T_ELSE, T_ELSEIF + * + * @return int[] + */ + private function getPreviousBlock(Tokens $tokens, $index) + { + $close = $previous = $tokens->getPrevMeaningfulToken($index); + // short 'if' detection + if ($tokens[$close]->equals('}')) { + $previous = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $close); + } + + $open = $tokens->getPrevTokenOfKind($previous, [[T_IF], [T_ELSE], [T_ELSEIF]]); + if ($tokens[$open]->isGivenKind(T_IF)) { + $elseCandidate = $tokens->getPrevMeaningfulToken($open); + if ($tokens[$elseCandidate]->isGivenKind(T_ELSE)) { + $open = $elseCandidate; + } + } + + return [$open, $close]; + } + + /** + * @param int $index Index of the token to check + * @param int $lowerLimitIndex Lower limit index. Since the token to check will always be in a conditional we must stop checking at this index + * + * @return bool + */ + private function isInConditional(Tokens $tokens, $index, $lowerLimitIndex) + { + $candidateIndex = $tokens->getPrevTokenOfKind($index, [')', ';', ':']); + if ($tokens[$candidateIndex]->equals(':')) { + return true; + } + + if (!$tokens[$candidateIndex]->equals(')')) { + return false; // token is ';' or close tag + } + + // token is always ')' here. + // If it is part of the condition the token is always in, return false. + // If it is not it is a nested condition so return true + $open = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $candidateIndex); + + return $tokens->getPrevMeaningfulToken($open) > $lowerLimitIndex; + } + + /** + * For internal use only, as it is not perfect. + * + * Returns if the token at given index is part of a if/elseif/else statement + * without {}. Assumes not passing the last `;`/close tag of the statement, not + * out of range index, etc. + * + * @param int $index Index of the token to check + * @param int $lowerLimitIndex + * + * @return bool + */ + private function isInConditionWithoutBraces(Tokens $tokens, $index, $lowerLimitIndex) + { + do { + if ($tokens[$index]->isComment() || $tokens[$index]->isWhitespace()) { + $index = $tokens->getPrevMeaningfulToken($index); + } + + $token = $tokens[$index]; + if ($token->isGivenKind([T_IF, T_ELSEIF, T_ELSE])) { + return true; + } + + if ($token->equals(';')) { + return false; + } + + if ($token->equals('{')) { + $index = $tokens->getPrevMeaningfulToken($index); + + // OK if belongs to: for, do, while, foreach + // Not OK if belongs to: if, else, elseif + if ($tokens[$index]->isGivenKind(T_DO)) { + --$index; + + continue; + } + + if (!$tokens[$index]->equals(')')) { + return false; // like `else {` + } + + $index = $tokens->findBlockStart( + Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, + $index + ); + + $index = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$index]->isGivenKind([T_IF, T_ELSEIF])) { + return false; + } + } elseif ($token->equals(')')) { + $type = Tokens::detectBlockType($token); + $index = $tokens->findBlockStart( + $type['type'], + $index + ); + + $index = $tokens->getPrevMeaningfulToken($index); + } else { + --$index; + } + } while ($index > $lowerLimitIndex); + + return false; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/AbstractPhpdocToTypeDeclarationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/AbstractPhpdocToTypeDeclarationFixer.php new file mode 100644 index 0000000..88da3c9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/AbstractPhpdocToTypeDeclarationFixer.php @@ -0,0 +1,240 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +abstract class AbstractPhpdocToTypeDeclarationFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var string + */ + private $classRegex = '/^\\\\?[a-zA-Z_\\x7f-\\xff](?:\\\\?[a-zA-Z0-9_\\x7f-\\xff]+)*$/'; + + /** + * @var array<string, int> + */ + private $versionSpecificTypes = [ + 'void' => 70100, + 'iterable' => 70100, + 'object' => 70200, + 'mixed' => 80000, + ]; + + /** + * @var array<string, bool> + */ + private $scalarTypes = [ + 'bool' => true, + 'float' => true, + 'int' => true, + 'string' => true, + ]; + + /** + * @var array<string, bool> + */ + private static $syntaxValidationCache = []; + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * @param string $type + * + * @return bool + */ + abstract protected function isSkippedType($type); + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('scalar_types', 'Fix also scalar types; may have unexpected behaviour due to PHP bad type coercion system.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + ]); + } + + /** + * @param int $index The index of the function token + * + * @return null|int + */ + protected function findFunctionDocComment(Tokens $tokens, $index) + { + do { + $index = $tokens->getPrevNonWhitespace($index); + } while ($tokens[$index]->isGivenKind([ + T_COMMENT, + T_ABSTRACT, + T_FINAL, + T_PRIVATE, + T_PROTECTED, + T_PUBLIC, + T_STATIC, + ])); + + if ($tokens[$index]->isGivenKind(T_DOC_COMMENT)) { + return $index; + } + + return null; + } + + /** + * @param string $name + * @param int $docCommentIndex + * + * @return Annotation[] + */ + protected function getAnnotationsFromDocComment($name, Tokens $tokens, $docCommentIndex) + { + $namespacesAnalyzer = new NamespacesAnalyzer(); + $namespace = $namespacesAnalyzer->getNamespaceAt($tokens, $docCommentIndex); + + $namespaceUsesAnalyzer = new NamespaceUsesAnalyzer(); + $namespaceUses = $namespaceUsesAnalyzer->getDeclarationsInNamespace($tokens, $namespace); + + $doc = new DocBlock( + $tokens[$docCommentIndex]->getContent(), + $namespace, + $namespaceUses + ); + + return $doc->getAnnotationsOfType($name); + } + + /** + * @param string $type + * @param bool $isNullable + * + * @return Token[] + */ + protected function createTypeDeclarationTokens($type, $isNullable) + { + static $specialTypes = [ + 'array' => [CT::T_ARRAY_TYPEHINT, 'array'], + 'callable' => [T_CALLABLE, 'callable'], + 'static' => [T_STATIC, 'static'], + ]; + + $newTokens = []; + + if (true === $isNullable && 'mixed' !== $type) { + $newTokens[] = new Token([CT::T_NULLABLE_TYPE, '?']); + } + + if (isset($specialTypes[$type])) { + $newTokens[] = new Token($specialTypes[$type]); + } else { + $typeUnqualified = ltrim($type, '\\'); + + if (isset($this->scalarTypes[$typeUnqualified]) || isset($this->versionSpecificTypes[$typeUnqualified])) { + // 'scalar's, 'void', 'iterable' and 'object' must be unqualified + $newTokens[] = new Token([T_STRING, $typeUnqualified]); + } else { + foreach (explode('\\', $type) as $nsIndex => $value) { + if (0 === $nsIndex && '' === $value) { + continue; + } + + if (0 < $nsIndex) { + $newTokens[] = new Token([T_NS_SEPARATOR, '\\']); + } + + $newTokens[] = new Token([T_STRING, $value]); + } + } + } + + return $newTokens; + } + + /** + * @param bool $isReturnType + * + * @return null|array + */ + protected function getCommonTypeFromAnnotation(Annotation $annotation, $isReturnType) + { + $typesExpression = $annotation->getTypeExpression(); + + $commonType = $typesExpression->getCommonType(); + $isNullable = $typesExpression->allowsNull(); + + if (null === $commonType) { + return null; + } + + if ($isNullable && (\PHP_VERSION_ID < 70100 || 'void' === $commonType)) { + return null; + } + + if ('static' === $commonType && (!$isReturnType || \PHP_VERSION_ID < 80000)) { + $commonType = 'self'; + } + + if ($this->isSkippedType($commonType)) { + return null; + } + + if (isset($this->versionSpecificTypes[$commonType]) && \PHP_VERSION_ID < $this->versionSpecificTypes[$commonType]) { + return null; + } + + if (isset($this->scalarTypes[$commonType])) { + if (false === $this->configuration['scalar_types']) { + return null; + } + } elseif (1 !== Preg::match($this->classRegex, $commonType)) { + return null; + } + + return [$commonType, $isNullable]; + } + + final protected function isValidSyntax($code) + { + if (!isset(self::$syntaxValidationCache[$code])) { + try { + Tokens::fromCode($code); + self::$syntaxValidationCache[$code] = true; + } catch (\ParseError $e) { + self::$syntaxValidationCache[$code] = false; + } + } + + return self::$syntaxValidationCache[$code]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractPhpdocTypesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/AbstractPhpdocTypesFixer.php similarity index 70% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractPhpdocTypesFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/AbstractPhpdocTypesFixer.php index 56c2e31..8b08eb6 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/AbstractPhpdocTypesFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/AbstractPhpdocTypesFixer.php @@ -10,50 +10,59 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS; +namespace PhpCsFixer; -use Symfony\CS\DocBlock\Annotation; -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; /** - * This abstract fixer provides a base for fixers to fix types in phpdoc. + * This abstract fixer provides a base for fixers to fix types in PHPDoc. * * @author Graham Campbell <graham@alt-three.com> + * + * @internal */ abstract class AbstractPhpdocTypesFixer extends AbstractFixer { /** * The annotation tags search inside. * - * @var string[]|null + * @var string[] */ - protected static $tags; + protected $tags; /** * {@inheritdoc} */ public function __construct() { - if (null === static::$tags) { - static::$tags = Annotation::getTagsWithTypes(); - } + parent::__construct(); + + $this->tags = Annotation::getTagsWithTypes(); } /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function isCandidate(Tokens $tokens) { - $tokens = Tokens::fromCode($content); + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } - foreach ($tokens as $token) { + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { if (!$token->isGivenKind(T_DOC_COMMENT)) { continue; } $doc = new DocBlock($token->getContent()); - $annotations = $doc->getAnnotationsOfType(static::$tags); + $annotations = $doc->getAnnotationsOfType($this->tags); if (empty($annotations)) { continue; @@ -63,10 +72,8 @@ public function fix(\SplFileInfo $file, $content) $this->fixTypes($annotation); } - $token->setContent($doc->getContent()); + $tokens[$index] = new Token([T_DOC_COMMENT, $doc->getContent()]); } - - return $tokens->generateCode(); } /** @@ -84,8 +91,6 @@ abstract protected function normalize($type); * We must be super careful not to modify parts of words. * * This will be nicely handled behind the scenes for us by the annotation class. - * - * @param Annotation $annotation */ private function fixTypes(Annotation $annotation) { @@ -99,8 +104,6 @@ private function fixTypes(Annotation $annotation) } /** - * Normalize the given types. - * * @param string[] $types * * @return string[] @@ -115,7 +118,7 @@ private function normalizeTypes(array $types) } /** - * Prepair the type and normalize it. + * Prepare the type and normalize it. * * @param string $type * @@ -123,8 +126,8 @@ private function normalizeTypes(array $types) */ private function normalizeType($type) { - if (substr($type, -2) === '[]') { - return $this->normalize(substr($type, 0, -2)).'[]'; + if ('[]' === substr($type, -2)) { + return $this->normalizeType(substr($type, 0, -2)).'[]'; } return $this->normalize($type); diff --git a/vendor/friendsofphp/php-cs-fixer/src/AbstractProxyFixer.php b/vendor/friendsofphp/php-cs-fixer/src/AbstractProxyFixer.php new file mode 100644 index 0000000..b173361 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/AbstractProxyFixer.php @@ -0,0 +1,122 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +abstract class AbstractProxyFixer extends AbstractFixer +{ + /** + * @var array<string, FixerInterface> + */ + protected $proxyFixers; + + public function __construct() + { + foreach (Utils::sortFixers($this->createProxyFixers()) as $proxyFixer) { + $this->proxyFixers[$proxyFixer->getName()] = $proxyFixer; + } + + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + foreach ($this->proxyFixers as $fixer) { + if ($fixer->isCandidate($tokens)) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + foreach ($this->proxyFixers as $fixer) { + if ($fixer->isRisky()) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + if (\count($this->proxyFixers) > 1) { + throw new \LogicException('You need to override this method to provide the priority of combined fixers.'); + } + + return reset($this->proxyFixers)->getPriority(); + } + + /** + * {@inheritdoc} + */ + public function supports(\SplFileInfo $file) + { + foreach ($this->proxyFixers as $fixer) { + if ($fixer->supports($file)) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function setWhitespacesConfig(WhitespacesFixerConfig $config) + { + parent::setWhitespacesConfig($config); + + foreach ($this->proxyFixers as $fixer) { + if ($fixer instanceof WhitespacesAwareFixerInterface) { + $fixer->setWhitespacesConfig($config); + } + } + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($this->proxyFixers as $fixer) { + $fixer->fix($file, $tokens); + } + } + + /** + * @return FixerInterface[] + */ + abstract protected function createProxyFixers(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Cache/Cache.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/Cache.php new file mode 100644 index 0000000..a2e7aa7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/Cache.php @@ -0,0 +1,138 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Cache; + +/** + * @author Andreas Möller <am@localheinz.com> + * + * @internal + */ +final class Cache implements CacheInterface +{ + /** + * @var SignatureInterface + */ + private $signature; + + /** + * @var array + */ + private $hashes = []; + + public function __construct(SignatureInterface $signature) + { + $this->signature = $signature; + } + + public function getSignature() + { + return $this->signature; + } + + public function has($file) + { + return \array_key_exists($file, $this->hashes); + } + + public function get($file) + { + if (!$this->has($file)) { + return null; + } + + return $this->hashes[$file]; + } + + public function set($file, $hash) + { + $this->hashes[$file] = $hash; + } + + public function clear($file) + { + unset($this->hashes[$file]); + } + + public function toJson() + { + $json = json_encode([ + 'php' => $this->getSignature()->getPhpVersion(), + 'version' => $this->getSignature()->getFixerVersion(), + 'indent' => $this->getSignature()->getIndent(), + 'lineEnding' => $this->getSignature()->getLineEnding(), + 'rules' => $this->getSignature()->getRules(), + 'hashes' => $this->hashes, + ]); + + if (JSON_ERROR_NONE !== json_last_error()) { + throw new \UnexpectedValueException(sprintf( + 'Can not encode cache signature to JSON, error: "%s". If you have non-UTF8 chars in your signature, like in license for `header_comment`, consider enabling `ext-mbstring` or install `symfony/polyfill-mbstring`.', + json_last_error_msg() + )); + } + + return $json; + } + + /** + * @param string $json + * + * @throws \InvalidArgumentException + * + * @return Cache + */ + public static function fromJson($json) + { + $data = json_decode($json, true); + + if (null === $data && JSON_ERROR_NONE !== json_last_error()) { + throw new \InvalidArgumentException(sprintf( + 'Value needs to be a valid JSON string, got "%s", error: "%s".', + $json, + json_last_error_msg() + )); + } + + $requiredKeys = [ + 'php', + 'version', + 'indent', + 'lineEnding', + 'rules', + 'hashes', + ]; + + $missingKeys = array_diff_key(array_flip($requiredKeys), $data); + + if (\count($missingKeys)) { + throw new \InvalidArgumentException(sprintf( + 'JSON data is missing keys "%s"', + implode('", "', $missingKeys) + )); + } + + $signature = new Signature( + $data['php'], + $data['version'], + $data['indent'], + $data['lineEnding'], + $data['rules'] + ); + + $cache = new self($signature); + + $cache->hashes = $data['hashes']; + + return $cache; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Cache/CacheInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/CacheInterface.php new file mode 100644 index 0000000..693b0ee --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/CacheInterface.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Cache; + +/** + * @author Andreas Möller <am@localheinz.com> + * + * @internal + */ +interface CacheInterface +{ + /** + * @return SignatureInterface + */ + public function getSignature(); + + /** + * @param string $file + * + * @return bool + */ + public function has($file); + + /** + * @param string $file + * + * @return null|int + */ + public function get($file); + + /** + * @param string $file + * @param int $hash + */ + public function set($file, $hash); + + /** + * @param string $file + */ + public function clear($file); + + /** + * @return string + */ + public function toJson(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Cache/CacheManagerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/CacheManagerInterface.php new file mode 100644 index 0000000..daa8bbd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/CacheManagerInterface.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Cache; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +interface CacheManagerInterface +{ + /** + * @param string $file + * @param string $fileContent + * + * @return bool + */ + public function needFixing($file, $fileContent); + + /** + * @param string $file + * @param string $fileContent + */ + public function setFile($file, $fileContent); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Cache/Directory.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/Directory.php new file mode 100644 index 0000000..cfe9195 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/Directory.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Cache; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class Directory implements DirectoryInterface +{ + /** + * @var string + */ + private $directoryName; + + /** + * @param string $directoryName + */ + public function __construct($directoryName) + { + $this->directoryName = $directoryName; + } + + /** + * {@inheritdoc} + */ + public function getRelativePathTo($file) + { + $file = $this->normalizePath($file); + + if ( + '' === $this->directoryName + || 0 !== stripos($file, $this->directoryName.\DIRECTORY_SEPARATOR) + ) { + return $file; + } + + return substr($file, \strlen($this->directoryName) + 1); + } + + private function normalizePath($path) + { + return str_replace(['\\', '/'], \DIRECTORY_SEPARATOR, $path); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigAwareInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/DirectoryInterface.php similarity index 56% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigAwareInterface.php rename to vendor/friendsofphp/php-cs-fixer/src/Cache/DirectoryInterface.php index 42be324..a22582e 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/ConfigAwareInterface.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/DirectoryInterface.php @@ -10,17 +10,17 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS; +namespace PhpCsFixer\Cache; /** - * @author Jordi Boggiano <j.boggiano@seld.be> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> */ -interface ConfigAwareInterface +interface DirectoryInterface { /** - * Sets the active config on the fixer. + * @param string $file * - * @param ConfigInterface $config + * @return string */ - public function setConfig(ConfigInterface $config); + public function getRelativePathTo($file); } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Cache/FileCacheManager.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/FileCacheManager.php new file mode 100644 index 0000000..9c7ca5b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/FileCacheManager.php @@ -0,0 +1,144 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Cache; + +/** + * Class supports caching information about state of fixing files. + * + * Cache is supported only for phar version and version installed via composer. + * + * File will be processed by PHP CS Fixer only if any of the following conditions is fulfilled: + * - cache is corrupt + * - fixer version changed + * - rules changed + * - file is new + * - file changed + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FileCacheManager implements CacheManagerInterface +{ + /** + * @var FileHandlerInterface + */ + private $handler; + + /** + * @var SignatureInterface + */ + private $signature; + + /** + * @var CacheInterface + */ + private $cache; + + /** + * @var bool + */ + private $isDryRun; + + /** + * @var DirectoryInterface + */ + private $cacheDirectory; + + /** + * @param bool $isDryRun + */ + public function __construct( + FileHandlerInterface $handler, + SignatureInterface $signature, + $isDryRun = false, + DirectoryInterface $cacheDirectory = null + ) { + $this->handler = $handler; + $this->signature = $signature; + $this->isDryRun = $isDryRun; + $this->cacheDirectory = $cacheDirectory ?: new Directory(''); + + $this->readCache(); + } + + public function __destruct() + { + $this->writeCache(); + } + + /** + * This class is not intended to be serialized, + * and cannot be deserialized (see __wakeup method). + * + * @return array + */ + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + /** + * Disable the deserialization of the class to prevent attacker executing + * code by leveraging the __destruct method. + * + * @see https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection + */ + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function needFixing($file, $fileContent) + { + $file = $this->cacheDirectory->getRelativePathTo($file); + + return !$this->cache->has($file) || $this->cache->get($file) !== $this->calcHash($fileContent); + } + + public function setFile($file, $fileContent) + { + $file = $this->cacheDirectory->getRelativePathTo($file); + + $hash = $this->calcHash($fileContent); + + if ($this->isDryRun && $this->cache->has($file) && $this->cache->get($file) !== $hash) { + $this->cache->clear($file); + + return; + } + + $this->cache->set($file, $hash); + } + + private function readCache() + { + $cache = $this->handler->read(); + + if (!$cache || !$this->signature->equals($cache->getSignature())) { + $cache = new Cache($this->signature); + } + + $this->cache = $cache; + } + + private function writeCache() + { + $this->handler->write($this->cache); + } + + private function calcHash($content) + { + return crc32($content); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Cache/FileHandler.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/FileHandler.php new file mode 100644 index 0000000..f0c6b69 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/FileHandler.php @@ -0,0 +1,110 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Cache; + +use Symfony\Component\Filesystem\Exception\IOException; + +/** + * @author Andreas Möller <am@localheinz.com> + * + * @internal + */ +final class FileHandler implements FileHandlerInterface +{ + /** + * @var string + */ + private $file; + + /** + * @param string $file + */ + public function __construct($file) + { + $this->file = $file; + } + + public function getFile() + { + return $this->file; + } + + public function read() + { + if (!file_exists($this->file)) { + return null; + } + + $content = file_get_contents($this->file); + + try { + $cache = Cache::fromJson($content); + } catch (\InvalidArgumentException $exception) { + return null; + } + + return $cache; + } + + public function write(CacheInterface $cache) + { + $content = $cache->toJson(); + + if (file_exists($this->file)) { + if (is_dir($this->file)) { + throw new IOException( + sprintf('Cannot write cache file "%s" as the location exists as directory.', realpath($this->file)), + 0, + null, + $this->file + ); + } + + if (!is_writable($this->file)) { + throw new IOException( + sprintf('Cannot write to file "%s" as it is not writable.', realpath($this->file)), + 0, + null, + $this->file + ); + } + } else { + $dir = \dirname($this->file); + + if (!is_dir($dir)) { + throw new IOException( + sprintf('Directory of cache file "%s" does not exists.', $this->file), + 0, + null, + $this->file + ); + } + + @touch($this->file); + @chmod($this->file, 0666); + } + + $bytesWritten = @file_put_contents($this->file, $content); + + if (false === $bytesWritten) { + $error = error_get_last(); + + throw new IOException( + sprintf('Failed to write file "%s", "%s".', $this->file, isset($error['message']) ? $error['message'] : 'no reason available'), + 0, + null, + $this->file + ); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Cache/FileHandlerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/FileHandlerInterface.php new file mode 100644 index 0000000..29ff5c9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/FileHandlerInterface.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Cache; + +/** + * @author Andreas Möller <am@localheinz.com> + * + * @internal + */ +interface FileHandlerInterface +{ + /** + * @return string + */ + public function getFile(); + + /** + * @return null|CacheInterface + */ + public function read(); + + public function write(CacheInterface $cache); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Cache/NullCacheManager.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/NullCacheManager.php new file mode 100644 index 0000000..74f3b62 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/NullCacheManager.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Cache; + +/** + * @author Andreas Möller <am@localheinz.com> + * + * @internal + */ +final class NullCacheManager implements CacheManagerInterface +{ + public function needFixing($file, $fileContent) + { + return true; + } + + public function setFile($file, $fileContent) + { + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Cache/Signature.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/Signature.php new file mode 100644 index 0000000..1af7a3f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/Signature.php @@ -0,0 +1,110 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Cache; + +/** + * @author Andreas Möller <am@localheinz.com> + * + * @internal + */ +final class Signature implements SignatureInterface +{ + /** + * @var string + */ + private $phpVersion; + + /** + * @var string + */ + private $fixerVersion; + + /** + * @var string + */ + private $indent; + + /** + * @var string + */ + private $lineEnding; + + /** + * @var array + */ + private $rules; + + /** + * @param string $phpVersion + * @param string $fixerVersion + * @param string $indent + * @param string $lineEnding + */ + public function __construct($phpVersion, $fixerVersion, $indent, $lineEnding, array $rules) + { + $this->phpVersion = $phpVersion; + $this->fixerVersion = $fixerVersion; + $this->indent = $indent; + $this->lineEnding = $lineEnding; + $this->rules = self::utf8Encode($rules); + } + + public function getPhpVersion() + { + return $this->phpVersion; + } + + public function getFixerVersion() + { + return $this->fixerVersion; + } + + public function getIndent() + { + return $this->indent; + } + + public function getLineEnding() + { + return $this->lineEnding; + } + + public function getRules() + { + return $this->rules; + } + + public function equals(SignatureInterface $signature) + { + return $this->phpVersion === $signature->getPhpVersion() + && $this->fixerVersion === $signature->getFixerVersion() + && $this->indent === $signature->getIndent() + && $this->lineEnding === $signature->getLineEnding() + && $this->rules === $signature->getRules(); + } + + private static function utf8Encode(array $data) + { + if (!\function_exists('mb_detect_encoding')) { + return $data; + } + + array_walk_recursive($data, static function (&$item) { + if (\is_string($item) && !mb_detect_encoding($item, 'utf-8', true)) { + $item = utf8_encode($item); + } + }); + + return $data; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Cache/SignatureInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Cache/SignatureInterface.php new file mode 100644 index 0000000..5a7131e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Cache/SignatureInterface.php @@ -0,0 +1,53 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Cache; + +/** + * @author Andreas Möller <am@localheinz.com> + * + * @internal + */ +interface SignatureInterface +{ + /** + * @return string + */ + public function getPhpVersion(); + + /** + * @return string + */ + public function getFixerVersion(); + + /** + * @return string + */ + public function getIndent(); + + /** + * @return string + */ + public function getLineEnding(); + + /** + * @return array + */ + public function getRules(); + + /** + * @param SignatureInterface $signature + * + * @return bool + */ + public function equals(self $signature); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Config.php b/vendor/friendsofphp/php-cs-fixer/src/Config.php new file mode 100644 index 0000000..8c0b4be --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Config.php @@ -0,0 +1,331 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Fixer\FixerInterface; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * @author Katsuhiro Ogawa <ko.fivestar@gmail.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +class Config implements ConfigInterface +{ + /** + * @var string + */ + private $cacheFile = '.php_cs.cache'; + + /** + * @var FixerInterface[] + */ + private $customFixers = []; + + /** + * @var null|iterable + */ + private $finder; + + /** + * @var string + */ + private $format = 'txt'; + + /** + * @var bool + */ + private $hideProgress = false; + + /** + * @var string + */ + private $indent = ' '; + + /** + * @var bool + */ + private $isRiskyAllowed = false; + + /** + * @var string + */ + private $lineEnding = "\n"; + + /** + * @var string + */ + private $name; + + /** + * @var null|string + */ + private $phpExecutable; + + /** + * @var array + */ + private $rules = ['@PSR2' => true]; + + /** + * @var bool + */ + private $usingCache = true; + + public function __construct($name = 'default') + { + $this->name = $name; + } + + /** + * @return static + * + * @deprecated since 2.17 + */ + public static function create() + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated since 2.17 and will be removed in 3.0, use the constructor instead.')); + + return new static(); + } + + /** + * {@inheritdoc} + */ + public function getCacheFile() + { + return $this->cacheFile; + } + + /** + * {@inheritdoc} + */ + public function getCustomFixers() + { + return $this->customFixers; + } + + /** + * @return Finder + */ + public function getFinder() + { + if (null === $this->finder) { + $this->finder = new Finder(); + } + + return $this->finder; + } + + /** + * {@inheritdoc} + */ + public function getFormat() + { + return $this->format; + } + + /** + * {@inheritdoc} + */ + public function getHideProgress() + { + return $this->hideProgress; + } + + /** + * {@inheritdoc} + */ + public function getIndent() + { + return $this->indent; + } + + /** + * {@inheritdoc} + */ + public function getLineEnding() + { + return $this->lineEnding; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function getPhpExecutable() + { + return $this->phpExecutable; + } + + /** + * {@inheritdoc} + */ + public function getRiskyAllowed() + { + return $this->isRiskyAllowed; + } + + /** + * {@inheritdoc} + */ + public function getRules() + { + return $this->rules; + } + + /** + * {@inheritdoc} + */ + public function getUsingCache() + { + return $this->usingCache; + } + + /** + * {@inheritdoc} + */ + public function registerCustomFixers($fixers) + { + if (false === \is_array($fixers) && false === $fixers instanceof \Traversable) { + throw new \InvalidArgumentException(sprintf( + 'Argument must be an array or a Traversable, got "%s".', + \is_object($fixers) ? \get_class($fixers) : \gettype($fixers) + )); + } + + foreach ($fixers as $fixer) { + $this->addCustomFixer($fixer); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setCacheFile($cacheFile) + { + $this->cacheFile = $cacheFile; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setFinder($finder) + { + if (false === \is_array($finder) && false === $finder instanceof \Traversable) { + throw new \InvalidArgumentException(sprintf( + 'Argument must be an array or a Traversable, got "%s".', + \is_object($finder) ? \get_class($finder) : \gettype($finder) + )); + } + + $this->finder = $finder; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setFormat($format) + { + $this->format = $format; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setHideProgress($hideProgress) + { + $this->hideProgress = $hideProgress; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setIndent($indent) + { + $this->indent = $indent; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setLineEnding($lineEnding) + { + $this->lineEnding = $lineEnding; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setPhpExecutable($phpExecutable) + { + $this->phpExecutable = $phpExecutable; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setRiskyAllowed($isRiskyAllowed) + { + $this->isRiskyAllowed = $isRiskyAllowed; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setRules(array $rules) + { + $this->rules = $rules; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setUsingCache($usingCache) + { + $this->usingCache = $usingCache; + + return $this; + } + + private function addCustomFixer(FixerInterface $fixer) + { + $this->customFixers[] = $fixer; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/ConfigInterface.php b/vendor/friendsofphp/php-cs-fixer/src/ConfigInterface.php new file mode 100644 index 0000000..a4bb9be --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/ConfigInterface.php @@ -0,0 +1,196 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Fixer\FixerInterface; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +interface ConfigInterface +{ + /** + * Returns the path to the cache file. + * + * @return null|string Returns null if not using cache + */ + public function getCacheFile(); + + /** + * Returns the custom fixers to use. + * + * @return FixerInterface[] + */ + public function getCustomFixers(); + + /** + * Returns files to scan. + * + * @return iterable|\Traversable + */ + public function getFinder(); + + /** + * @return string + */ + public function getFormat(); + + /** + * Returns true if progress should be hidden. + * + * @return bool + */ + public function getHideProgress(); + + /** + * @return string + */ + public function getIndent(); + + /** + * @return string + */ + public function getLineEnding(); + + /** + * Returns the name of the configuration. + * + * The name must be all lowercase and without any spaces. + * + * @return string The name of the configuration + */ + public function getName(); + + /** + * Get configured PHP executable, if any. + * + * @return null|string + */ + public function getPhpExecutable(); + + /** + * Check if it is allowed to run risky fixers. + * + * @return bool + */ + public function getRiskyAllowed(); + + /** + * Get rules. + * + * Keys of array are names of fixers/sets, values are true/false. + * + * @return array + */ + public function getRules(); + + /** + * Returns true if caching should be enabled. + * + * @return bool + */ + public function getUsingCache(); + + /** + * Adds a suite of custom fixers. + * + * Name of custom fixer should follow `VendorName/rule_name` convention. + * + * @param FixerInterface[]|iterable|\Traversable $fixers + * + * @return self + */ + public function registerCustomFixers($fixers); + + /** + * Sets the path to the cache file. + * + * @param string $cacheFile + * + * @return self + */ + public function setCacheFile($cacheFile); + + /** + * @param iterable|string[]|\Traversable $finder + * + * @return self + */ + public function setFinder($finder); + + /** + * @param string $format + * + * @return self + */ + public function setFormat($format); + + /** + * @param bool $hideProgress + * + * @return self + */ + public function setHideProgress($hideProgress); + + /** + * @param string $indent + * + * @return self + */ + public function setIndent($indent); + + /** + * @param string $lineEnding + * + * @return self + */ + public function setLineEnding($lineEnding); + + /** + * Set PHP executable. + * + * @param null|string $phpExecutable + * + * @return self + */ + public function setPhpExecutable($phpExecutable); + + /** + * Set if it is allowed to run risky fixers. + * + * @param bool $isRiskyAllowed + * + * @return self + */ + public function setRiskyAllowed($isRiskyAllowed); + + /** + * Set rules. + * + * Keys of array are names of fixers or sets. + * Value for set must be bool (turn it on or off). + * Value for fixer may be bool (turn it on or off) or array of configuration + * (turn it on and contains configuration for FixerInterface::configure method). + * + * @return self + */ + public function setRules(array $rules); + + /** + * @param bool $usingCache + * + * @return self + */ + public function setUsingCache($usingCache); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidConfigurationException.php b/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidConfigurationException.php new file mode 100644 index 0000000..3c4e439 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidConfigurationException.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\ConfigurationException; + +use PhpCsFixer\Console\Command\FixCommandExitStatusCalculator; + +/** + * Exceptions of this type are thrown on misconfiguration of the Fixer. + * + * @author SpacePossum + * + * @internal + * @final Only internal extending this class is supported + */ +class InvalidConfigurationException extends \InvalidArgumentException +{ + /** + * @param string $message + * @param null|int $code + * @param null|\Throwable $previous + */ + public function __construct($message, $code = null, $previous = null) + { + parent::__construct( + $message, + null === $code ? FixCommandExitStatusCalculator::EXIT_STATUS_FLAG_HAS_INVALID_CONFIG : $code, + $previous + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidFixerConfigurationException.php b/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidFixerConfigurationException.php new file mode 100644 index 0000000..b5c3322 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidFixerConfigurationException.php @@ -0,0 +1,54 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\ConfigurationException; + +use PhpCsFixer\Console\Command\FixCommandExitStatusCalculator; + +/** + * Exception thrown by Fixers on misconfiguration. + * + * @author SpacePossum + * + * @internal + * @final Only internal extending this class is supported + */ +class InvalidFixerConfigurationException extends InvalidConfigurationException +{ + /** + * @var string + */ + private $fixerName; + + /** + * @param string $fixerName + * @param string $message + * @param null|\Throwable $previous + */ + public function __construct($fixerName, $message, $previous = null) + { + parent::__construct( + sprintf('[%s] %s', $fixerName, $message), + FixCommandExitStatusCalculator::EXIT_STATUS_FLAG_HAS_INVALID_FIXER_CONFIG, + $previous + ); + $this->fixerName = $fixerName; + } + + /** + * @return string + */ + public function getFixerName() + { + return $this->fixerName; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidForEnvFixerConfigurationException.php b/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidForEnvFixerConfigurationException.php new file mode 100644 index 0000000..5cb0efb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/InvalidForEnvFixerConfigurationException.php @@ -0,0 +1,22 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\ConfigurationException; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class InvalidForEnvFixerConfigurationException extends InvalidFixerConfigurationException +{ +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/RequiredFixerConfigurationException.php b/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/RequiredFixerConfigurationException.php new file mode 100644 index 0000000..d7645db --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/ConfigurationException/RequiredFixerConfigurationException.php @@ -0,0 +1,22 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\ConfigurationException; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class RequiredFixerConfigurationException extends InvalidFixerConfigurationException +{ +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Application.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Application.php new file mode 100644 index 0000000..af2ce50 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Application.php @@ -0,0 +1,148 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console; + +use PhpCsFixer\Console\Command\DescribeCommand; +use PhpCsFixer\Console\Command\FixCommand; +use PhpCsFixer\Console\Command\HelpCommand; +use PhpCsFixer\Console\Command\ListFilesCommand; +use PhpCsFixer\Console\Command\ListSetsCommand; +use PhpCsFixer\Console\Command\SelfUpdateCommand; +use PhpCsFixer\Console\SelfUpdate\GithubClient; +use PhpCsFixer\Console\SelfUpdate\NewVersionChecker; +use PhpCsFixer\PharChecker; +use PhpCsFixer\ToolInfo; +use PhpCsFixer\Utils; +use Symfony\Component\Console\Application as BaseApplication; +use Symfony\Component\Console\Command\ListCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class Application extends BaseApplication +{ + const VERSION = '2.19.3'; + const VERSION_CODENAME = 'Testament'; + + /** + * @var ToolInfo + */ + private $toolInfo; + + public function __construct() + { + if (!getenv('PHP_CS_FIXER_FUTURE_MODE')) { + error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED); + } + + parent::__construct('PHP CS Fixer', self::VERSION); + + $this->toolInfo = new ToolInfo(); + + // in alphabetical order + $this->add(new DescribeCommand()); + $this->add(new FixCommand($this->toolInfo)); + $this->add(new ListFilesCommand($this->toolInfo)); + $this->add(new ListSetsCommand()); + $this->add(new SelfUpdateCommand( + new NewVersionChecker(new GithubClient()), + $this->toolInfo, + new PharChecker() + )); + } + + /** + * @return int + */ + public static function getMajorVersion() + { + return (int) explode('.', self::VERSION)[0]; + } + + /** + * {@inheritdoc} + */ + public function doRun(InputInterface $input, OutputInterface $output) + { + $stdErr = $output instanceof ConsoleOutputInterface + ? $output->getErrorOutput() + : ($input->hasParameterOption('--format', true) && 'txt' !== $input->getParameterOption('--format', null, true) ? null : $output) + ; + + if (null !== $stdErr) { + $warningsDetector = new WarningsDetector($this->toolInfo); + $warningsDetector->detectOldVendor(); + $warningsDetector->detectOldMajor(); + $warnings = $warningsDetector->getWarnings(); + + if ($warnings) { + foreach ($warnings as $warning) { + $stdErr->writeln(sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', $warning)); + } + $stdErr->writeln(''); + } + } + + $result = parent::doRun($input, $output); + + if ( + null !== $stdErr + && $output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE + ) { + $triggeredDeprecations = Utils::getTriggeredDeprecations(); + if ($triggeredDeprecations) { + $stdErr->writeln(''); + $stdErr->writeln($stdErr->isDecorated() ? '<bg=yellow;fg=black;>Detected deprecations in use:</>' : 'Detected deprecations in use:'); + foreach ($triggeredDeprecations as $deprecation) { + $stdErr->writeln(sprintf('- %s', $deprecation)); + } + } + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function getLongVersion() + { + $version = implode('', [ + parent::getLongVersion(), + self::VERSION_CODENAME ? sprintf(' <info>%s</info>', self::VERSION_CODENAME) : '', // @phpstan-ignore-line to avoid `Ternary operator condition is always true|false.` + ' by <comment>Fabien Potencier</comment> and <comment>Dariusz Ruminski</comment>', + ]); + + $commit = '@git-commit@'; + + if ('@'.'git-commit@' !== $commit) { // @phpstan-ignore-line as `$commit` is replaced during phar building + $version .= ' ('.substr($commit, 0, 7).')'; + } + + return $version; + } + + /** + * {@inheritdoc} + */ + protected function getDefaultCommands() + { + return [new HelpCommand(), new ListCommand()]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Command/DescribeCommand.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/DescribeCommand.php new file mode 100644 index 0000000..e4b2ccb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/DescribeCommand.php @@ -0,0 +1,468 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Command; + +use PhpCsFixer\Differ\DiffConsoleFormatter; +use PhpCsFixer\Differ\FullDiffer; +use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\DefinedFixerInterface; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\FixerConfiguration\AliasedFixerOption; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\DeprecatedFixerOption; +use PhpCsFixer\FixerDefinition\CodeSampleInterface; +use PhpCsFixer\FixerDefinition\FileSpecificCodeSampleInterface; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSampleInterface; +use PhpCsFixer\FixerFactory; +use PhpCsFixer\Preg; +use PhpCsFixer\RuleSet\RuleSets; +use PhpCsFixer\StdinFileInfo; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Utils; +use PhpCsFixer\WordMatcher; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + * + * @internal + */ +final class DescribeCommand extends Command +{ + /** + * @var string + */ + protected static $defaultName = 'describe'; + + /** + * @var string[] + */ + private $setNames; + + /** + * @var FixerFactory + */ + private $fixerFactory; + + /** + * @var array<string, FixerInterface> + */ + private $fixers; + + public function __construct(FixerFactory $fixerFactory = null) + { + parent::__construct(); + + if (null === $fixerFactory) { + $fixerFactory = new FixerFactory(); + $fixerFactory->registerBuiltInFixers(); + } + + $this->fixerFactory = $fixerFactory; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition( + [ + new InputArgument('name', InputArgument::REQUIRED, 'Name of rule / set.'), + ] + ) + ->setDescription('Describe rule / ruleset.') + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity() && $output instanceof ConsoleOutputInterface) { + $stdErr = $output->getErrorOutput(); + $stdErr->writeln($this->getApplication()->getLongVersion()); + $stdErr->writeln(sprintf('Runtime: <info>PHP %s</info>', PHP_VERSION)); + } + + $name = $input->getArgument('name'); + + try { + if ('@' === $name[0]) { + $this->describeSet($output, $name); + + return 0; + } + + $this->describeRule($output, $name); + } catch (DescribeNameNotFoundException $e) { + $matcher = new WordMatcher( + 'set' === $e->getType() ? $this->getSetNames() : array_keys($this->getFixers()) + ); + + $alternative = $matcher->match($name); + + $this->describeList($output, $e->getType()); + + throw new \InvalidArgumentException(sprintf( + '%s "%s" not found.%s', + ucfirst($e->getType()), + $name, + null === $alternative ? '' : ' Did you mean "'.$alternative.'"?' + )); + } + + return 0; + } + + /** + * @param string $name + */ + private function describeRule(OutputInterface $output, $name) + { + $fixers = $this->getFixers(); + + if (!isset($fixers[$name])) { + throw new DescribeNameNotFoundException($name, 'rule'); + } + + /** @var FixerInterface $fixer */ + $fixer = $fixers[$name]; + + if ($fixer instanceof DefinedFixerInterface) { + $definition = $fixer->getDefinition(); + } else { + $definition = new FixerDefinition('Description is not available.', []); + } + + $description = $definition->getSummary(); + + if ($fixer instanceof DeprecatedFixerInterface) { + $successors = $fixer->getSuccessorsNames(); + $message = [] === $successors + ? 'will be removed on next major version' + : sprintf('use %s instead', Utils::naturalLanguageJoinWithBackticks($successors)); + $message = Preg::replace('/(`.+?`)/', '<info>$1</info>', $message); + $description .= sprintf(' <error>DEPRECATED</error>: %s.', $message); + } + + $output->writeln(sprintf('<info>Description of</info> %s <info>rule</info>.', $name)); + + if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { + $output->writeln(sprintf('Fixer class: <comment>%s</comment>.', \get_class($fixer))); + } + + $output->writeln($description); + + if ($definition->getDescription()) { + $output->writeln($definition->getDescription()); + } + + $output->writeln(''); + + if ($fixer->isRisky()) { + $output->writeln('<error>Fixer applying this rule is risky.</error>'); + + if ($definition->getRiskyDescription()) { + $output->writeln($definition->getRiskyDescription()); + } + + $output->writeln(''); + } + + if ($fixer instanceof ConfigurationDefinitionFixerInterface) { + $configurationDefinition = $fixer->getConfigurationDefinition(); + $options = $configurationDefinition->getOptions(); + + $output->writeln(sprintf('Fixer is configurable using following option%s:', 1 === \count($options) ? '' : 's')); + + foreach ($options as $option) { + $line = '* <info>'.OutputFormatter::escape($option->getName()).'</info>'; + $allowed = HelpCommand::getDisplayableAllowedValues($option); + + if (null !== $allowed) { + foreach ($allowed as &$value) { + if ($value instanceof AllowedValueSubset) { + $value = 'a subset of <comment>'.HelpCommand::toString($value->getAllowedValues()).'</comment>'; + } else { + $value = '<comment>'.HelpCommand::toString($value).'</comment>'; + } + } + } else { + $allowed = array_map( + static function ($type) { + return '<comment>'.$type.'</comment>'; + }, + $option->getAllowedTypes() + ); + } + + if (null !== $allowed) { + $line .= ' ('.implode(', ', $allowed).')'; + } + + $description = Preg::replace('/(`.+?`)/', '<info>$1</info>', OutputFormatter::escape($option->getDescription())); + $line .= ': '.lcfirst(Preg::replace('/\.$/', '', $description)).'; '; + + if ($option->hasDefault()) { + $line .= sprintf( + 'defaults to <comment>%s</comment>', + HelpCommand::toString($option->getDefault()) + ); + } else { + $line .= '<comment>required</comment>'; + } + + if ($option instanceof DeprecatedFixerOption) { + $line .= '. <error>DEPRECATED</error>: '.Preg::replace( + '/(`.+?`)/', + '<info>$1</info>', + OutputFormatter::escape(lcfirst($option->getDeprecationMessage())) + ); + } + + if ($option instanceof AliasedFixerOption) { + $line .= '; <error>DEPRECATED</error> alias: <comment>'.$option->getAlias().'</comment>'; + } + + $output->writeln($line); + } + + $output->writeln(''); + } elseif ($fixer instanceof ConfigurableFixerInterface) { + $output->writeln('<comment>Fixer is configurable.</comment>'); + + if ($definition->getConfigurationDescription()) { + $output->writeln($definition->getConfigurationDescription()); + } + + if ($definition->getDefaultConfiguration()) { + $output->writeln(sprintf('Default configuration: <comment>%s</comment>.', HelpCommand::toString($definition->getDefaultConfiguration()))); + } + + $output->writeln(''); + } + + /** @var CodeSampleInterface[] $codeSamples */ + $codeSamples = array_filter($definition->getCodeSamples(), static function (CodeSampleInterface $codeSample) { + if ($codeSample instanceof VersionSpecificCodeSampleInterface) { + return $codeSample->isSuitableFor(\PHP_VERSION_ID); + } + + return true; + }); + + if (!\count($codeSamples)) { + $output->writeln([ + 'Fixing examples can not be demonstrated on the current PHP version.', + '', + ]); + } else { + $output->writeln('Fixing examples:'); + + $differ = new FullDiffer(); + $diffFormatter = new DiffConsoleFormatter( + $output->isDecorated(), + sprintf( + '<comment> ---------- begin diff ----------</comment>%s%%s%s<comment> ----------- end diff -----------</comment>', + PHP_EOL, + PHP_EOL + ) + ); + + foreach ($codeSamples as $index => $codeSample) { + $old = $codeSample->getCode(); + $tokens = Tokens::fromCode($old); + + $configuration = $codeSample->getConfiguration(); + + if ($fixer instanceof ConfigurableFixerInterface) { + $fixer->configure(null === $configuration ? [] : $configuration); + } + + $file = $codeSample instanceof FileSpecificCodeSampleInterface + ? $codeSample->getSplFileInfo() + : new StdinFileInfo(); + + $fixer->fix($file, $tokens); + + $diff = $differ->diff($old, $tokens->generateCode()); + + if ($fixer instanceof ConfigurableFixerInterface) { + if (null === $configuration) { + $output->writeln(sprintf(' * Example #%d. Fixing with the <comment>default</comment> configuration.', $index + 1)); + } else { + $output->writeln(sprintf(' * Example #%d. Fixing with configuration: <comment>%s</comment>.', $index + 1, HelpCommand::toString($codeSample->getConfiguration()))); + } + } else { + $output->writeln(sprintf(' * Example #%d.', $index + 1)); + } + + $output->writeln([$diffFormatter->format($diff, ' %s'), '']); + } + } + } + + /** + * @param string $name + */ + private function describeSet(OutputInterface $output, $name) + { + if (!\in_array($name, $this->getSetNames(), true)) { + throw new DescribeNameNotFoundException($name, 'set'); + } + + $ruleSetDefinitions = RuleSets::getSetDefinitions(); + $fixers = $this->getFixers(); + + $output->writeln(sprintf('<info>Description of the</info> %s <info>set.</info>', $ruleSetDefinitions[$name]->getName())); + $output->writeln($this->replaceRstLinks($ruleSetDefinitions[$name]->getDescription())); + + if ($ruleSetDefinitions[$name]->isRisky()) { + $output->writeln('This set contains <error>risky</error> rules.'); + } + + $output->writeln(''); + + $help = ''; + + foreach ($ruleSetDefinitions[$name]->getRules() as $rule => $config) { + if ('@' === $rule[0]) { + $set = $ruleSetDefinitions[$rule]; + $help .= sprintf( + " * <info>%s</info>%s\n | %s\n\n", + $rule, + $set->isRisky() ? ' <error>risky</error>' : '', + $this->replaceRstLinks($set->getDescription()) + ); + + continue; + } + + $fixer = $fixers[$rule]; + + if (!$fixer instanceof DefinedFixerInterface) { + throw new \RuntimeException(sprintf( + 'Cannot describe rule %s, the fixer does not implement "%s".', + $rule, + DefinedFixerInterface::class + )); + } + + $definition = $fixer->getDefinition(); + $help .= sprintf( + " * <info>%s</info>%s\n | %s\n%s\n", + $rule, + $fixer->isRisky() ? ' <error>risky</error>' : '', + $definition->getSummary(), + true !== $config ? sprintf(" <comment>| Configuration: %s</comment>\n", HelpCommand::toString($config)) : '' + ); + } + + $output->write($help); + } + + /** + * @return array<string, FixerInterface> + */ + private function getFixers() + { + if (null !== $this->fixers) { + return $this->fixers; + } + + $fixers = []; + + foreach ($this->fixerFactory->getFixers() as $fixer) { + $fixers[$fixer->getName()] = $fixer; + } + + $this->fixers = $fixers; + ksort($this->fixers); + + return $this->fixers; + } + + /** + * @return string[] + */ + private function getSetNames() + { + if (null !== $this->setNames) { + return $this->setNames; + } + + $this->setNames = RuleSets::getSetDefinitionNames(); + + return $this->setNames; + } + + /** + * @param string $type 'rule'|'set' + */ + private function describeList(OutputInterface $output, $type) + { + if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) { + $describe = [ + 'sets' => $this->getSetNames(), + 'rules' => $this->getFixers(), + ]; + } elseif ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { + $describe = 'set' === $type ? ['sets' => $this->getSetNames()] : ['rules' => $this->getFixers()]; + } else { + return; + } + + /** @var string[] $items */ + foreach ($describe as $list => $items) { + $output->writeln(sprintf('<comment>Defined %s:</comment>', $list)); + + foreach ($items as $name => $item) { + $output->writeln(sprintf('* <info>%s</info>', \is_string($name) ? $name : $item)); + } + } + } + + /** + * @param string $content + * + * @return string + */ + private function replaceRstLinks($content) + { + return Preg::replaceCallback( + '/(`[^<]+<[^>]+>`_)/', + static function (array $matches) { + return Preg::replaceCallback( + '/`(.*)<(.*)>`_/', + static function (array $matches) { + return $matches[1].'('.$matches[2].')'; + }, + $matches[1] + ); + }, + $content + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Command/DescribeNameNotFoundException.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/DescribeNameNotFoundException.php new file mode 100644 index 0000000..bfe5c0b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/DescribeNameNotFoundException.php @@ -0,0 +1,59 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Command; + +/** + * @author SpacePossum + * + * @internal + */ +final class DescribeNameNotFoundException extends \InvalidArgumentException +{ + /** + * @var string + */ + private $name; + + /** + * @var string 'rule'|'set' + */ + private $type; + + /** + * @param string $name + * @param string $type + */ + public function __construct($name, $type) + { + $this->name = $name; + $this->type = $type; + + parent::__construct(); + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Command/DocumentationCommand.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/DocumentationCommand.php new file mode 100644 index 0000000..205d93a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/DocumentationCommand.php @@ -0,0 +1,124 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Command; + +use PhpCsFixer\Documentation\DocumentationGenerator; +use PhpCsFixer\FixerFactory; +use PhpCsFixer\RuleSet\RuleSets; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Finder\Finder; +use Symfony\Component\Finder\SplFileInfo; + +/** + * @internal + */ +final class DocumentationCommand extends Command +{ + /** + * @var string + */ + protected static $defaultName = 'documentation'; + + /** + * @var DocumentationGenerator + */ + private $generator; + + public function __construct($name = null) + { + parent::__construct($name); + + $this->generator = new DocumentationGenerator(); + } + + protected function configure() + { + $this + ->setAliases(['doc']) + ->setDescription('Dumps the documentation of the project into its /doc directory.') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $fixerFactory = new FixerFactory(); + $fixerFactory->registerBuiltInFixers(); + $fixers = $fixerFactory->getFixers(); + + $this->generateFixersDocs($fixers); + $this->generateRuleSetsDocs($fixers); + + $output->writeln('Docs updated.'); + + return 0; + } + + private function generateFixersDocs(array $fixers) + { + $filesystem = new Filesystem(); + + // Array of existing fixer docs. + // We first override existing files, and then we will delete files that are no longer needed. + // We cannot remove all files first, as generation of docs is re-using existing docs to extract code-samples for + // VersionSpecificCodeSample under incompatible PHP version. + $docForFixerRelativePaths = []; + + foreach ($fixers as $fixer) { + $docForFixerRelativePaths[] = $this->generator->getFixerDocumentationFileRelativePath($fixer); + $filesystem->dumpFile( + $this->generator->getFixerDocumentationFilePath($fixer), + $this->generator->generateFixerDocumentation($fixer) + ); + } + + /** @var SplFileInfo $file */ + foreach ( + (new Finder())->files() + ->in($this->generator->getFixersDocumentationDirectoryPath()) + ->notPath($docForFixerRelativePaths) as $file + ) { + $filesystem->remove($file->getPathname()); + } + + $index = $this->generator->getFixersDocumentationIndexFilePath(); + + if (false === @file_put_contents($index, $this->generator->generateFixersDocumentationIndex($fixers))) { + throw new \RuntimeException("Failed updating file {$index}."); + } + } + + private function generateRuleSetsDocs(array $fixers) + { + $filesystem = new Filesystem(); + + /** @var SplFileInfo $file */ + foreach ((new Finder())->files()->in($this->generator->getRuleSetsDocumentationDirectoryPath()) as $file) { + $filesystem->remove($file->getPathname()); + } + + $index = $this->generator->getRuleSetsDocumentationIndexFilePath(); + $paths = []; + + foreach (RuleSets::getSetDefinitions() as $name => $definition) { + $paths[$name] = $path = $this->generator->getRuleSetsDocumentationFilePath($name); + $filesystem->dumpFile($path, $this->generator->generateRuleSetsDocumentation($definition, $fixers)); + } + + if (false === @file_put_contents($index, $this->generator->generateRuleSetsDocumentationIndex($paths))) { + throw new \RuntimeException("Failed updating file {$index}."); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Command/FixCommand.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/FixCommand.php new file mode 100644 index 0000000..541fd8a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/FixCommand.php @@ -0,0 +1,279 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Command; + +use PhpCsFixer\Config; +use PhpCsFixer\ConfigInterface; +use PhpCsFixer\Console\ConfigurationResolver; +use PhpCsFixer\Console\Output\ErrorOutput; +use PhpCsFixer\Console\Output\NullOutput; +use PhpCsFixer\Console\Output\ProcessOutput; +use PhpCsFixer\Console\Report\FixReport\ReportSummary; +use PhpCsFixer\Error\ErrorsManager; +use PhpCsFixer\Runner\Runner; +use PhpCsFixer\ToolInfoInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Terminal; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FixCommand extends Command +{ + /** + * @var string + */ + protected static $defaultName = 'fix'; + + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * @var ErrorsManager + */ + private $errorsManager; + + /** + * @var Stopwatch + */ + private $stopwatch; + + /** + * @var ConfigInterface + */ + private $defaultConfig; + + /** + * @var ToolInfoInterface + */ + private $toolInfo; + + public function __construct(ToolInfoInterface $toolInfo) + { + parent::__construct(); + + $this->defaultConfig = new Config(); + $this->errorsManager = new ErrorsManager(); + $this->eventDispatcher = new EventDispatcher(); + $this->stopwatch = new Stopwatch(); + $this->toolInfo = $toolInfo; + } + + /** + * {@inheritdoc} + * + * Override here to only generate the help copy when used. + */ + public function getHelp() + { + return HelpCommand::getHelpCopy(); + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition( + [ + new InputArgument('path', InputArgument::IS_ARRAY, 'The path.'), + new InputOption('path-mode', '', InputOption::VALUE_REQUIRED, 'Specify path mode (can be override or intersection).', ConfigurationResolver::PATH_MODE_OVERRIDE), + new InputOption('allow-risky', '', InputOption::VALUE_REQUIRED, 'Are risky fixers allowed (can be yes or no).'), + new InputOption('config', '', InputOption::VALUE_REQUIRED, 'The path to a .php-cs-fixer.php file.'), + new InputOption('dry-run', '', InputOption::VALUE_NONE, 'Only shows which files would have been modified.'), + new InputOption('rules', '', InputOption::VALUE_REQUIRED, 'The rules.'), + new InputOption('using-cache', '', InputOption::VALUE_REQUIRED, 'Does cache should be used (can be yes or no).'), + new InputOption('cache-file', '', InputOption::VALUE_REQUIRED, 'The path to the cache file.'), + new InputOption('diff', '', InputOption::VALUE_NONE, 'Also produce diff for each file.'), + new InputOption('diff-format', '', InputOption::VALUE_REQUIRED, 'Specify diff format.'), + new InputOption('format', '', InputOption::VALUE_REQUIRED, 'To output results in other formats.'), + new InputOption('stop-on-violation', '', InputOption::VALUE_NONE, 'Stop execution on first violation.'), + new InputOption('show-progress', '', InputOption::VALUE_REQUIRED, 'Type of progress indicator (none, run-in, estimating, estimating-max or dots).'), + ] + ) + ->setDescription('Fixes a directory or a file.') + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $verbosity = $output->getVerbosity(); + + $passedConfig = $input->getOption('config'); + $passedRules = $input->getOption('rules'); + + $resolver = new ConfigurationResolver( + $this->defaultConfig, + [ + 'allow-risky' => $input->getOption('allow-risky'), + 'config' => $passedConfig, + 'dry-run' => $input->getOption('dry-run'), + 'rules' => $passedRules, + 'path' => $input->getArgument('path'), + 'path-mode' => $input->getOption('path-mode'), + 'using-cache' => $input->getOption('using-cache'), + 'cache-file' => $input->getOption('cache-file'), + 'format' => $input->getOption('format'), + 'diff' => $input->getOption('diff'), + 'diff-format' => $input->getOption('diff-format'), + 'stop-on-violation' => $input->getOption('stop-on-violation'), + 'verbosity' => $verbosity, + 'show-progress' => $input->getOption('show-progress'), + ], + getcwd(), + $this->toolInfo + ); + + $reporter = $resolver->getReporter(); + + $stdErr = $output instanceof ConsoleOutputInterface + ? $output->getErrorOutput() + : ('txt' === $reporter->getFormat() ? $output : null) + ; + + if (null !== $stdErr) { + if (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) { + $stdErr->writeln($this->getApplication()->getLongVersion()); + $stdErr->writeln(sprintf('Runtime: <info>PHP %s</info>', PHP_VERSION)); + } + + if (null !== $passedConfig && null !== $passedRules) { + if (getenv('PHP_CS_FIXER_FUTURE_MODE')) { + throw new \RuntimeException('Passing both `config` and `rules` options is not possible. This check was performed as `PHP_CS_FIXER_FUTURE_MODE` env var is set.'); + } + + $stdErr->writeln([ + sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', 'When passing both "--config" and "--rules" the rules within the configuration file are not used.'), + sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', 'Passing both options is deprecated; version v3.0 PHP-CS-Fixer will exit with a configuration error code.'), + ]); + } + + $configFile = $resolver->getConfigFile(); + $stdErr->writeln(sprintf('Loaded config <comment>%s</comment>%s.', $resolver->getConfig()->getName(), null === $configFile ? '' : ' from "'.$configFile.'"')); + + if ($resolver->getUsingCache()) { + $cacheFile = $resolver->getCacheFile(); + + if (is_file($cacheFile)) { + $stdErr->writeln(sprintf('Using cache file "%s".', $cacheFile)); + } + } + } + + $progressType = $resolver->getProgress(); + $finder = $resolver->getFinder(); + + if (null !== $stdErr && $resolver->configFinderIsOverridden()) { + $stdErr->writeln( + sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', 'Paths from configuration file have been overridden by paths provided as command arguments.') + ); + } + + // @TODO 3.0 remove `run-in` and `estimating` + if ('none' === $progressType || null === $stdErr) { + $progressOutput = new NullOutput(); + } elseif ('run-in' === $progressType) { + $progressOutput = new ProcessOutput($stdErr, $this->eventDispatcher, null, null); + } else { + $finder = new \ArrayIterator(iterator_to_array($finder)); + $progressOutput = new ProcessOutput( + $stdErr, + $this->eventDispatcher, + 'estimating' !== $progressType ? (new Terminal())->getWidth() : null, + \count($finder) + ); + } + + $runner = new Runner( + $finder, + $resolver->getFixers(), + $resolver->getDiffer(), + 'none' !== $progressType ? $this->eventDispatcher : null, + $this->errorsManager, + $resolver->getLinter(), + $resolver->isDryRun(), + $resolver->getCacheManager(), + $resolver->getDirectory(), + $resolver->shouldStopOnViolation() + ); + + $this->stopwatch->start('fixFiles'); + $changed = $runner->fix(); + $this->stopwatch->stop('fixFiles'); + + $progressOutput->printLegend(); + + $fixEvent = $this->stopwatch->getEvent('fixFiles'); + + $reportSummary = new ReportSummary( + $changed, + $fixEvent->getDuration(), + $fixEvent->getMemory(), + OutputInterface::VERBOSITY_VERBOSE <= $verbosity, + $resolver->isDryRun(), + $output->isDecorated() + ); + + $output->isDecorated() + ? $output->write($reporter->generate($reportSummary)) + : $output->write($reporter->generate($reportSummary), false, OutputInterface::OUTPUT_RAW) + ; + + $invalidErrors = $this->errorsManager->getInvalidErrors(); + $exceptionErrors = $this->errorsManager->getExceptionErrors(); + $lintErrors = $this->errorsManager->getLintErrors(); + + if (null !== $stdErr) { + $errorOutput = new ErrorOutput($stdErr); + + if (\count($invalidErrors) > 0) { + $errorOutput->listErrors('linting before fixing', $invalidErrors); + } + + if (\count($exceptionErrors) > 0) { + $errorOutput->listErrors('fixing', $exceptionErrors); + } + + if (\count($lintErrors) > 0) { + $errorOutput->listErrors('linting after fixing', $lintErrors); + } + } + + $exitStatusCalculator = new FixCommandExitStatusCalculator(); + + return $exitStatusCalculator->calculate( + $resolver->isDryRun(), + \count($changed) > 0, + \count($invalidErrors) > 0, + \count($exceptionErrors) > 0, + \count($lintErrors) > 0 + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Command/FixCommandExitStatusCalculator.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/FixCommandExitStatusCalculator.php new file mode 100644 index 0000000..732ddd9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/FixCommandExitStatusCalculator.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Command; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FixCommandExitStatusCalculator +{ + // Exit status 1 is reserved for environment constraints not matched. + const EXIT_STATUS_FLAG_HAS_INVALID_FILES = 4; + const EXIT_STATUS_FLAG_HAS_CHANGED_FILES = 8; + const EXIT_STATUS_FLAG_HAS_INVALID_CONFIG = 16; + const EXIT_STATUS_FLAG_HAS_INVALID_FIXER_CONFIG = 32; + const EXIT_STATUS_FLAG_EXCEPTION_IN_APP = 64; + + /** + * @param bool $isDryRun + * @param bool $hasChangedFiles + * @param bool $hasInvalidErrors + * @param bool $hasExceptionErrors + * @param bool $hasLintErrorsAfterFixing + * + * @return int + */ + public function calculate($isDryRun, $hasChangedFiles, $hasInvalidErrors, $hasExceptionErrors, $hasLintErrorsAfterFixing) + { + $exitStatus = 0; + + if ($isDryRun) { + if ($hasChangedFiles) { + $exitStatus |= self::EXIT_STATUS_FLAG_HAS_CHANGED_FILES; + } + + if ($hasInvalidErrors) { + $exitStatus |= self::EXIT_STATUS_FLAG_HAS_INVALID_FILES; + } + } + + if ($hasExceptionErrors || $hasLintErrorsAfterFixing) { + $exitStatus |= self::EXIT_STATUS_FLAG_EXCEPTION_IN_APP; + } + + return $exitStatus; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Command/HelpCommand.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/HelpCommand.php new file mode 100644 index 0000000..96e7e77 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/HelpCommand.php @@ -0,0 +1,675 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Command; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Console\Application; +use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\FixerConfiguration\AliasedFixerOption; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\DeprecatedFixerOption; +use PhpCsFixer\FixerConfiguration\FixerOptionInterface; +use PhpCsFixer\FixerFactory; +use PhpCsFixer\Preg; +use PhpCsFixer\RuleSet\RuleSet; +use PhpCsFixer\RuleSet\RuleSets; +use PhpCsFixer\Utils; +use Symfony\Component\Console\Command\HelpCommand as BaseHelpCommand; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + * + * @internal + */ +final class HelpCommand extends BaseHelpCommand +{ + /** + * @var string + */ + protected static $defaultName = 'help'; + + /** + * Returns help-copy suitable for console output. + * + * @return string + */ + public static function getHelpCopy() + { + $template = + <<<'EOF' +The <info>%command.name%</info> command tries to fix as much coding standards +problems as possible on a given file or files in a given directory and its subdirectories: + + <info>$ php %command.full_name% /path/to/dir</info> + <info>$ php %command.full_name% /path/to/file</info> + +By default <comment>--path-mode</comment> is set to `override`, which means, that if you specify the path to a file or a directory via +command arguments, then the paths provided to a `Finder` in config file will be ignored. You can use <comment>--path-mode=intersection</comment> +to merge paths from the config file and from the argument: + + <info>$ php %command.full_name% --path-mode=intersection /path/to/dir</info> + +The <comment>--format</comment> option for the output format. Supported formats are `txt` (default one), `json`, `xml`, `checkstyle`, `junit` and `gitlab`. + +NOTE: the output for the following formats are generated in accordance with schemas + +* `checkstyle` follows the common `"checkstyle" XML schema </doc/schemas/fix/checkstyle.xsd>`_ +* `json` follows the `own JSON schema </doc/schemas/fix/schema.json>`_ +* `junit` follows the `JUnit XML schema from Jenkins </doc/schemas/fix/junit-10.xsd>`_ +* `xml` follows the `own XML schema </doc/schemas/fix/xml.xsd>`_ + +The <comment>--quiet</comment> Do not output any message. + +The <comment>--verbose</comment> option will show the applied rules. When using the `txt` format it will also display progress notifications. + +NOTE: if there is an error like "errors reported during linting after fixing", you can use this to be even more verbose for debugging purpose + +* `-v`: verbose +* `-vv`: very verbose +* `-vvv`: debug + +The <comment>--rules</comment> option limits the rules to apply to the +project: + + <info>$ php %command.full_name% /path/to/project --rules=@PSR2</info> + +By default the PSR1 and PSR2 rules are used. + +The <comment>--rules</comment> option lets you choose the exact rules to +apply (the rule names must be separated by a comma): + + <info>$ php %command.full_name% /path/to/dir --rules=line_ending,full_opening_tag,indentation_type</info> + +You can also exclude the rules you don't want by placing a dash in front of the rule name, if this is more convenient, +using <comment>-name_of_fixer</comment>: + + <info>$ php %command.full_name% /path/to/dir --rules=-full_opening_tag,-indentation_type</info> + +When using combinations of exact and exclude rules, applying exact rules along with above excluded results: + + <info>$ php %command.full_name% /path/to/project --rules=@Symfony,-@PSR1,-blank_line_before_statement,strict_comparison</info> + +Complete configuration for rules can be supplied using a `json` formatted string. + + <info>$ php %command.full_name% /path/to/project --rules='{"concat_space": {"spacing": "none"}}'</info> + +The <comment>--dry-run</comment> flag will run the fixer without making changes to your files. + +The <comment>--diff</comment> flag can be used to let the fixer output all the changes it makes. + +The <comment>--diff-format</comment> option allows to specify in which format the fixer should output the changes it makes: + +* <comment>udiff</comment>: unified diff format; +* <comment>sbd</comment>: Sebastianbergmann/diff format (default when using `--diff` without specifying `diff-format`). + +The <comment>--allow-risky</comment> option (pass `yes` or `no`) allows you to set whether risky rules may run. Default value is taken from config file. +A rule is considered risky if it could change code behaviour. By default no risky rules are run. + +The <comment>--stop-on-violation</comment> flag stops the execution upon first file that needs to be fixed. + +The <comment>--show-progress</comment> option allows you to choose the way process progress is rendered: + +* <comment>none</comment>: disables progress output; +* <comment>run-in</comment>: [deprecated] simple single-line progress output; +* <comment>estimating</comment>: [deprecated] multiline progress output with number of files and percentage on each line. Note that with this option, the files list is evaluated before processing to get the total number of files and then kept in memory to avoid using the file iterator twice. This has an impact on memory usage so using this option is not recommended on very large projects; +* <comment>estimating-max</comment>: [deprecated] same as <comment>dots</comment>; +* <comment>dots</comment>: same as <comment>estimating</comment> but using all terminal columns instead of default 80. + +If the option is not provided, it defaults to <comment>run-in</comment> unless a config file that disables output is used, in which case it defaults to <comment>none</comment>. This option has no effect if the verbosity of the command is less than <comment>verbose</comment>. + + <info>$ php %command.full_name% --verbose --show-progress=estimating</info> + +The command can also read from standard input, in which case it won't +automatically fix anything: + + <info>$ cat foo.php | php %command.full_name% --diff -</info> + +Finally, if you don't need BC kept on CLI level, you might use `PHP_CS_FIXER_FUTURE_MODE` to start using options that +would be default in next MAJOR release (unified differ, estimating, full-width progress indicator): + + <info>$ PHP_CS_FIXER_FUTURE_MODE=1 php %command.full_name% -v --diff</info> + +Rules +----- + +Use the following command to quickly understand what a rule will do to your code: + + <info>$ php php-cs-fixer.phar describe align_multiline_comment</info> + +To visualize all the rules that belong to a ruleset: + + <info>$ php php-cs-fixer.phar describe @PSR2</info> + +Choose from the list of available rules: + +%%%FIXERS_DETAILS%%% + +The <comment>--dry-run</comment> option displays the files that need to be +fixed but without actually modifying them: + + <info>$ php %command.full_name% /path/to/code --dry-run</info> + +Config file +----------- + +Instead of using command line options to customize the rule, you can save the +project configuration in a <comment>.php-cs-fixer.dist.php</comment> file in the root directory of your project. +The file must return an instance of `PhpCsFixer\ConfigInterface` (<url>%%%CONFIG_INTERFACE_URL%%%</url>) +which lets you configure the rules, the files and directories that +need to be analyzed. You may also create <comment>.php-cs-fixer.php</comment> file, which is +the local configuration that will be used instead of the project configuration. It +is a good practice to add that file into your <comment>.gitignore</comment> file. +With the <comment>--config</comment> option you can specify the path to the +<comment>.php-cs-fixer.php</comment> file. + +The example below will add two rules to the default list of PSR2 set rules: + + <?php + + $finder = PhpCsFixer\Finder::create() + ->exclude('somedir') + ->notPath('src/Symfony/Component/Translation/Tests/fixtures/resources.php') + ->in(__DIR__) + ; + + $config = new Config(); + + return $config + ->setRules([ + '@PSR2' => true, + 'strict_param' => true, + 'array_syntax' => ['syntax' => 'short'], + ]) + ->setFinder($finder) + ; + + ?> + +**NOTE**: `exclude` will work only for directories, so if you need to exclude file, try `notPath`. +Both `exclude` and `notPath` methods accept only relative paths to the ones defined with the `in` method. + +See `Symfony\Finder` (<url>https://symfony.com/doc/current/components/finder.html</url>) +online documentation for other `Finder` methods. + +You may also use an exclude list for the rules instead of the above shown include approach. +The following example shows how to use all `Symfony` rules but the `full_opening_tag` rule. + + <?php + + $finder = PhpCsFixer\Finder::create() + ->exclude('somedir') + ->in(__DIR__) + ; + + $config = new Config(); + + return $config + ->setRules([ + '@Symfony' => true, + 'full_opening_tag' => false, + ]) + ->setFinder($finder) + ; + + ?> + +You may want to use non-linux whitespaces in your project. Then you need to +configure them in your config file. + + <?php + + $config = new Config(); + + return $config + ->setIndent("\t") + ->setLineEnding("\r\n") + ; + + ?> + +By using `--using-cache` option with `yes` or `no` you can set if the caching +mechanism should be used. + +Caching +------- + +The caching mechanism is enabled by default. This will speed up further runs by +fixing only files that were modified since the last run. The tool will fix all +files if the tool version has changed or the list of rules has changed. +Cache is supported only for tool downloaded as phar file or installed via +composer. + +Cache can be disabled via `--using-cache` option or config file: + + <?php + + $config = new Config(); + + return $config->setUsingCache(false); + + ?> + +Cache file can be specified via `--cache-file` option or config file: + + <?php + + $config = new Config(); + + return $config->setCacheFile(__DIR__.'/.php_cs.cache'); + + ?> + +Using PHP CS Fixer on CI +------------------------ + +Require `friendsofphp/php-cs-fixer` as a `dev` dependency: + + $ ./composer.phar require --dev friendsofphp/php-cs-fixer + +Then, add the following command to your CI: + +%%%CI_INTEGRATION%%% + +Where `$COMMIT_RANGE` is your range of commits, e.g. `$TRAVIS_COMMIT_RANGE` or `HEAD~..HEAD`. + +Exit code +--------- + +Exit code of the fix command is built using following bit flags: + +* 0 - OK. +* 1 - General error (or PHP minimal requirement not matched). +* 4 - Some files have invalid syntax (only in dry-run mode). +* 8 - Some files need fixing (only in dry-run mode). +* 16 - Configuration error of the application. +* 32 - Configuration error of a Fixer. +* 64 - Exception raised within the application. + +EOF + ; + + return strtr($template, [ + '%%%CONFIG_INTERFACE_URL%%%' => sprintf( + 'https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/v%s/src/ConfigInterface.php', + self::getLatestReleaseVersionFromChangeLog() + ), + '%%%CI_INTEGRATION%%%' => implode("\n", array_map( + static function ($line) { return ' $ '.$line; }, + \array_slice(file(__DIR__.'/../../../ci-integration.sh', FILE_IGNORE_NEW_LINES), 3) + )), + '%%%FIXERS_DETAILS%%%' => self::getFixersHelp(), + ]); + } + + /** + * @param mixed $value + * + * @return string + */ + public static function toString($value) + { + return \is_array($value) + ? static::arrayToString($value) + : static::scalarToString($value) + ; + } + + /** + * Returns the allowed values of the given option that can be converted to a string. + * + * @return null|array + */ + public static function getDisplayableAllowedValues(FixerOptionInterface $option) + { + $allowed = $option->getAllowedValues(); + + if (null !== $allowed) { + $allowed = array_filter($allowed, static function ($value) { + return !($value instanceof \Closure); + }); + + usort($allowed, static function ($valueA, $valueB) { + if ($valueA instanceof AllowedValueSubset) { + return -1; + } + + if ($valueB instanceof AllowedValueSubset) { + return 1; + } + + return strcasecmp( + self::toString($valueA), + self::toString($valueB) + ); + }); + + if (0 === \count($allowed)) { + $allowed = null; + } + } + + return $allowed; + } + + /** + * @throws \RuntimeException when failing to parse the change log file + * + * @return string + */ + public static function getLatestReleaseVersionFromChangeLog() + { + static $version = null; + + if (null !== $version) { + return $version; + } + + $changelogFile = self::getChangeLogFile(); + if (null === $changelogFile) { + $version = Application::VERSION; + + return $version; + } + + $changelog = @file_get_contents($changelogFile); + if (false === $changelog) { + $error = error_get_last(); + + throw new \RuntimeException(sprintf( + 'Failed to read content of the changelog file "%s".%s', + $changelogFile, + $error ? ' '.$error['message'] : '' + )); + } + + for ($i = Application::getMajorVersion(); $i > 0; --$i) { + if (1 === Preg::match('/Changelog for v('.$i.'.\d+.\d+)/', $changelog, $matches)) { + $version = $matches[1]; + + break; + } + } + + if (null === $version) { + throw new \RuntimeException(sprintf('Failed to parse changelog data of "%s".', $changelogFile)); + } + + return $version; + } + + /** + * {@inheritdoc} + */ + protected function initialize(InputInterface $input, OutputInterface $output) + { + $output->getFormatter()->setStyle('url', new OutputFormatterStyle('blue')); + } + + /** + * @return null|string + */ + private static function getChangeLogFile() + { + $changelogFile = __DIR__.'/../../../CHANGELOG.md'; + + return is_file($changelogFile) ? $changelogFile : null; + } + + /** + * @return string + */ + private static function getFixersHelp() + { + $help = ''; + $fixerFactory = new FixerFactory(); + /** @var AbstractFixer[] $fixers */ + $fixers = $fixerFactory->registerBuiltInFixers()->getFixers(); + + // sort fixers by name + usort( + $fixers, + static function (FixerInterface $a, FixerInterface $b) { + return strcmp($a->getName(), $b->getName()); + } + ); + + $ruleSets = []; + foreach (RuleSets::getSetDefinitionNames() as $setName) { + $ruleSets[$setName] = new RuleSet([$setName => true]); + } + + $getSetsWithRule = static function ($rule) use ($ruleSets) { + $sets = []; + + foreach ($ruleSets as $setName => $ruleSet) { + if ($ruleSet->hasRule($rule)) { + $sets[] = $setName; + } + } + + return $sets; + }; + + $count = \count($fixers) - 1; + foreach ($fixers as $i => $fixer) { + $sets = $getSetsWithRule($fixer->getName()); + + $description = $fixer->getDefinition()->getSummary(); + + if ($fixer instanceof DeprecatedFixerInterface) { + $successors = $fixer->getSuccessorsNames(); + $message = [] === $successors + ? 'will be removed on next major version' + : sprintf('use %s instead', Utils::naturalLanguageJoinWithBackticks($successors)); + $description .= sprintf(' DEPRECATED: %s.', $message); + } + + $description = implode("\n | ", self::wordwrap( + Preg::replace('/(`.+?`)/', '<info>$1</info>', $description), + 72 + )); + + if (!empty($sets)) { + $help .= sprintf(" * <comment>%s</comment> [%s]\n | %s\n", $fixer->getName(), implode(', ', $sets), $description); + } else { + $help .= sprintf(" * <comment>%s</comment>\n | %s\n", $fixer->getName(), $description); + } + + if ($fixer->isRisky()) { + $help .= sprintf( + " | *Risky rule: %s.*\n", + Preg::replace( + '/(`.+?`)/', + '<info>$1</info>', + lcfirst(Preg::replace('/\.$/', '', $fixer->getDefinition()->getRiskyDescription())) + ) + ); + } + + if ($fixer instanceof ConfigurationDefinitionFixerInterface) { + $configurationDefinition = $fixer->getConfigurationDefinition(); + $configurationDefinitionOptions = $configurationDefinition->getOptions(); + if (\count($configurationDefinitionOptions)) { + $help .= " |\n | Configuration options:\n"; + + usort( + $configurationDefinitionOptions, + static function (FixerOptionInterface $optionA, FixerOptionInterface $optionB) { + return strcmp($optionA->getName(), $optionB->getName()); + } + ); + + foreach ($configurationDefinitionOptions as $option) { + $line = '<info>'.OutputFormatter::escape($option->getName()).'</info>'; + + $allowed = self::getDisplayableAllowedValues($option); + if (null !== $allowed) { + foreach ($allowed as &$value) { + if ($value instanceof AllowedValueSubset) { + $value = 'a subset of <comment>'.self::toString($value->getAllowedValues()).'</comment>'; + } else { + $value = '<comment>'.self::toString($value).'</comment>'; + } + } + } else { + $allowed = array_map( + static function ($type) { + return '<comment>'.$type.'</comment>'; + }, + $option->getAllowedTypes() + ); + } + + if (null !== $allowed) { + $line .= ' ('.implode(', ', $allowed).')'; + } + + $line .= ': '.Preg::replace( + '/(`.+?`)/', + '<info>$1</info>', + lcfirst(Preg::replace('/\.$/', '', OutputFormatter::escape($option->getDescription()))) + ).'; '; + if ($option->hasDefault()) { + $line .= 'defaults to <comment>'.self::toString($option->getDefault()).'</comment>'; + } else { + $line .= 'required'; + } + + if ($option instanceof DeprecatedFixerOption) { + $line .= '. DEPRECATED: '.Preg::replace( + '/(`.+?`)/', + '<info>$1</info>', + lcfirst(Preg::replace('/\.$/', '', OutputFormatter::escape($option->getDeprecationMessage()))) + ); + } + + if ($option instanceof AliasedFixerOption) { + $line .= '; DEPRECATED alias: <comment>'.$option->getAlias().'</comment>'; + } + + foreach (self::wordwrap($line, 72) as $index => $line) { + $help .= (0 === $index ? ' | - ' : ' | ').$line."\n"; + } + } + } + } elseif ($fixer instanceof ConfigurableFixerInterface) { + $help .= " | *Configurable rule.*\n"; + } + + if ($count !== $i) { + $help .= "\n"; + } + } + + // prevent "\</foo>" from being rendered as an escaped literal style tag + return Preg::replace('#\\\\(</.*?>)#', '<<$1', $help); + } + + /** + * Wraps a string to the given number of characters, ignoring style tags. + * + * @param string $string + * @param int $width + * + * @return string[] + */ + private static function wordwrap($string, $width) + { + $result = []; + $currentLine = 0; + $lineLength = 0; + foreach (explode(' ', $string) as $word) { + $wordLength = \strlen(Preg::replace('~</?(\w+)>~', '', $word)); + if (0 !== $lineLength) { + ++$wordLength; // space before word + } + + if ($lineLength + $wordLength > $width) { + ++$currentLine; + $lineLength = 0; + } + + $result[$currentLine][] = $word; + $lineLength += $wordLength; + } + + return array_map(static function ($line) { + return implode(' ', $line); + }, $result); + } + + /** + * @param mixed $value + * + * @return string + */ + private static function scalarToString($value) + { + $str = var_export($value, true); + + return Preg::replace('/\bNULL\b/', 'null', $str); + } + + /** + * @return string + */ + private static function arrayToString(array $value) + { + if (0 === \count($value)) { + return '[]'; + } + + $isHash = static::isHash($value); + $str = '['; + + foreach ($value as $k => $v) { + if ($isHash) { + $str .= static::scalarToString($k).' => '; + } + + $str .= \is_array($v) + ? static::arrayToString($v).', ' + : static::scalarToString($v).', ' + ; + } + + return substr($str, 0, -2).']'; + } + + /** + * @return bool + */ + private static function isHash(array $array) + { + $i = 0; + + foreach ($array as $k => $v) { + if ($k !== $i) { + return true; + } + + ++$i; + } + + return false; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Command/ListFilesCommand.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/ListFilesCommand.php new file mode 100644 index 0000000..0b1439e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/ListFilesCommand.php @@ -0,0 +1,99 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Command; + +use PhpCsFixer\Config; +use PhpCsFixer\ConfigInterface; +use PhpCsFixer\Console\ConfigurationResolver; +use PhpCsFixer\ToolInfoInterface; +use SplFileInfo; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Markus Staab <markus.staab@redaxo.org> + * + * @internal + */ +final class ListFilesCommand extends Command +{ + /** + * @var string + */ + protected static $defaultName = 'list-files'; + + /** + * @var ConfigInterface + */ + private $defaultConfig; + + /** + * @var ToolInfoInterface + */ + private $toolInfo; + + public function __construct(ToolInfoInterface $toolInfo) + { + parent::__construct(); + + $this->defaultConfig = new Config(); + $this->toolInfo = $toolInfo; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition( + [ + new InputOption('config', '', InputOption::VALUE_REQUIRED, 'The path to a .php-cs-fixer.php file.'), + ] + ) + ->setDescription('List all files being fixed by the given config.') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $passedConfig = $input->getOption('config'); + $cwd = getcwd(); + + $resolver = new ConfigurationResolver( + $this->defaultConfig, + [ + 'config' => $passedConfig, + ], + $cwd, + $this->toolInfo + ); + + $finder = $resolver->getFinder(); + + /** @var SplFileInfo $file */ + foreach ($finder as $file) { + if ($file->isFile()) { + $relativePath = str_replace($cwd, '.', $file->getRealPath()); + // unify directory separators across operating system + $relativePath = str_replace('/', \DIRECTORY_SEPARATOR, $relativePath); + + $output->writeln(escapeshellarg($relativePath)); + } + } + + return 0; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Command/ListSetsCommand.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/ListSetsCommand.php new file mode 100644 index 0000000..3c6a6e7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/ListSetsCommand.php @@ -0,0 +1,92 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Command; + +use PhpCsFixer\ConfigurationException\InvalidConfigurationException; +use PhpCsFixer\Console\Report\ListSetsReport\ReporterFactory; +use PhpCsFixer\Console\Report\ListSetsReport\ReporterInterface; +use PhpCsFixer\Console\Report\ListSetsReport\ReportSummary; +use PhpCsFixer\Console\Report\ListSetsReport\TextReporter; +use PhpCsFixer\RuleSet\RuleSets; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ListSetsCommand extends Command +{ + /** + * @var string + */ + protected static $defaultName = 'list-sets'; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition( + [ + new InputOption('format', '', InputOption::VALUE_REQUIRED, 'To output results in other formats.', (new TextReporter())->getFormat()), + ] + ) + ->setDescription('List all available RuleSets.') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $reporter = $this->resolveReporterWithFactory( + $input->getOption('format'), + new ReporterFactory() + ); + $reportSummary = new ReportSummary( + array_values(RuleSets::getSetDefinitions()) + ); + $report = $reporter->generate($reportSummary); + + $output->isDecorated() + ? $output->write(OutputFormatter::escape($report)) + : $output->write($report, false, OutputInterface::OUTPUT_RAW) + ; + + return 0; + } + + /** + * @param string $format + * + * @return ReporterInterface + */ + private function resolveReporterWithFactory($format, ReporterFactory $factory) + { + try { + $factory->registerBuiltInReporters(); + $reporter = $factory->getReporter($format); + } catch (\UnexpectedValueException $e) { + $formats = $factory->getFormats(); + sort($formats); + + throw new InvalidConfigurationException(sprintf('The format "%s" is not defined, supported are "%s".', $format, implode('", "', $formats))); + } + + return $reporter; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Command/SelfUpdateCommand.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/SelfUpdateCommand.php new file mode 100644 index 0000000..4021db5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Command/SelfUpdateCommand.php @@ -0,0 +1,187 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Command; + +use PhpCsFixer\Console\SelfUpdate\NewVersionCheckerInterface; +use PhpCsFixer\PharCheckerInterface; +use PhpCsFixer\Preg; +use PhpCsFixer\ToolInfoInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Igor Wiedler <igor@wiedler.ch> + * @author Stephane PY <py.stephane1@gmail.com> + * @author Grégoire Pineau <lyrixx@lyrixx.info> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + * + * @internal + */ +final class SelfUpdateCommand extends Command +{ + /** + * @var string + */ + protected static $defaultName = 'self-update'; + + /** + * @var NewVersionCheckerInterface + */ + private $versionChecker; + + /** + * @var ToolInfoInterface + */ + private $toolInfo; + + /** + * @var PharCheckerInterface + */ + private $pharChecker; + + public function __construct( + NewVersionCheckerInterface $versionChecker, + ToolInfoInterface $toolInfo, + PharCheckerInterface $pharChecker + ) { + parent::__construct(); + + $this->versionChecker = $versionChecker; + $this->toolInfo = $toolInfo; + $this->pharChecker = $pharChecker; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setAliases(['selfupdate']) + ->setDefinition( + [ + new InputOption('--force', '-f', InputOption::VALUE_NONE, 'Force update to next major version if available.'), + ] + ) + ->setDescription('Update php-cs-fixer.phar to the latest stable version.') + ->setHelp( + <<<'EOT' +The <info>%command.name%</info> command replace your php-cs-fixer.phar by the +latest version released on: +<comment>https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases</comment> + +<info>$ php php-cs-fixer.phar %command.name%</info> + +EOT + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity() && $output instanceof ConsoleOutputInterface) { + $stdErr = $output->getErrorOutput(); + $stdErr->writeln($this->getApplication()->getLongVersion()); + $stdErr->writeln(sprintf('Runtime: <info>PHP %s</info>', PHP_VERSION)); + } + + if (!$this->toolInfo->isInstalledAsPhar()) { + $output->writeln('<error>Self-update is available only for PHAR version.</error>'); + + return 1; + } + + $currentVersion = $this->getApplication()->getVersion(); + Preg::match('/^v?(?<major>\d+)\./', $currentVersion, $matches); + $currentMajor = (int) $matches['major']; + + try { + $latestVersion = $this->versionChecker->getLatestVersion(); + $latestVersionOfCurrentMajor = $this->versionChecker->getLatestVersionOfMajor($currentMajor); + } catch (\Exception $exception) { + $output->writeln(sprintf( + '<error>Unable to determine newest version: %s</error>', + $exception->getMessage() + )); + + return 1; + } + + if (1 !== $this->versionChecker->compareVersions($latestVersion, $currentVersion)) { + $output->writeln('<info>PHP CS Fixer is already up to date.</info>'); + + return 0; + } + + $remoteTag = $latestVersion; + + if ( + 0 !== $this->versionChecker->compareVersions($latestVersionOfCurrentMajor, $latestVersion) + && true !== $input->getOption('force') + ) { + $output->writeln(sprintf('<info>A new major version of PHP CS Fixer is available</info> (<comment>%s</comment>)', $latestVersion)); + $output->writeln(sprintf('<info>Before upgrading please read</info> https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/%s/UPGRADE-v%s.md', $latestVersion, $currentMajor + 1)); + $output->writeln('<info>If you are ready to upgrade run this command with</info> <comment>-f</comment>'); + $output->writeln('<info>Checking for new minor/patch version...</info>'); + + if (1 !== $this->versionChecker->compareVersions($latestVersionOfCurrentMajor, $currentVersion)) { + $output->writeln('<info>No minor update for PHP CS Fixer.</info>'); + + return 0; + } + + $remoteTag = $latestVersionOfCurrentMajor; + } + + $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; + + if (!is_writable($localFilename)) { + $output->writeln(sprintf('<error>No permission to update</error> "%s" <error>file.</error>', $localFilename)); + + return 1; + } + + $tempFilename = \dirname($localFilename).'/'.basename($localFilename, '.phar').'-tmp.phar'; + $remoteFilename = $this->toolInfo->getPharDownloadUri($remoteTag); + + if (false === @copy($remoteFilename, $tempFilename)) { + $output->writeln(sprintf('<error>Unable to download new version</error> %s <error>from the server.</error>', $remoteTag)); + + return 1; + } + + chmod($tempFilename, 0777 & ~umask()); + + $pharInvalidityReason = $this->pharChecker->checkFileValidity($tempFilename); + if (null !== $pharInvalidityReason) { + unlink($tempFilename); + $output->writeln(sprintf('<error>The download of</error> %s <error>is corrupt (%s).</error>', $remoteTag, $pharInvalidityReason)); + $output->writeln('<error>Please re-run the "self-update" command to try again.</error>'); + + return 1; + } + + rename($tempFilename, $localFilename); + + $output->writeln(sprintf('<info>PHP CS Fixer updated</info> (<comment>%s</comment> -> <comment>%s</comment>)', $currentVersion, $remoteTag)); + + return 0; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/ConfigurationResolver.php b/vendor/friendsofphp/php-cs-fixer/src/Console/ConfigurationResolver.php new file mode 100644 index 0000000..01358fb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/ConfigurationResolver.php @@ -0,0 +1,991 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console; + +use PhpCsFixer\Cache\CacheManagerInterface; +use PhpCsFixer\Cache\Directory; +use PhpCsFixer\Cache\DirectoryInterface; +use PhpCsFixer\Cache\FileCacheManager; +use PhpCsFixer\Cache\FileHandler; +use PhpCsFixer\Cache\NullCacheManager; +use PhpCsFixer\Cache\Signature; +use PhpCsFixer\ConfigInterface; +use PhpCsFixer\ConfigurationException\InvalidConfigurationException; +use PhpCsFixer\Console\Report\FixReport\ReporterFactory; +use PhpCsFixer\Console\Report\FixReport\ReporterInterface; +use PhpCsFixer\Differ\DifferInterface; +use PhpCsFixer\Differ\NullDiffer; +use PhpCsFixer\Differ\SebastianBergmannDiffer; +use PhpCsFixer\Differ\UnifiedDiffer; +use PhpCsFixer\Finder; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\FixerFactory; +use PhpCsFixer\Linter\Linter; +use PhpCsFixer\Linter\LinterInterface; +use PhpCsFixer\RuleSet\RuleSet; +use PhpCsFixer\StdinFileInfo; +use PhpCsFixer\ToolInfoInterface; +use PhpCsFixer\Utils; +use PhpCsFixer\WhitespacesFixerConfig; +use PhpCsFixer\WordMatcher; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Finder\Finder as SymfonyFinder; + +/** + * The resolver that resolves configuration to use by command line options and config. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Katsuhiro Ogawa <ko.fivestar@gmail.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ConfigurationResolver +{ + const PATH_MODE_OVERRIDE = 'override'; + const PATH_MODE_INTERSECTION = 'intersection'; + + /** + * @var null|bool + */ + private $allowRisky; + + /** + * @var null|ConfigInterface + */ + private $config; + + /** + * @var null|string + */ + private $configFile; + + /** + * @var string + */ + private $cwd; + + /** + * @var ConfigInterface + */ + private $defaultConfig; + + /** + * @var null|ReporterInterface + */ + private $reporter; + + /** + * @var null|bool + */ + private $isStdIn; + + /** + * @var null|bool + */ + private $isDryRun; + + /** + * @var null|FixerInterface[] + */ + private $fixers; + + /** + * @var null|bool + */ + private $configFinderIsOverridden; + + /** + * @var ToolInfoInterface + */ + private $toolInfo; + + /** + * @var array + */ + private $options = [ + 'allow-risky' => null, + 'cache-file' => null, + 'config' => null, + 'diff' => null, + 'diff-format' => null, + 'dry-run' => null, + 'format' => null, + 'path' => [], + 'path-mode' => self::PATH_MODE_OVERRIDE, + 'rules' => null, + 'show-progress' => null, + 'stop-on-violation' => null, + 'using-cache' => null, + 'verbosity' => null, + ]; + + private $cacheFile; + + /** + * @var null|CacheManagerInterface + */ + private $cacheManager; + + /** + * @var null|DifferInterface + */ + private $differ; + + /** + * @var null|Directory + */ + private $directory; + + /** + * @var null|iterable + */ + private $finder; + + private $format; + + /** + * @var null|Linter + */ + private $linter; + + private $path; + + /** + * @var null|string + */ + private $progress; + + /** + * @var null|RuleSet + */ + private $ruleSet; + + /** + * @var null|bool + */ + private $usingCache; + + /** + * @var FixerFactory + */ + private $fixerFactory; + + /** + * @param string $cwd + */ + public function __construct( + ConfigInterface $config, + array $options, + $cwd, + ToolInfoInterface $toolInfo + ) { + $this->cwd = $cwd; + $this->defaultConfig = $config; + $this->toolInfo = $toolInfo; + + foreach ($options as $name => $value) { + $this->setOption($name, $value); + } + } + + /** + * @return null|string + */ + public function getCacheFile() + { + if (!$this->getUsingCache()) { + return null; + } + + if (null === $this->cacheFile) { + if (null === $this->options['cache-file']) { + $this->cacheFile = $this->getConfig()->getCacheFile(); + } else { + $this->cacheFile = $this->options['cache-file']; + } + } + + return $this->cacheFile; + } + + /** + * @return CacheManagerInterface + */ + public function getCacheManager() + { + if (null === $this->cacheManager) { + $cacheFile = $this->getCacheFile(); + + if (null === $cacheFile) { + $this->cacheManager = new NullCacheManager(); + } else { + $this->cacheManager = new FileCacheManager( + new FileHandler($cacheFile), + new Signature( + PHP_VERSION, + $this->toolInfo->getVersion(), + $this->getConfig()->getIndent(), + $this->getConfig()->getLineEnding(), + $this->getRules() + ), + $this->isDryRun(), + $this->getDirectory() + ); + } + } + + return $this->cacheManager; + } + + /** + * @return ConfigInterface + */ + public function getConfig() + { + if (null === $this->config) { + foreach ($this->computeConfigFiles() as $configFile) { + if (!file_exists($configFile)) { + continue; + } + + $configFileBasename = basename($configFile); + $deprecatedConfigs = [ + '.php_cs' => '.php-cs-fixer.php', + '.php_cs.dist' => '.php-cs-fixer.dist.php', + ]; + + if (isset($deprecatedConfigs[$configFileBasename])) { + $message = "Configuration file `{$configFileBasename}` is deprecated, rename to `{$deprecatedConfigs[$configFileBasename]}`."; + Utils::triggerDeprecation(new InvalidConfigurationException($message)); + } + + $config = self::separatedContextLessInclude($configFile); + + // verify that the config has an instance of Config + if (!$config instanceof ConfigInterface) { + throw new InvalidConfigurationException(sprintf('The config file: "%s" does not return a "PhpCsFixer\ConfigInterface" instance. Got: "%s".', $configFile, \is_object($config) ? \get_class($config) : \gettype($config))); + } + + $this->config = $config; + $this->configFile = $configFile; + + break; + } + + if (null === $this->config) { + $this->config = $this->defaultConfig; + } + } + + return $this->config; + } + + /** + * @return null|string + */ + public function getConfigFile() + { + if (null === $this->configFile) { + $this->getConfig(); + } + + return $this->configFile; + } + + /** + * @return DifferInterface + */ + public function getDiffer() + { + if (null === $this->differ) { + $mapper = [ + 'null' => static function () { return new NullDiffer(); }, + 'sbd' => static function () { return new SebastianBergmannDiffer(); }, + 'udiff' => static function () { return new UnifiedDiffer(); }, + ]; + + if (!$this->options['diff']) { + $defaultOption = 'null'; + } elseif (getenv('PHP_CS_FIXER_FUTURE_MODE')) { + $defaultOption = 'udiff'; + } else { + $defaultOption = 'sbd'; // @TODO: 3.0 change to udiff as default + } + + $option = isset($this->options['diff-format']) + ? $this->options['diff-format'] + : $defaultOption; + + if (!\is_string($option)) { + throw new InvalidConfigurationException(sprintf( + '"diff-format" must be a string, "%s" given.', + \gettype($option) + )); + } + + if (is_subclass_of($option, DifferInterface::class)) { + $this->differ = new $option(); + } elseif (!isset($mapper[$option])) { + throw new InvalidConfigurationException(sprintf( + '"diff-format" must be any of "%s", got "%s".', + implode('", "', array_keys($mapper)), + $option + )); + } else { + $this->differ = $mapper[$option](); + } + } + + return $this->differ; + } + + /** + * @return DirectoryInterface + */ + public function getDirectory() + { + if (null === $this->directory) { + $path = $this->getCacheFile(); + if (null === $path) { + $absolutePath = $this->cwd; + } else { + $filesystem = new Filesystem(); + + $absolutePath = $filesystem->isAbsolutePath($path) + ? $path + : $this->cwd.\DIRECTORY_SEPARATOR.$path; + } + + $this->directory = new Directory(\dirname($absolutePath)); + } + + return $this->directory; + } + + /** + * @return FixerInterface[] An array of FixerInterface + */ + public function getFixers() + { + if (null === $this->fixers) { + $this->fixers = $this->createFixerFactory() + ->useRuleSet($this->getRuleSet()) + ->setWhitespacesConfig(new WhitespacesFixerConfig($this->config->getIndent(), $this->config->getLineEnding())) + ->getFixers() + ; + + if (false === $this->getRiskyAllowed()) { + $riskyFixers = array_map( + static function (FixerInterface $fixer) { + return $fixer->getName(); + }, + array_filter( + $this->fixers, + static function (FixerInterface $fixer) { + return $fixer->isRisky(); + } + ) + ); + + if (\count($riskyFixers)) { + throw new InvalidConfigurationException(sprintf('The rules contain risky fixers ("%s"), but they are not allowed to run. Perhaps you forget to use --allow-risky=yes option?', implode('", "', $riskyFixers))); + } + } + } + + return $this->fixers; + } + + /** + * @return LinterInterface + */ + public function getLinter() + { + if (null === $this->linter) { + $this->linter = new Linter($this->getConfig()->getPhpExecutable()); + } + + return $this->linter; + } + + /** + * Returns path. + * + * @return string[] + */ + public function getPath() + { + if (null === $this->path) { + $filesystem = new Filesystem(); + $cwd = $this->cwd; + + if (1 === \count($this->options['path']) && '-' === $this->options['path'][0]) { + $this->path = $this->options['path']; + } else { + $this->path = array_map( + static function ($rawPath) use ($cwd, $filesystem) { + $path = trim($rawPath); + + if ('' === $path) { + throw new InvalidConfigurationException("Invalid path: \"{$rawPath}\"."); + } + + $absolutePath = $filesystem->isAbsolutePath($path) + ? $path + : $cwd.\DIRECTORY_SEPARATOR.$path; + + if (!file_exists($absolutePath)) { + throw new InvalidConfigurationException(sprintf( + 'The path "%s" is not readable.', + $path + )); + } + + return $absolutePath; + }, + $this->options['path'] + ); + } + } + + return $this->path; + } + + /** + * @throws InvalidConfigurationException + * + * @return string + */ + public function getProgress() + { + if (null === $this->progress) { + if (OutputInterface::VERBOSITY_VERBOSE <= $this->options['verbosity'] && 'txt' === $this->getFormat()) { + $progressType = $this->options['show-progress']; + $progressTypes = ['none', 'run-in', 'estimating', 'estimating-max', 'dots']; + + if (null === $progressType) { + $default = 'run-in'; + + if (getenv('PHP_CS_FIXER_FUTURE_MODE')) { + $default = 'dots'; + } + + $progressType = $this->getConfig()->getHideProgress() ? 'none' : $default; + } elseif (!\in_array($progressType, $progressTypes, true)) { + throw new InvalidConfigurationException(sprintf( + 'The progress type "%s" is not defined, supported are "%s".', + $progressType, + implode('", "', $progressTypes) + )); + } elseif (\in_array($progressType, ['estimating', 'estimating-max', 'run-in'], true)) { + Utils::triggerDeprecation(new \InvalidArgumentException( + 'Passing `estimating`, `estimating-max` or `run-in` is deprecated and will not be supported in 3.0, use `none` or `dots` instead.' + )); + } + + $this->progress = $progressType; + } else { + $this->progress = 'none'; + } + } + + return $this->progress; + } + + /** + * @return ReporterInterface + */ + public function getReporter() + { + if (null === $this->reporter) { + $reporterFactory = new ReporterFactory(); + $reporterFactory->registerBuiltInReporters(); + + $format = $this->getFormat(); + + try { + $this->reporter = $reporterFactory->getReporter($format); + } catch (\UnexpectedValueException $e) { + $formats = $reporterFactory->getFormats(); + sort($formats); + + throw new InvalidConfigurationException(sprintf('The format "%s" is not defined, supported are "%s".', $format, implode('", "', $formats))); + } + } + + return $this->reporter; + } + + /** + * @return bool + */ + public function getRiskyAllowed() + { + if (null === $this->allowRisky) { + if (null === $this->options['allow-risky']) { + $this->allowRisky = $this->getConfig()->getRiskyAllowed(); + } else { + $this->allowRisky = $this->resolveOptionBooleanValue('allow-risky'); + } + } + + return $this->allowRisky; + } + + /** + * Returns rules. + * + * @return array + */ + public function getRules() + { + return $this->getRuleSet()->getRules(); + } + + /** + * @return bool + */ + public function getUsingCache() + { + if (null === $this->usingCache) { + if (null === $this->options['using-cache']) { + $this->usingCache = $this->getConfig()->getUsingCache(); + } else { + $this->usingCache = $this->resolveOptionBooleanValue('using-cache'); + } + } + + $this->usingCache = $this->usingCache && ($this->toolInfo->isInstalledAsPhar() || $this->toolInfo->isInstalledByComposer()); + + return $this->usingCache; + } + + public function getFinder() + { + if (null === $this->finder) { + $this->finder = $this->resolveFinder(); + } + + return $this->finder; + } + + /** + * Returns dry-run flag. + * + * @return bool + */ + public function isDryRun() + { + if (null === $this->isDryRun) { + if ($this->isStdIn()) { + // Can't write to STDIN + $this->isDryRun = true; + } else { + $this->isDryRun = $this->options['dry-run']; + } + } + + return $this->isDryRun; + } + + public function shouldStopOnViolation() + { + return $this->options['stop-on-violation']; + } + + /** + * @return bool + */ + public function configFinderIsOverridden() + { + if (null === $this->configFinderIsOverridden) { + $this->resolveFinder(); + } + + return $this->configFinderIsOverridden; + } + + /** + * Compute file candidates for config file. + * + * @return string[] + */ + private function computeConfigFiles() + { + $configFile = $this->options['config']; + + if (null !== $configFile) { + if (false === file_exists($configFile) || false === is_readable($configFile)) { + throw new InvalidConfigurationException(sprintf('Cannot read config file "%s".', $configFile)); + } + + return [$configFile]; + } + + $path = $this->getPath(); + + if ($this->isStdIn() || 0 === \count($path)) { + $configDir = $this->cwd; + } elseif (1 < \count($path)) { + throw new InvalidConfigurationException('For multiple paths config parameter is required.'); + } elseif (!is_file($path[0])) { + $configDir = $path[0]; + } else { + $dirName = pathinfo($path[0], PATHINFO_DIRNAME); + $configDir = $dirName ?: $path[0]; + } + + $candidates = [ + $configDir.\DIRECTORY_SEPARATOR.'.php-cs-fixer.php', + $configDir.\DIRECTORY_SEPARATOR.'.php-cs-fixer.dist.php', + $configDir.\DIRECTORY_SEPARATOR.'.php_cs', // old v2 config, present here only to throw nice error message later + $configDir.\DIRECTORY_SEPARATOR.'.php_cs.dist', // old v2 config, present here only to throw nice error message later + ]; + + if ($configDir !== $this->cwd) { + $candidates[] = $this->cwd.\DIRECTORY_SEPARATOR.'.php-cs-fixer.php'; + $candidates[] = $this->cwd.\DIRECTORY_SEPARATOR.'.php-cs-fixer.dist.php'; + $candidates[] = $this->cwd.\DIRECTORY_SEPARATOR.'.php_cs'; // old v2 config, present here only to throw nice error message later + $candidates[] = $this->cwd.\DIRECTORY_SEPARATOR.'.php_cs.dist'; // old v2 config, present here only to throw nice error message later + } + + return $candidates; + } + + /** + * @return FixerFactory + */ + private function createFixerFactory() + { + if (null === $this->fixerFactory) { + $fixerFactory = new FixerFactory(); + $fixerFactory->registerBuiltInFixers(); + $fixerFactory->registerCustomFixers($this->getConfig()->getCustomFixers()); + + $this->fixerFactory = $fixerFactory; + } + + return $this->fixerFactory; + } + + /** + * @return string + */ + private function getFormat() + { + if (null === $this->format) { + $this->format = null === $this->options['format'] + ? $this->getConfig()->getFormat() + : $this->options['format']; + } + + return $this->format; + } + + private function getRuleSet() + { + if (null === $this->ruleSet) { + $rules = $this->parseRules(); + $this->validateRules($rules); + + $this->ruleSet = new RuleSet($rules); + } + + return $this->ruleSet; + } + + /** + * @return bool + */ + private function isStdIn() + { + if (null === $this->isStdIn) { + $this->isStdIn = 1 === \count($this->options['path']) && '-' === $this->options['path'][0]; + } + + return $this->isStdIn; + } + + /** + * @param iterable $iterable + * + * @return \Traversable + */ + private function iterableToTraversable($iterable) + { + return \is_array($iterable) ? new \ArrayIterator($iterable) : $iterable; + } + + /** + * Compute rules. + * + * @return array + */ + private function parseRules() + { + if (null === $this->options['rules']) { + return $this->getConfig()->getRules(); + } + + $rules = trim($this->options['rules']); + if ('' === $rules) { + throw new InvalidConfigurationException('Empty rules value is not allowed.'); + } + + if ('{' === $rules[0]) { + $rules = json_decode($rules, true); + if (JSON_ERROR_NONE !== json_last_error()) { + throw new InvalidConfigurationException(sprintf('Invalid JSON rules input: "%s".', json_last_error_msg())); + } + + return $rules; + } + + $rules = []; + + foreach (explode(',', $this->options['rules']) as $rule) { + $rule = trim($rule); + if ('' === $rule) { + throw new InvalidConfigurationException('Empty rule name is not allowed.'); + } + + if ('-' === $rule[0]) { + $rules[substr($rule, 1)] = false; + } else { + $rules[$rule] = true; + } + } + + return $rules; + } + + /** + * @throws InvalidConfigurationException + */ + private function validateRules(array $rules) + { + /** + * Create a ruleset that contains all configured rules, even when they originally have been disabled. + * + * @see RuleSet::resolveSet() + */ + $ruleSet = []; + foreach ($rules as $key => $value) { + if (\is_int($key)) { + throw new InvalidConfigurationException(sprintf('Missing value for "%s" rule/set.', $value)); + } + + $ruleSet[$key] = true; + } + $ruleSet = new RuleSet($ruleSet); + + /** @var string[] $configuredFixers */ + $configuredFixers = array_keys($ruleSet->getRules()); + + $fixers = $this->createFixerFactory()->getFixers(); + + /** @var string[] $availableFixers */ + $availableFixers = array_map(static function (FixerInterface $fixer) { + return $fixer->getName(); + }, $fixers); + + $unknownFixers = array_diff( + $configuredFixers, + $availableFixers + ); + + if (\count($unknownFixers)) { + $matcher = new WordMatcher($availableFixers); + + $message = 'The rules contain unknown fixers: '; + foreach ($unknownFixers as $unknownFixer) { + $alternative = $matcher->match($unknownFixer); + $message .= sprintf( + '"%s"%s, ', + $unknownFixer, + null === $alternative ? '' : ' (did you mean "'.$alternative.'"?)' + ); + } + + throw new InvalidConfigurationException(substr($message, 0, -2).'.'); + } + + foreach ($fixers as $fixer) { + $fixerName = $fixer->getName(); + if (isset($rules[$fixerName]) && $fixer instanceof DeprecatedFixerInterface) { + $successors = $fixer->getSuccessorsNames(); + $messageEnd = [] === $successors + ? sprintf(' and will be removed in version %d.0.', Application::getMajorVersion() + 1) + : sprintf('. Use %s instead.', str_replace('`', '"', Utils::naturalLanguageJoinWithBackticks($successors))); + + Utils::triggerDeprecation(new \RuntimeException("Rule \"{$fixerName}\" is deprecated{$messageEnd}")); + } + } + } + + /** + * Apply path on config instance. + */ + private function resolveFinder() + { + $this->configFinderIsOverridden = false; + + if ($this->isStdIn()) { + return new \ArrayIterator([new StdinFileInfo()]); + } + + $modes = [self::PATH_MODE_OVERRIDE, self::PATH_MODE_INTERSECTION]; + + if (!\in_array( + $this->options['path-mode'], + $modes, + true + )) { + throw new InvalidConfigurationException(sprintf( + 'The path-mode "%s" is not defined, supported are "%s".', + $this->options['path-mode'], + implode('", "', $modes) + )); + } + + $isIntersectionPathMode = self::PATH_MODE_INTERSECTION === $this->options['path-mode']; + + $paths = array_filter(array_map( + static function ($path) { + return realpath($path); + }, + $this->getPath() + )); + + if (!\count($paths)) { + if ($isIntersectionPathMode) { + return new \ArrayIterator([]); + } + + return $this->iterableToTraversable($this->getConfig()->getFinder()); + } + + $pathsByType = [ + 'file' => [], + 'dir' => [], + ]; + + foreach ($paths as $path) { + if (is_file($path)) { + $pathsByType['file'][] = $path; + } else { + $pathsByType['dir'][] = $path.\DIRECTORY_SEPARATOR; + } + } + + $nestedFinder = null; + $currentFinder = $this->iterableToTraversable($this->getConfig()->getFinder()); + + try { + $nestedFinder = $currentFinder instanceof \IteratorAggregate ? $currentFinder->getIterator() : $currentFinder; + } catch (\Exception $e) { + } + + if ($isIntersectionPathMode) { + if (null === $nestedFinder) { + throw new InvalidConfigurationException( + 'Cannot create intersection with not-fully defined Finder in configuration file.' + ); + } + + return new \CallbackFilterIterator( + new \IteratorIterator($nestedFinder), + static function (\SplFileInfo $current) use ($pathsByType) { + $currentRealPath = $current->getRealPath(); + + if (\in_array($currentRealPath, $pathsByType['file'], true)) { + return true; + } + + foreach ($pathsByType['dir'] as $path) { + if (0 === strpos($currentRealPath, $path)) { + return true; + } + } + + return false; + } + ); + } + + if (null !== $this->getConfigFile() && null !== $nestedFinder) { + $this->configFinderIsOverridden = true; + } + + if ($currentFinder instanceof SymfonyFinder && null === $nestedFinder) { + // finder from configuration Symfony finder and it is not fully defined, we may fulfill it + return $currentFinder->in($pathsByType['dir'])->append($pathsByType['file']); + } + + return Finder::create()->in($pathsByType['dir'])->append($pathsByType['file']); + } + + /** + * Set option that will be resolved. + * + * @param string $name + * @param mixed $value + */ + private function setOption($name, $value) + { + if (!\array_key_exists($name, $this->options)) { + throw new InvalidConfigurationException(sprintf('Unknown option name: "%s".', $name)); + } + + $this->options[$name] = $value; + } + + /** + * @param string $optionName + * + * @return bool + */ + private function resolveOptionBooleanValue($optionName) + { + $value = $this->options[$optionName]; + if (\is_bool($value)) { + return $value; + } + + if (!\is_string($value)) { + throw new InvalidConfigurationException(sprintf('Expected boolean or string value for option "%s".', $optionName)); + } + + if ('yes' === $value) { + return true; + } + + if ('no' === $value) { + return false; + } + + Utils::triggerDeprecation(new InvalidConfigurationException( + sprintf('Expected "yes" or "no" for option "%s", other values are deprecated and support will be removed in 3.0. Got "%s", this implicitly set the option to "false".', $optionName, $value) + )); + + return false; + } + + private static function separatedContextLessInclude($path) + { + return include $path; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Output/ErrorOutput.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Output/ErrorOutput.php new file mode 100644 index 0000000..aafd6fe --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Output/ErrorOutput.php @@ -0,0 +1,154 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Output; + +use PhpCsFixer\Differ\DiffConsoleFormatter; +use PhpCsFixer\Error\Error; +use PhpCsFixer\Linter\LintingException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author SpacePossum + * + * @internal + */ +final class ErrorOutput +{ + /** + * @var OutputInterface + */ + private $output; + + /** + * @var bool + */ + private $isDecorated; + + public function __construct(OutputInterface $output) + { + $this->output = $output; + $this->isDecorated = $output->isDecorated(); + } + + /** + * @param string $process + * @param Error[] $errors + */ + public function listErrors($process, array $errors) + { + $this->output->writeln(['', sprintf( + 'Files that were not fixed due to errors reported during %s:', + $process + )]); + + $showDetails = $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE; + $showTrace = $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG; + foreach ($errors as $i => $error) { + $this->output->writeln(sprintf('%4d) %s', $i + 1, $error->getFilePath())); + $e = $error->getSource(); + if (!$showDetails || null === $e) { + continue; + } + + $class = sprintf('[%s]', \get_class($e)); + $message = $e->getMessage(); + $code = $e->getCode(); + if (0 !== $code) { + $message .= " ({$code})"; + } + + $length = max(\strlen($class), \strlen($message)); + $lines = [ + '', + $class, + $message, + '', + ]; + + $this->output->writeln(''); + + foreach ($lines as $line) { + if (\strlen($line) < $length) { + $line .= str_repeat(' ', $length - \strlen($line)); + } + + $this->output->writeln(sprintf(' <error> %s </error>', $this->prepareOutput($line))); + } + + if ($showTrace && !$e instanceof LintingException) { // stack trace of lint exception is of no interest + $this->output->writeln(''); + $stackTrace = $e->getTrace(); + foreach ($stackTrace as $trace) { + if (isset($trace['class'], $trace['function']) && \Symfony\Component\Console\Command\Command::class === $trace['class'] && 'run' === $trace['function']) { + $this->output->writeln(' [ ... ]'); + + break; + } + + $this->outputTrace($trace); + } + } + + if (Error::TYPE_LINT === $error->getType() && 0 < \count($error->getAppliedFixers())) { + $this->output->writeln(''); + $this->output->writeln(sprintf(' Applied fixers: <comment>%s</comment>', implode(', ', $error->getAppliedFixers()))); + + $diff = $error->getDiff(); + if (!empty($diff)) { + $diffFormatter = new DiffConsoleFormatter( + $this->isDecorated, + sprintf( + '<comment> ---------- begin diff ----------</comment>%s%%s%s<comment> ----------- end diff -----------</comment>', + PHP_EOL, + PHP_EOL + ) + ); + + $this->output->writeln($diffFormatter->format($diff)); + } + } + } + } + + private function outputTrace(array $trace) + { + if (isset($trace['class'], $trace['type'], $trace['function'])) { + $this->output->writeln(sprintf( + ' <comment>%s</comment>%s<comment>%s()</comment>', + $this->prepareOutput($trace['class']), + $this->prepareOutput($trace['type']), + $this->prepareOutput($trace['function']) + )); + } elseif (isset($trace['function'])) { + $this->output->writeln(sprintf(' <comment>%s()</comment>', $this->prepareOutput($trace['function']))); + } + + if (isset($trace['file'])) { + $this->output->writeln(sprintf(' in <info>%s</info> at line <info>%d</info>', $this->prepareOutput($trace['file']), $trace['line'])); + } + } + + /** + * @param string $string + * + * @return string + */ + private function prepareOutput($string) + { + return $this->isDecorated + ? OutputFormatter::escape($string) + : $string + ; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Output/NullOutput.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Output/NullOutput.php new file mode 100644 index 0000000..281388c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Output/NullOutput.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Output; + +/** + * @internal + */ +final class NullOutput implements ProcessOutputInterface +{ + public function printLegend() + { + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Output/ProcessOutput.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Output/ProcessOutput.php new file mode 100644 index 0000000..32d6278 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Output/ProcessOutput.php @@ -0,0 +1,167 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Output; + +use PhpCsFixer\FixerFileProcessedEvent; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Output writer to show the process of a FixCommand. + * + * @internal + */ +final class ProcessOutput implements ProcessOutputInterface +{ + /** + * File statuses map. + * + * @var array + */ + private static $eventStatusMap = [ + FixerFileProcessedEvent::STATUS_UNKNOWN => ['symbol' => '?', 'format' => '%s', 'description' => 'unknown'], + FixerFileProcessedEvent::STATUS_INVALID => ['symbol' => 'I', 'format' => '<bg=red>%s</bg=red>', 'description' => 'invalid file syntax (file ignored)'], + FixerFileProcessedEvent::STATUS_SKIPPED => ['symbol' => 'S', 'format' => '<fg=cyan>%s</fg=cyan>', 'description' => 'skipped (cached or empty file)'], + FixerFileProcessedEvent::STATUS_NO_CHANGES => ['symbol' => '.', 'format' => '%s', 'description' => 'no changes'], + FixerFileProcessedEvent::STATUS_FIXED => ['symbol' => 'F', 'format' => '<fg=green>%s</fg=green>', 'description' => 'fixed'], + FixerFileProcessedEvent::STATUS_EXCEPTION => ['symbol' => 'E', 'format' => '<bg=red>%s</bg=red>', 'description' => 'error'], + FixerFileProcessedEvent::STATUS_LINT => ['symbol' => 'E', 'format' => '<bg=red>%s</bg=red>', 'description' => 'error'], + ]; + + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * @var OutputInterface + */ + private $output; + + /** + * @var null|int + */ + private $files; + + /** + * @var int + */ + private $processedFiles = 0; + + /** + * @var null|int + */ + private $symbolsPerLine; + + /** + * @TODO 3.0 make all parameters mandatory (`null` not allowed) + * + * @param null|int $width + * @param null|int $nbFiles + */ + public function __construct(OutputInterface $output, EventDispatcherInterface $dispatcher, $width, $nbFiles) + { + $this->output = $output; + $this->eventDispatcher = $dispatcher; + $this->eventDispatcher->addListener(FixerFileProcessedEvent::NAME, [$this, 'onFixerFileProcessed']); + $this->symbolsPerLine = $width; + + if (null !== $nbFiles) { + $this->files = $nbFiles; + + // max number of characters per line + // - total length x 2 (e.g. " 1 / 123" => 6 digits and padding spaces) + // - 11 (extra spaces, parentheses and percentage characters, e.g. " x / x (100%)") + $this->symbolsPerLine = max(1, ($width ?: 80) - \strlen((string) $this->files) * 2 - 11); + } + } + + public function __destruct() + { + $this->eventDispatcher->removeListener(FixerFileProcessedEvent::NAME, [$this, 'onFixerFileProcessed']); + } + + /** + * This class is not intended to be serialized, + * and cannot be deserialized (see __wakeup method). + * + * @return array + */ + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + /** + * Disable the deserialization of the class to prevent attacker executing + * code by leveraging the __destruct method. + * + * @see https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection + */ + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function onFixerFileProcessed(FixerFileProcessedEvent $event) + { + if ( + null === $this->files + && null !== $this->symbolsPerLine + && 0 === $this->processedFiles % $this->symbolsPerLine + && 0 !== $this->processedFiles + ) { + $this->output->writeln(''); + } + + $status = self::$eventStatusMap[$event->getStatus()]; + $this->output->write($this->output->isDecorated() ? sprintf($status['format'], $status['symbol']) : $status['symbol']); + + ++$this->processedFiles; + + if (null !== $this->files) { + $symbolsOnCurrentLine = $this->processedFiles % $this->symbolsPerLine; + $isLast = $this->processedFiles === $this->files; + + if (0 === $symbolsOnCurrentLine || $isLast) { + $this->output->write(sprintf( + '%s %'.\strlen((string) $this->files).'d / %d (%3d%%)', + $isLast && 0 !== $symbolsOnCurrentLine ? str_repeat(' ', $this->symbolsPerLine - $symbolsOnCurrentLine) : '', + $this->processedFiles, + $this->files, + round($this->processedFiles / $this->files * 100) + )); + + if (!$isLast) { + $this->output->writeln(''); + } + } + } + } + + public function printLegend() + { + $symbols = []; + + foreach (self::$eventStatusMap as $status) { + $symbol = $status['symbol']; + if ('' === $symbol || isset($symbols[$symbol])) { + continue; + } + + $symbols[$symbol] = sprintf('%s-%s', $this->output->isDecorated() ? sprintf($status['format'], $symbol) : $symbol, $status['description']); + } + + $this->output->write(sprintf("\nLegend: %s\n", implode(', ', $symbols))); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FinderInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Output/ProcessOutputInterface.php similarity index 68% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/FinderInterface.php rename to vendor/friendsofphp/php-cs-fixer/src/Console/Output/ProcessOutputInterface.php index f50abf0..2d78382 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FinderInterface.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Output/ProcessOutputInterface.php @@ -10,12 +10,12 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS; +namespace PhpCsFixer\Console\Output; /** - * @author Fabien Potencier <fabien@symfony.com> + * @internal */ -interface FinderInterface +interface ProcessOutputInterface { - public function setDir($dir); + public function printLegend(); } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/CheckstyleReporter.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/CheckstyleReporter.php new file mode 100644 index 0000000..a967e11 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/CheckstyleReporter.php @@ -0,0 +1,74 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\FixReport; + +use Symfony\Component\Console\Formatter\OutputFormatter; + +/** + * @author Kévin Gomez <contact@kevingomez.fr> + * + * @internal + */ +final class CheckstyleReporter implements ReporterInterface +{ + /** + * {@inheritdoc} + */ + public function getFormat() + { + return 'checkstyle'; + } + + /** + * {@inheritdoc} + */ + public function generate(ReportSummary $reportSummary) + { + if (!\extension_loaded('dom')) { + throw new \RuntimeException('Cannot generate report! `ext-dom` is not available!'); + } + + $dom = new \DOMDocument('1.0', 'UTF-8'); + $checkstyles = $dom->appendChild($dom->createElement('checkstyle')); + + foreach ($reportSummary->getChanged() as $filePath => $fixResult) { + /** @var \DOMElement $file */ + $file = $checkstyles->appendChild($dom->createElement('file')); + $file->setAttribute('name', $filePath); + + foreach ($fixResult['appliedFixers'] as $appliedFixer) { + $error = $this->createError($dom, $appliedFixer); + $file->appendChild($error); + } + } + + $dom->formatOutput = true; + + return $reportSummary->isDecoratedOutput() ? OutputFormatter::escape($dom->saveXML()) : $dom->saveXML(); + } + + /** + * @param string $appliedFixer + * + * @return \DOMElement + */ + private function createError(\DOMDocument $dom, $appliedFixer) + { + $error = $dom->createElement('error'); + $error->setAttribute('severity', 'warning'); + $error->setAttribute('source', 'PHP-CS-Fixer.'.$appliedFixer); + $error->setAttribute('message', 'Found violation(s) of type: '.$appliedFixer); + + return $error; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/GitlabReporter.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/GitlabReporter.php new file mode 100644 index 0000000..2743624 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/GitlabReporter.php @@ -0,0 +1,60 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\FixReport; + +use Symfony\Component\Console\Formatter\OutputFormatter; + +/** + * Generates a report according to gitlabs subset of codeclimate json files. + * + * @see https://github.com/codeclimate/spec/blob/master/SPEC.md#data-types + * + * @author Hans-Christian Otto <c.otto@suora.com> + * + * @internal + */ +final class GitlabReporter implements ReporterInterface +{ + public function getFormat() + { + return 'gitlab'; + } + + /** + * Process changed files array. Returns generated report. + * + * @return string + */ + public function generate(ReportSummary $reportSummary) + { + $report = []; + foreach ($reportSummary->getChanged() as $fileName => $change) { + foreach ($change['appliedFixers'] as $fixerName) { + $report[] = [ + 'description' => $fixerName, + 'fingerprint' => md5($fileName.$fixerName), + 'location' => [ + 'path' => $fileName, + 'lines' => [ + 'begin' => 0, // line numbers are required in the format, but not available to reports + ], + ], + ]; + } + } + + $jsonString = json_encode($report); + + return $reportSummary->isDecoratedOutput() ? OutputFormatter::escape($jsonString) : $jsonString; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/JsonReporter.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/JsonReporter.php new file mode 100644 index 0000000..2e678ce --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/JsonReporter.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\FixReport; + +use Symfony\Component\Console\Formatter\OutputFormatter; + +/** + * @author Boris Gorbylev <ekho@ekho.name> + * + * @internal + */ +final class JsonReporter implements ReporterInterface +{ + /** + * {@inheritdoc} + */ + public function getFormat() + { + return 'json'; + } + + /** + * {@inheritdoc} + */ + public function generate(ReportSummary $reportSummary) + { + $jFiles = []; + + foreach ($reportSummary->getChanged() as $file => $fixResult) { + $jfile = ['name' => $file]; + + if ($reportSummary->shouldAddAppliedFixers()) { + $jfile['appliedFixers'] = $fixResult['appliedFixers']; + } + + if (!empty($fixResult['diff'])) { + $jfile['diff'] = $fixResult['diff']; + } + + $jFiles[] = $jfile; + } + + $json = [ + 'files' => $jFiles, + ]; + + if (null !== $reportSummary->getTime()) { + $json['time'] = [ + 'total' => round($reportSummary->getTime() / 1000, 3), + ]; + } + + if (null !== $reportSummary->getMemory()) { + $json['memory'] = round($reportSummary->getMemory() / 1024 / 1024, 3); + } + + $json = json_encode($json); + + return $reportSummary->isDecoratedOutput() ? OutputFormatter::escape($json) : $json; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/JunitReporter.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/JunitReporter.php new file mode 100644 index 0000000..c48d803 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/JunitReporter.php @@ -0,0 +1,141 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\FixReport; + +use PhpCsFixer\Preg; +use Symfony\Component\Console\Formatter\OutputFormatter; + +/** + * @author Boris Gorbylev <ekho@ekho.name> + * + * @internal + */ +final class JunitReporter implements ReporterInterface +{ + /** + * {@inheritdoc} + */ + public function getFormat() + { + return 'junit'; + } + + /** + * {@inheritdoc} + */ + public function generate(ReportSummary $reportSummary) + { + if (!\extension_loaded('dom')) { + throw new \RuntimeException('Cannot generate report! `ext-dom` is not available!'); + } + + $dom = new \DOMDocument('1.0', 'UTF-8'); + $testsuites = $dom->appendChild($dom->createElement('testsuites')); + /** @var \DomElement $testsuite */ + $testsuite = $testsuites->appendChild($dom->createElement('testsuite')); + $testsuite->setAttribute('name', 'PHP CS Fixer'); + + if (\count($reportSummary->getChanged())) { + $this->createFailedTestCases($dom, $testsuite, $reportSummary); + } else { + $this->createSuccessTestCase($dom, $testsuite); + } + + if ($reportSummary->getTime()) { + $testsuite->setAttribute( + 'time', + sprintf( + '%.3f', + $reportSummary->getTime() / 1000 + ) + ); + } + + $dom->formatOutput = true; + + return $reportSummary->isDecoratedOutput() ? OutputFormatter::escape($dom->saveXML()) : $dom->saveXML(); + } + + private function createSuccessTestCase(\DOMDocument $dom, \DOMElement $testsuite) + { + $testcase = $dom->createElement('testcase'); + $testcase->setAttribute('name', 'All OK'); + $testcase->setAttribute('assertions', '1'); + + $testsuite->appendChild($testcase); + $testsuite->setAttribute('tests', '1'); + $testsuite->setAttribute('assertions', '1'); + $testsuite->setAttribute('failures', '0'); + $testsuite->setAttribute('errors', '0'); + } + + private function createFailedTestCases(\DOMDocument $dom, \DOMElement $testsuite, ReportSummary $reportSummary) + { + $assertionsCount = 0; + foreach ($reportSummary->getChanged() as $file => $fixResult) { + $testcase = $this->createFailedTestCase( + $dom, + $file, + $fixResult, + $reportSummary->shouldAddAppliedFixers() + ); + $testsuite->appendChild($testcase); + $assertionsCount += (int) $testcase->getAttribute('assertions'); + } + + $testsuite->setAttribute('tests', (string) \count($reportSummary->getChanged())); + $testsuite->setAttribute('assertions', (string) $assertionsCount); + $testsuite->setAttribute('failures', (string) $assertionsCount); + $testsuite->setAttribute('errors', '0'); + } + + /** + * @param string $file + * @param bool $shouldAddAppliedFixers + * + * @return \DOMElement + */ + private function createFailedTestCase(\DOMDocument $dom, $file, array $fixResult, $shouldAddAppliedFixers) + { + $appliedFixersCount = \count($fixResult['appliedFixers']); + + $testName = str_replace('.', '_DOT_', Preg::replace('@\.'.pathinfo($file, PATHINFO_EXTENSION).'$@', '', $file)); + + $testcase = $dom->createElement('testcase'); + $testcase->setAttribute('name', $testName); + $testcase->setAttribute('file', $file); + $testcase->setAttribute('assertions', (string) $appliedFixersCount); + + $failure = $dom->createElement('failure'); + $failure->setAttribute('type', 'code_style'); + $testcase->appendChild($failure); + + if ($shouldAddAppliedFixers) { + $failureContent = "applied fixers:\n---------------\n"; + + foreach ($fixResult['appliedFixers'] as $appliedFixer) { + $failureContent .= "* {$appliedFixer}\n"; + } + } else { + $failureContent = "Wrong code style\n"; + } + + if (!empty($fixResult['diff'])) { + $failureContent .= "\nDiff:\n---------------\n\n".$fixResult['diff']; + } + + $failure->appendChild($dom->createCDATASection(trim($failureContent))); + + return $testcase; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReportSummary.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReportSummary.php new file mode 100644 index 0000000..6168fd5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReportSummary.php @@ -0,0 +1,122 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\FixReport; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ReportSummary +{ + /** + * @var bool + */ + private $addAppliedFixers; + + /** + * @var array + */ + private $changed; + + /** + * @var bool + */ + private $isDecoratedOutput; + + /** + * @var bool + */ + private $isDryRun; + + /** + * @var int + */ + private $memory; + + /** + * @var int + */ + private $time; + + /** + * @param int $time duration in milliseconds + * @param int $memory memory usage in bytes + * @param bool $addAppliedFixers + * @param bool $isDryRun + * @param bool $isDecoratedOutput + */ + public function __construct( + array $changed, + $time, + $memory, + $addAppliedFixers, + $isDryRun, + $isDecoratedOutput + ) { + $this->changed = $changed; + $this->time = $time; + $this->memory = $memory; + $this->addAppliedFixers = $addAppliedFixers; + $this->isDryRun = $isDryRun; + $this->isDecoratedOutput = $isDecoratedOutput; + } + + /** + * @return bool + */ + public function isDecoratedOutput() + { + return $this->isDecoratedOutput; + } + + /** + * @return bool + */ + public function isDryRun() + { + return $this->isDryRun; + } + + /** + * @return array + */ + public function getChanged() + { + return $this->changed; + } + + /** + * @return int + */ + public function getMemory() + { + return $this->memory; + } + + /** + * @return int + */ + public function getTime() + { + return $this->time; + } + + /** + * @return bool + */ + public function shouldAddAppliedFixers() + { + return $this->addAppliedFixers; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReporterFactory.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReporterFactory.php new file mode 100644 index 0000000..18c39ac --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReporterFactory.php @@ -0,0 +1,95 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\FixReport; + +use Symfony\Component\Finder\Finder as SymfonyFinder; +use Symfony\Component\Finder\SplFileInfo; + +/** + * @author Boris Gorbylev <ekho@ekho.name> + * + * @internal + */ +final class ReporterFactory +{ + /** @var ReporterInterface[] */ + private $reporters = []; + + public function registerBuiltInReporters() + { + /** @var null|string[] $builtInReporters */ + static $builtInReporters; + + if (null === $builtInReporters) { + $builtInReporters = []; + + /** @var SplFileInfo $file */ + foreach (SymfonyFinder::create()->files()->name('*Reporter.php')->in(__DIR__) as $file) { + $relativeNamespace = $file->getRelativePath(); + $builtInReporters[] = sprintf( + '%s\\%s%s', + __NAMESPACE__, + $relativeNamespace ? $relativeNamespace.'\\' : '', + $file->getBasename('.php') + ); + } + } + + foreach ($builtInReporters as $reporterClass) { + $this->registerReporter(new $reporterClass()); + } + + return $this; + } + + /** + * @return $this + */ + public function registerReporter(ReporterInterface $reporter) + { + $format = $reporter->getFormat(); + + if (isset($this->reporters[$format])) { + throw new \UnexpectedValueException(sprintf('Reporter for format "%s" is already registered.', $format)); + } + + $this->reporters[$format] = $reporter; + + return $this; + } + + /** + * @return string[] + */ + public function getFormats() + { + $formats = array_keys($this->reporters); + sort($formats); + + return $formats; + } + + /** + * @param string $format + * + * @return ReporterInterface + */ + public function getReporter($format) + { + if (!isset($this->reporters[$format])) { + throw new \UnexpectedValueException(sprintf('Reporter for format "%s" is not registered.', $format)); + } + + return $this->reporters[$format]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReporterInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReporterInterface.php new file mode 100644 index 0000000..252b18a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/ReporterInterface.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\FixReport; + +/** + * @author Boris Gorbylev <ekho@ekho.name> + * + * @internal + */ +interface ReporterInterface +{ + /** + * @return string + */ + public function getFormat(); + + /** + * Process changed files array. Returns generated report. + * + * @return string + */ + public function generate(ReportSummary $reportSummary); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/TextReporter.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/TextReporter.php new file mode 100644 index 0000000..71f6018 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/TextReporter.php @@ -0,0 +1,108 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\FixReport; + +use PhpCsFixer\Differ\DiffConsoleFormatter; + +/** + * @author Boris Gorbylev <ekho@ekho.name> + * + * @internal + */ +final class TextReporter implements ReporterInterface +{ + /** + * {@inheritdoc} + */ + public function getFormat() + { + return 'txt'; + } + + /** + * {@inheritdoc} + */ + public function generate(ReportSummary $reportSummary) + { + $output = ''; + + $i = 0; + foreach ($reportSummary->getChanged() as $file => $fixResult) { + ++$i; + $output .= sprintf('%4d) %s', $i, $file); + + if ($reportSummary->shouldAddAppliedFixers()) { + $output .= $this->getAppliedFixers($reportSummary->isDecoratedOutput(), $fixResult); + } + + $output .= $this->getDiff($reportSummary->isDecoratedOutput(), $fixResult); + $output .= PHP_EOL; + } + + return $output.$this->getFooter($reportSummary->getTime(), $reportSummary->getMemory(), $reportSummary->isDryRun()); + } + + /** + * @param bool $isDecoratedOutput + * + * @return string + */ + private function getAppliedFixers($isDecoratedOutput, array $fixResult) + { + return sprintf( + $isDecoratedOutput ? ' (<comment>%s</comment>)' : ' (%s)', + implode(', ', $fixResult['appliedFixers']) + ); + } + + /** + * @param bool $isDecoratedOutput + * + * @return string + */ + private function getDiff($isDecoratedOutput, array $fixResult) + { + if (empty($fixResult['diff'])) { + return ''; + } + + $diffFormatter = new DiffConsoleFormatter($isDecoratedOutput, sprintf( + '<comment> ---------- begin diff ----------</comment>%s%%s%s<comment> ----------- end diff -----------</comment>', + PHP_EOL, + PHP_EOL + )); + + return PHP_EOL.$diffFormatter->format($fixResult['diff']).PHP_EOL; + } + + /** + * @param int $time + * @param int $memory + * @param bool $isDryRun + * + * @return string + */ + private function getFooter($time, $memory, $isDryRun) + { + if (0 === $time || 0 === $memory) { + return ''; + } + + return PHP_EOL.sprintf( + '%s all files in %.3f seconds, %.3f MB memory used'.PHP_EOL, + $isDryRun ? 'Checked' : 'Fixed', + $time / 1000, + $memory / 1024 / 1024 + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/XmlReporter.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/XmlReporter.php new file mode 100644 index 0000000..17401bd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/FixReport/XmlReporter.php @@ -0,0 +1,140 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\FixReport; + +use Symfony\Component\Console\Formatter\OutputFormatter; + +/** + * @author Boris Gorbylev <ekho@ekho.name> + * + * @internal + */ +final class XmlReporter implements ReporterInterface +{ + /** + * {@inheritdoc} + */ + public function getFormat() + { + return 'xml'; + } + + /** + * {@inheritdoc} + */ + public function generate(ReportSummary $reportSummary) + { + if (!\extension_loaded('dom')) { + throw new \RuntimeException('Cannot generate report! `ext-dom` is not available!'); + } + + $dom = new \DOMDocument('1.0', 'UTF-8'); + // new nodes should be added to this or existing children + $root = $dom->createElement('report'); + $dom->appendChild($root); + + $filesXML = $dom->createElement('files'); + $root->appendChild($filesXML); + + $i = 1; + foreach ($reportSummary->getChanged() as $file => $fixResult) { + $fileXML = $dom->createElement('file'); + $fileXML->setAttribute('id', (string) $i++); + $fileXML->setAttribute('name', $file); + $filesXML->appendChild($fileXML); + + if ($reportSummary->shouldAddAppliedFixers()) { + $fileXML->appendChild($this->createAppliedFixersElement($dom, $fixResult)); + } + + if (!empty($fixResult['diff'])) { + $fileXML->appendChild($this->createDiffElement($dom, $fixResult)); + } + } + + if (0 !== $reportSummary->getTime()) { + $root->appendChild($this->createTimeElement($reportSummary->getTime(), $dom)); + } + + if (0 !== $reportSummary->getMemory()) { + $root->appendChild($this->createMemoryElement($reportSummary->getMemory(), $dom)); + } + + $dom->formatOutput = true; + + return $reportSummary->isDecoratedOutput() ? OutputFormatter::escape($dom->saveXML()) : $dom->saveXML(); + } + + /** + * @param \DOMDocument $dom + * + * @return \DOMElement + */ + private function createAppliedFixersElement($dom, array $fixResult) + { + $appliedFixersXML = $dom->createElement('applied_fixers'); + + foreach ($fixResult['appliedFixers'] as $appliedFixer) { + $appliedFixerXML = $dom->createElement('applied_fixer'); + $appliedFixerXML->setAttribute('name', $appliedFixer); + $appliedFixersXML->appendChild($appliedFixerXML); + } + + return $appliedFixersXML; + } + + /** + * @return \DOMElement + */ + private function createDiffElement(\DOMDocument $dom, array $fixResult) + { + $diffXML = $dom->createElement('diff'); + $diffXML->appendChild($dom->createCDATASection($fixResult['diff'])); + + return $diffXML; + } + + /** + * @param float $time + * + * @return \DOMElement + */ + private function createTimeElement($time, \DOMDocument $dom) + { + $time = round($time / 1000, 3); + + $timeXML = $dom->createElement('time'); + $timeXML->setAttribute('unit', 's'); + $timeTotalXML = $dom->createElement('total'); + $timeTotalXML->setAttribute('value', (string) $time); + $timeXML->appendChild($timeTotalXML); + + return $timeXML; + } + + /** + * @param float $memory + * + * @return \DOMElement + */ + private function createMemoryElement($memory, \DOMDocument $dom) + { + $memory = round($memory / 1024 / 1024, 3); + + $memoryXML = $dom->createElement('memory'); + $memoryXML->setAttribute('value', (string) $memory); + $memoryXML->setAttribute('unit', 'MB'); + + return $memoryXML; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/JsonReporter.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/JsonReporter.php new file mode 100644 index 0000000..bf868eb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/JsonReporter.php @@ -0,0 +1,54 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\ListSetsReport; + +use PhpCsFixer\RuleSet\RuleSetDescriptionInterface; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class JsonReporter implements ReporterInterface +{ + /** + * {@inheritdoc} + */ + public function getFormat() + { + return 'json'; + } + + /** + * {@inheritdoc} + */ + public function generate(ReportSummary $reportSummary) + { + $json = ['sets' => []]; + + $sets = $reportSummary->getSets(); + usort($sets, function (RuleSetDescriptionInterface $a, RuleSetDescriptionInterface $b) { + return $a->getName() > $b->getName() ? 1 : -1; + }); + + foreach ($sets as $set) { + $json['sets'][$set->getName()] = [ + 'description' => $set->getDescription(), + 'isRisky' => $set->isRisky(), + 'name' => $set->getName(), + ]; + } + + return json_encode($json, JSON_PRETTY_PRINT); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReportSummary.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReportSummary.php new file mode 100644 index 0000000..75b8529 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReportSummary.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\ListSetsReport; + +use PhpCsFixer\RuleSet\RuleSetDescriptionInterface; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ReportSummary +{ + /** + * @var RuleSetDescriptionInterface[] + */ + private $sets; + + /** + * @param RuleSetDescriptionInterface[] $sets + */ + public function __construct( + array $sets + ) { + $this->sets = $sets; + } + + /** + * @return RuleSetDescriptionInterface[] + */ + public function getSets() + { + return $this->sets; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReporterFactory.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReporterFactory.php new file mode 100644 index 0000000..c5207c5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReporterFactory.php @@ -0,0 +1,95 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\ListSetsReport; + +use Symfony\Component\Finder\Finder as SymfonyFinder; +use Symfony\Component\Finder\SplFileInfo; + +/** + * @author Boris Gorbylev <ekho@ekho.name> + * + * @internal + */ +final class ReporterFactory +{ + /** @var ReporterInterface[] */ + private $reporters = []; + + public function registerBuiltInReporters() + { + /** @var null|string[] $builtInReporters */ + static $builtInReporters; + + if (null === $builtInReporters) { + $builtInReporters = []; + + /** @var SplFileInfo $file */ + foreach (SymfonyFinder::create()->files()->name('*Reporter.php')->in(__DIR__) as $file) { + $relativeNamespace = $file->getRelativePath(); + $builtInReporters[] = sprintf( + '%s\\%s%s', + __NAMESPACE__, + $relativeNamespace ? $relativeNamespace.'\\' : '', + $file->getBasename('.php') + ); + } + } + + foreach ($builtInReporters as $reporterClass) { + $this->registerReporter(new $reporterClass()); + } + + return $this; + } + + /** + * @return $this + */ + public function registerReporter(ReporterInterface $reporter) + { + $format = $reporter->getFormat(); + + if (isset($this->reporters[$format])) { + throw new \UnexpectedValueException(sprintf('Reporter for format "%s" is already registered.', $format)); + } + + $this->reporters[$format] = $reporter; + + return $this; + } + + /** + * @return string[] + */ + public function getFormats() + { + $formats = array_keys($this->reporters); + sort($formats); + + return $formats; + } + + /** + * @param string $format + * + * @return ReporterInterface + */ + public function getReporter($format) + { + if (!isset($this->reporters[$format])) { + throw new \UnexpectedValueException(sprintf('Reporter for format "%s" is not registered.', $format)); + } + + return $this->reporters[$format]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReporterInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReporterInterface.php new file mode 100644 index 0000000..b074f50 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/ReporterInterface.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\ListSetsReport; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +interface ReporterInterface +{ + /** + * @return string + */ + public function getFormat(); + + /** + * Process changed files array. Returns generated report. + * + * @return string + */ + public function generate(ReportSummary $reportSummary); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/TextReporter.php b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/TextReporter.php new file mode 100644 index 0000000..1eb4a5d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/Report/ListSetsReport/TextReporter.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\Report\ListSetsReport; + +use PhpCsFixer\RuleSet\RuleSetDescriptionInterface; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class TextReporter implements ReporterInterface +{ + /** + * {@inheritdoc} + */ + public function getFormat() + { + return 'txt'; + } + + /** + * {@inheritdoc} + */ + public function generate(ReportSummary $reportSummary) + { + $output = ''; + $i = 0; + + $sets = $reportSummary->getSets(); + usort($sets, function (RuleSetDescriptionInterface $a, RuleSetDescriptionInterface $b) { + return $a->getName() > $b->getName() ? 1 : -1; + }); + + foreach ($sets as $set) { + ++$i; + $output .= sprintf('%2d) %s', $i, $set->getName()).PHP_EOL.' '.$set->getDescription().PHP_EOL; + + if ($set->isRisky()) { + $output .= ' Set contains risky rules.'.PHP_EOL; + } + } + + return $output; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/GithubClient.php b/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/GithubClient.php new file mode 100644 index 0000000..7cae3ac --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/GithubClient.php @@ -0,0 +1,52 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\SelfUpdate; + +/** + * @internal + */ +final class GithubClient implements GithubClientInterface +{ + /** + * {@inheritdoc} + */ + public function getTags() + { + $url = 'https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/tags'; + + $result = @file_get_contents( + $url, + false, + stream_context_create([ + 'http' => [ + 'header' => 'User-Agent: FriendsOfPHP/PHP-CS-Fixer', + ], + ]) + ); + + if (false === $result) { + throw new \RuntimeException(sprintf('Failed to load tags at "%s".', $url)); + } + + $result = json_decode($result, true); + if (JSON_ERROR_NONE !== json_last_error()) { + throw new \RuntimeException(sprintf( + 'Failed to read response from "%s" as JSON: %s.', + $url, + json_last_error_msg() + )); + } + + return $result; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/GithubClientInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/GithubClientInterface.php new file mode 100644 index 0000000..a9671ac --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/GithubClientInterface.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\SelfUpdate; + +/** + * @internal + */ +interface GithubClientInterface +{ + /** + * @return array + */ + public function getTags(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/NewVersionChecker.php b/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/NewVersionChecker.php new file mode 100644 index 0000000..023d6e7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/NewVersionChecker.php @@ -0,0 +1,114 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\SelfUpdate; + +use Composer\Semver\Comparator; +use Composer\Semver\Semver; +use Composer\Semver\VersionParser; + +/** + * @internal + */ +final class NewVersionChecker implements NewVersionCheckerInterface +{ + /** + * @var GithubClientInterface + */ + private $githubClient; + + /** + * @var VersionParser + */ + private $versionParser; + + /** + * @var null|string[] + */ + private $availableVersions; + + public function __construct(GithubClientInterface $githubClient) + { + $this->githubClient = $githubClient; + $this->versionParser = new VersionParser(); + } + + /** + * {@inheritdoc} + */ + public function getLatestVersion() + { + $this->retrieveAvailableVersions(); + + return $this->availableVersions[0]; + } + + /** + * {@inheritdoc} + */ + public function getLatestVersionOfMajor($majorVersion) + { + $this->retrieveAvailableVersions(); + + $semverConstraint = '^'.$majorVersion; + + foreach ($this->availableVersions as $availableVersion) { + if (Semver::satisfies($availableVersion, $semverConstraint)) { + return $availableVersion; + } + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function compareVersions($versionA, $versionB) + { + $versionA = $this->versionParser->normalize($versionA); + $versionB = $this->versionParser->normalize($versionB); + + if (Comparator::lessThan($versionA, $versionB)) { + return -1; + } + + if (Comparator::greaterThan($versionA, $versionB)) { + return 1; + } + + return 0; + } + + private function retrieveAvailableVersions() + { + if (null !== $this->availableVersions) { + return; + } + + foreach ($this->githubClient->getTags() as $tag) { + $version = $tag['name']; + + try { + $this->versionParser->normalize($version); + + if ('stable' === VersionParser::parseStability($version)) { + $this->availableVersions[] = $version; + } + } catch (\UnexpectedValueException $exception) { + // not a valid version tag + } + } + + $this->availableVersions = Semver::rsort($this->availableVersions); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/NewVersionCheckerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/NewVersionCheckerInterface.php new file mode 100644 index 0000000..b596d58 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/SelfUpdate/NewVersionCheckerInterface.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Console\SelfUpdate; + +/** + * @internal + */ +interface NewVersionCheckerInterface +{ + /** + * Returns the tag of the latest version. + * + * @return string + */ + public function getLatestVersion(); + + /** + * Returns the tag of the latest minor/patch version of the given major version. + * + * @param int $majorVersion + * + * @return null|string + */ + public function getLatestVersionOfMajor($majorVersion); + + /** + * Returns -1, 0, or 1 if the first version is respectively less than, + * equal to, or greater than the second. + * + * @param string $versionA + * @param string $versionB + * + * @return int + */ + public function compareVersions($versionA, $versionB); +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/WarningsDetector.php b/vendor/friendsofphp/php-cs-fixer/src/Console/WarningsDetector.php similarity index 51% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/WarningsDetector.php rename to vendor/friendsofphp/php-cs-fixer/src/Console/WarningsDetector.php index c3b16ce..5ec3514 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Console/WarningsDetector.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Console/WarningsDetector.php @@ -10,9 +10,10 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Console; +namespace PhpCsFixer\Console; -use Symfony\CS\ToolInfo; +use PhpCsFixer\ToolInfo; +use PhpCsFixer\ToolInfoInterface; /** * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> @@ -21,24 +22,33 @@ */ final class WarningsDetector { + /** + * @var ToolInfoInterface + */ + private $toolInfo; + /** * @var string[] */ - private $warnings = array(); + private $warnings = []; - public function detectOldMajor() + public function __construct(ToolInfoInterface $toolInfo) { - // @TODO to be removed at v2 - $this->warnings[] = 'You are running PHP CS Fixer v1, which is not maintained anymore. Please update to v2.'; + $this->toolInfo = $toolInfo; + } - // @TODO to be activated at v3 - // $this->warnings[] = 'You are running PHP CS Fixer v2, which is not maintained anymore. Please update to v3.'; + public function detectOldMajor() + { + $currentMajorVersion = \intval(explode('.', Application::VERSION)[0], 10); + $nextMajorVersion = $currentMajorVersion + 1; + $this->warnings[] = "You are running PHP CS Fixer v{$currentMajorVersion}, which is not maintained anymore. Please update to v{$nextMajorVersion}."; + $this->warnings[] = "You may find an UPGRADE guide at https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/v{$nextMajorVersion}.3.0/UPGRADE-v{$nextMajorVersion}.md ."; } public function detectOldVendor() { - if (ToolInfo::isInstalledByComposer()) { - $details = ToolInfo::getComposerInstallationDetails(); + if ($this->toolInfo->isInstalledByComposer()) { + $details = $this->toolInfo->getComposerInstallationDetails(); if (ToolInfo::COMPOSER_LEGACY_PACKAGE_NAME === $details['name']) { $this->warnings[] = sprintf( 'You are running PHP CS Fixer installed with old vendor `%s`. Please update to `%s`.', @@ -49,25 +59,18 @@ public function detectOldVendor() } } - public function detectXdebug() - { - if (extension_loaded('xdebug')) { - $this->warnings[] = 'You are running PHP CS Fixer with xdebug enabled. This has a major impact on runtime performance.'; - } - } - /** * @return string[] */ public function getWarnings() { - if (!count($this->warnings)) { - return array(); + if (!\count($this->warnings)) { + return []; } return array_unique(array_merge( $this->warnings, - array('If you need help while solving warnings, ask at https://gitter.im/PHP-CS-Fixer, we will help you!') + ['If you need help while solving warnings, ask at https://gitter.im/PHP-CS-Fixer, we will help you!'] )); } } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Differ/DiffConsoleFormatter.php b/vendor/friendsofphp/php-cs-fixer/src/Differ/DiffConsoleFormatter.php new file mode 100644 index 0000000..831404d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Differ/DiffConsoleFormatter.php @@ -0,0 +1,102 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Differ; + +use PhpCsFixer\Preg; +use Symfony\Component\Console\Formatter\OutputFormatter; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class DiffConsoleFormatter +{ + /** + * @var bool + */ + private $isDecoratedOutput; + + /** + * @var string + */ + private $template; + + /** + * @param bool $isDecoratedOutput + * @param string $template + */ + public function __construct($isDecoratedOutput, $template = '%s') + { + $this->isDecoratedOutput = $isDecoratedOutput; + $this->template = $template; + } + + /** + * @param string $diff + * @param string $lineTemplate + * + * @return string + */ + public function format($diff, $lineTemplate = '%s') + { + $isDecorated = $this->isDecoratedOutput; + + $template = $isDecorated + ? $this->template + : Preg::replace('/<[^<>]+>/', '', $this->template) + ; + + return sprintf( + $template, + implode( + PHP_EOL, + array_map( + static function ($line) use ($isDecorated, $lineTemplate) { + if ($isDecorated) { + $count = 0; + $line = Preg::replaceCallback( + [ + '/^(\+.*)/', + '/^(\-.*)/', + '/^(@.*)/', + ], + static function ($matches) { + if ('+' === $matches[0][0]) { + $colour = 'green'; + } elseif ('-' === $matches[0][0]) { + $colour = 'red'; + } else { + $colour = 'cyan'; + } + + return sprintf('<fg=%s>%s</fg=%s>', $colour, OutputFormatter::escape($matches[0]), $colour); + }, + $line, + 1, + $count + ); + + if (0 === $count) { + $line = OutputFormatter::escape($line); + } + } + + return sprintf($lineTemplate, $line); + }, + Preg::split('#\R#u', $diff) + ) + ) + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Differ/DifferInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Differ/DifferInterface.php new file mode 100644 index 0000000..e530d26 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Differ/DifferInterface.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Differ; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +interface DifferInterface +{ + /** + * Create diff. + * + * @param string $old + * @param string $new + * + * @return string + * + * TODO: on 3.0 pass the file name (if applicable) for which this diff is + */ + public function diff($old, $new); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Differ/FullDiffer.php b/vendor/friendsofphp/php-cs-fixer/src/Differ/FullDiffer.php new file mode 100644 index 0000000..9dcb7cc --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Differ/FullDiffer.php @@ -0,0 +1,48 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Differ; + +use PhpCsFixer\Diff\v3_0\Differ; +use PhpCsFixer\Diff\v3_0\Output\StrictUnifiedDiffOutputBuilder; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FullDiffer implements DifferInterface +{ + /** + * @var Differ + */ + private $differ; + + public function __construct() + { + $this->differ = new Differ(new StrictUnifiedDiffOutputBuilder([ + 'collapseRanges' => false, + 'commonLineThreshold' => 100, + 'contextLines' => 100, + 'fromFile' => 'Original', + 'toFile' => 'New', + ])); + } + + /** + * {@inheritdoc} + */ + public function diff($old, $new) + { + return $this->differ->diff($old, $new); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Differ/NullDiffer.php b/vendor/friendsofphp/php-cs-fixer/src/Differ/NullDiffer.php new file mode 100644 index 0000000..12399c4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Differ/NullDiffer.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Differ; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NullDiffer implements DifferInterface +{ + /** + * {@inheritdoc} + */ + public function diff($old, $new) + { + return ''; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Differ/SebastianBergmannDiffer.php b/vendor/friendsofphp/php-cs-fixer/src/Differ/SebastianBergmannDiffer.php new file mode 100644 index 0000000..d829dbc --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Differ/SebastianBergmannDiffer.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Differ; + +use PhpCsFixer\Diff\v1_4\Differ; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class SebastianBergmannDiffer implements DifferInterface +{ + /** + * @var Differ + */ + private $differ; + + public function __construct() + { + $this->differ = new Differ(); + } + + /** + * {@inheritdoc} + */ + public function diff($old, $new) + { + return $this->differ->diff($old, $new); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Differ/SebastianBergmannShortDiffer.php b/vendor/friendsofphp/php-cs-fixer/src/Differ/SebastianBergmannShortDiffer.php new file mode 100644 index 0000000..4c7f2e2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Differ/SebastianBergmannShortDiffer.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Differ; + +use PhpCsFixer\Diff\v1_4\Differ; + +/** + * @author SpacePossum + */ +final class SebastianBergmannShortDiffer implements DifferInterface +{ + /** + * @var Differ + */ + private $differ; + + public function __construct() + { + $this->differ = new Differ("--- Original\n+++ New\n", false); + } + + /** + * {@inheritdoc} + */ + public function diff($old, $new) + { + return $this->differ->diff($old, $new); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Differ/UnifiedDiffer.php b/vendor/friendsofphp/php-cs-fixer/src/Differ/UnifiedDiffer.php new file mode 100644 index 0000000..aa88a64 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Differ/UnifiedDiffer.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Differ; + +use PhpCsFixer\Diff\v3_0\Differ; +use PhpCsFixer\Diff\v3_0\Output\StrictUnifiedDiffOutputBuilder; + +/** + * @author SpacePossum + */ +final class UnifiedDiffer implements DifferInterface +{ + /** + * @var Differ + */ + private $differ; + + public function __construct() + { + $this->differ = new Differ(new StrictUnifiedDiffOutputBuilder([ + 'fromFile' => 'Original', + 'toFile' => 'New', + ])); + } + + /** + * {@inheritdoc} + */ + public function diff($old, $new) + { + return $this->differ->diff($old, $new); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/DocBlock/Annotation.php b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/Annotation.php new file mode 100644 index 0000000..f19572d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/Annotation.php @@ -0,0 +1,320 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\DocBlock; + +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis; + +/** + * This represents an entire annotation from a docblock. + * + * @author Graham Campbell <graham@alt-three.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @final + */ +class Annotation +{ + /** + * All the annotation tag names with types. + * + * @var string[] + */ + private static $tags = [ + 'method', + 'param', + 'property', + 'property-read', + 'property-write', + 'return', + 'throws', + 'type', + 'var', + ]; + + /** + * The lines that make up the annotation. + * + * @var Line[] + */ + private $lines; + + /** + * The position of the first line of the annotation in the docblock. + * + * @var int + */ + private $start; + + /** + * The position of the last line of the annotation in the docblock. + * + * @var int + */ + private $end; + + /** + * The associated tag. + * + * @var null|Tag + */ + private $tag; + + /** + * Lazy loaded, cached types content. + * + * @var null|string + */ + private $typesContent; + + /** + * The cached types. + * + * @var null|string[] + */ + private $types; + + /** + * @var null|NamespaceAnalysis + */ + private $namespace; + + /** + * @var NamespaceUseAnalysis[] + */ + private $namespaceUses; + + /** + * Create a new line instance. + * + * @param Line[] $lines + * @param null|NamespaceAnalysis $namespace + * @param NamespaceUseAnalysis[] $namespaceUses + */ + public function __construct(array $lines, $namespace = null, array $namespaceUses = []) + { + $this->lines = array_values($lines); + $this->namespace = $namespace; + $this->namespaceUses = $namespaceUses; + + $keys = array_keys($lines); + + $this->start = $keys[0]; + $this->end = end($keys); + } + + /** + * Get the string representation of object. + * + * @return string + */ + public function __toString() + { + return $this->getContent(); + } + + /** + * Get all the annotation tag names with types. + * + * @return string[] + */ + public static function getTagsWithTypes() + { + return self::$tags; + } + + /** + * Get the start position of this annotation. + * + * @return int + */ + public function getStart() + { + return $this->start; + } + + /** + * Get the end position of this annotation. + * + * @return int + */ + public function getEnd() + { + return $this->end; + } + + /** + * Get the associated tag. + * + * @return Tag + */ + public function getTag() + { + if (null === $this->tag) { + $this->tag = new Tag($this->lines[0]); + } + + return $this->tag; + } + + /** + * @return TypeExpression + * + * @internal + */ + public function getTypeExpression() + { + return new TypeExpression($this->getTypesContent(), $this->namespace, $this->namespaceUses); + } + + /** + * @return null|string + * + * @internal + */ + public function getVariableName() + { + $type = preg_quote($this->getTypesContent(), '/'); + $regex = "/@{$this->tag->getName()}\\s+{$type}\\s+(?<variable>\\$.+?)(?:[\\s*]|$)/"; + + if (Preg::match($regex, $this->lines[0]->getContent(), $matches)) { + return $matches['variable']; + } + + return null; + } + + /** + * Get the types associated with this annotation. + * + * @return string[] + */ + public function getTypes() + { + if (null === $this->types) { + $this->types = $this->getTypeExpression()->getTypes(); + } + + return $this->types; + } + + /** + * Set the types associated with this annotation. + * + * @param string[] $types + */ + public function setTypes(array $types) + { + $pattern = '/'.preg_quote($this->getTypesContent(), '/').'/'; + + $this->lines[0]->setContent(Preg::replace($pattern, implode('|', $types), $this->lines[0]->getContent(), 1)); + + $this->clearCache(); + } + + /** + * Get the normalized types associated with this annotation, so they can easily be compared. + * + * @return string[] + */ + public function getNormalizedTypes() + { + $normalized = array_map(static function ($type) { + return strtolower($type); + }, $this->getTypes()); + + sort($normalized); + + return $normalized; + } + + /** + * Remove this annotation by removing all its lines. + */ + public function remove() + { + foreach ($this->lines as $line) { + if ($line->isTheStart() && $line->isTheEnd()) { + // Single line doc block, remove entirely + $line->remove(); + } elseif ($line->isTheStart()) { + // Multi line doc block, but start is on the same line as the first annotation, keep only the start + $content = Preg::replace('#(\s*/\*\*).*#', '$1', $line->getContent()); + + $line->setContent($content); + } elseif ($line->isTheEnd()) { + // Multi line doc block, but end is on the same line as the last annotation, keep only the end + $content = Preg::replace('#(\s*)\S.*(\*/.*)#', '$1$2', $line->getContent()); + + $line->setContent($content); + } else { + // Multi line doc block, neither start nor end on this line, can be removed safely + $line->remove(); + } + } + + $this->clearCache(); + } + + /** + * Get the annotation content. + * + * @return string + */ + public function getContent() + { + return implode('', $this->lines); + } + + public function supportTypes() + { + return \in_array($this->getTag()->getName(), self::$tags, true); + } + + /** + * Get the current types content. + * + * Be careful modifying the underlying line as that won't flush the cache. + * + * @return string + */ + private function getTypesContent() + { + if (null === $this->typesContent) { + $name = $this->getTag()->getName(); + + if (!$this->supportTypes()) { + throw new \RuntimeException('This tag does not support types.'); + } + + $matchingResult = Preg::match( + '{^(?:\s*\*|/\*\*)\s*@'.$name.'\s+'.TypeExpression::REGEX_TYPES.'(?:[*\h\v].*)?\r?$}sx', + $this->lines[0]->getContent(), + $matches + ); + + $this->typesContent = 1 === $matchingResult + ? $matches['types'] + : ''; + } + + return $this->typesContent; + } + + private function clearCache() + { + $this->types = null; + $this->typesContent = null; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/DocBlock/DocBlock.php b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/DocBlock.php new file mode 100644 index 0000000..8ca3142 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/DocBlock.php @@ -0,0 +1,288 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\DocBlock; + +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis; + +/** + * This class represents a docblock. + * + * It internally splits it up into "lines" that we can manipulate. + * + * @author Graham Campbell <graham@alt-three.com> + * + * @final + */ +class DocBlock +{ + /** + * The array of lines. + * + * @var Line[] + */ + private $lines = []; + + /** + * The array of annotations. + * + * @var null|Annotation[] + */ + private $annotations; + + /** + * @var null|NamespaceAnalysis + */ + private $namespace; + + /** + * @var NamespaceUseAnalysis[] + */ + private $namespaceUses; + + /** + * Create a new docblock instance. + * + * @param string $content + * @param null|NamespaceAnalysis $namespace + * @param NamespaceUseAnalysis[] $namespaceUses + */ + public function __construct($content, $namespace = null, array $namespaceUses = []) + { + foreach (Preg::split('/([^\n\r]+\R*)/', $content, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $line) { + $this->lines[] = new Line($line); + } + + $this->namespace = $namespace; + $this->namespaceUses = $namespaceUses; + } + + /** + * Get the string representation of object. + * + * @return string + */ + public function __toString() + { + return $this->getContent(); + } + + /** + * Get this docblock's lines. + * + * @return Line[] + */ + public function getLines() + { + return $this->lines; + } + + /** + * Get a single line. + * + * @param int $pos + * + * @return null|Line + */ + public function getLine($pos) + { + return isset($this->lines[$pos]) ? $this->lines[$pos] : null; + } + + /** + * Get this docblock's annotations. + * + * @return Annotation[] + */ + public function getAnnotations() + { + if (null !== $this->annotations) { + return $this->annotations; + } + + $this->annotations = []; + $total = \count($this->lines); + + for ($index = 0; $index < $total; ++$index) { + if ($this->lines[$index]->containsATag()) { + // get all the lines that make up the annotation + $lines = \array_slice($this->lines, $index, $this->findAnnotationLength($index), true); + $annotation = new Annotation($lines, $this->namespace, $this->namespaceUses); + // move the index to the end of the annotation to avoid + // checking it again because we know the lines inside the + // current annotation cannot be part of another annotation + $index = $annotation->getEnd(); + // add the current annotation to the list of annotations + $this->annotations[] = $annotation; + } + } + + return $this->annotations; + } + + public function isMultiLine() + { + return 1 !== \count($this->lines); + } + + /** + * Take a one line doc block, and turn it into a multi line doc block. + * + * @param string $indent + * @param string $lineEnd + */ + public function makeMultiLine($indent, $lineEnd) + { + if ($this->isMultiLine()) { + return; + } + + $lineContent = $this->getSingleLineDocBlockEntry($this->lines[0]); + + if ('' === $lineContent) { + $this->lines = [ + new Line('/**'.$lineEnd), + new Line($indent.' *'.$lineEnd), + new Line($indent.' */'), + ]; + + return; + } + + $this->lines = [ + new Line('/**'.$lineEnd), + new Line($indent.' * '.$lineContent.$lineEnd), + new Line($indent.' */'), + ]; + } + + public function makeSingleLine() + { + if (!$this->isMultiLine()) { + return; + } + + $usefulLines = array_filter( + $this->lines, + static function (Line $line) { + return $line->containsUsefulContent(); + } + ); + + if (1 < \count($usefulLines)) { + return; + } + + $lineContent = ''; + if (\count($usefulLines)) { + $lineContent = $this->getSingleLineDocBlockEntry(array_shift($usefulLines)); + } + + $this->lines = [new Line('/** '.$lineContent.' */')]; + } + + /** + * @param int $pos + * + * @return null|Annotation + */ + public function getAnnotation($pos) + { + $annotations = $this->getAnnotations(); + + return isset($annotations[$pos]) ? $annotations[$pos] : null; + } + + /** + * Get specific types of annotations only. + * + * If none exist, we're returning an empty array. + * + * @param string|string[] $types + * + * @return Annotation[] + */ + public function getAnnotationsOfType($types) + { + $annotations = []; + $types = (array) $types; + + foreach ($this->getAnnotations() as $annotation) { + $tag = $annotation->getTag()->getName(); + foreach ($types as $type) { + if ($type === $tag) { + $annotations[] = $annotation; + } + } + } + + return $annotations; + } + + /** + * Get the actual content of this docblock. + * + * @return string + */ + public function getContent() + { + return implode('', $this->lines); + } + + private function findAnnotationLength($start) + { + $index = $start; + + while ($line = $this->getLine(++$index)) { + if ($line->containsATag()) { + // we've 100% reached the end of the description if we get here + break; + } + + if (!$line->containsUsefulContent()) { + // if next line is also non-useful, or contains a tag, then we're done here + $next = $this->getLine($index + 1); + if (null === $next || !$next->containsUsefulContent() || $next->containsATag()) { + break; + } + // otherwise, continue, the annotation must have contained a blank line in its description + } + } + + return $index - $start; + } + + /** + * @return string + */ + private function getSingleLineDocBlockEntry(Line $line) + { + $lineString = $line->getContent(); + + if (0 === \strlen($lineString)) { + return $lineString; + } + + $lineString = str_replace('*/', '', $lineString); + $lineString = trim($lineString); + + if ('/**' === substr($lineString, 0, 3)) { + $lineString = substr($lineString, 3); + } elseif ('*' === substr($lineString, 0, 1)) { + $lineString = substr($lineString, 1); + } + + return trim($lineString); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Line.php b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/Line.php similarity index 84% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Line.php rename to vendor/friendsofphp/php-cs-fixer/src/DocBlock/Line.php index db2ed49..e1eadf6 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/Line.php +++ b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/Line.php @@ -10,12 +10,16 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\DocBlock; +namespace PhpCsFixer\DocBlock; + +use PhpCsFixer\Preg; /** * This represents a line of a docblock. * * @author Graham Campbell <graham@alt-three.com> + * + * @final */ class Line { @@ -49,7 +53,7 @@ public function __toString() /** * Get the content of this line. * - * @return int + * @return string */ public function getContent() { @@ -65,7 +69,7 @@ public function getContent() */ public function containsUsefulContent() { - return 0 !== preg_match('/\\*\s*\S+/', $this->content) && !$this->isTheStart() && !$this->isTheEnd(); + return 0 !== Preg::match('/\\*\s*\S+/', $this->content) && '' !== trim(str_replace(['/', '*'], ' ', $this->content)); } /** @@ -77,7 +81,7 @@ public function containsUsefulContent() */ public function containsATag() { - return 0 !== preg_match('/\\*\s*@/', $this->content); + return 0 !== Preg::match('/\\*\s*@/', $this->content); } /** @@ -131,8 +135,12 @@ public function remove() */ public function addBlank() { - preg_match_all('/\ *\*/', $this->content, $matches); + $matched = Preg::match('/^(\h*\*)[^\r\n]*(\r?\n)$/', $this->content, $matches); + + if (1 !== $matched) { + return; + } - $this->content .= $matches[0][0]."\n"; + $this->content .= $matches[1].$matches[2]; } } diff --git a/vendor/friendsofphp/php-cs-fixer/src/DocBlock/ShortDescription.php b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/ShortDescription.php new file mode 100644 index 0000000..e4228ba --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/ShortDescription.php @@ -0,0 +1,65 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\DocBlock; + +/** + * This class represents a short description (aka summary) of a docblock. + * + * @internal + */ +final class ShortDescription +{ + /** + * The docblock containing the short description. + * + * @var DocBlock + */ + private $doc; + + public function __construct(DocBlock $doc) + { + $this->doc = $doc; + } + + /** + * Get the line index of the line containing the end of the short + * description, if present. + * + * @return null|int + */ + public function getEnd() + { + $reachedContent = false; + + foreach ($this->doc->getLines() as $index => $line) { + // we went past a description, then hit a tag or blank line, so + // the last line of the description must be the one before this one + if ($reachedContent && ($line->containsATag() || !$line->containsUsefulContent())) { + return $index - 1; + } + + // no short description was found + if ($line->containsATag()) { + return null; + } + + // we've reached content, but need to check the next lines too + // in case the short description is multi-line + if ($line->containsUsefulContent()) { + $reachedContent = true; + } + } + + return null; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/DocBlock/Tag.php b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/Tag.php new file mode 100644 index 0000000..299e2b4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/Tag.php @@ -0,0 +1,113 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\DocBlock; + +use PhpCsFixer\Preg; + +/** + * This represents a tag, as defined by the proposed PSR PHPDoc standard. + * + * @author Graham Campbell <graham@alt-three.com> + * + * @final + */ +class Tag +{ + /** + * All the tags defined by the proposed PSR PHPDoc standard. + * + * @var string[] + */ + private static $tags = [ + 'api', 'author', 'category', 'copyright', 'deprecated', 'example', + 'global', 'internal', 'license', 'link', 'method', 'package', 'param', + 'property', 'property-read', 'property-write', 'return', 'see', + 'since', 'subpackage', 'throws', 'todo', 'uses', 'var', 'version', + ]; + + /** + * The line containing the tag. + * + * @var Line + */ + private $line; + + /** + * The cached tag name. + * + * @var null|string + */ + private $name; + + /** + * Create a new tag instance. + */ + public function __construct(Line $line) + { + $this->line = $line; + } + + /** + * Get the tag name. + * + * This may be "param", or "return", etc. + * + * @return string + */ + public function getName() + { + if (null === $this->name) { + Preg::matchAll('/@[a-zA-Z0-9_-]+(?=\s|$)/', $this->line->getContent(), $matches); + + if (isset($matches[0][0])) { + $this->name = ltrim($matches[0][0], '@'); + } else { + $this->name = 'other'; + } + } + + return $this->name; + } + + /** + * Set the tag name. + * + * This will also be persisted to the upstream line and annotation. + * + * @param string $name + */ + public function setName($name) + { + $current = $this->getName(); + + if ('other' === $current) { + throw new \RuntimeException('Cannot set name on unknown tag.'); + } + + $this->line->setContent(Preg::replace("/@{$current}/", "@{$name}", $this->line->getContent(), 1)); + + $this->name = $name; + } + + /** + * Is the tag a known tag? + * + * This is defined by if it exists in the proposed PSR PHPDoc standard. + * + * @return bool + */ + public function valid() + { + return \in_array($this->getName(), self::$tags, true); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/TagComparator.php b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/TagComparator.php similarity index 70% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/TagComparator.php rename to vendor/friendsofphp/php-cs-fixer/src/DocBlock/TagComparator.php index 4ac510f..d31fd09 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/DocBlock/TagComparator.php +++ b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/TagComparator.php @@ -10,13 +10,15 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\DocBlock; +namespace PhpCsFixer\DocBlock; /** * This class is responsible for comparing tags to see if they should be kept * together, or kept apart. * * @author Graham Campbell <graham@alt-three.com> + * + * @final */ class TagComparator { @@ -25,19 +27,16 @@ class TagComparator * * @var array */ - private static $groups = array( - array('deprecated', 'link', 'see', 'since'), - array('author', 'copyright', 'license'), - array('category', 'package', 'subpackage'), - array('property', 'property-read', 'property-write'), - ); + private static $groups = [ + ['deprecated', 'link', 'see', 'since'], + ['author', 'copyright', 'license'], + ['category', 'package', 'subpackage'], + ['property', 'property-read', 'property-write'], + ]; /** * Should the given tags be kept together, or kept apart? * - * @param Tag $first - * @param Tag $second - * * @return bool */ public static function shouldBeTogether(Tag $first, Tag $second) @@ -50,7 +49,7 @@ public static function shouldBeTogether(Tag $first, Tag $second) } foreach (self::$groups as $group) { - if (in_array($firstName, $group, true) && in_array($secondName, $group, true)) { + if (\in_array($firstName, $group, true) && \in_array($secondName, $group, true)) { return true; } } diff --git a/vendor/friendsofphp/php-cs-fixer/src/DocBlock/TypeExpression.php b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/TypeExpression.php new file mode 100644 index 0000000..1e68589 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/DocBlock/TypeExpression.php @@ -0,0 +1,293 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\DocBlock; + +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis; + +/** + * @internal + */ +final class TypeExpression +{ + /** + * Regex to match any types, shall be used with `x` modifier. + */ + const REGEX_TYPES = ' + (?<types> # alternation of several types separated by `|` + (?<type> # single type + \?? # optionally nullable + (?: + (?<object_like_array> + array\h*\{ + (?<object_like_array_key> + \h*[^?:\h]+\h*\??\h*:\h*(?&types) + ) + (?:\h*,(?&object_like_array_key))* + \h*\} + ) + | + (?<callable> # callable syntax, e.g. `callable(string): bool` + (?:callable|Closure)\h*\(\h* + (?&types) + (?: + \h*,\h* + (?&types) + )* + \h*\) + (?: + \h*\:\h* + (?&types) + )? + ) + | + (?<generic> # generic syntax, e.g.: `array<int, \Foo\Bar>` + (?&name)+ + \h*<\h* + (?&types) + (?: + \h*,\h* + (?&types) + )* + \h*> + ) + | + (?<class_constant> # class constants with optional wildcard, e.g.: `Foo::*`, `Foo::CONST_A`, `FOO::CONST_*` + (?&name)::(\*|\w+\*?) + ) + | + (?<array> # array expression, e.g.: `string[]`, `string[][]` + (?&name)(\[\])+ + ) + | + (?<constant> # single constant value (case insensitive), e.g.: 1, `\'a\'` + (?i) + null | true | false + | [\d.]+ + | \'[^\']+?\' | "[^"]+?" + | [@$]?(?:this | self | static) + (?-i) + ) + | + (?<name> # single type, e.g.: `null`, `int`, `\Foo\Bar` + [\\\\\w-]++ + ) + ) + (?: # intersection + \h*&\h* + (?&type) + )* + ) + (?: + \h*\|\h* + (?&type) + )* + ) + '; + + /** + * @var string[] + */ + private $types = []; + + /** + * @var null|NamespaceAnalysis + */ + private $namespace; + + /** + * @var NamespaceUseAnalysis[] + */ + private $namespaceUses; + + /** + * @param string $value + * @param null|NamespaceAnalysis $namespace + * @param NamespaceUseAnalysis[] $namespaceUses + */ + public function __construct($value, $namespace, array $namespaceUses) + { + while ('' !== $value && false !== $value) { + Preg::match( + '{^'.self::REGEX_TYPES.'$}x', + $value, + $matches + ); + + $this->types[] = $matches['type']; + $value = Preg::replace( + '/^'.preg_quote($matches['type'], '/').'(\h*\|\h*)?/', + '', + $value + ); + } + + $this->namespace = $namespace; + $this->namespaceUses = $namespaceUses; + } + + /** + * @return string[] + */ + public function getTypes() + { + return $this->types; + } + + /** + * @return null|string + */ + public function getCommonType() + { + $aliases = [ + 'true' => 'bool', + 'false' => 'bool', + 'boolean' => 'bool', + 'integer' => 'int', + 'double' => 'float', + 'real' => 'float', + 'callback' => 'callable', + ]; + + $mainType = null; + + foreach ($this->types as $type) { + if ('null' === $type) { + continue; + } + + if (isset($aliases[$type])) { + $type = $aliases[$type]; + } elseif (1 === Preg::match('/\[\]$/', $type)) { + $type = 'array'; + } elseif (1 === Preg::match('/^(.+?)</', $type, $matches)) { + $type = $matches[1]; + } + + if (null === $mainType || $type === $mainType) { + $mainType = $type; + + continue; + } + + $mainType = $this->getParentType($type, $mainType); + + if (null === $mainType) { + return null; + } + } + + return $mainType; + } + + /** + * @return bool + */ + public function allowsNull() + { + foreach ($this->types as $type) { + if (\in_array($type, ['null', 'mixed'], true)) { + return true; + } + } + + return false; + } + + private function getParentType($type1, $type2) + { + $types = [ + $this->normalize($type1), + $this->normalize($type2), + ]; + natcasesort($types); + $types = implode('|', $types); + + $parents = [ + 'array|iterable' => 'iterable', + 'array|Traversable' => 'iterable', + 'iterable|Traversable' => 'iterable', + 'self|static' => 'self', + ]; + + if (isset($parents[$types])) { + return $parents[$types]; + } + + return null; + } + + /** + * @param string $type + * + * @return string + */ + private function normalize($type) + { + $aliases = [ + 'true' => 'bool', + 'false' => 'bool', + 'boolean' => 'bool', + 'integer' => 'int', + 'double' => 'float', + 'real' => 'float', + 'callback' => 'callable', + ]; + + if (isset($aliases[$type])) { + return $aliases[$type]; + } + + if (\in_array($type, [ + 'void', + 'null', + 'bool', + 'int', + 'float', + 'string', + 'array', + 'iterable', + 'object', + 'callable', + 'resource', + 'mixed', + ], true)) { + return $type; + } + + if (1 === Preg::match('/\[\]$/', $type)) { + return 'array'; + } + + if (1 === Preg::match('/^(.+?)</', $type, $matches)) { + return $matches[1]; + } + + if (0 === strpos($type, '\\')) { + return substr($type, 1); + } + + foreach ($this->namespaceUses as $namespaceUse) { + if ($namespaceUse->getShortName() === $type) { + return $namespaceUse->getFullName(); + } + } + + if (null === $this->namespace || '' === $this->namespace->getShortName()) { + return $type; + } + + return "{$this->namespace->getFullName()}\\{$type}"; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Doctrine/Annotation/Token.php b/vendor/friendsofphp/php-cs-fixer/src/Doctrine/Annotation/Token.php new file mode 100644 index 0000000..890b5e4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Doctrine/Annotation/Token.php @@ -0,0 +1,99 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Doctrine\Annotation; + +use Doctrine\Common\Annotations\DocLexer; + +/** + * A Doctrine annotation token. + * + * @internal + */ +final class Token +{ + /** + * @var int + */ + private $type; + + /** + * @var string + */ + private $content; + + /** + * @param int $type The type + * @param string $content The content + */ + public function __construct($type = DocLexer::T_NONE, $content = '') + { + $this->type = $type; + $this->content = $content; + } + + /** + * @return int + */ + public function getType() + { + return $this->type; + } + + /** + * @param int $type + */ + public function setType($type) + { + $this->type = $type; + } + + /** + * @return string + */ + public function getContent() + { + return $this->content; + } + + /** + * @param string $content + */ + public function setContent($content) + { + $this->content = $content; + } + + /** + * Returns whether the token type is one of the given types. + * + * @param int|int[] $types + * + * @return bool + */ + public function isType($types) + { + if (!\is_array($types)) { + $types = [$types]; + } + + return \in_array($this->getType(), $types, true); + } + + /** + * Overrides the content with an empty string. + */ + public function clear() + { + $this->setContent(''); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Doctrine/Annotation/Tokens.php b/vendor/friendsofphp/php-cs-fixer/src/Doctrine/Annotation/Tokens.php new file mode 100644 index 0000000..141e1b3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Doctrine/Annotation/Tokens.php @@ -0,0 +1,378 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Doctrine\Annotation; + +use Doctrine\Common\Annotations\DocLexer; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token as PhpToken; + +/** + * A list of Doctrine annotation tokens. + * + * @internal + */ +final class Tokens extends \SplFixedArray +{ + /** + * @param string[] $ignoredTags + * + * @throws \InvalidArgumentException + * + * @return self + */ + public static function createFromDocComment(PhpToken $input, array $ignoredTags = []) + { + if (!$input->isGivenKind(T_DOC_COMMENT)) { + throw new \InvalidArgumentException('Input must be a T_DOC_COMMENT token.'); + } + + $tokens = new self(); + + $content = $input->getContent(); + $ignoredTextPosition = 0; + $currentPosition = 0; + $token = null; + while (false !== $nextAtPosition = strpos($content, '@', $currentPosition)) { + if (0 !== $nextAtPosition && !Preg::match('/\s/', $content[$nextAtPosition - 1])) { + $currentPosition = $nextAtPosition + 1; + + continue; + } + + $lexer = new DocLexer(); + $lexer->setInput(substr($content, $nextAtPosition)); + + $scannedTokens = []; + $index = 0; + $nbScannedTokensToUse = 0; + $nbScopes = 0; + while (null !== $token = $lexer->peek()) { + if (0 === $index && DocLexer::T_AT !== $token['type']) { + break; + } + + if (1 === $index) { + if (DocLexer::T_IDENTIFIER !== $token['type'] || \in_array($token['value'], $ignoredTags, true)) { + break; + } + + $nbScannedTokensToUse = 2; + } + + if ($index >= 2 && 0 === $nbScopes && !\in_array($token['type'], [DocLexer::T_NONE, DocLexer::T_OPEN_PARENTHESIS], true)) { + break; + } + + $scannedTokens[] = $token; + + if (DocLexer::T_OPEN_PARENTHESIS === $token['type']) { + ++$nbScopes; + } elseif (DocLexer::T_CLOSE_PARENTHESIS === $token['type']) { + if (0 === --$nbScopes) { + $nbScannedTokensToUse = \count($scannedTokens); + + break; + } + } + + ++$index; + } + + if (0 !== $nbScopes) { + break; + } + + if (0 !== $nbScannedTokensToUse) { + $ignoredTextLength = $nextAtPosition - $ignoredTextPosition; + if (0 !== $ignoredTextLength) { + $tokens[] = new Token(DocLexer::T_NONE, substr($content, $ignoredTextPosition, $ignoredTextLength)); + } + + $lastTokenEndIndex = 0; + foreach (\array_slice($scannedTokens, 0, $nbScannedTokensToUse) as $token) { + if (DocLexer::T_STRING === $token['type']) { + $token['value'] = '"'.str_replace('"', '""', $token['value']).'"'; + } + + $missingTextLength = $token['position'] - $lastTokenEndIndex; + if ($missingTextLength > 0) { + $tokens[] = new Token(DocLexer::T_NONE, substr( + $content, + $nextAtPosition + $lastTokenEndIndex, + $missingTextLength + )); + } + + $tokens[] = new Token($token['type'], $token['value']); + $lastTokenEndIndex = $token['position'] + \strlen($token['value']); + } + + $currentPosition = $ignoredTextPosition = $nextAtPosition + $token['position'] + \strlen($token['value']); + } else { + $currentPosition = $nextAtPosition + 1; + } + } + + if ($ignoredTextPosition < \strlen($content)) { + $tokens[] = new Token(DocLexer::T_NONE, substr($content, $ignoredTextPosition)); + } + + return $tokens; + } + + /** + * Returns the index of the closest next token that is neither a comment nor a whitespace token. + * + * @param int $index + * + * @return null|int + */ + public function getNextMeaningfulToken($index) + { + return $this->getMeaningfulTokenSibling($index, 1); + } + + /** + * Returns the index of the closest previous token that is neither a comment nor a whitespace token. + * + * @param int $index + * + * @return null|int + */ + public function getPreviousMeaningfulToken($index) + { + return $this->getMeaningfulTokenSibling($index, -1); + } + + /** + * Returns the index of the closest next token of the given type. + * + * @param string|string[] $type + * @param int $index + * + * @return null|int + */ + public function getNextTokenOfType($type, $index) + { + return $this->getTokenOfTypeSibling($index, $type, 1); + } + + /** + * Returns the index of the closest previous token of the given type. + * + * @param string|string[] $type + * @param int $index + * + * @return null|int + */ + public function getPreviousTokenOfType($type, $index) + { + return $this->getTokenOfTypeSibling($index, $type, -1); + } + + /** + * Returns the index of the last token that is part of the annotation at the given index. + * + * @param int $index + * + * @return null|int + */ + public function getAnnotationEnd($index) + { + $currentIndex = null; + + if (isset($this[$index + 2])) { + if ($this[$index + 2]->isType(DocLexer::T_OPEN_PARENTHESIS)) { + $currentIndex = $index + 2; + } elseif ( + isset($this[$index + 3]) + && $this[$index + 2]->isType(DocLexer::T_NONE) + && $this[$index + 3]->isType(DocLexer::T_OPEN_PARENTHESIS) + && Preg::match('/^(\R\s*\*\s*)*\s*$/', $this[$index + 2]->getContent()) + ) { + $currentIndex = $index + 3; + } + } + + if (null !== $currentIndex) { + $level = 0; + for ($max = \count($this); $currentIndex < $max; ++$currentIndex) { + if ($this[$currentIndex]->isType(DocLexer::T_OPEN_PARENTHESIS)) { + ++$level; + } elseif ($this[$currentIndex]->isType(DocLexer::T_CLOSE_PARENTHESIS)) { + --$level; + } + + if (0 === $level) { + return $currentIndex; + } + } + + return null; + } + + return $index + 1; + } + + /** + * Returns the index of the close brace that matches the open brace at the given index. + * + * @param int $index + * + * @return null|int + */ + public function getArrayEnd($index) + { + $level = 1; + for (++$index, $max = \count($this); $index < $max; ++$index) { + if ($this[$index]->isType(DocLexer::T_OPEN_CURLY_BRACES)) { + ++$level; + } elseif ($this[$index]->isType($index, DocLexer::T_CLOSE_CURLY_BRACES)) { + --$level; + } + + if (0 === $level) { + return $index; + } + } + + return null; + } + + /** + * Returns the code from the tokens. + * + * @return string + */ + public function getCode() + { + $code = ''; + foreach ($this as $token) { + $code .= $token->getContent(); + } + + return $code; + } + + /** + * Inserts a token at the given index. + * + * @param int $index + */ + public function insertAt($index, Token $token) + { + $this->setSize($this->getSize() + 1); + + for ($i = $this->getSize() - 1; $i > $index; --$i) { + $this[$i] = isset($this[$i - 1]) ? $this[$i - 1] : new Token(); + } + + $this[$index] = $token; + } + + /** + * {@inheritdoc} + * + * @throws \InvalidArgumentException + */ + public function offsetSet($index, $token) + { + if (!$token instanceof Token) { + $type = \gettype($token); + if ('object' === $type) { + $type = \get_class($token); + } + + throw new \InvalidArgumentException(sprintf( + 'Token must be an instance of PhpCsFixer\\Doctrine\\Annotation\\Token, %s given.', + $type + )); + } + + if (null === $index) { + $index = \count($this); + $this->setSize($this->getSize() + 1); + } + + parent::offsetSet($index, $token); + } + + /** + * {@inheritdoc} + * + * @throws \OutOfBoundsException + */ + public function offsetUnset($index) + { + if (!isset($this[$index])) { + throw new \OutOfBoundsException(sprintf('Index "%s" is invalid or does not exist.', $index)); + } + + $max = \count($this) - 1; + while ($index < $max) { + $this[$index] = $this[$index + 1]; + ++$index; + } + + parent::offsetUnset($index); + + $this->setSize($max); + } + + /** + * @param int $index + * @param int $direction + * + * @return null|int + */ + private function getMeaningfulTokenSibling($index, $direction) + { + while (true) { + $index += $direction; + + if (!$this->offsetExists($index)) { + break; + } + + if (!$this[$index]->isType(DocLexer::T_NONE)) { + return $index; + } + } + + return null; + } + + /** + * @param int $index + * @param string|string[] $type + * @param int $direction + * + * @return null|int + */ + private function getTokenOfTypeSibling($index, $type, $direction) + { + while (true) { + $index += $direction; + + if (!$this->offsetExists($index)) { + break; + } + + if ($this[$index]->isType($type)) { + return $index; + } + } + + return null; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Documentation/DocumentationGenerator.php b/vendor/friendsofphp/php-cs-fixer/src/Documentation/DocumentationGenerator.php new file mode 100644 index 0000000..c39c055 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Documentation/DocumentationGenerator.php @@ -0,0 +1,556 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Documentation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Console\Command\HelpCommand; +use PhpCsFixer\Differ\FullDiffer; +use PhpCsFixer\Fixer\Basic\Psr0Fixer; +use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\DefinedFixerInterface; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\FixerConfiguration\AliasedFixerOption; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\DeprecatedFixerOptionInterface; +use PhpCsFixer\FixerDefinition\CodeSampleInterface; +use PhpCsFixer\FixerDefinition\FileSpecificCodeSampleInterface; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSampleInterface; +use PhpCsFixer\Preg; +use PhpCsFixer\RuleSet\RuleSet; +use PhpCsFixer\RuleSet\RuleSetDescriptionInterface; +use PhpCsFixer\RuleSet\RuleSets; +use PhpCsFixer\StdinFileInfo; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Utils; + +/** + * @internal + */ +final class DocumentationGenerator +{ + /** + * @var FullDiffer + */ + private $differ; + + /** + * @var string + */ + private $path; + + public function __construct() + { + $this->differ = new FullDiffer(); + + $this->path = \dirname(__DIR__, 2).'/doc'; + } + + /** + * @return string + */ + public function getFixersDocumentationDirectoryPath() + { + return $this->path.'/rules'; + } + + /** + * @return string + */ + public function getFixersDocumentationIndexFilePath() + { + return $this->getFixersDocumentationDirectoryPath().'/index.rst'; + } + + /** + * @param AbstractFixer[] $fixers + * + * @return string + */ + public function generateFixersDocumentationIndex(array $fixers) + { + $overrideGroups = [ + 'PhpUnit' => 'PHPUnit', + 'PhpTag' => 'PHP Tag', + 'Phpdoc' => 'PHPDoc', + ]; + + usort($fixers, function (FixerInterface $a, FixerInterface $b) { + return strcmp(\get_class($a), \get_class($b)); + }); + + $documentation = <<<'RST' +======================= +List of Available Rules +======================= +RST; + + $currentGroup = null; + foreach ($fixers as $fixer) { + $namespace = Preg::replace('/^.*\\\\(.+)\\\\.+Fixer$/', '$1', \get_class($fixer)); + if (isset($overrideGroups[$namespace])) { + $group = $overrideGroups[$namespace]; + } else { + $group = Preg::replace('/(?<=[[:lower:]])(?=[[:upper:]])/', ' ', $namespace); + } + + if ($group !== $currentGroup) { + $underline = str_repeat('-', \strlen($group)); + $documentation .= "\n\n{$group}\n{$underline}\n"; + + $currentGroup = $group; + } + + $summary = str_replace('`', '``', $fixer->getDefinition()->getSummary()); + + $attributes = []; + if ($fixer instanceof DeprecatedFixerInterface) { + $attributes[] = 'deprecated'; + } + if ($fixer->isRisky()) { + $attributes[] = 'risky'; + } + + if ([] !== $attributes) { + $attributes = ' *('.implode(', ', $attributes).')*'; + } else { + $attributes = ''; + } + + $path = './'.$this->getFixerDocumentationFileRelativePath($fixer); + + $documentation .= <<<RST + +- `{$fixer->getName()} <{$path}>`_{$attributes} + {$summary} +RST; + } + + return "{$documentation}\n"; + } + + /** + * @return string + */ + public function getFixerDocumentationFilePath(FixerInterface $fixer) + { + return $this->getFixersDocumentationDirectoryPath().'/'.Preg::replaceCallback( + '/^.*\\\\(.+)\\\\(.+)Fixer$/', + function (array $matches) { + return Utils::camelCaseToUnderscore($matches[1]).'/'.Utils::camelCaseToUnderscore($matches[2]); + }, + \get_class($fixer) + ).'.rst'; + } + + /** + * @return string + */ + public function getFixerDocumentationFileRelativePath(FixerInterface $fixer) + { + return Preg::replace( + '#^'.preg_quote($this->getFixersDocumentationDirectoryPath(), '#').'/#', + '', + $this->getFixerDocumentationFilePath($fixer) + ); + } + + /** + * @return string + */ + public function generateFixerDocumentation(FixerInterface $fixer) + { + $name = $fixer->getName(); + $title = "Rule ``{$name}``"; + $titleLine = str_repeat('=', \strlen($title)); + + $doc = "{$titleLine}\n{$title}\n{$titleLine}"; + + if ($fixer instanceof DeprecatedFixerInterface) { + $doc .= "\n\n.. warning:: This rule is deprecated and will be removed on next major version."; + + $alternatives = $fixer->getSuccessorsNames(); + if ([] !== $alternatives) { + $doc .= $this->toRst(sprintf( + "\n\nYou should use %s instead.", + Utils::naturalLanguageJoinWithBackticks($alternatives) + ), 3); + } + } + + $riskyDescription = null; + $samples = []; + + if ($fixer instanceof DefinedFixerInterface) { + $definition = $fixer->getDefinition(); + + $doc .= "\n\n".$this->toRst($definition->getSummary()); + + $description = $definition->getDescription(); + if (null !== $description) { + $description = $this->toRst($description); + $doc .= <<<RST + + +Description +----------- + +{$description} +RST; + } + + $riskyDescription = $definition->getRiskyDescription(); + $samples = $definition->getCodeSamples(); + } elseif ($fixer->isRisky()) { + $riskyDescription = 'Changes applied by the rule to your code might change its behavior.'; + } + + if (null !== $riskyDescription) { + $riskyDescription = $this->toRst($riskyDescription, 3); + + $doc .= <<<RST + + +.. warning:: Using this rule is risky. + + {$riskyDescription} +RST; + } + + if ($fixer instanceof ConfigurationDefinitionFixerInterface) { + $doc .= <<<'RST' + + +Configuration +------------- +RST; + + $configurationDefinition = $fixer->getConfigurationDefinition(); + + foreach ($configurationDefinition->getOptions() as $option) { + $optionInfo = "``{$option->getName()}``"; + $optionInfo .= "\n".str_repeat('~', \strlen($optionInfo)); + + if ($option instanceof DeprecatedFixerOptionInterface) { + $optionInfo .= "\n\n.. warning:: This option is deprecated and will be removed on next major version. {$this->toRst($option->getDeprecationMessage())}"; + } + + $optionInfo .= "\n\n".$this->toRst($option->getDescription()); + + if ($option instanceof AliasedFixerOption) { + $optionInfo .= "\n\n.. note:: The previous name of this option was ``{$option->getAlias()}`` but it is now deprecated and will be removed on next major version."; + } + + $allowed = HelpCommand::getDisplayableAllowedValues($option); + $allowedKind = 'Allowed values'; + if (null !== $allowed) { + foreach ($allowed as &$value) { + if ($value instanceof AllowedValueSubset) { + $value = 'a subset of ``'.HelpCommand::toString($value->getAllowedValues()).'``'; + } else { + $value = '``'.HelpCommand::toString($value).'``'; + } + } + } else { + $allowedKind = 'Allowed types'; + $allowed = array_map(function ($value) { + return '``'.$value.'``'; + }, $option->getAllowedTypes()); + } + + if (null !== $allowed) { + $allowed = implode(', ', $allowed); + $optionInfo .= "\n\n{$allowedKind}: {$allowed}"; + } + + if ($option->hasDefault()) { + $default = HelpCommand::toString($option->getDefault()); + $optionInfo .= "\n\nDefault value: ``{$default}``"; + } else { + $optionInfo .= "\n\nThis option is required."; + } + + $doc .= "\n\n{$optionInfo}"; + } + } elseif ($fixer instanceof ConfigurableFixerInterface) { + $doc .= "\n\nThis rule is configurable."; + } + + if (0 !== \count($samples)) { + $doc .= <<<'RST' + + +Examples +-------- +RST; + + foreach ($samples as $index => $sample) { + $title = sprintf('Example #%d', $index + 1); + $titleLine = str_repeat('~', \strlen($title)); + $doc .= "\n\n{$title}\n{$titleLine}"; + + if ($fixer instanceof ConfigurableFixerInterface) { + if (null === $sample->getConfiguration()) { + $doc .= "\n\n*Default* configuration."; + } else { + $doc .= sprintf( + "\n\nWith configuration: ``%s``.", + HelpCommand::toString($sample->getConfiguration()) + ); + } + } + + $doc .= "\n".$this->generateSampleDiff($fixer, $sample, $index + 1, $name); + } + } + + $ruleSetConfigs = []; + + foreach (RuleSets::getSetDefinitionNames() as $set) { + $ruleSet = new RuleSet([$set => true]); + + if ($ruleSet->hasRule($name)) { + $ruleSetConfigs[$set] = $ruleSet->getRuleConfiguration($name); + } + } + + if ([] !== $ruleSetConfigs) { + $plural = 1 !== \count($ruleSetConfigs) ? 's' : ''; + $doc .= <<<RST + + +Rule sets +--------- + +The rule is part of the following rule set{$plural}: +RST; + + foreach ($ruleSetConfigs as $set => $config) { + $ruleSetPath = $this->getRuleSetsDocumentationFilePath($set); + $ruleSetPath = substr($ruleSetPath, strrpos($ruleSetPath, '/')); + + $doc .= <<<RST + + +{$set} + Using the `{$set} <./../../ruleSets{$ruleSetPath}>`_ rule set will enable the ``{$name}`` rule +RST; + + if (null !== $config) { + $doc .= " with the config below:\n\n ``".HelpCommand::toString($config).'``'; + } elseif ($fixer instanceof ConfigurationDefinitionFixerInterface) { + $doc .= ' with the default config.'; + } else { + $doc .= '.'; + } + } + } + + return "{$doc}\n"; + } + + /** + * @return string + */ + public function getRuleSetsDocumentationDirectoryPath() + { + return $this->path.'/ruleSets'; + } + + /** + * @return string + */ + public function getRuleSetsDocumentationIndexFilePath() + { + return $this->getRuleSetsDocumentationDirectoryPath().'/index.rst'; + } + + /** + * @param AbstractFixer[] $fixers + * + * @return string + */ + public function generateRuleSetsDocumentation(RuleSetDescriptionInterface $definition, array $fixers) + { + $fixerNames = []; + foreach ($fixers as $fixer) { + $fixerNames[$fixer->getName()] = $fixer; + } + + $title = "Rule set ``{$definition->getName()}``"; + $titleLine = str_repeat('=', \strlen($title)); + $doc = "{$titleLine}\n{$title}\n{$titleLine}\n\n".$definition->getDescription(); + if ($definition->isRisky()) { + $doc .= ' This set contains rules that are risky.'; + } + $doc .= "\n\n"; + + $rules = $definition->getRules(); + + if (\count($rules) < 1) { + $doc .= 'This is an empty set.'; + } else { + $doc .= "Rules\n-----\n"; + + foreach ($rules as $rule => $config) { + if ('@' === $rule[0]) { + $ruleSetPath = $this->getRuleSetsDocumentationFilePath($rule); + $ruleSetPath = substr($ruleSetPath, strrpos($ruleSetPath, '/')); + + $doc .= "\n- `{$rule} <.{$ruleSetPath}>`_"; + } else { + $path = Preg::replace( + '#^'.preg_quote($this->getFixersDocumentationDirectoryPath(), '#').'/#', + './../rules/', + $this->getFixerDocumentationFilePath($fixerNames[$rule]) + ); + + $doc .= "\n- `{$rule} <{$path}>`_"; + } + + if (!\is_bool($config)) { + $doc .= "\n config:\n ``".HelpCommand::toString($config).'``'; + } + } + } + + return $doc."\n"; + } + + /** + * @param string $name + * + * @return string + */ + public function getRuleSetsDocumentationFilePath($name) + { + return $this->getRuleSetsDocumentationDirectoryPath().'/'.str_replace(':risky', 'Risky', ucfirst(substr($name, 1))).'.rst'; + } + + /** + * @return string + */ + public function generateRuleSetsDocumentationIndex(array $setDefinitions) + { + $documentation = <<<'RST' +=========================== +List of Available Rule sets +=========================== +RST; + foreach ($setDefinitions as $name => $path) { + $path = substr($path, strrpos($path, '/')); + $documentation .= "\n- `{$name} <.{$path}>`_"; + } + + return $documentation."\n"; + } + + /** + * @param int $sampleNumber + * @param string $ruleName + * + * @return string + */ + private function generateSampleDiff(FixerInterface $fixer, CodeSampleInterface $sample, $sampleNumber, $ruleName) + { + if ($sample instanceof VersionSpecificCodeSampleInterface && !$sample->isSuitableFor(\PHP_VERSION_ID)) { + $existingFile = @file_get_contents($this->getFixerDocumentationFilePath($fixer)); + + if (false !== $existingFile) { + Preg::match("/\\RExample #{$sampleNumber}\\R.+?(?<diff>\\R\\.\\. code-block:: diff\\R\\R.*?)\\R(?:\\R\\S|$)/s", $existingFile, $matches); + + if (isset($matches['diff'])) { + return $matches['diff']; + } + } + + $error = <<<RST + +.. error:: + Cannot generate diff for code sample #{$sampleNumber} of rule {$ruleName}: + the sample is not suitable for current version of PHP (%s). +RST; + + return sprintf($error, PHP_VERSION); + } + + $old = $sample->getCode(); + + $tokens = Tokens::fromCode($old); + $file = $sample instanceof FileSpecificCodeSampleInterface + ? $sample->getSplFileInfo() + : new StdinFileInfo() + ; + + if ($fixer instanceof ConfigurableFixerInterface) { + $configuration = $sample->getConfiguration(); + + if (null === $configuration) { + $configuration = []; + } + + if ($fixer instanceof Psr0Fixer && isset($configuration['dir']) && 0 === strpos($configuration['dir'], './')) { + // Psr0Fixer relies on realpath() which fails for directories + // relative to some path when the working directory is a + // different path. Using an absolute path prevents this issue. + $configuration['dir'] = \dirname(__DIR__, 2).substr($configuration['dir'], 1); + } + + $fixer->configure($configuration); + } + + $fixer->fix($file, $tokens); + + $diff = $this->differ->diff($old, $tokens->generateCode()); + $diff = Preg::replace('/@@[ \+\-\d,]+@@\n/', '', $diff); + $diff = Preg::replace('/\r/', '^M', $diff); + $diff = Preg::replace('/^ $/m', '', $diff); + $diff = Preg::replace('/\n$/', '', $diff); + + return <<<RST + +.. code-block:: diff + + {$this->indent($diff, 3)} +RST; + } + + /** + * @param string $string + * @param int $indent + * + * @return string + */ + private function toRst($string, $indent = 0) + { + $string = wordwrap(Preg::replace('/(?<!`)(`.*?`)(?!`)/', '`$1`', $string), 80 - $indent); + + if (0 !== $indent) { + $string = $this->indent($string, $indent); + } + + return $string; + } + + /** + * @param string $string + * @param int $indent + * + * @return string + */ + private function indent($string, $indent) + { + return Preg::replace('/(\n)(?!\n|$)/', '$1'.str_repeat(' ', $indent), $string); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Error/Error.php b/vendor/friendsofphp/php-cs-fixer/src/Error/Error.php new file mode 100644 index 0000000..d7aae68 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Error/Error.php @@ -0,0 +1,118 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Error; + +/** + * An abstraction for errors that can occur before and during fixing. + * + * @author Andreas Möller <am@localheinz.com> + * + * @internal + */ +final class Error +{ + /** + * Error which has occurred in linting phase, before applying any fixers. + */ + const TYPE_INVALID = 1; + + /** + * Error which has occurred during fixing phase. + */ + const TYPE_EXCEPTION = 2; + + /** + * Error which has occurred in linting phase, after applying any fixers. + */ + const TYPE_LINT = 3; + + /** + * @var int + */ + private $type; + + /** + * @var string + */ + private $filePath; + + /** + * @var null|\Throwable + */ + private $source; + + /** + * @var array + */ + private $appliedFixers; + + /** + * @var null|string + */ + private $diff; + + /** + * @param int $type + * @param string $filePath + * @param null|\Throwable $source + * @param null|string $diff + */ + public function __construct($type, $filePath, $source = null, array $appliedFixers = [], $diff = null) + { + $this->type = $type; + $this->filePath = $filePath; + $this->source = $source; + $this->appliedFixers = $appliedFixers; + $this->diff = $diff; + } + + /** + * @return string + */ + public function getFilePath() + { + return $this->filePath; + } + + /** + * @return null|\Throwable + */ + public function getSource() + { + return $this->source; + } + + /** + * @return int + */ + public function getType() + { + return $this->type; + } + + /** + * @return array + */ + public function getAppliedFixers() + { + return $this->appliedFixers; + } + + /** + * @return null|string + */ + public function getDiff() + { + return $this->diff; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Error/ErrorsManager.php b/vendor/friendsofphp/php-cs-fixer/src/Error/ErrorsManager.php new file mode 100644 index 0000000..a5d0959 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Error/ErrorsManager.php @@ -0,0 +1,79 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Error; + +/** + * Manager of errors that occur during fixing. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ErrorsManager +{ + /** + * @var Error[] + */ + private $errors = []; + + /** + * Returns errors reported during linting before fixing. + * + * @return Error[] + */ + public function getInvalidErrors() + { + return array_filter($this->errors, static function (Error $error) { + return Error::TYPE_INVALID === $error->getType(); + }); + } + + /** + * Returns errors reported during fixing. + * + * @return Error[] + */ + public function getExceptionErrors() + { + return array_filter($this->errors, static function (Error $error) { + return Error::TYPE_EXCEPTION === $error->getType(); + }); + } + + /** + * Returns errors reported during linting after fixing. + * + * @return Error[] + */ + public function getLintErrors() + { + return array_filter($this->errors, static function (Error $error) { + return Error::TYPE_LINT === $error->getType(); + }); + } + + /** + * Returns true if no errors were reported. + * + * @return bool + */ + public function isEmpty() + { + return empty($this->errors); + } + + public function report(Error $error) + { + $this->errors[] = $error; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Event/Event.php b/vendor/friendsofphp/php-cs-fixer/src/Event/Event.php new file mode 100644 index 0000000..7234b83 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Event/Event.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Event; + +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +// @TODO PHP 7.1 +// @TODO PHP CS Fixer 3.0 +// Since PHP-CS-FIXER is PHP 5.6 compliant we can't always use Symfony Contracts (currently needs PHP ^7.1.3) +// This conditional inheritance will be useless when PHP-CS-FIXER no longer supports PHP versions +// inferior to Symfony/Contracts PHP minimal version +if (is_subclass_of(EventDispatcher::class, EventDispatcherInterface::class)) { + class Event extends \Symfony\Contracts\EventDispatcher\Event + { + } +} else { + class Event extends \Symfony\Component\EventDispatcher\Event + { + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FileReader.php b/vendor/friendsofphp/php-cs-fixer/src/FileReader.php new file mode 100644 index 0000000..3efa2b8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FileReader.php @@ -0,0 +1,84 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * File reader that unify access to regular file and stdin-alike file. + * + * Regular file could be read multiple times with `file_get_contents`, but file provided on stdin can not. + * Consecutive try will provide empty content for stdin-alike file. + * This reader unifies access to them. + * + * @internal + */ +final class FileReader +{ + /** + * @var null|string + */ + private $stdinContent; + + /** + * @return self + */ + public static function createSingleton() + { + static $instance = null; + + if (!$instance) { + $instance = new self(); + } + + return $instance; + } + + /** + * @param string $filePath + * + * @return string + */ + public function read($filePath) + { + if ('php://stdin' === $filePath) { + if (null === $this->stdinContent) { + $this->stdinContent = $this->readRaw($filePath); + } + + return $this->stdinContent; + } + + return $this->readRaw($filePath); + } + + /** + * @param string $realPath + * + * @return string + */ + private function readRaw($realPath) + { + $content = @file_get_contents($realPath); + + if (false === $content) { + $error = error_get_last(); + + throw new \RuntimeException(sprintf( + 'Failed to read content from "%s".%s', + $realPath, + $error ? ' '.$error['message'] : '' + )); + } + + return $content; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FileRemoval.php b/vendor/friendsofphp/php-cs-fixer/src/FileRemoval.php similarity index 61% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/FileRemoval.php rename to vendor/friendsofphp/php-cs-fixer/src/FileRemoval.php index 5bac667..670cc59 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FileRemoval.php +++ b/vendor/friendsofphp/php-cs-fixer/src/FileRemoval.php @@ -10,7 +10,7 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS; +namespace PhpCsFixer; /** * Handles files removal with possibility to remove them on shutdown. @@ -27,11 +27,38 @@ final class FileRemoval * * @var array */ - private $files = array(); + private $files = []; public function __construct() { - register_shutdown_function(array($this, 'clean')); + register_shutdown_function([$this, 'clean']); + } + + public function __destruct() + { + $this->clean(); + } + + /** + * This class is not intended to be serialized, + * and cannot be deserialized (see __wakeup method). + * + * @return array + */ + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + /** + * Disable the deserialization of the class to prevent attacker executing + * code by leveraging the __destruct method. + * + * @see https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection + */ + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } /** @@ -54,7 +81,6 @@ public function delete($path) if (isset($this->files[$path])) { unset($this->files[$path]); } - $this->unlink($path); } @@ -66,8 +92,7 @@ public function clean() foreach ($this->files as $file => $value) { $this->unlink($file); } - - $this->files = array(); + $this->files = []; } private function unlink($path) diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder.php b/vendor/friendsofphp/php-cs-fixer/src/Finder.php similarity index 83% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder.php rename to vendor/friendsofphp/php-cs-fixer/src/Finder.php index 9409d84..807a633 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Finder.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Finder.php @@ -10,12 +10,13 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS; +namespace PhpCsFixer; use Symfony\Component\Finder\Finder as BaseFinder; /** * @author Fabien Potencier <fabien@symfony.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> */ class Finder extends BaseFinder { @@ -26,9 +27,6 @@ public function __construct() $this ->files() ->name('*.php') - ->name('*.twig') - ->ignoreDotFiles(true) - ->ignoreVCS(true) ->exclude('vendor') ; } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/AbstractIncrementOperatorFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/AbstractIncrementOperatorFixer.php new file mode 100644 index 0000000..82ad245 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/AbstractIncrementOperatorFixer.php @@ -0,0 +1,61 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Tokenizer\Tokens; + +abstract class AbstractIncrementOperatorFixer extends AbstractFixer +{ + /** + * @param int $index + * + * @return int + */ + final protected function findStart(Tokens $tokens, $index) + { + do { + $index = $tokens->getPrevMeaningfulToken($index); + $token = $tokens[$index]; + + $blockType = Tokens::detectBlockType($token); + if (null !== $blockType && !$blockType['isStart']) { + $index = $tokens->findBlockStart($blockType['type'], $index); + $token = $tokens[$index]; + } + } while (!$token->equalsAny(['$', [T_VARIABLE]])); + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + $prevToken = $tokens[$prevIndex]; + + if ($prevToken->equals('$')) { + return $this->findStart($tokens, $index); + } + + if ($prevToken->isObjectOperator()) { + return $this->findStart($tokens, $prevIndex); + } + + if ($prevToken->isGivenKind(T_PAAMAYIM_NEKUDOTAYIM)) { + $prevPrevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + if (!$tokens[$prevPrevIndex]->isGivenKind([T_STATIC, T_STRING])) { + return $this->findStart($tokens, $prevIndex); + } + + $index = $tokens->getTokenNotOfKindsSibling($prevIndex, -1, [T_NS_SEPARATOR, T_STATIC, T_STRING]); + $index = $tokens->getNextMeaningfulToken($index); + } + + return $index; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/AbstractPhpUnitFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/AbstractPhpUnitFixer.php new file mode 100644 index 0000000..65b53dd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/AbstractPhpUnitFixer.php @@ -0,0 +1,70 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Indicator\PhpUnitTestCaseIndicator; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +abstract class AbstractPhpUnitFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + final public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_CLASS, T_STRING]); + } + + final protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $phpUnitTestCaseIndicator = new PhpUnitTestCaseIndicator(); + + foreach ($phpUnitTestCaseIndicator->findPhpUnitClasses($tokens) as $indices) { + $this->applyPhpUnitClassFix($tokens, $indices[0], $indices[1]); + } + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + abstract protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex); + + /** + * @param int $index + * + * @return int + */ + final protected function getDocBlockIndex(Tokens $tokens, $index) + { + do { + $index = $tokens->getPrevNonWhitespace($index); + } while ($tokens[$index]->isGivenKind([T_PUBLIC, T_PROTECTED, T_PRIVATE, T_FINAL, T_ABSTRACT, T_COMMENT])); + + return $index; + } + + /** + * @param int $index + * + * @return bool + */ + final protected function isPHPDoc(Tokens $tokens, $index) + { + return $tokens[$index]->isGivenKind(T_DOC_COMMENT); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/ArrayPushFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/ArrayPushFixer.php new file mode 100644 index 0000000..0174500 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/ArrayPushFixer.php @@ -0,0 +1,227 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class ArrayPushFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Converts simple usages of `array_push($x, $y);` to `$x[] = $y;`.', + [new VersionSpecificCodeSample("<?php\narray_push(\$x, \$y);\n", new VersionSpecification(70000))], + null, + 'Risky when the function `array_push` is overridden.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(T_STRING) && $tokens->count() > 7; + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + + for ($index = $tokens->count() - 7; $index > 0; --$index) { + if (!$tokens[$index]->equals([T_STRING, 'array_push'], false)) { + continue; + } + + if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) { + continue; // redeclare/override + } + + // meaningful before must be `<?php`, `{`, `}` or `;` + + $callIndex = $index; + $index = $tokens->getPrevMeaningfulToken($index); + $namespaceSeparatorIndex = null; + + if ($tokens[$index]->isGivenKind(T_NS_SEPARATOR)) { + $namespaceSeparatorIndex = $index; + $index = $tokens->getPrevMeaningfulToken($index); + } + + if (!$tokens[$index]->equalsAny([';', '{', '}', ')', [T_OPEN_TAG]])) { + continue; + } + + // figure out where the arguments list opens + + $openBraceIndex = $tokens->getNextMeaningfulToken($callIndex); + $blockType = Tokens::detectBlockType($tokens[$openBraceIndex]); + + if (null === $blockType || Tokens::BLOCK_TYPE_PARENTHESIS_BRACE !== $blockType['type']) { + continue; + } + + // figure out where the arguments list closes + + $closeBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openBraceIndex); + + // meaningful after `)` must be `;`, `? >` or nothing + + $afterCloseBraceIndex = $tokens->getNextMeaningfulToken($closeBraceIndex); + + if (null !== $afterCloseBraceIndex && !$tokens[$afterCloseBraceIndex]->equalsAny([';', [T_CLOSE_TAG]])) { + continue; + } + + // must have 2 arguments + + // first argument must be a variable (with possibly array indexing etc.), + // after that nothing meaningful should be there till the next `,` or `)` + // if `)` than we cannot fix it (it is a single argument call) + + $firstArgumentStop = $this->getFirstArgumentEnd($tokens, $openBraceIndex); + $firstArgumentStop = $tokens->getNextMeaningfulToken($firstArgumentStop); + + if (!$tokens[$firstArgumentStop]->equals(',')) { + return; + } + + // second argument can be about anything but ellipsis, we must make sure there is not + // a third argument (or more) passed to `array_push` + + $secondArgumentStart = $tokens->getNextMeaningfulToken($firstArgumentStop); + $secondArgumentStop = $this->getSecondArgumentEnd($tokens, $secondArgumentStart, $closeBraceIndex); + + if (null === $secondArgumentStop) { + continue; + } + + // candidate is valid, replace tokens + + $tokens->clearTokenAndMergeSurroundingWhitespace($closeBraceIndex); + $tokens->clearTokenAndMergeSurroundingWhitespace($firstArgumentStop); + $tokens->insertAt( + $firstArgumentStop, + [ + new Token('['), + new Token(']'), + new Token([T_WHITESPACE, ' ']), + new Token('='), + ] + ); + $tokens->clearTokenAndMergeSurroundingWhitespace($openBraceIndex); + $tokens->clearTokenAndMergeSurroundingWhitespace($callIndex); + + if (null !== $namespaceSeparatorIndex) { + $tokens->clearTokenAndMergeSurroundingWhitespace($namespaceSeparatorIndex); + } + } + } + + /** + * @param int $index + * + * @return int + */ + private function getFirstArgumentEnd(Tokens $tokens, $index) + { + $nextIndex = $tokens->getNextMeaningfulToken($index); + $nextToken = $tokens[$nextIndex]; + + while ($nextToken->equalsAny([ + '$', + '[', + '(', + [CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN], + [CT::T_DYNAMIC_PROP_BRACE_OPEN], + [CT::T_DYNAMIC_VAR_BRACE_OPEN], + [CT::T_NAMESPACE_OPERATOR], + [T_NS_SEPARATOR], + [T_STATIC], + [T_STRING], + [T_VARIABLE], + ])) { + $blockType = Tokens::detectBlockType($nextToken); + + if (null !== $blockType) { + $nextIndex = $tokens->findBlockEnd($blockType['type'], $nextIndex); + } + + $index = $nextIndex; + $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); + $nextToken = $tokens[$nextIndex]; + } + + if ($nextToken->isGivenKind(T_OBJECT_OPERATOR)) { + return $this->getFirstArgumentEnd($tokens, $nextIndex); + } + + if ($nextToken->isGivenKind(T_PAAMAYIM_NEKUDOTAYIM)) { + return $this->getFirstArgumentEnd($tokens, $tokens->getNextMeaningfulToken($nextIndex)); + } + + return $index; + } + + /** + * @param int $index + * @param int $endIndex boundary, i.e. tokens index of `)` + * + * @return null|int + */ + private function getSecondArgumentEnd(Tokens $tokens, $index, $endIndex) + { + if ($tokens[$index]->isGivenKind(T_ELLIPSIS)) { + return null; + } + + $index = $tokens->getNextMeaningfulToken($index); + + for (; $index <= $endIndex; ++$index) { + $blockType = Tokens::detectBlockType($tokens[$index]); + + while (null !== $blockType && $blockType['isStart']) { + $index = $tokens->findBlockEnd($blockType['type'], $index); + $index = $tokens->getNextMeaningfulToken($index); + $blockType = Tokens::detectBlockType($tokens[$index]); + } + + if ($tokens[$index]->equals(',') || $tokens[$index]->isGivenKind([T_YIELD, T_YIELD_FROM, T_LOGICAL_AND, T_LOGICAL_OR, T_LOGICAL_XOR])) { + return null; + } + } + + return $endIndex; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/BacktickToShellExecFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/BacktickToShellExecFixer.php new file mode 100644 index 0000000..5aa1e5f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/BacktickToShellExecFixer.php @@ -0,0 +1,145 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class BacktickToShellExecFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound('`'); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Converts backtick operators to `shell_exec` calls.', + [ + new CodeSample( + <<<'EOT' +<?php +$plain = `ls -lah`; +$withVar = `ls -lah $var1 ${var2} {$var3} {$var4[0]} {$var5->call()}`; + +EOT + ), + ], + 'Conversion is done only when it is non risky, so when special chars like single-quotes, double-quotes and backticks are not used inside the command.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before EscapeImplicitBackslashesFixer, ExplicitStringVariableFixer, NativeFunctionInvocationFixer, SingleQuoteFixer. + */ + public function getPriority() + { + return 2; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $backtickStarted = false; + $backtickTokens = []; + for ($index = $tokens->count() - 1; $index > 0; --$index) { + $token = $tokens[$index]; + if (!$token->equals('`')) { + if ($backtickStarted) { + $backtickTokens[$index] = $token; + } + + continue; + } + + $backtickTokens[$index] = $token; + if ($backtickStarted) { + $this->fixBackticks($tokens, $backtickTokens); + $backtickTokens = []; + } + $backtickStarted = !$backtickStarted; + } + } + + /** + * Override backtick code with corresponding double-quoted string. + */ + private function fixBackticks(Tokens $tokens, array $backtickTokens) + { + // Track indexes for final override + ksort($backtickTokens); + $openingBacktickIndex = key($backtickTokens); + end($backtickTokens); + $closingBacktickIndex = key($backtickTokens); + + // Strip enclosing backticks + array_shift($backtickTokens); + array_pop($backtickTokens); + + // Double-quoted strings are parsed differently if they contain + // variables or not, so we need to build the new token array accordingly + $count = \count($backtickTokens); + + $newTokens = [ + new Token([T_STRING, 'shell_exec']), + new Token('('), + ]; + if (1 !== $count) { + $newTokens[] = new Token('"'); + } + foreach ($backtickTokens as $token) { + if (!$token->isGivenKind(T_ENCAPSED_AND_WHITESPACE)) { + $newTokens[] = $token; + + continue; + } + $content = $token->getContent(); + // Escaping special chars depends on the context: too tricky + if (Preg::match('/[`"\']/u', $content)) { + return; + } + + $kind = T_ENCAPSED_AND_WHITESPACE; + if (1 === $count) { + $content = '"'.$content.'"'; + $kind = T_CONSTANT_ENCAPSED_STRING; + } + + $newTokens[] = new Token([$kind, $content]); + } + if (1 !== $count) { + $newTokens[] = new Token('"'); + } + $newTokens[] = new Token(')'); + + $tokens->overrideRange($openingBacktickIndex, $closingBacktickIndex, $newTokens); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EregToPregFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/EregToPregFixer.php similarity index 58% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EregToPregFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/EregToPregFixer.php index be93693..253aa4b 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/EregToPregFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/EregToPregFixer.php @@ -10,50 +10,81 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Contrib; - -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; -use Symfony\CS\Utils; +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\PregException; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Utils; /** * @author Matteo Beccati <matteo@beccati.com> */ -class EregToPregFixer extends AbstractFixer +final class EregToPregFixer extends AbstractFixer { /** * @var array the list of the ext/ereg function names, their preg equivalent and the preg modifier(s), if any * all condensed in an array of arrays */ - private static $functions = array( - array('ereg', 'preg_match', ''), - array('eregi', 'preg_match', 'i'), - array('ereg_replace', 'preg_replace', ''), - array('eregi_replace', 'preg_replace', 'i'), - array('split', 'preg_split', ''), - array('spliti', 'preg_split', 'i'), - ); + private static $functions = [ + ['ereg', 'preg_match', ''], + ['eregi', 'preg_match', 'i'], + ['ereg_replace', 'preg_replace', ''], + ['eregi_replace', 'preg_replace', 'i'], + ['split', 'preg_split', ''], + ['spliti', 'preg_split', 'i'], + ]; /** * @var array the list of preg delimiters, in order of preference */ - private static $delimiters = array('/', '#', '!'); + private static $delimiters = ['/', '#', '!']; /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function getDefinition() { - if (!$this->cursoryMatch($content)) { - return $content; - } + return new FixerDefinition( + 'Replace deprecated `ereg` regular expression functions with `preg`.', + [new CodeSample("<?php \$x = ereg('[A-Z]');\n")], + null, + 'Risky if the `ereg` function is overridden.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } - $tokens = Tokens::fromCode($content); + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { $end = $tokens->count() - 1; + $functionsAnalyzer = new FunctionsAnalyzer(); foreach (self::$functions as $map) { // the sequence is the function name, followed by "(" and a quoted string - $seq = array(array(T_STRING, $map[0]), '(', array(T_CONSTANT_ENCAPSED_STRING)); + $seq = [[T_STRING, $map[0]], '(', [T_CONSTANT_ENCAPSED_STRING]]; $currIndex = 0; while (null !== $currIndex) { @@ -73,21 +104,20 @@ public function fix(\SplFileInfo $file, $content) // advance tokenizer cursor $currIndex = $match[2]; - // ensure it's a function call (not a method / static call) - $prev = $tokens->getPrevMeaningfulToken($match[0]); - if (null === $prev || $tokens[$prev]->isGivenKind(array(T_OBJECT_OPERATOR, T_DOUBLE_COLON))) { + if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $match[0])) { continue; } // ensure the first parameter is just a string (e.g. has nothing appended) $next = $tokens->getNextMeaningfulToken($match[2]); - if (null === $next || !$tokens[$next]->equalsAny(array(',', ')'))) { + if (null === $next || !$tokens[$next]->equalsAny([',', ')'])) { continue; } // convert to PCRE - $string = substr($tokens[$match[2]]->getContent(), 1, -1); - $quote = substr($tokens[$match[2]]->getContent(), 0, 1); + $regexTokenContent = $tokens[$match[2]]->getContent(); + $string = substr($regexTokenContent, 1, -1); + $quote = $regexTokenContent[0]; $delim = $this->getBestDelimiter($string); $preg = $delim.addcslashes($string, $delim).$delim.'D'.$map[2]; @@ -97,20 +127,10 @@ public function fix(\SplFileInfo $file, $content) } // modify function and argument - $tokens[$match[2]]->setContent($quote.$preg.$quote); - $tokens[$match[0]]->setContent($map[1]); + $tokens[$match[0]] = new Token([T_STRING, $map[1]]); + $tokens[$match[2]] = new Token([T_CONSTANT_ENCAPSED_STRING, $quote.$preg.$quote]); } } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Replace deprecated ereg regular expression functions with preg. Warning! This could change code behavior.'; } /** @@ -122,7 +142,13 @@ public function getDescription() */ private function checkPreg($pattern) { - return false !== @preg_match($pattern, ''); + try { + Preg::match($pattern, ''); + + return true; + } catch (PregException $e) { + return false; + } } /** @@ -135,19 +161,19 @@ private function checkPreg($pattern) private function getBestDelimiter($pattern) { // try do find something that's not used - $delimiters = array(); + $delimiters = []; foreach (self::$delimiters as $k => $d) { if (false === strpos($pattern, $d)) { return $d; } - $delimiters[$d] = array(substr_count($pattern, $d), $k); + $delimiters[$d] = [substr_count($pattern, $d), $k]; } // return the least used delimiter, using the position in the list as a tie breaker - uasort($delimiters, function ($a, $b) { + uasort($delimiters, static function (array $a, array $b) { if ($a[0] === $b[0]) { - return Utils::cmpInt($a, $b); + return Utils::cmpInt($a[1], $b[1]); } return $a[0] < $b[0] ? -1 : 1; @@ -155,17 +181,4 @@ private function getBestDelimiter($pattern) return key($delimiters); } - - /** - * Perform a quick search to see if any ext/ereg functions are used. - * - * @param string $content the content itself - * - * @return bool - */ - private function cursoryMatch($content) - { - // just searching for "ereg" or "split" will do, since all the function names start with either of them - return false !== stripos($content, 'ereg') || false !== stripos($content, 'split'); - } } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/MbStrFunctionsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/MbStrFunctionsFixer.php new file mode 100644 index 0000000..8c61cb7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/MbStrFunctionsFixer.php @@ -0,0 +1,130 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFunctionReferenceFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class MbStrFunctionsFixer extends AbstractFunctionReferenceFixer +{ + /** + * @var array the list of the string-related function names and their mb_ equivalent + */ + private static $functionsMap = [ + 'str_split' => ['alternativeName' => 'mb_str_split', 'argumentCount' => [1, 2, 3]], + 'stripos' => ['alternativeName' => 'mb_stripos', 'argumentCount' => [2, 3]], + 'stristr' => ['alternativeName' => 'mb_stristr', 'argumentCount' => [2, 3]], + 'strlen' => ['alternativeName' => 'mb_strlen', 'argumentCount' => [1]], + 'strpos' => ['alternativeName' => 'mb_strpos', 'argumentCount' => [2, 3]], + 'strrchr' => ['alternativeName' => 'mb_strrchr', 'argumentCount' => [2]], + 'strripos' => ['alternativeName' => 'mb_strripos', 'argumentCount' => [2, 3]], + 'strrpos' => ['alternativeName' => 'mb_strrpos', 'argumentCount' => [2, 3]], + 'strstr' => ['alternativeName' => 'mb_strstr', 'argumentCount' => [2, 3]], + 'strtolower' => ['alternativeName' => 'mb_strtolower', 'argumentCount' => [1]], + 'strtoupper' => ['alternativeName' => 'mb_strtoupper', 'argumentCount' => [1]], + 'substr' => ['alternativeName' => 'mb_substr', 'argumentCount' => [2, 3]], + 'substr_count' => ['alternativeName' => 'mb_substr_count', 'argumentCount' => [2, 3, 4]], + ]; + + /** + * @var array<string, array> + */ + private $functions; + + public function __construct() + { + parent::__construct(); + + $this->functions = array_filter( + self::$functionsMap, + static function (array $mapping) { + return \function_exists($mapping['alternativeName']) && (new \ReflectionFunction($mapping['alternativeName']))->isInternal(); + } + ); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replace non multibyte-safe functions with corresponding mb function.', + [ + new CodeSample( + '<?php +$a = strlen($a); +$a = strpos($a, $b); +$a = strrpos($a, $b); +$a = substr($a, $b); +$a = strtolower($a); +$a = strtoupper($a); +$a = stripos($a, $b); +$a = strripos($a, $b); +$a = strstr($a, $b); +$a = stristr($a, $b); +$a = strrchr($a, $b); +$a = substr_count($a, $b); +' + ), + ], + null, + 'Risky when any of the functions are overridden.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $argumentsAnalyzer = new ArgumentsAnalyzer(); + foreach ($this->functions as $functionIdentity => $functionReplacement) { + $currIndex = 0; + while (null !== $currIndex) { + // try getting function reference and translate boundaries for humans + $boundaries = $this->find($functionIdentity, $tokens, $currIndex, $tokens->count() - 1); + if (null === $boundaries) { + // next function search, as current one not found + continue 2; + } + + list($functionName, $openParenthesis, $closeParenthesis) = $boundaries; + $count = $argumentsAnalyzer->countArguments($tokens, $openParenthesis, $closeParenthesis); + if (!\in_array($count, $functionReplacement['argumentCount'], true)) { + continue 2; + } + + // analysing cursor shift, so nested calls could be processed + $currIndex = $openParenthesis; + + $tokens[$functionName] = new Token([T_STRING, $functionReplacement['alternativeName']]); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoAliasFunctionsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoAliasFunctionsFixer.php new file mode 100644 index 0000000..f655074 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoAliasFunctionsFixer.php @@ -0,0 +1,258 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Vladimir Reznichenko <kalessil@gmail.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NoAliasFunctionsFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** @var array<string, array<int|string>|string> stores alias (key) - master (value) functions mapping */ + private $aliases = []; + + /** @var array<string, string> stores alias (key) - master (value) functions mapping */ + private static $internalSet = [ + 'chop' => 'rtrim', + 'close' => 'closedir', + 'doubleval' => 'floatval', + 'fputs' => 'fwrite', + 'get_required_files' => 'get_included_files', + 'ini_alter' => 'ini_set', + 'is_double' => 'is_float', + 'is_integer' => 'is_int', + 'is_long' => 'is_int', + 'is_real' => 'is_float', + 'is_writeable' => 'is_writable', + 'join' => 'implode', + 'key_exists' => 'array_key_exists', + 'magic_quotes_runtime' => 'set_magic_quotes_runtime', + 'pos' => 'current', + 'show_source' => 'highlight_file', + 'sizeof' => 'count', + 'strchr' => 'strstr', + 'user_error' => 'trigger_error', + ]; + + /** @var array<string, string> stores alias (key) - master (value) functions mapping */ + private static $imapSet = [ + 'imap_create' => 'imap_createmailbox', + 'imap_fetchtext' => 'imap_body', + 'imap_header' => 'imap_headerinfo', + 'imap_listmailbox' => 'imap_list', + 'imap_listsubscribed' => 'imap_lsub', + 'imap_rename' => 'imap_renamemailbox', + 'imap_scan' => 'imap_listscan', + 'imap_scanmailbox' => 'imap_listscan', + ]; + + /** @var array<string, string> stores alias (key) - master (value) functions mapping */ + private static $mbregSet = [ + 'mbereg' => 'mb_ereg', + 'mbereg_match' => 'mb_ereg_match', + 'mbereg_replace' => 'mb_ereg_replace', + 'mbereg_search' => 'mb_ereg_search', + 'mbereg_search_getpos' => 'mb_ereg_search_getpos', + 'mbereg_search_getregs' => 'mb_ereg_search_getregs', + 'mbereg_search_init' => 'mb_ereg_search_init', + 'mbereg_search_pos' => 'mb_ereg_search_pos', + 'mbereg_search_regs' => 'mb_ereg_search_regs', + 'mbereg_search_setpos' => 'mb_ereg_search_setpos', + 'mberegi' => 'mb_eregi', + 'mberegi_replace' => 'mb_eregi_replace', + 'mbregex_encoding' => 'mb_regex_encoding', + 'mbsplit' => 'mb_split', + ]; + + private static $exifSet = [ + 'read_exif_data' => 'exif_read_data', + ]; + + private static $timeSet = [ + 'mktime' => ['time', 0], + 'gmmktime' => ['time', 0], + ]; + + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->aliases = []; + foreach ($this->configuration['sets'] as $set) { + if ('@all' === $set) { + $this->aliases = self::$internalSet; + $this->aliases = array_merge($this->aliases, self::$imapSet); + $this->aliases = array_merge($this->aliases, self::$mbregSet); + $this->aliases = array_merge($this->aliases, self::$timeSet); + $this->aliases = array_merge($this->aliases, self::$exifSet); + + break; + } + + if ('@internal' === $set) { + $this->aliases = array_merge($this->aliases, self::$internalSet); + } elseif ('@IMAP' === $set) { + $this->aliases = array_merge($this->aliases, self::$imapSet); + } elseif ('@mbreg' === $set) { + $this->aliases = array_merge($this->aliases, self::$mbregSet); + } elseif ('@time' === $set) { + $this->aliases = array_merge($this->aliases, self::$timeSet); + } elseif ('@exif' === $set) { + $this->aliases = array_merge($this->aliases, self::$exifSet); + } + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Master functions shall be used instead of aliases.', + [ + new CodeSample( + '<?php +$a = chop($b); +close($b); +$a = doubleval($b); +$a = fputs($b, $c); +$a = get_required_files(); +ini_alter($b, $c); +$a = is_double($b); +$a = is_integer($b); +$a = is_long($b); +$a = is_real($b); +$a = is_writeable($b); +$a = join($glue, $pieces); +$a = key_exists($key, $array); +magic_quotes_runtime($new_setting); +$a = pos($array); +$a = show_source($filename, true); +$a = sizeof($b); +$a = strchr($haystack, $needle); +$a = imap_header($imap_stream, 1); +user_error($message); +mbereg_search_getregs(); +' + ), + new CodeSample( + '<?php +$a = is_double($b); +mbereg_search_getregs(); +', + ['sets' => ['@mbreg']] + ), + ], + null, + 'Risky when any of the alias functions are overridden.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before ImplodeCallFixer, PhpUnitDedicateAssertFixer. + */ + public function getPriority() + { + return 40; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + /** @var Token $token */ + foreach ($tokens->findGivenKind(T_STRING) as $index => $token) { + // check mapping hit + $tokenContent = strtolower($token->getContent()); + if (!isset($this->aliases[$tokenContent])) { + continue; + } + + // skip expressions without parameters list + $openParenthesis = $tokens->getNextMeaningfulToken($index); + + if (!$tokens[$openParenthesis]->equals('(')) { + continue; + } + + if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) { + continue; + } + + if (\is_array($this->aliases[$tokenContent])) { + list($alias, $numberOfArguments) = $this->aliases[$tokenContent]; + + $count = $argumentsAnalyzer->countArguments($tokens, $openParenthesis, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesis)); + + if ($numberOfArguments !== $count) { + continue; + } + } else { + $alias = $this->aliases[$tokenContent]; + } + + $tokens[$index] = new Token([T_STRING, $alias]); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $sets = ['@internal', '@IMAP', '@mbreg', '@all', '@time', '@exif']; + + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('sets', 'List of sets to fix. Defined sets are `@internal` (native functions), `@IMAP` (IMAP functions), `@mbreg` (from `ext-mbstring`) `@all` (all listed sets).')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset($sets)]) + ->setDefault(['@internal', '@IMAP']) + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoAliasLanguageConstructCallFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoAliasLanguageConstructCallFixer.php new file mode 100644 index 0000000..277de9d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoAliasLanguageConstructCallFixer.php @@ -0,0 +1,68 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class NoAliasLanguageConstructCallFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Master language constructs shall be used instead of aliases.', + [ + new CodeSample( + '<?php +die; +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_EXIT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_EXIT)) { + continue; + } + + if ('exit' === strtolower($token->getContent())) { + continue; + } + + $tokens[$index] = new Token([T_EXIT, 'exit']); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoMixedEchoPrintFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoMixedEchoPrintFixer.php new file mode 100644 index 0000000..66cbad9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/NoMixedEchoPrintFixer.php @@ -0,0 +1,162 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Sullivan Senechal <soullivaneuh@gmail.com> + * @author SpacePossum + */ +final class NoMixedEchoPrintFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @deprecated will be removed in 3.0 + */ + public static $defaultConfig = ['use' => 'echo']; + + /** + * @var string + */ + private $callBack; + + /** + * @var int T_ECHO or T_PRINT + */ + private $candidateTokenType; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + if ('echo' === $this->configuration['use']) { + $this->candidateTokenType = T_PRINT; + $this->callBack = 'fixPrintToEcho'; + } else { + $this->candidateTokenType = T_ECHO; + $this->callBack = 'fixEchoToPrint'; + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Either language construct `print` or `echo` should be used.', + [ + new CodeSample("<?php print 'example';\n"), + new CodeSample("<?php echo('example');\n", ['use' => 'print']), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after EchoTagSyntaxFixer, NoShortEchoTagFixer. + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound($this->candidateTokenType); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $callBack = $this->callBack; + foreach ($tokens as $index => $token) { + if ($token->isGivenKind($this->candidateTokenType)) { + $this->{$callBack}($tokens, $index); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('use', 'The desired language construct.')) + ->setAllowedValues(['print', 'echo']) + ->setDefault('echo') + ->getOption(), + ]); + } + + /** + * @param int $index + */ + private function fixEchoToPrint(Tokens $tokens, $index) + { + $nextTokenIndex = $tokens->getNextMeaningfulToken($index); + $endTokenIndex = $tokens->getNextTokenOfKind($index, [';', [T_CLOSE_TAG]]); + $canBeConverted = true; + + for ($i = $nextTokenIndex; $i < $endTokenIndex; ++$i) { + if ($tokens[$i]->equalsAny(['(', [CT::T_ARRAY_SQUARE_BRACE_OPEN]])) { + $blockType = Tokens::detectBlockType($tokens[$i]); + $i = $tokens->findBlockEnd($blockType['type'], $i); + } + + if ($tokens[$i]->equals(',')) { + $canBeConverted = false; + + break; + } + } + + if (false === $canBeConverted) { + return; + } + + $tokens[$index] = new Token([T_PRINT, 'print']); + } + + /** + * @param int $index + */ + private function fixPrintToEcho(Tokens $tokens, $index) + { + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; + + if (!$prevToken->equalsAny([';', '{', '}', ')', [T_OPEN_TAG], [T_ELSE]])) { + return; + } + + $tokens[$index] = new Token([T_ECHO, 'echo']); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/PowToExponentiationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/PowToExponentiationFixer.php new file mode 100644 index 0000000..6b55d4c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/PowToExponentiationFixer.php @@ -0,0 +1,239 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFunctionReferenceFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class PowToExponentiationFixer extends AbstractFunctionReferenceFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + // minimal candidate to fix is seven tokens: pow(x,y); + return $tokens->count() > 7 && $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Converts `pow` to the `**` operator.', + [ + new CodeSample( + "<?php\n pow(\$a, 1);\n" + ), + ], + null, + 'Risky when the function `pow` is overridden.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before BinaryOperatorSpacesFixer, MethodArgumentSpaceFixer, NativeFunctionCasingFixer, NoSpacesAfterFunctionNameFixer, NoSpacesInsideParenthesisFixer. + */ + public function getPriority() + { + return 32; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $candidates = $this->findPowCalls($tokens); + $argumentsAnalyzer = new ArgumentsAnalyzer(); + $numberOfTokensAdded = 0; + $previousCloseParenthesisIndex = \count($tokens); + + foreach (array_reverse($candidates) as $candidate) { + // if in the previous iteration(s) tokens were added to the collection and this is done within the tokens + // indexes of the current candidate than the index of the close ')' of the candidate has moved and so + // the index needs to be updated + if ($previousCloseParenthesisIndex < $candidate[2]) { + $previousCloseParenthesisIndex = $candidate[2]; + $candidate[2] += $numberOfTokensAdded; + } else { + $previousCloseParenthesisIndex = $candidate[2]; + $numberOfTokensAdded = 0; + } + + $arguments = $argumentsAnalyzer->getArguments($tokens, $candidate[1], $candidate[2]); + + if (2 !== \count($arguments)) { + continue; + } + + for ($i = $candidate[1]; $i < $candidate[2]; ++$i) { + if ($tokens[$i]->isGivenKind(T_ELLIPSIS)) { + continue 2; + } + } + + $numberOfTokensAdded += $this->fixPowToExponentiation( + $tokens, + $candidate[0], // functionNameIndex, + $candidate[1], // openParenthesisIndex, + $candidate[2], // closeParenthesisIndex, + $arguments + ); + } + } + + /** + * @return array[] + */ + private function findPowCalls(Tokens $tokens) + { + $candidates = []; + + // Minimal candidate to fix is seven tokens: pow(x,y); + $end = \count($tokens) - 6; + + // First possible location is after the open token: 1 + for ($i = 1; $i < $end; ++$i) { + $candidate = $this->find('pow', $tokens, $i, $end); + + if (null === $candidate) { + break; + } + + $i = $candidate[1]; // proceed to openParenthesisIndex + $candidates[] = $candidate; + } + + return $candidates; + } + + /** + * @param int $functionNameIndex + * @param int $openParenthesisIndex + * @param int $closeParenthesisIndex + * @param array<int, int> $arguments + * + * @return int number of tokens added to the collection + */ + private function fixPowToExponentiation(Tokens $tokens, $functionNameIndex, $openParenthesisIndex, $closeParenthesisIndex, array $arguments) + { + // find the argument separator ',' directly after the last token of the first argument; + // replace it with T_POW '**' + $tokens[$tokens->getNextTokenOfKind(reset($arguments), [','])] = new Token([T_POW, '**']); + + // clean up the function call tokens prt. I + $tokens->clearAt($closeParenthesisIndex); + $previousIndex = $tokens->getPrevMeaningfulToken($closeParenthesisIndex); + + if ($tokens[$previousIndex]->equals(',')) { + $tokens->clearAt($previousIndex); // trailing ',' in function call (PHP 7.3) + } + + $added = 0; + + // check if the arguments need to be wrapped in parenthesis + foreach (array_reverse($arguments, true) as $argumentStartIndex => $argumentEndIndex) { + if ($this->isParenthesisNeeded($tokens, $argumentStartIndex, $argumentEndIndex)) { + $tokens->insertAt($argumentEndIndex + 1, new Token(')')); + $tokens->insertAt($argumentStartIndex, new Token('(')); + $added += 2; + } + } + + // clean up the function call tokens prt. II + $tokens->clearAt($openParenthesisIndex); + $tokens->clearAt($functionNameIndex); + + $prevMeaningfulTokenIndex = $tokens->getPrevMeaningfulToken($functionNameIndex); + + if ($tokens[$prevMeaningfulTokenIndex]->isGivenKind(T_NS_SEPARATOR)) { + $tokens->clearAt($prevMeaningfulTokenIndex); + } + + return $added; + } + + /** + * @param int $argumentStartIndex + * @param int $argumentEndIndex + * + * @return bool + */ + private function isParenthesisNeeded(Tokens $tokens, $argumentStartIndex, $argumentEndIndex) + { + static $allowedKinds = null; + + if (null === $allowedKinds) { + $allowedKinds = $this->getAllowedKinds(); + } + + for ($i = $argumentStartIndex; $i <= $argumentEndIndex; ++$i) { + if ($tokens[$i]->isGivenKind($allowedKinds) || $tokens->isEmptyAt($i)) { + continue; + } + + $blockType = Tokens::detectBlockType($tokens[$i]); + + if (null !== $blockType) { + $i = $tokens->findBlockEnd($blockType['type'], $i); + + continue; + } + + if ($tokens[$i]->equals('$')) { + $i = $tokens->getNextMeaningfulToken($i); + if ($tokens[$i]->isGivenKind(CT::T_DYNAMIC_VAR_BRACE_OPEN)) { + $i = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_DYNAMIC_VAR_BRACE, $i); + + continue; + } + } + + if ($tokens[$i]->equals('+') && $tokens->getPrevMeaningfulToken($i) < $argumentStartIndex) { + continue; + } + + return true; + } + + return false; + } + + /** + * @return int[] + */ + private function getAllowedKinds() + { + return array_merge( + [ + T_DNUMBER, T_LNUMBER, T_VARIABLE, T_STRING, T_CONSTANT_ENCAPSED_STRING, T_DOUBLE_CAST, + T_INT_CAST, T_INC, T_DEC, T_NS_SEPARATOR, T_WHITESPACE, T_DOUBLE_COLON, T_LINE, T_COMMENT, T_DOC_COMMENT, + CT::T_NAMESPACE_OPERATOR, + ], + Token::getObjectOperatorKinds() + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/RandomApiMigrationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/RandomApiMigrationFixer.php new file mode 100644 index 0000000..46db387 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/RandomApiMigrationFixer.php @@ -0,0 +1,174 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFunctionReferenceFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; + +/** + * @author Vladimir Reznichenko <kalessil@gmail.com> + */ +final class RandomApiMigrationFixer extends AbstractFunctionReferenceFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var array + */ + private static $argumentCounts = [ + 'getrandmax' => [0], + 'mt_rand' => [1, 2], + 'rand' => [0, 2], + 'srand' => [0, 1], + 'random_int' => [0, 2], + ]; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + foreach ($this->configuration['replacements'] as $functionName => $replacement) { + $this->configuration['replacements'][$functionName] = [ + 'alternativeName' => $replacement, + 'argumentCount' => self::$argumentCounts[$functionName], + ]; + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replaces `rand`, `srand`, `getrandmax` functions calls with their `mt_*` analogs or `random_int`.', + [ + new CodeSample("<?php\n\$a = getrandmax();\n\$a = rand(\$b, \$c);\n\$a = srand();\n"), + new CodeSample( + "<?php\n\$a = getrandmax();\n\$a = rand(\$b, \$c);\n\$a = srand();\n", + ['replacements' => ['getrandmax' => 'mt_getrandmax']] + ), + new CodeSample( + "<?php \$a = rand(\$b, \$c);\n", + ['replacements' => ['rand' => 'random_int']] + ), + ], + null, + 'Risky when the configured functions are overridden. Or when relying on the seed based generating of the numbers.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + foreach ($this->configuration['replacements'] as $functionIdentity => $functionReplacement) { + if ($functionIdentity === $functionReplacement['alternativeName']) { + continue; + } + + $currIndex = 0; + + while (null !== $currIndex) { + // try getting function reference and translate boundaries for humans + $boundaries = $this->find($functionIdentity, $tokens, $currIndex, $tokens->count() - 1); + + if (null === $boundaries) { + // next function search, as current one not found + continue 2; + } + + list($functionName, $openParenthesis, $closeParenthesis) = $boundaries; + $count = $argumentsAnalyzer->countArguments($tokens, $openParenthesis, $closeParenthesis); + + if (!\in_array($count, $functionReplacement['argumentCount'], true)) { + continue 2; + } + + // analysing cursor shift, so nested calls could be processed + $currIndex = $openParenthesis; + $tokens[$functionName] = new Token([T_STRING, $functionReplacement['alternativeName']]); + + if (0 === $count && 'random_int' === $functionReplacement['alternativeName']) { + $tokens->insertAt($currIndex + 1, [ + new Token([T_LNUMBER, '0']), + new Token(','), + new Token([T_WHITESPACE, ' ']), + new Token([T_STRING, 'getrandmax']), + new Token('('), + new Token(')'), + ]); + + $currIndex += 6; + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolverRootless('replacements', [ + (new FixerOptionBuilder('replacements', 'Mapping between replaced functions with the new ones.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([static function ($value) { + foreach ($value as $functionName => $replacement) { + if (!\array_key_exists($functionName, self::$argumentCounts)) { + throw new InvalidOptionsException(sprintf( + 'Function "%s" is not handled by the fixer.', + $functionName + )); + } + + if (!\is_string($replacement)) { + throw new InvalidOptionsException(sprintf( + 'Replacement for function "%s" must be a string, "%s" given.', + $functionName, + \is_object($replacement) ? \get_class($replacement) : \gettype($replacement) + )); + } + } + + return true; + }]) + ->setDefault([ + 'getrandmax' => 'mt_getrandmax', + 'rand' => 'mt_rand', // @TODO change to `random_int` as default on 4.0 + 'srand' => 'mt_srand', + ]) + ->getOption(), + ], $this->getName()); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/SetTypeToCastFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/SetTypeToCastFixer.php new file mode 100644 index 0000000..b01b4af --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Alias/SetTypeToCastFixer.php @@ -0,0 +1,250 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Alias; + +use PhpCsFixer\AbstractFunctionReferenceFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class SetTypeToCastFixer extends AbstractFunctionReferenceFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Cast shall be used, not `settype`.', + [ + new CodeSample( + '<?php +settype($foo, "integer"); +settype($bar, "string"); +settype($bar, "null"); +' + ), + ], + null, + 'Risky when the `settype` function is overridden or when used as the 2nd or 3rd expression in a `for` loop .' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_CONSTANT_ENCAPSED_STRING, T_STRING, T_VARIABLE]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $map = [ + 'array' => [T_ARRAY_CAST, '(array)'], + 'bool' => [T_BOOL_CAST, '(bool)'], + 'boolean' => [T_BOOL_CAST, '(bool)'], + 'double' => [T_DOUBLE_CAST, '(float)'], + 'float' => [T_DOUBLE_CAST, '(float)'], + 'int' => [T_INT_CAST, '(int)'], + 'integer' => [T_INT_CAST, '(int)'], + 'object' => [T_OBJECT_CAST, '(object)'], + 'string' => [T_STRING_CAST, '(string)'], + // note: `'null' is dealt with later on + ]; + + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + foreach (array_reverse($this->findSettypeCalls($tokens)) as $candidate) { + $functionNameIndex = $candidate[0]; + + $arguments = $argumentsAnalyzer->getArguments($tokens, $candidate[1], $candidate[2]); + if (2 !== \count($arguments)) { + continue; // function must be overridden or used incorrectly + } + + $prev = $tokens->getPrevMeaningfulToken($functionNameIndex); + + if (!$tokens[$prev]->equalsAny([';', '{', '}', [T_OPEN_TAG]])) { + continue; // return value of the function is used + } + + reset($arguments); + + // --- Test first argument -------------------- + + $firstArgumentStart = key($arguments); + if ($tokens[$firstArgumentStart]->isComment() || $tokens[$firstArgumentStart]->isWhitespace()) { + $firstArgumentStart = $tokens->getNextMeaningfulToken($firstArgumentStart); + } + + if (!$tokens[$firstArgumentStart]->isGivenKind(T_VARIABLE)) { + continue; // settype only works with variables pass by reference, function must be overridden + } + + $commaIndex = $tokens->getNextMeaningfulToken($firstArgumentStart); + + if (null === $commaIndex || !$tokens[$commaIndex]->equals(',')) { + continue; // first argument is complex statement; function must be overridden + } + + // --- Test second argument ------------------- + + next($arguments); + $secondArgumentStart = key($arguments); + $secondArgumentEnd = $arguments[$secondArgumentStart]; + + if ($tokens[$secondArgumentStart]->isComment() || $tokens[$secondArgumentStart]->isWhitespace()) { + $secondArgumentStart = $tokens->getNextMeaningfulToken($secondArgumentStart); + } + + if ( + !$tokens[$secondArgumentStart]->isGivenKind(T_CONSTANT_ENCAPSED_STRING) + || $tokens->getNextMeaningfulToken($secondArgumentStart) < $secondArgumentEnd + ) { + continue; // second argument is of the wrong type or is a (complex) statement of some sort (function is overridden) + } + + // --- Test type ------------------------------ + + $type = strtolower(trim($tokens[$secondArgumentStart]->getContent(), '"\'"')); + + if ('null' !== $type && !isset($map[$type])) { + continue; // we don't know how to map + } + + // --- Fixing --------------------------------- + + $argumentToken = $tokens[$firstArgumentStart]; + + $this->removeSettypeCall( + $tokens, + $functionNameIndex, + $candidate[1], + $firstArgumentStart, + $commaIndex, + $secondArgumentStart, + $candidate[2] + ); + + if ('null' === $type) { + $this->findSettypeNullCall($tokens, $functionNameIndex, $argumentToken); + } else { + $this->fixSettypeCall($tokens, $functionNameIndex, $argumentToken, new Token($map[$type])); + } + } + } + + private function findSettypeCalls(Tokens $tokens) + { + $candidates = []; + + $end = \count($tokens); + for ($i = 1; $i < $end; ++$i) { + $candidate = $this->find('settype', $tokens, $i, $end); + if (null === $candidate) { + break; + } + + $i = $candidate[1]; // proceed to openParenthesisIndex + $candidates[] = $candidate; + } + + return $candidates; + } + + /** + * @param int $functionNameIndex + * @param int $openParenthesisIndex + * @param int $firstArgumentStart + * @param int $commaIndex + * @param int $secondArgumentStart + * @param int $closeParenthesisIndex + */ + private function removeSettypeCall( + Tokens $tokens, + $functionNameIndex, + $openParenthesisIndex, + $firstArgumentStart, + $commaIndex, + $secondArgumentStart, + $closeParenthesisIndex + ) { + $tokens->clearTokenAndMergeSurroundingWhitespace($closeParenthesisIndex); + $prevIndex = $tokens->getPrevMeaningfulToken($closeParenthesisIndex); + if ($tokens[$prevIndex]->equals(',')) { + $tokens->clearTokenAndMergeSurroundingWhitespace($prevIndex); + } + $tokens->clearTokenAndMergeSurroundingWhitespace($secondArgumentStart); + $tokens->clearTokenAndMergeSurroundingWhitespace($commaIndex); + $tokens->clearTokenAndMergeSurroundingWhitespace($firstArgumentStart); + $tokens->clearTokenAndMergeSurroundingWhitespace($openParenthesisIndex); + $tokens->clearAt($functionNameIndex); // we'll be inserting here so no need to merge the space tokens + $tokens->clearEmptyTokens(); + } + + /** + * @param int $functionNameIndex + */ + private function fixSettypeCall( + Tokens $tokens, + $functionNameIndex, + Token $argumentToken, + Token $castToken + ) { + $tokens->insertAt( + $functionNameIndex, + [ + clone $argumentToken, + new Token([T_WHITESPACE, ' ']), + new Token('='), + new Token([T_WHITESPACE, ' ']), + $castToken, + new Token([T_WHITESPACE, ' ']), + clone $argumentToken, + ] + ); + + $tokens->removeTrailingWhitespace($functionNameIndex + 6); // 6 = number of inserted tokens -1 for offset correction + } + + /** + * @param int $functionNameIndex + */ + private function findSettypeNullCall( + Tokens $tokens, + $functionNameIndex, + Token $argumentToken + ) { + $tokens->insertAt( + $functionNameIndex, + [ + clone $argumentToken, + new Token([T_WHITESPACE, ' ']), + new Token('='), + new Token([T_WHITESPACE, ' ']), + new Token([T_STRING, 'null']), + ] + ); + + $tokens->removeTrailingWhitespace($functionNameIndex + 4); // 4 = number of inserted tokens -1 for offset correction + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/ArraySyntaxFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/ArraySyntaxFixer.php new file mode 100644 index 0000000..90b8d2d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/ArraySyntaxFixer.php @@ -0,0 +1,156 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ArrayNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Gregor Harlan <gharlan@web.de> + * @author Sebastiaan Stok <s.stok@rollerscapes.net> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +final class ArraySyntaxFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var null|int + */ + private $candidateTokenKind; + + /** + * @var null|string + */ + private $fixCallback; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->resolveCandidateTokenKind(); + $this->resolveFixCallback(); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHP arrays should be declared using the configured syntax.', + [ + new CodeSample( + "<?php\n[1,2];\n" + ), + new VersionSpecificCodeSample( + "<?php\narray(1,2);\n", + new VersionSpecification(50400), + ['syntax' => 'short'] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BinaryOperatorSpacesFixer, TernaryOperatorSpacesFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound($this->candidateTokenKind); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $callback = $this->fixCallback; + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + if ($tokens[$index]->isGivenKind($this->candidateTokenKind)) { + $this->{$callback}($tokens, $index); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('syntax', 'Whether to use the `long` or `short` array syntax.')) + ->setAllowedValues(['long', 'short']) + ->setDefault('long') // TODO @3.0 change to short + ->getOption(), + ]); + } + + /** + * @param int $index + */ + private function fixToLongArraySyntax(Tokens $tokens, $index) + { + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $index); + + $tokens[$index] = new Token('('); + $tokens[$closeIndex] = new Token(')'); + + $tokens->insertAt($index, new Token([T_ARRAY, 'array'])); + } + + /** + * @param int $index + */ + private function fixToShortArraySyntax(Tokens $tokens, $index) + { + $openIndex = $tokens->getNextTokenOfKind($index, ['(']); + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); + + $tokens[$openIndex] = new Token([CT::T_ARRAY_SQUARE_BRACE_OPEN, '[']); + $tokens[$closeIndex] = new Token([CT::T_ARRAY_SQUARE_BRACE_CLOSE, ']']); + + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } + + private function resolveFixCallback() + { + $this->fixCallback = sprintf('fixTo%sArraySyntax', ucfirst($this->configuration['syntax'])); + } + + private function resolveCandidateTokenKind() + { + $this->candidateTokenKind = 'long' === $this->configuration['syntax'] ? CT::T_ARRAY_SQUARE_BRACE_OPEN : T_ARRAY; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoMultilineWhitespaceAroundDoubleArrowFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoMultilineWhitespaceAroundDoubleArrowFixer.php new file mode 100644 index 0000000..ba0a4f0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoMultilineWhitespaceAroundDoubleArrowFixer.php @@ -0,0 +1,86 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ArrayNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Carlos Cirello <carlos.cirello.nl@gmail.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Graham Campbell <graham@alt-three.com> + */ +final class NoMultilineWhitespaceAroundDoubleArrowFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Operator `=>` should not be surrounded by multi-line whitespaces.', + [new CodeSample("<?php\n\$a = array(1\n\n=> 2);\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BinaryOperatorSpacesFixer, TrailingCommaInMultilineFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOUBLE_ARROW); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOUBLE_ARROW)) { + continue; + } + + $this->fixWhitespace($tokens, $index - 1); + // do not move anything about if there is a comment following the whitespace + if (!$tokens[$index + 2]->isComment()) { + $this->fixWhitespace($tokens, $index + 1); + } + } + } + + /** + * @param int $index + */ + private function fixWhitespace(Tokens $tokens, $index) + { + $token = $tokens[$index]; + + if ($token->isWhitespace() && !$token->isWhitespace(" \t")) { + $tokens[$index] = new Token([T_WHITESPACE, rtrim($token->getContent()).' ']); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleArrayNoTrailingCommaFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoTrailingCommaInSinglelineArrayFixer.php similarity index 53% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleArrayNoTrailingCommaFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoTrailingCommaInSinglelineArrayFixer.php index cfb7673..f2a1017 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/SingleArrayNoTrailingCommaFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoTrailingCommaInSinglelineArrayFixer.php @@ -10,54 +10,72 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Symfony; +namespace PhpCsFixer\Fixer\ArrayNotation; -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; /** * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> * @author Sebastiaan Stok <s.stok@rollerscapes.net> */ -class SingleArrayNoTrailingCommaFixer extends AbstractFixer +final class NoTrailingCommaInSinglelineArrayFixer extends AbstractFixer { /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function getDefinition() { - $tokens = Tokens::fromCode($content); - - for ($index = 0, $c = $tokens->count(); $index < $c; ++$index) { - if ($tokens->isArray($index)) { - $this->fixArray($tokens, $index); - } - } + return new FixerDefinition( + 'PHP single-line arrays should not have trailing comma.', + [new CodeSample("<?php\n\$a = array('sample', );\n")] + ); + } - return $tokens->generateCode(); + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN]); } /** * {@inheritdoc} */ - public function getDescription() + protected function applyFix(\SplFileInfo $file, Tokens $tokens) { - return 'PHP single-line arrays should not have trailing comma.'; + $tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($index = 0, $c = $tokens->count(); $index < $c; ++$index) { + if ($tokensAnalyzer->isArray($index)) { + $this->fixArray($tokens, $index); + } + } } + /** + * @param int $index + */ private function fixArray(Tokens $tokens, $index) { - if ($tokens->isArrayMultiLine($index)) { + $tokensAnalyzer = new TokensAnalyzer($tokens); + + if ($tokensAnalyzer->isArrayMultiLine($index)) { return; } $startIndex = $index; if ($tokens[$startIndex]->isGivenKind(T_ARRAY)) { - $startIndex = $tokens->getNextTokenOfKind($startIndex, array('(')); + $startIndex = $tokens->getNextTokenOfKind($startIndex, ['(']); $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); } else { - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $startIndex); + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $startIndex); } $beforeEndIndex = $tokens->getPrevMeaningfulToken($endIndex); @@ -65,7 +83,7 @@ private function fixArray(Tokens $tokens, $index) if ($beforeEndToken->equals(',')) { $tokens->removeTrailingWhitespace($beforeEndIndex); - $beforeEndToken->clear(); + $tokens->clearAt($beforeEndIndex); } } } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoWhitespaceBeforeCommaInArrayFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoWhitespaceBeforeCommaInArrayFixer.php new file mode 100644 index 0000000..ce6bddb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NoWhitespaceBeforeCommaInArrayFixer.php @@ -0,0 +1,152 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ArrayNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerConfiguration\InvalidOptionsForEnvException; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Options; + +/** + * @author Adam Marczuk <adam@marczuk.info> + */ +final class NoWhitespaceBeforeCommaInArrayFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'In array declaration, there MUST NOT be a whitespace before each comma.', + [ + new CodeSample("<?php \$x = array(1 , \"2\");\n"), + new VersionSpecificCodeSample( + <<<'SAMPLE' +<?php + $x = [<<<EOD +foo +EOD + , 'bar' + ]; + +SAMPLE + , + new VersionSpecification(70300), + ['after_heredoc' => true] + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + if ($tokens[$index]->isGivenKind([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN])) { + $this->fixSpacing($index, $tokens); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('after_heredoc', 'Whether the whitespace between heredoc end and comma should be removed.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->setNormalizer(static function (Options $options, $value) { + if (\PHP_VERSION_ID < 70300 && $value) { + throw new InvalidOptionsForEnvException('"after_heredoc" option can only be enabled with PHP 7.3+.'); + } + + return $value; + }) + ->getOption(), + ]); + } + + /** + * Method to fix spacing in array declaration. + * + * @param int $index + */ + private function fixSpacing($index, Tokens $tokens) + { + if ($tokens[$index]->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { + $startIndex = $index; + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $startIndex); + } else { + $startIndex = $tokens->getNextTokenOfKind($index, ['(']); + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); + } + + for ($i = $endIndex - 1; $i > $startIndex; --$i) { + $i = $this->skipNonArrayElements($i, $tokens); + $currentToken = $tokens[$i]; + $prevIndex = $tokens->getPrevNonWhitespace($i - 1); + + if ( + $currentToken->equals(',') && !$tokens[$prevIndex]->isComment() + && ($this->configuration['after_heredoc'] || !$tokens[$prevIndex]->equals([T_END_HEREDOC])) + ) { + $tokens->removeLeadingWhitespace($i); + } + } + } + + /** + * Method to move index over the non-array elements like function calls or function declarations. + * + * @param int $index + * + * @return int New index + */ + private function skipNonArrayElements($index, Tokens $tokens) + { + if ($tokens[$index]->equals('}')) { + return $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + } + + if ($tokens[$index]->equals(')')) { + $startIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + $startIndex = $tokens->getPrevMeaningfulToken($startIndex); + if (!$tokens[$startIndex]->isGivenKind([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN])) { + return $startIndex; + } + } + + return $index; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NormalizeIndexBraceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NormalizeIndexBraceFixer.php new file mode 100644 index 0000000..733dc23 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/NormalizeIndexBraceFixer.php @@ -0,0 +1,59 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ArrayNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NormalizeIndexBraceFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Array index should always be written by using square braces.', + [new CodeSample("<?php\necho \$sample{\$index};\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if ($token->isGivenKind(CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN)) { + $tokens[$index] = new Token('['); + } elseif ($token->isGivenKind(CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE)) { + $tokens[$index] = new Token(']'); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/TrailingCommaInMultilineArrayFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/TrailingCommaInMultilineArrayFixer.php new file mode 100644 index 0000000..9b2fa4d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/TrailingCommaInMultilineArrayFixer.php @@ -0,0 +1,104 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ArrayNotation; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\ControlStructure\TrailingCommaInMultilineFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; + +/** + * @author Sebastiaan Stok <s.stok@rollerscapes.net> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @deprecated + */ +final class TrailingCommaInMultilineArrayFixer extends AbstractProxyFixer implements ConfigurationDefinitionFixerInterface, DeprecatedFixerInterface +{ + /** + * @var TrailingCommaInMultilineFixer + */ + private $fixer; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHP multi-line arrays should have a trailing comma.', + [ + new CodeSample("<?php\narray(\n 1,\n 2\n);\n"), + new VersionSpecificCodeSample( + <<<'SAMPLE' +<?php + $x = [ + 'foo', + <<<EOD + bar + EOD + ]; + +SAMPLE + , + new VersionSpecification(70300), + ['after_heredoc' => true] + ), + ] + ); + } + + public function configure(array $configuration = null) + { + $configuration['elements'] = [TrailingCommaInMultilineFixer::ELEMENTS_ARRAYS]; + $this->getFixer()->configure($configuration); + $this->configuration = $configuration; + } + + public function getConfigurationDefinition() + { + return new FixerConfigurationResolver([ + $this->getFixer()->getConfigurationDefinition()->getOptions()[0], + ]); + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + return [$this->getFixer()]; + } + + private function getFixer() + { + if (null === $this->fixer) { + $this->fixer = new TrailingCommaInMultilineFixer(); + } + + return $this->fixer; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/TrimArraySpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/TrimArraySpacesFixer.php similarity index 52% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/TrimArraySpacesFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/TrimArraySpacesFixer.php index b0a58b5..a5bbc67 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/TrimArraySpacesFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/TrimArraySpacesFixer.php @@ -10,85 +10,94 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Symfony; +namespace PhpCsFixer\Fixer\ArrayNotation; -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; /** * @author Jared Henderson <jared@netrivet.com> */ -class TrimArraySpacesFixer extends AbstractFixer +final class TrimArraySpacesFixer extends AbstractFixer { /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function getDefinition() { - $tokens = Tokens::fromCode($content); - - for ($index = 0, $c = $tokens->count(); $index < $c; ++$index) { - if ($tokens->isArray($index)) { - self::fixArray($tokens, $index); - } - } + return new FixerDefinition( + 'Arrays should be formatted like function/method arguments, without leading or trailing single line space.', + [new CodeSample("<?php\n\$sample = array( );\n\$sample = array( 'a', 'b' );\n")] + ); + } - return $tokens->generateCode(); + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN]); } /** * {@inheritdoc} */ - public function getDescription() + protected function applyFix(\SplFileInfo $file, Tokens $tokens) { - return 'Arrays should be formatted like function/method arguments, without leading or trailing single line space.'; + for ($index = 0, $c = $tokens->count(); $index < $c; ++$index) { + if ($tokens[$index]->isGivenKind([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN])) { + self::fixArray($tokens, $index); + } + } } /** * Method to trim leading/trailing whitespace within single line arrays. * - * @param Tokens $tokens - * @param int $index + * @param int $index */ private static function fixArray(Tokens $tokens, $index) { - static $whitespaceOptions = array('whitespaces' => " \t"); - $startIndex = $index; if ($tokens[$startIndex]->isGivenKind(T_ARRAY)) { $startIndex = $tokens->getNextMeaningfulToken($startIndex); $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); } else { - $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $startIndex); + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $startIndex); } - $nextToken = $tokens[$startIndex + 1]; + $nextIndex = $startIndex + 1; + $nextToken = $tokens[$nextIndex]; $nextNonWhitespaceIndex = $tokens->getNextNonWhitespace($startIndex); $nextNonWhitespaceToken = $tokens[$nextNonWhitespaceIndex]; + $tokenAfterNextNonWhitespaceToken = $tokens[$nextNonWhitespaceIndex + 1]; - $prevToken = $tokens[$endIndex - 1]; + $prevIndex = $endIndex - 1; + $prevToken = $tokens[$prevIndex]; $prevNonWhitespaceIndex = $tokens->getPrevNonWhitespace($endIndex); $prevNonWhitespaceToken = $tokens[$prevNonWhitespaceIndex]; if ( - $nextToken->isWhitespace($whitespaceOptions) + $nextToken->isWhitespace(" \t") && ( !$nextNonWhitespaceToken->isComment() || $nextNonWhitespaceIndex === $prevNonWhitespaceIndex - || false === strpos($nextNonWhitespaceToken->getContent(), "\n") + || $tokenAfterNextNonWhitespaceToken->isWhitespace(" \t") + || '/*' === substr($nextNonWhitespaceToken->getContent(), 0, 2) ) ) { - $nextToken->clear(); + $tokens->clearAt($nextIndex); } if ( - $prevToken->isWhitespace($whitespaceOptions) + $prevToken->isWhitespace(" \t") && !$prevNonWhitespaceToken->equals(',') - // TODO: following condition should be removed on 2.0 line thanks to WhitespacyCommentTransformer - && !($prevNonWhitespaceToken->isComment() && $prevNonWhitespaceToken->getContent() !== rtrim($prevNonWhitespaceToken->getContent())) ) { - $prevToken->clear(); + $tokens->clearAt($prevIndex); } } } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/WhitespaceAfterCommaInArrayFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/WhitespaceAfterCommaInArrayFixer.php new file mode 100644 index 0000000..bc58a4d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ArrayNotation/WhitespaceAfterCommaInArrayFixer.php @@ -0,0 +1,102 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ArrayNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Adam Marczuk <adam@marczuk.info> + */ +final class WhitespaceAfterCommaInArrayFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'In array declaration, there MUST be a whitespace after each comma.', + [new CodeSample("<?php\n\$sample = array(1,'a',\$b,);\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensToInsert = []; + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + if (!$tokens[$index]->isGivenKind([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN])) { + continue; + } + + if ($tokens[$index]->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { + $startIndex = $index; + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $startIndex); + } else { + $startIndex = $tokens->getNextTokenOfKind($index, ['(']); + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); + } + + for ($i = $endIndex - 1; $i > $startIndex; --$i) { + $i = $this->skipNonArrayElements($i, $tokens); + if ($tokens[$i]->equals(',') && !$tokens[$i + 1]->isWhitespace()) { + $tokensToInsert[$i + 1] = new Token([T_WHITESPACE, ' ']); + } + } + } + + if ([] !== $tokensToInsert) { + $tokens->insertSlices($tokensToInsert); + } + } + + /** + * Method to move index over the non-array elements like function calls or function declarations. + * + * @param int $index + * + * @return int New index + */ + private function skipNonArrayElements($index, Tokens $tokens) + { + if ($tokens[$index]->equals('}')) { + return $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + } + + if ($tokens[$index]->equals(')')) { + $startIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + $startIndex = $tokens->getPrevMeaningfulToken($startIndex); + if (!$tokens[$startIndex]->isGivenKind([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN])) { + return $startIndex; + } + } + + return $index; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/BracesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/BracesFixer.php new file mode 100644 index 0000000..ae912f9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/BracesFixer.php @@ -0,0 +1,1059 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Basic; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * Fixer for rules defined in PSR2 ¶4.1, ¶4.4, ¶5. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class BracesFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @internal + */ + const LINE_NEXT = 'next'; + + /** + * @internal + */ + const LINE_SAME = 'same'; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'The body of each structure MUST be enclosed by braces. Braces should be properly placed. Body of braces should be properly indented.', + [ + new CodeSample( + '<?php + +class Foo { + public function bar($baz) { + if ($baz = 900) echo "Hello!"; + + if ($baz = 9000) + echo "Wait!"; + + if ($baz == true) + { + echo "Why?"; + } + else + { + echo "Ha?"; + } + + if (is_array($baz)) + foreach ($baz as $b) + { + echo $b; + } + } +} +' + ), + new CodeSample( + '<?php +$positive = function ($item) { return $item >= 0; }; +$negative = function ($item) { + return $item < 0; }; +', + ['allow_single_line_closure' => true] + ), + new CodeSample( + '<?php + +class Foo +{ + public function bar($baz) + { + if ($baz = 900) echo "Hello!"; + + if ($baz = 9000) + echo "Wait!"; + + if ($baz == true) + { + echo "Why?"; + } + else + { + echo "Ha?"; + } + + if (is_array($baz)) + foreach ($baz as $b) + { + echo $b; + } + } +} +', + ['position_after_functions_and_oop_constructs' => self::LINE_SAME] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before ArrayIndentationFixer, MethodArgumentSpaceFixer, MethodChainingIndentationFixer. + * Must run after ClassAttributesSeparationFixer, ClassDefinitionFixer, ElseifFixer, LineEndingFixer, MethodSeparationFixer, NoAlternativeSyntaxFixer, NoEmptyStatementFixer, NoUselessElseFixer, SingleLineThrowFixer, SingleSpaceAfterConstructFixer, SingleTraitInsertPerStatementFixer. + */ + public function getPriority() + { + return 35; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $this->fixCommentBeforeBrace($tokens); + $this->fixMissingControlBraces($tokens); + $this->fixIndents($tokens); + $this->fixControlContinuationBraces($tokens); + $this->fixSpaceAroundToken($tokens); + $this->fixDoWhile($tokens); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('allow_single_line_anonymous_class_with_empty_body', 'Whether single line anonymous class with empty body notation should be allowed.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + (new FixerOptionBuilder('allow_single_line_closure', 'Whether single line lambda notation should be allowed.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + (new FixerOptionBuilder('position_after_functions_and_oop_constructs', 'whether the opening brace should be placed on "next" or "same" line after classy constructs (non-anonymous classes, interfaces, traits, methods and non-lambda functions).')) + ->setAllowedValues([self::LINE_NEXT, self::LINE_SAME]) + ->setDefault(self::LINE_NEXT) + ->getOption(), + (new FixerOptionBuilder('position_after_control_structures', 'whether the opening brace should be placed on "next" or "same" line after control structures.')) + ->setAllowedValues([self::LINE_NEXT, self::LINE_SAME]) + ->setDefault(self::LINE_SAME) + ->getOption(), + (new FixerOptionBuilder('position_after_anonymous_constructs', 'whether the opening brace should be placed on "next" or "same" line after anonymous constructs (anonymous classes and lambda functions).')) + ->setAllowedValues([self::LINE_NEXT, self::LINE_SAME]) + ->setDefault(self::LINE_SAME) + ->getOption(), + ]); + } + + private function fixCommentBeforeBrace(Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + $controlTokens = $this->getControlTokens(); + + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + $token = $tokens[$index]; + + if ($token->isGivenKind($controlTokens)) { + $prevIndex = $this->findParenthesisEnd($tokens, $index); + } elseif ( + ($token->isGivenKind(T_FUNCTION) && $tokensAnalyzer->isLambda($index)) + || ($token->isGivenKind(T_CLASS) && $tokensAnalyzer->isAnonymousClass($index)) + ) { + $prevIndex = $tokens->getNextTokenOfKind($index, ['{']); + $prevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + } else { + continue; + } + + $commentIndex = $tokens->getNextNonWhitespace($prevIndex); + $commentToken = $tokens[$commentIndex]; + + if (!$commentToken->isGivenKind(T_COMMENT) || 0 === strpos($commentToken->getContent(), '/*')) { + continue; + } + + $braceIndex = $tokens->getNextMeaningfulToken($commentIndex); + $braceToken = $tokens[$braceIndex]; + + if (!$braceToken->equals('{')) { + continue; + } + + /** @var Token $tokenTmp */ + $tokenTmp = $tokens[$braceIndex]; + + $newBraceIndex = $prevIndex + 1; + for ($i = $braceIndex; $i > $newBraceIndex; --$i) { + // we might be moving one white space next to another, these have to be merged + /** @var Token $previousToken */ + $previousToken = $tokens[$i - 1]; + $tokens[$i] = $previousToken; + if ($tokens[$i]->isWhitespace() && $tokens[$i + 1]->isWhitespace()) { + $tokens[$i] = new Token([T_WHITESPACE, $tokens[$i]->getContent().$tokens[$i + 1]->getContent()]); + $tokens->clearAt($i + 1); + } + } + + $tokens[$newBraceIndex] = $tokenTmp; + $c = $tokens[$braceIndex]->getContent(); + if (substr_count($c, "\n") > 1) { + // left trim till last line break + $tokens[$braceIndex] = new Token([T_WHITESPACE, substr($c, strrpos($c, "\n"))]); + } + } + } + + private function fixControlContinuationBraces(Tokens $tokens) + { + $controlContinuationTokens = $this->getControlContinuationTokens(); + + for ($index = \count($tokens) - 1; 0 <= $index; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind($controlContinuationTokens)) { + continue; + } + + $prevIndex = $tokens->getPrevNonWhitespace($index); + $prevToken = $tokens[$prevIndex]; + + if (!$prevToken->equals('}')) { + continue; + } + + $tokens->ensureWhitespaceAtIndex( + $index - 1, + 1, + self::LINE_NEXT === $this->configuration['position_after_control_structures'] ? + $this->whitespacesConfig->getLineEnding().WhitespacesAnalyzer::detectIndent($tokens, $index) + : ' ' + ); + } + } + + private function fixDoWhile(Tokens $tokens) + { + for ($index = \count($tokens) - 1; 0 <= $index; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_DO)) { + continue; + } + + $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $index); + $startBraceIndex = $tokens->getNextNonWhitespace($parenthesisEndIndex); + $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startBraceIndex); + $nextNonWhitespaceIndex = $tokens->getNextNonWhitespace($endBraceIndex); + $nextNonWhitespaceToken = $tokens[$nextNonWhitespaceIndex]; + + if (!$nextNonWhitespaceToken->isGivenKind(T_WHILE)) { + continue; + } + + $tokens->ensureWhitespaceAtIndex($nextNonWhitespaceIndex - 1, 1, ' '); + } + } + + private function fixIndents(Tokens $tokens) + { + $classyTokens = Token::getClassyTokenKinds(); + $classyAndFunctionTokens = array_merge([T_FUNCTION], $classyTokens); + $controlTokens = $this->getControlTokens(); + $indentTokens = array_filter( + array_merge($classyAndFunctionTokens, $controlTokens), + static function ($item) { + return T_SWITCH !== $item; + } + ); + $tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($index = 0, $limit = \count($tokens); $index < $limit; ++$index) { + $token = $tokens[$index]; + + // if token is not a structure element - continue + if (!$token->isGivenKind($indentTokens)) { + continue; + } + + // do not change indent for `while` in `do ... while ...` + if ( + $token->isGivenKind(T_WHILE) + && $tokensAnalyzer->isWhilePartOfDoWhile($index) + ) { + continue; + } + + if ( + $this->configuration['allow_single_line_anonymous_class_with_empty_body'] + && $token->isGivenKind(T_CLASS) + ) { + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prevIndex]->isGivenKind(T_NEW)) { + $braceStartIndex = $tokens->getNextTokenOfKind($index, ['{']); + $braceEndIndex = $tokens->getNextMeaningfulToken($braceStartIndex); + + if ('}' === $tokens[$braceEndIndex]->getContent() && !$this->isMultilined($tokens, $index, $braceEndIndex)) { + $index = $braceEndIndex; + + continue; + } + } + } + + if ( + $this->configuration['allow_single_line_closure'] + && $token->isGivenKind(T_FUNCTION) + && $tokensAnalyzer->isLambda($index) + ) { + $braceEndIndex = $tokens->findBlockEnd( + Tokens::BLOCK_TYPE_CURLY_BRACE, + $tokens->getNextTokenOfKind($index, ['{']) + ); + + if (!$this->isMultilined($tokens, $index, $braceEndIndex)) { + $index = $braceEndIndex; + + continue; + } + } + + if ($token->isGivenKind($classyAndFunctionTokens)) { + $startBraceIndex = $tokens->getNextTokenOfKind($index, [';', '{']); + $startBraceToken = $tokens[$startBraceIndex]; + } else { + $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $index); + $startBraceIndex = $tokens->getNextNonWhitespace($parenthesisEndIndex); + $startBraceToken = $tokens[$startBraceIndex]; + } + + // structure without braces block - nothing to do, e.g. do { } while (true); + if (!$startBraceToken->equals('{')) { + continue; + } + + $nextNonWhitespaceIndex = $tokens->getNextNonWhitespace($startBraceIndex, " \t"); + $nextNonWhitespace = $tokens[$nextNonWhitespaceIndex]; + + /* if CLOSE_TAG is after { on the same line, do not indent. e.g. <?php if ($condition) { ?> */ + if ($nextNonWhitespace->isGivenKind(T_CLOSE_TAG)) { + continue; + } + + /* if CLOSE_TAG is after { on the next line and a comment on this line, do not indent. e.g. <?php if ($condition) { // \n?> */ + if ($nextNonWhitespace->isComment() && $tokens[$tokens->getNextMeaningfulToken($nextNonWhitespaceIndex)]->isGivenKind(T_CLOSE_TAG)) { + continue; + } + + $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startBraceIndex); + + $indent = WhitespacesAnalyzer::detectIndent($tokens, $index); + + // fix indent near closing brace + $tokens->ensureWhitespaceAtIndex($endBraceIndex - 1, 1, $this->whitespacesConfig->getLineEnding().$indent); + + // fix indent between braces + $lastCommaIndex = $tokens->getPrevTokenOfKind($endBraceIndex - 1, [';', '}']); + + $nestLevel = 1; + for ($nestIndex = $lastCommaIndex; $nestIndex >= $startBraceIndex; --$nestIndex) { + $nestToken = $tokens[$nestIndex]; + + if ($nestToken->equalsAny([')', [CT::T_BRACE_CLASS_INSTANTIATION_CLOSE]])) { + $nestIndex = $tokens->findBlockStart( + $nestToken->equals(')') ? Tokens::BLOCK_TYPE_PARENTHESIS_BRACE : Tokens::BLOCK_TYPE_BRACE_CLASS_INSTANTIATION, + $nestIndex + ); + + continue; + } + + if (1 === $nestLevel) { + // Next token is the beginning of a line that can be indented when + // the current token is a `;`, a `}` or the opening `{` of current + // scope. Current token may also be a comment that follows `;` or + // `}`, in which case indentation will only be fixed if this + // comment is followed by a newline. + $nextLineCanBeIndented = false; + if ($nestToken->equalsAny([';', '}'])) { + $nextLineCanBeIndented = true; + } elseif ($this->isCommentWithFixableIndentation($tokens, $nestIndex)) { + for ($i = $nestIndex; $i > $startBraceIndex; --$i) { + if ($tokens[$i]->equalsAny([';', '}'])) { + $nextLineCanBeIndented = true; + + break; + } + + if (!$tokens[$i]->isWhitespace() && !$tokens[$i]->isComment()) { + break; + } + } + + if ($nextLineCanBeIndented || $i === $startBraceIndex) { + $nextToken = $tokens[$nestIndex + 1]; + $nextLineCanBeIndented = $nextToken->isWhitespace() && 1 === Preg::match('/\R/', $nextToken->getContent()); + } + } + + if (!$nextLineCanBeIndented) { + continue; + } + + $nextNonWhitespaceNestIndex = $tokens->getNextNonWhitespace($nestIndex); + $nextNonWhitespaceNestToken = $tokens[$nextNonWhitespaceNestIndex]; + + if ( + // next Token is not a comment on its own line + !($nextNonWhitespaceNestToken->isComment() && ( + !$tokens[$nextNonWhitespaceNestIndex - 1]->isWhitespace() + || !Preg::match('/\R/', $tokens[$nextNonWhitespaceNestIndex - 1]->getContent()) + )) + // and it is not a `$foo = function () {};` situation + && !($nestToken->equals('}') && $nextNonWhitespaceNestToken->equalsAny([';', ',', ']', [CT::T_ARRAY_SQUARE_BRACE_CLOSE]])) + // and it is not a `Foo::{bar}()` situation + && !($nestToken->equals('}') && $nextNonWhitespaceNestToken->equals('(')) + // and it is not a `${"a"}->...` and `${"b{$foo}"}->...` situation + && !($nestToken->equals('}') && $tokens[$nestIndex - 1]->equalsAny(['"', "'", [T_CONSTANT_ENCAPSED_STRING], [T_VARIABLE]])) + // and next token is not a closing tag that would break heredoc/nowdoc syntax + && !($tokens[$nestIndex - 1]->isGivenKind(T_END_HEREDOC) && $nextNonWhitespaceNestToken->isGivenKind(T_CLOSE_TAG)) + ) { + if ( + ( + self::LINE_NEXT !== $this->configuration['position_after_control_structures'] + && $nextNonWhitespaceNestToken->isGivenKind($this->getControlContinuationTokens()) + && !$tokens[$tokens->getPrevNonWhitespace($nextNonWhitespaceNestIndex)]->isComment() + ) + || $nextNonWhitespaceNestToken->isGivenKind(T_CLOSE_TAG) + || ( + self::LINE_NEXT !== $this->configuration['position_after_control_structures'] + && $nextNonWhitespaceNestToken->isGivenKind(T_WHILE) + && $tokensAnalyzer->isWhilePartOfDoWhile($nextNonWhitespaceNestIndex) + ) + ) { + $whitespace = ' '; + } else { + $nextToken = $tokens[$nestIndex + 1]; + $nextWhitespace = ''; + + if ($nextToken->isWhitespace()) { + $nextWhitespace = rtrim($nextToken->getContent(), " \t"); + + if ('' !== $nextWhitespace) { + $nextWhitespace = Preg::replace( + sprintf('/%s$/', $this->whitespacesConfig->getLineEnding()), + '', + $nextWhitespace, + 1 + ); + } + } + + $whitespace = $nextWhitespace.$this->whitespacesConfig->getLineEnding().$indent; + + if (!$nextNonWhitespaceNestToken->equals('}')) { + $determineIsIndentableBlockContent = static function ($contentIndex) use ($tokens) { + if (!$tokens[$contentIndex]->isComment()) { + return true; + } + + if (!$tokens[$tokens->getPrevMeaningfulToken($contentIndex)]->equals(';')) { + return true; + } + + $nextIndex = $tokens->getNextMeaningfulToken($contentIndex); + + if (!$tokens[$nextIndex]->equals('}')) { + return true; + } + + $nextNextIndex = $tokens->getNextMeaningfulToken($nextIndex); + + if (null === $nextNextIndex) { + return true; + } + + if ($tokens[$nextNextIndex]->equalsAny([ + [T_ELSE], + [T_ELSEIF], + ',', + ])) { + return false; + } + + return true; + }; + + // add extra indent only if current content is not a comment for content outside of current block + if ($determineIsIndentableBlockContent($nestIndex + 2)) { + $whitespace .= $this->whitespacesConfig->getIndent(); + } + } + } + + $this->ensureWhitespaceAtIndexAndIndentMultilineComment($tokens, $nestIndex + 1, $whitespace); + } + } + + if ($nestToken->equals('}')) { + ++$nestLevel; + + continue; + } + + if ($nestToken->equals('{')) { + --$nestLevel; + + continue; + } + } + + // fix indent near opening brace + if (isset($tokens[$startBraceIndex + 2]) && $tokens[$startBraceIndex + 2]->equals('}')) { + $tokens->ensureWhitespaceAtIndex($startBraceIndex + 1, 0, $this->whitespacesConfig->getLineEnding().$indent); + } else { + $nextToken = $tokens[$startBraceIndex + 1]; + $nextNonWhitespaceToken = $tokens[$tokens->getNextNonWhitespace($startBraceIndex)]; + + // set indent only if it is not a case, when comment is following { on same line + if ( + !$nextNonWhitespaceToken->isComment() + || ($nextToken->isWhitespace() && 1 === substr_count($nextToken->getContent(), "\n")) // preserve blank lines + ) { + $this->ensureWhitespaceAtIndexAndIndentMultilineComment( + $tokens, + $startBraceIndex + 1, + $this->whitespacesConfig->getLineEnding().$indent.$this->whitespacesConfig->getIndent() + ); + } + } + + if ($token->isGivenKind($classyTokens) && !$tokensAnalyzer->isAnonymousClass($index)) { + if (self::LINE_SAME === $this->configuration['position_after_functions_and_oop_constructs'] && !$tokens[$tokens->getPrevNonWhitespace($startBraceIndex)]->isComment()) { + $ensuredWhitespace = ' '; + } else { + $ensuredWhitespace = $this->whitespacesConfig->getLineEnding().$indent; + } + + $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, $ensuredWhitespace); + } elseif ( + $token->isGivenKind(T_FUNCTION) && !$tokensAnalyzer->isLambda($index) + || ( + self::LINE_NEXT === $this->configuration['position_after_control_structures'] && $token->isGivenKind($controlTokens) + || ( + self::LINE_NEXT === $this->configuration['position_after_anonymous_constructs'] + && ( + $token->isGivenKind(T_FUNCTION) && $tokensAnalyzer->isLambda($index) + || $token->isGivenKind(T_CLASS) && $tokensAnalyzer->isAnonymousClass($index) + ) + ) + ) + ) { + $isAnonymousClass = $token->isGivenKind($classyTokens) && $tokensAnalyzer->isAnonymousClass($index); + + $closingParenthesisIndex = $tokens->getPrevTokenOfKind($startBraceIndex, [')']); + if (null === $closingParenthesisIndex && !$isAnonymousClass) { + continue; + } + + if ( + !$isAnonymousClass + && $tokens[$closingParenthesisIndex - 1]->isWhitespace() + && false !== strpos($tokens[$closingParenthesisIndex - 1]->getContent(), "\n") + ) { + if (!$tokens[$startBraceIndex - 2]->isComment()) { + $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); + } + } else { + if ( + self::LINE_SAME === $this->configuration['position_after_functions_and_oop_constructs'] + && ( + $token->isGivenKind(T_FUNCTION) && !$tokensAnalyzer->isLambda($index) + || $token->isGivenKind($classyTokens) && !$tokensAnalyzer->isAnonymousClass($index) + ) + && !$tokens[$tokens->getPrevNonWhitespace($startBraceIndex)]->isComment() + ) { + $ensuredWhitespace = ' '; + } else { + $ensuredWhitespace = $this->whitespacesConfig->getLineEnding().$indent; + } + + $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, $ensuredWhitespace); + } + } else { + $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); + } + + // reset loop limit due to collection change + $limit = \count($tokens); + } + } + + private function fixMissingControlBraces(Tokens $tokens) + { + $controlTokens = $this->getControlTokens(); + + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind($controlTokens)) { + continue; + } + + $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $index); + $nextAfterParenthesisEndIndex = $tokens->getNextMeaningfulToken($parenthesisEndIndex); + $tokenAfterParenthesis = $tokens[$nextAfterParenthesisEndIndex]; + + // if Token after parenthesis is { then we do not need to insert brace, but to fix whitespace before it + if ($tokenAfterParenthesis->equals('{') && self::LINE_SAME === $this->configuration['position_after_control_structures']) { + $tokens->ensureWhitespaceAtIndex($parenthesisEndIndex + 1, 0, ' '); + + continue; + } + + // do not add braces for cases: + // - structure without block, e.g. while ($iter->next()); + // - structure with block, e.g. while ($i) {...}, while ($i) : {...} endwhile; + if ($tokenAfterParenthesis->equalsAny([';', '{', ':'])) { + continue; + } + + // do not add for short 'if' followed by alternative loop, + // for example: if ($a) while ($b): ? > X < ?php endwhile; ? > + if ($tokenAfterParenthesis->isGivenKind([T_FOR, T_FOREACH, T_SWITCH, T_WHILE])) { + $tokenAfterParenthesisBlockEnd = $tokens->findBlockEnd( // go to ')' + Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, + $tokens->getNextMeaningfulToken($nextAfterParenthesisEndIndex) + ); + + if ($tokens[$tokens->getNextMeaningfulToken($tokenAfterParenthesisBlockEnd)]->equals(':')) { + continue; + } + } + + $statementEndIndex = $this->findStatementEnd($tokens, $parenthesisEndIndex); + + // insert closing brace + $tokens->insertAt($statementEndIndex + 1, [new Token([T_WHITESPACE, ' ']), new Token('}')]); + + // insert missing `;` if needed + if (!$tokens[$statementEndIndex]->equalsAny([';', '}'])) { + $tokens->insertAt($statementEndIndex + 1, new Token(';')); + } + + // insert opening brace + $tokens->insertAt($parenthesisEndIndex + 1, new Token('{')); + $tokens->ensureWhitespaceAtIndex($parenthesisEndIndex + 1, 0, ' '); + } + } + + private function fixSpaceAroundToken(Tokens $tokens) + { + $controlTokens = $this->getControlTokens(); + + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + $token = $tokens[$index]; + + // Declare tokens don't follow the same rules are other control statements + if ($token->isGivenKind(T_DECLARE)) { + $this->fixDeclareStatement($tokens, $index); + } elseif ($token->isGivenKind($controlTokens) || $token->isGivenKind(CT::T_USE_LAMBDA)) { + $nextNonWhitespaceIndex = $tokens->getNextNonWhitespace($index); + + if (!$tokens[$nextNonWhitespaceIndex]->equals(':')) { + $tokens->ensureWhitespaceAtIndex( + $index + 1, + 0, + self::LINE_NEXT === $this->configuration['position_after_control_structures'] && !$tokens[$nextNonWhitespaceIndex]->equals('(') ? + $this->whitespacesConfig->getLineEnding().WhitespacesAnalyzer::detectIndent($tokens, $index) + : ' ' + ); + } + + $prevToken = $tokens[$index - 1]; + + if (!$prevToken->isWhitespace() && !$prevToken->isComment() && !$prevToken->isGivenKind(T_OPEN_TAG)) { + $tokens->ensureWhitespaceAtIndex($index - 1, 1, ' '); + } + } + } + } + + /** + * @param int $structureTokenIndex + * + * @return int + */ + private function findParenthesisEnd(Tokens $tokens, $structureTokenIndex) + { + $nextIndex = $tokens->getNextMeaningfulToken($structureTokenIndex); + $nextToken = $tokens[$nextIndex]; + + // return if next token is not opening parenthesis + if (!$nextToken->equals('(')) { + return $structureTokenIndex; + } + + return $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nextIndex); + } + + /** + * @param int $parenthesisEndIndex + * + * @return int + */ + private function findStatementEnd(Tokens $tokens, $parenthesisEndIndex) + { + $nextIndex = $tokens->getNextMeaningfulToken($parenthesisEndIndex); + $nextToken = $tokens[$nextIndex]; + + if (!$nextToken) { + return $parenthesisEndIndex; + } + + if ($nextToken->equals('{')) { + return $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $nextIndex); + } + + if ($nextToken->isGivenKind($this->getControlTokens())) { + $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $nextIndex); + + $endIndex = $this->findStatementEnd($tokens, $parenthesisEndIndex); + + if ($nextToken->isGivenKind([T_IF, T_TRY, T_DO])) { + $openingTokenKind = $nextToken->getId(); + + while (true) { + $nextIndex = $tokens->getNextMeaningfulToken($endIndex); + $nextToken = isset($nextIndex) ? $tokens[$nextIndex] : null; + if ($nextToken && $nextToken->isGivenKind($this->getControlContinuationTokensForOpeningToken($openingTokenKind))) { + $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $nextIndex); + + $endIndex = $this->findStatementEnd($tokens, $parenthesisEndIndex); + + if ($nextToken->isGivenKind($this->getFinalControlContinuationTokensForOpeningToken($openingTokenKind))) { + return $endIndex; + } + } else { + break; + } + } + } + + return $endIndex; + } + + $index = $parenthesisEndIndex; + + while (true) { + $token = $tokens[++$index]; + + // if there is some block in statement (eg lambda function) we need to skip it + if ($token->equals('{')) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + continue; + } + + if ($token->equals(';')) { + return $index; + } + + if ($token->isGivenKind(T_CLOSE_TAG)) { + return $tokens->getPrevNonWhitespace($index); + } + } + } + + private function getControlTokens() + { + static $tokens = [ + T_DECLARE, + T_DO, + T_ELSE, + T_ELSEIF, + T_FINALLY, + T_FOR, + T_FOREACH, + T_IF, + T_WHILE, + T_TRY, + T_CATCH, + T_SWITCH, + ]; + + // @TODO: drop condition when PHP 8.0+ is required + if (\defined('T_MATCH')) { + $tokens['match'] = T_MATCH; + } + + return $tokens; + } + + private function getControlContinuationTokens() + { + static $tokens = [ + T_CATCH, + T_ELSE, + T_ELSEIF, + T_FINALLY, + ]; + + return $tokens; + } + + private function getControlContinuationTokensForOpeningToken($openingTokenKind) + { + if (T_IF === $openingTokenKind) { + return [ + T_ELSE, + T_ELSEIF, + ]; + } + + if (T_DO === $openingTokenKind) { + return [T_WHILE]; + } + + if (T_TRY === $openingTokenKind) { + return [ + T_CATCH, + T_FINALLY, + ]; + } + + return []; + } + + private function getFinalControlContinuationTokensForOpeningToken($openingTokenKind) + { + if (T_IF === $openingTokenKind) { + return [T_ELSE]; + } + + if (T_TRY === $openingTokenKind) { + return [T_FINALLY]; + } + + return []; + } + + /** + * @param int $index + */ + private function fixDeclareStatement(Tokens $tokens, $index) + { + $tokens->removeTrailingWhitespace($index); + + $startParenthesisIndex = $tokens->getNextTokenOfKind($index, ['(']); + $tokens->removeTrailingWhitespace($startParenthesisIndex); + + $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex); + $tokens->removeLeadingWhitespace($endParenthesisIndex); + + $startBraceIndex = $tokens->getNextTokenOfKind($endParenthesisIndex, [';', '{']); + $startBraceToken = $tokens[$startBraceIndex]; + + if ($startBraceToken->equals('{')) { + $this->fixSingleLineWhitespaceForDeclare($tokens, $startBraceIndex); + } + } + + /** + * @param int $startBraceIndex + */ + private function fixSingleLineWhitespaceForDeclare(Tokens $tokens, $startBraceIndex) + { + // fix single-line whitespace before { + // eg: `declare(ticks=1){` => `declare(ticks=1) {` + // eg: `declare(ticks=1) {` => `declare(ticks=1) {` + if ( + !$tokens[$startBraceIndex - 1]->isWhitespace() + || $tokens[$startBraceIndex - 1]->isWhitespace(" \t") + ) { + $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); + } + } + + /** + * @param int $index + * @param string $whitespace + */ + private function ensureWhitespaceAtIndexAndIndentMultilineComment(Tokens $tokens, $index, $whitespace) + { + if ($tokens[$index]->isWhitespace()) { + $nextTokenIndex = $tokens->getNextNonWhitespace($index); + } else { + $nextTokenIndex = $index; + } + + $nextToken = $tokens[$nextTokenIndex]; + if ($nextToken->isComment()) { + $previousToken = $tokens[$nextTokenIndex - 1]; + $nextTokenContent = $nextToken->getContent(); + + // do not indent inline comments used to comment out unused code + if ( + $previousToken->isWhitespace() + && 1 === Preg::match('/\R$/', $previousToken->getContent()) + && ( + (0 === strpos($nextTokenContent, '//'.$this->whitespacesConfig->getIndent()) || '//' === $nextTokenContent) + || (0 === strpos($nextTokenContent, '#'.$this->whitespacesConfig->getIndent()) || '#' === $nextTokenContent) + ) + ) { + return; + } + + $tokens[$nextTokenIndex] = new Token([ + $nextToken->getId(), + Preg::replace( + '/(\R)'.WhitespacesAnalyzer::detectIndent($tokens, $nextTokenIndex).'(\h*\S+.*)/', + '$1'.Preg::replace('/^.*\R(\h*)$/s', '$1', $whitespace).'$2', + $nextToken->getContent() + ), + ]); + } + + $tokens->ensureWhitespaceAtIndex($index, 0, $whitespace); + } + + /** + * @param int $startParenthesisIndex + * @param int $endParenthesisIndex + * + * @return bool + */ + private function isMultilined(Tokens $tokens, $startParenthesisIndex, $endParenthesisIndex) + { + for ($i = $startParenthesisIndex; $i < $endParenthesisIndex; ++$i) { + if (false !== strpos($tokens[$i]->getContent(), "\n")) { + return true; + } + } + + return false; + } + + /** + * Returns whether the token at given index is a comment whose indentation + * can be fixed. + * + * Indentation of a comment is not changed when the comment is part of a + * multi-line message whose lines are all single-line comments and at least + * one line has meaningful content. + * + * @param int $index + * + * @return bool + */ + private function isCommentWithFixableIndentation(Tokens $tokens, $index) + { + if (!$tokens[$index]->isComment()) { + return false; + } + + if (0 === strpos($tokens[$index]->getContent(), '/*')) { + return true; + } + + $firstCommentIndex = $index; + while (true) { + $i = $this->getSiblingContinuousSingleLineComment($tokens, $firstCommentIndex, false); + if (null === $i) { + break; + } + + $firstCommentIndex = $i; + } + + $lastCommentIndex = $index; + while (true) { + $i = $this->getSiblingContinuousSingleLineComment($tokens, $lastCommentIndex, true); + if (null === $i) { + break; + } + + $lastCommentIndex = $i; + } + + if ($firstCommentIndex === $lastCommentIndex) { + return true; + } + + for ($i = $firstCommentIndex + 1; $i < $lastCommentIndex; ++$i) { + if (!$tokens[$i]->isWhitespace() && !$tokens[$i]->isComment()) { + return false; + } + } + + return true; + } + + /** + * @param int $index + * @param bool $after + * + * @return null|int + */ + private function getSiblingContinuousSingleLineComment(Tokens $tokens, $index, $after) + { + $siblingIndex = $index; + do { + $siblingIndex = $tokens->getTokenOfKindSibling($siblingIndex, $after ? 1 : -1, [[T_COMMENT]]); + + if (null === $siblingIndex) { + return null; + } + } while (0 === strpos($tokens[$siblingIndex]->getContent(), '/*')); + + $newLines = 0; + for ($i = min($siblingIndex, $index) + 1, $max = max($siblingIndex, $index); $i < $max; ++$i) { + if ($tokens[$i]->isWhitespace() && Preg::match('/\R/', $tokens[$i]->getContent())) { + if (1 === $newLines || Preg::match('/\R.*\R/', $tokens[$i]->getContent())) { + return null; + } + + ++$newLines; + } + } + + return $siblingIndex; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/EncodingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/EncodingFixer.php new file mode 100644 index 0000000..f7499c4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/EncodingFixer.php @@ -0,0 +1,97 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Basic; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR1 ¶2.2. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class EncodingFixer extends AbstractFixer +{ + /** + * @var string + */ + private $BOM; + + public function __construct() + { + parent::__construct(); + + $this->BOM = pack('CCC', 0xef, 0xbb, 0xbf); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHP code MUST use only UTF-8 without BOM (remove BOM).', + [ + new CodeSample( + $this->BOM.'<?php + +echo "Hello!"; +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + // must run first (at least before Fixers that using Tokens) - for speed reason of whole fixing process + return 100; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $content = $tokens[0]->getContent(); + + if (0 === strncmp($content, $this->BOM, 3)) { + /** @var false|string $newContent until support for PHP 5.6 is dropped */ + $newContent = substr($content, 3); + + if (false === $newContent) { + $newContent = ''; // substr returns false rather than an empty string when starting at the end + } + + if ('' === $newContent) { + $tokens->clearAt(0); + } else { + $tokens[0] = new Token([$tokens[0]->getId(), $newContent]); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/NonPrintableCharacterFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/NonPrintableCharacterFixer.php new file mode 100644 index 0000000..d006925 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/NonPrintableCharacterFixer.php @@ -0,0 +1,180 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Basic; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerConfiguration\InvalidOptionsForEnvException; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Options; + +/** + * Removes Zero-width space (ZWSP), Non-breaking space (NBSP) and other invisible unicode symbols. + * + * @author Ivan Boprzenkov <ivan.borzenkov@gmail.com> + */ +final class NonPrintableCharacterFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + private $symbolsReplace; + + private static $tokens = [ + T_STRING_VARNAME, + T_INLINE_HTML, + T_VARIABLE, + T_COMMENT, + T_ENCAPSED_AND_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_DOC_COMMENT, + ]; + + public function __construct() + { + parent::__construct(); + + $this->symbolsReplace = [ + pack('H*', 'e2808b') => ['', '200b'], // ZWSP U+200B + pack('H*', 'e28087') => [' ', '2007'], // FIGURE SPACE U+2007 + pack('H*', 'e280af') => [' ', '202f'], // NBSP U+202F + pack('H*', 'e281a0') => ['', '2060'], // WORD JOINER U+2060 + pack('H*', 'c2a0') => [' ', 'a0'], // NO-BREAK SPACE U+A0 + ]; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Remove Zero-width space (ZWSP), Non-breaking space (NBSP) and other invisible unicode symbols.', + [ + new CodeSample( + '<?php echo "'.pack('H*', 'e2808b').'Hello'.pack('H*', 'e28087').'World'.pack('H*', 'c2a0')."!\";\n" + ), + new VersionSpecificCodeSample( + '<?php echo "'.pack('H*', 'e2808b').'Hello'.pack('H*', 'e28087').'World'.pack('H*', 'c2a0')."!\";\n", + new VersionSpecification(70000), + ['use_escape_sequences_in_strings' => true] + ), + ], + null, + 'Risky when strings contain intended invisible characters.' + ); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(self::$tokens); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('use_escape_sequences_in_strings', 'Whether characters should be replaced with escape sequences in strings.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) // @TODO 3.0 change to true + ->setNormalizer(static function (Options $options, $value) { + if (\PHP_VERSION_ID < 70000 && $value) { + throw new InvalidOptionsForEnvException('Escape sequences require PHP 7.0+.'); + } + + return $value; + }) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $replacements = []; + $escapeSequences = []; + foreach ($this->symbolsReplace as $character => list($replacement, $codepoint)) { + $replacements[$character] = $replacement; + $escapeSequences[$character] = '\u{'.$codepoint.'}'; + } + + foreach ($tokens as $index => $token) { + $content = $token->getContent(); + + if ( + $this->configuration['use_escape_sequences_in_strings'] + && $token->isGivenKind([T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE]) + ) { + if (!Preg::match('/'.implode('|', array_keys($escapeSequences)).'/', $content)) { + continue; + } + + $previousToken = $tokens[$index - 1]; + $stringTypeChanged = false; + $swapQuotes = false; + + if ($previousToken->isGivenKind(T_START_HEREDOC)) { + $previousTokenContent = $previousToken->getContent(); + + if (false !== strpos($previousTokenContent, '\'')) { + $tokens[$index - 1] = new Token([T_START_HEREDOC, str_replace('\'', '', $previousTokenContent)]); + $stringTypeChanged = true; + } + } elseif ("'" === $content[0]) { + $stringTypeChanged = true; + $swapQuotes = true; + } + + if ($swapQuotes) { + $content = str_replace("\\'", "'", $content); + } + if ($stringTypeChanged) { + $content = Preg::replace('/(\\\\{1,2})/', '\\\\\\\\', $content); + $content = str_replace('$', '\$', $content); + } + if ($swapQuotes) { + $content = str_replace('"', '\"', $content); + $content = Preg::replace('/^\'(.*)\'$/', '"$1"', $content); + } + + $tokens[$index] = new Token([$token->getId(), strtr($content, $escapeSequences)]); + + continue; + } + + if ($token->isGivenKind(self::$tokens)) { + $tokens[$index] = new Token([$token->getId(), strtr($content, $replacements)]); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/Psr0Fixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/Psr0Fixer.php new file mode 100644 index 0000000..0f4d626 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/Psr0Fixer.php @@ -0,0 +1,96 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Basic; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author Jordi Boggiano <j.boggiano@seld.be> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Bram Gotink <bram@gotink.me> + * @author Graham Campbell <graham@alt-three.com> + * + * @deprecated + */ +final class Psr0Fixer extends AbstractProxyFixer implements ConfigurationDefinitionFixerInterface, DeprecatedFixerInterface +{ + /** + * @var PsrAutoloadingFixer + */ + private $fixer; + + public function __construct() + { + $this->fixer = new PsrAutoloadingFixer(); + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + $definition = $this->fixer->getDefinition(); + + return new FixerDefinition( + 'Classes must be in a path that matches their namespace, be at least one namespace deep and the class name should match the file name.', + $definition->getCodeSamples(), + $definition->getDescription(), + $definition->getRiskyDescription() + ); + } + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->fixer->configure($configuration); + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return [$this->fixer->getName()]; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('dir', 'The directory where the project code is placed.')) + ->setAllowedTypes(['string']) + ->setDefault('') + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + return [$this->fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/Psr4Fixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/Psr4Fixer.php new file mode 100644 index 0000000..255de24 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/Psr4Fixer.php @@ -0,0 +1,70 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Basic; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author Jordi Boggiano <j.boggiano@seld.be> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Bram Gotink <bram@gotink.me> + * @author Graham Campbell <graham@alt-three.com> + * + * @deprecated + */ +final class Psr4Fixer extends AbstractProxyFixer implements DeprecatedFixerInterface +{ + /** + * @var PsrAutoloadingFixer + */ + private $fixer; + + public function __construct() + { + $this->fixer = new PsrAutoloadingFixer(); + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + $definition = $this->fixer->getDefinition(); + + return new FixerDefinition( + 'Class names should match the file name.', + \array_slice($definition->getCodeSamples(), 0, 1), + $definition->getDescription(), + $definition->getRiskyDescription() + ); + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return [$this->fixer->getName()]; + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + return [$this->fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/PsrAutoloadingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/PsrAutoloadingFixer.php new file mode 100644 index 0000000..8bb6d2c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Basic/PsrAutoloadingFixer.php @@ -0,0 +1,292 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Basic; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\FileSpecificCodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\StdinFileInfo; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Jordi Boggiano <j.boggiano@seld.be> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Bram Gotink <bram@gotink.me> + * @author Graham Campbell <graham@alt-three.com> + * @author Kuba Werłos <werlos@gmail.com> + */ +final class PsrAutoloadingFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Classes must be in a path that matches their namespace, be at least one namespace deep and the class name should match the file name.', + [ + new FileSpecificCodeSample( + '<?php +namespace PhpCsFixer\FIXER\Basic; +class InvalidName {} +', + new \SplFileInfo(__FILE__) + ), + new FileSpecificCodeSample( + '<?php +namespace PhpCsFixer\FIXER\Basic; +class InvalidName {} +', + new \SplFileInfo(__FILE__), + ['dir' => './src'] + ), + ], + null, + 'This fixer may change your class name, which will break the code that depends on the old name.' + ); + } + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + if (null !== $this->configuration['dir']) { + $this->configuration['dir'] = realpath($this->configuration['dir']); + } + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds()); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + public function supports(\SplFileInfo $file) + { + if ($file instanceof StdinFileInfo) { + return false; + } + + if ( + // ignore file with extension other than php + ('php' !== $file->getExtension()) + // ignore file with name that cannot be a class name + || 0 === Preg::match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $file->getBasename('.php')) + ) { + return false; + } + + try { + $tokens = Tokens::fromCode(sprintf('<?php class %s {}', $file->getBasename('.php'))); + + if ($tokens[3]->isKeyword() || $tokens[3]->isMagicConstant()) { + // name can not be a class name - detected by PHP 5.x + return false; + } + } catch (\ParseError $e) { + // name can not be a class name - detected by PHP 7.x + return false; + } + + // ignore stubs/fixtures, since they are typically containing invalid files for various reasons + return !Preg::match('{[/\\\\](stub|fixture)s?[/\\\\]}i', $file->getRealPath()); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('dir', 'If provided, the directory where the project code is placed.')) + ->setAllowedTypes(['null', 'string']) + ->setDefault(null) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if (null !== $this->configuration['dir'] && 0 !== strpos($file->getRealPath(), $this->configuration['dir'])) { + return; + } + + $namespace = null; + $namespaceStartIndex = null; + $namespaceEndIndex = null; + + $classyName = null; + $classyIndex = null; + + foreach ($tokens as $index => $token) { + if ($token->isGivenKind(T_NAMESPACE)) { + if (null !== $namespace) { + return; + } + + $namespaceStartIndex = $tokens->getNextMeaningfulToken($index); + $namespaceEndIndex = $tokens->getNextTokenOfKind($namespaceStartIndex, [';']); + + $namespace = trim($tokens->generatePartialCode($namespaceStartIndex, $namespaceEndIndex - 1)); + } elseif ($token->isClassy()) { + if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_NEW)) { + continue; + } + + if (null !== $classyName) { + return; + } + + $classyIndex = $tokens->getNextMeaningfulToken($index); + $classyName = $tokens[$classyIndex]->getContent(); + } + } + + if (null === $classyName) { + return; + } + + $expectedClassyName = $this->calculateClassyName($file, $namespace, $classyName); + + if ($classyName !== $expectedClassyName) { + $tokens[$classyIndex] = new Token([T_STRING, $expectedClassyName]); + } + + if (null === $this->configuration['dir'] || null === $namespace) { + return; + } + + if (!is_dir($this->configuration['dir'])) { + return; + } + + $configuredDir = realpath($this->configuration['dir']); + $fileDir = \dirname($file->getRealPath()); + if (\strlen($configuredDir) >= \strlen($fileDir)) { + return; + } + + $newNamespace = substr(str_replace('/', '\\', $fileDir), \strlen($configuredDir) + 1); + $originalNamespace = substr($namespace, -\strlen($newNamespace)); + + if ($originalNamespace !== $newNamespace && strtolower($originalNamespace) === strtolower($newNamespace)) { + $tokens->clearRange($namespaceStartIndex, $namespaceEndIndex); + $namespace = substr($namespace, 0, -\strlen($newNamespace)).$newNamespace; + + $newNamespace = Tokens::fromCode('<?php namespace '.$namespace.';'); + $newNamespace->clearRange(0, 2); + $newNamespace->clearEmptyTokens(); + + $tokens->insertAt($namespaceStartIndex, $newNamespace); + } + } + + /** + * @param null|string $namespace + * @param string $currentName + * + * @return string + */ + private function calculateClassyName(\SplFileInfo $file, $namespace, $currentName) + { + $name = $file->getBasename('.php'); + + $maxNamespace = $this->calculateMaxNamespace($file, $namespace); + + if (null !== $this->configuration['dir']) { + return ('' !== $maxNamespace ? (str_replace('\\', '_', $maxNamespace).'_') : '').$name; + } + + $namespaceParts = array_reverse(explode('\\', $maxNamespace)); + + foreach ($namespaceParts as $namespacePart) { + $nameCandidate = sprintf('%s_%s', $namespacePart, $name); + if (strtolower($nameCandidate) !== strtolower(substr($currentName, -\strlen($nameCandidate)))) { + break; + } + $name = $nameCandidate; + } + + return $name; + } + + /** + * @param null|string $namespace + * + * @return string + */ + private function calculateMaxNamespace(\SplFileInfo $file, $namespace) + { + if (null === $this->configuration['dir']) { + $root = \dirname($file->getRealPath()); + while ($root !== \dirname($root)) { + $root = \dirname($root); + } + } else { + $root = realpath($this->configuration['dir']); + } + + $namespaceAccordingToFileLocation = trim(str_replace(\DIRECTORY_SEPARATOR, '\\', substr(\dirname($file->getRealPath()), \strlen($root))), '\\'); + + if (null === $namespace) { + return $namespaceAccordingToFileLocation; + } + + $namespaceAccordingToFileLocationPartsReversed = array_reverse(explode('\\', $namespaceAccordingToFileLocation)); + $namespacePartsReversed = array_reverse(explode('\\', $namespace)); + + foreach ($namespacePartsReversed as $key => $namespaceParte) { + if (!isset($namespaceAccordingToFileLocationPartsReversed[$key])) { + break; + } + if (strtolower($namespaceParte) !== strtolower($namespaceAccordingToFileLocationPartsReversed[$key])) { + break; + } + unset($namespaceAccordingToFileLocationPartsReversed[$key]); + } + + return implode('\\', array_reverse($namespaceAccordingToFileLocationPartsReversed)); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/ConstantCaseFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/ConstantCaseFixer.php new file mode 100644 index 0000000..9e6dc81 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/ConstantCaseFixer.php @@ -0,0 +1,155 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Casing; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for constants case. + * + * @author Pol Dellaiera <pol.dellaiera@protonmail.com> + */ +final class ConstantCaseFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * Hold the function that will be used to convert the constants. + * + * @var callable + */ + private $fixFunction; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + if ('lower' === $this->configuration['case']) { + $this->fixFunction = static function ($token) { + return strtolower($token); + }; + } + + if ('upper' === $this->configuration['case']) { + $this->fixFunction = static function ($token) { + return strtoupper($token); + }; + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'The PHP constants `true`, `false`, and `null` MUST be written using the correct casing.', + [ + new CodeSample("<?php\n\$a = FALSE;\n\$b = True;\n\$c = nuLL;\n"), + new CodeSample("<?php\n\$a = FALSE;\n\$b = True;\n\$c = nuLL;\n", ['case' => 'upper']), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('case', 'Whether to use the `upper` or `lower` case syntax.')) + ->setAllowedValues(['upper', 'lower']) + ->setDefault('lower') + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $fixFunction = $this->fixFunction; + + foreach ($tokens as $index => $token) { + if (!$token->isNativeConstant()) { + continue; + } + + if ( + $this->isNeighbourAccepted($tokens, $tokens->getPrevMeaningfulToken($index)) + && $this->isNeighbourAccepted($tokens, $tokens->getNextMeaningfulToken($index)) + ) { + $tokens[$index] = new Token([$token->getId(), $fixFunction($token->getContent())]); + } + } + } + + /** + * @param int $index + * + * @return bool + */ + private function isNeighbourAccepted(Tokens $tokens, $index) + { + static $forbiddenTokens = null; + + if (null === $forbiddenTokens) { + $forbiddenTokens = array_merge( + [ + T_AS, + T_CLASS, + T_CONST, + T_EXTENDS, + T_IMPLEMENTS, + T_INSTANCEOF, + T_INSTEADOF, + T_INTERFACE, + T_NEW, + T_NS_SEPARATOR, + T_PAAMAYIM_NEKUDOTAYIM, + T_TRAIT, + T_USE, + CT::T_USE_TRAIT, + CT::T_USE_LAMBDA, + ], + Token::getObjectOperatorKinds() + ); + } + + $token = $tokens[$index]; + + if ($token->equalsAny(['{', '}'])) { + return false; + } + + return !$token->isGivenKind($forbiddenTokens); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseConstantsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseConstantsFixer.php new file mode 100644 index 0000000..fc393b3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseConstantsFixer.php @@ -0,0 +1,60 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Casing; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * Fixer for rules defined in PSR2 ¶2.5. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @deprecated proxy to ConstantCaseFixer + */ +final class LowercaseConstantsFixer extends AbstractProxyFixer implements DeprecatedFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'The PHP constants `true`, `false`, and `null` MUST be in lower case.', + [new CodeSample("<?php\n\$a = FALSE;\n\$b = True;\n\$c = nuLL;\n")] + ); + } + + /** + * Returns names of fixers to use instead, if any. + * + * @return string[] + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + $fixer = new ConstantCaseFixer(); + $fixer->configure(['case' => 'lower']); + + return [$fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseKeywordsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseKeywordsFixer.php new file mode 100644 index 0000000..a6e8e3e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseKeywordsFixer.php @@ -0,0 +1,75 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Casing; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR2 ¶2.5. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class LowercaseKeywordsFixer extends AbstractFixer +{ + private static $excludedTokens = [T_HALT_COMPILER]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHP keywords MUST be in lower case.', + [ + new CodeSample( + '<?php + FOREACH($a AS $B) { + TRY { + NEW $C($a, ISSET($B)); + WHILE($B) { + INCLUDE "test.php"; + } + } CATCH(\Exception $e) { + EXIT(1); + } + } +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getKeywords()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if ($token->isKeyword() && !$token->isGivenKind(self::$excludedTokens)) { + $tokens[$index] = new Token([$token->getId(), strtolower($token->getContent())]); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseStaticReferenceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseStaticReferenceFixer.php new file mode 100644 index 0000000..28cb37c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/LowercaseStaticReferenceFixer.php @@ -0,0 +1,105 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Casing; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Kuba Werłos <werlos@gmail.com> + */ +final class LowercaseStaticReferenceFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Class static references `self`, `static` and `parent` MUST be in lower case.', + [ + new CodeSample('<?php +class Foo extends Bar +{ + public function baz1() + { + return STATIC::baz2(); + } + + public function baz2($x) + { + return $x instanceof Self; + } + + public function baz3(PaRent $x) + { + return true; + } +} +'), + new VersionSpecificCodeSample( + '<?php +class Foo extends Bar +{ + public function baz(?self $x) : SELF + { + return false; + } +} +', + new VersionSpecification(70100) + ), + ] + ); + } + + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_STATIC, T_STRING]); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->equalsAny([[T_STRING, 'self'], [T_STATIC, 'static'], [T_STRING, 'parent']], false)) { + continue; + } + + $newContent = strtolower($token->getContent()); + if ($token->getContent() === $newContent) { + continue; // case is already correct + } + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prevIndex]->isGivenKind([T_CONST, T_DOUBLE_COLON, T_FUNCTION, T_NAMESPACE, T_NS_SEPARATOR, T_PRIVATE, T_PROTECTED, T_PUBLIC]) || $tokens[$prevIndex]->isObjectOperator()) { + continue; + } + + $nextIndex = $tokens->getNextMeaningfulToken($index); + if ($tokens[$nextIndex]->isGivenKind([T_FUNCTION, T_NS_SEPARATOR, T_PRIVATE, T_PROTECTED, T_PUBLIC])) { + continue; + } + + if ('static' === $newContent && $tokens[$nextIndex]->isGivenKind(T_VARIABLE)) { + continue; + } + + $tokens[$index] = new Token([$token->getId(), $newContent]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/MagicConstantCasingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/MagicConstantCasingFixer.php new file mode 100644 index 0000000..be9484f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/MagicConstantCasingFixer.php @@ -0,0 +1,98 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Casing; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author ntzm + */ +final class MagicConstantCasingFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Magic constants should be referred to using the correct casing.', + [new CodeSample("<?php\necho __dir__;\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound($this->getMagicConstantTokens()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $magicConstants = $this->getMagicConstants(); + $magicConstantTokens = $this->getMagicConstantTokens(); + + foreach ($tokens as $index => $token) { + if ($token->isGivenKind($magicConstantTokens)) { + $tokens[$index] = new Token([$token->getId(), $magicConstants[$token->getId()]]); + } + } + } + + /** + * @return array<int, string> + */ + private function getMagicConstants() + { + static $magicConstants = null; + + if (null === $magicConstants) { + $magicConstants = [ + T_LINE => '__LINE__', + T_FILE => '__FILE__', + T_DIR => '__DIR__', + T_FUNC_C => '__FUNCTION__', + T_CLASS_C => '__CLASS__', + T_METHOD_C => '__METHOD__', + T_NS_C => '__NAMESPACE__', + CT::T_CLASS_CONSTANT => 'class', + T_TRAIT_C => '__TRAIT__', + ]; + } + + return $magicConstants; + } + + /** + * @return array<int> + */ + private function getMagicConstantTokens() + { + static $magicConstantTokens = null; + + if (null === $magicConstantTokens) { + $magicConstantTokens = array_keys($this->getMagicConstants()); + } + + return $magicConstantTokens; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/MagicMethodCasingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/MagicMethodCasingFixer.php new file mode 100644 index 0000000..a3a722c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/MagicMethodCasingFixer.php @@ -0,0 +1,228 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Casing; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class MagicMethodCasingFixer extends AbstractFixer +{ + private static $magicNames = [ + '__call' => '__call', + '__callstatic' => '__callStatic', + '__clone' => '__clone', + '__construct' => '__construct', + '__debuginfo' => '__debugInfo', + '__destruct' => '__destruct', + '__get' => '__get', + '__invoke' => '__invoke', + '__isset' => '__isset', + '__serialize' => '__serialize', + '__set' => '__set', + '__set_state' => '__set_state', + '__sleep' => '__sleep', + '__tostring' => '__toString', + '__unserialize' => '__unserialize', + '__unset' => '__unset', + '__wakeup' => '__wakeup', + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Magic method definitions and calls must be using the correct casing.', + [ + new CodeSample( + '<?php +class Foo +{ + public function __Sleep() + { + } +} +' + ), + new CodeSample( + '<?php +$foo->__INVOKE(1); +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING) && $tokens->isAnyTokenKindsFound(array_merge([T_FUNCTION, T_DOUBLE_COLON], Token::getObjectOperatorKinds())); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $inClass = 0; + $tokenCount = \count($tokens); + + for ($index = 1; $index < $tokenCount - 2; ++$index) { + if (0 === $inClass && $tokens[$index]->isClassy()) { + $inClass = 1; + $index = $tokens->getNextTokenOfKind($index, ['{']); + + continue; + } + + if (0 !== $inClass) { + if ($tokens[$index]->equals('{')) { + ++$inClass; + + continue; + } + + if ($tokens[$index]->equals('}')) { + --$inClass; + + continue; + } + } + + if (!$tokens[$index]->isGivenKind(T_STRING)) { + continue; // wrong type + } + + $content = $tokens[$index]->getContent(); + if ('__' !== substr($content, 0, 2)) { + continue; // cheap look ahead + } + + $name = strtolower($content); + + if (!$this->isMagicMethodName($name)) { + continue; // method name is not one of the magic ones we can fix + } + + $nameInCorrectCasing = $this->getMagicMethodNameInCorrectCasing($name); + if ($nameInCorrectCasing === $content) { + continue; // method name is already in the correct casing, no fix needed + } + + if ($this->isFunctionSignature($tokens, $index)) { + if (0 !== $inClass) { + // this is a method definition we want to fix + $this->setTokenToCorrectCasing($tokens, $index, $nameInCorrectCasing); + } + + continue; + } + + if ($this->isMethodCall($tokens, $index)) { + $this->setTokenToCorrectCasing($tokens, $index, $nameInCorrectCasing); + + continue; + } + + if ( + ('__callstatic' === $name || '__set_state' === $name) + && $this->isStaticMethodCall($tokens, $index) + ) { + $this->setTokenToCorrectCasing($tokens, $index, $nameInCorrectCasing); + } + } + } + + /** + * @param int $index + * + * @return bool + */ + private function isFunctionSignature(Tokens $tokens, $index) + { + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if (!$tokens[$prevIndex]->isGivenKind(T_FUNCTION)) { + return false; // not a method signature + } + + return $tokens[$tokens->getNextMeaningfulToken($index)]->equals('('); + } + + /** + * @param int $index + * + * @return bool + */ + private function isMethodCall(Tokens $tokens, $index) + { + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if (!$tokens[$prevIndex]->isObjectOperator()) { + return false; // not a "simple" method call + } + + return $tokens[$tokens->getNextMeaningfulToken($index)]->equals('('); + } + + /** + * @param int $index + * + * @return bool + */ + private function isStaticMethodCall(Tokens $tokens, $index) + { + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if (!$tokens[$prevIndex]->isGivenKind(T_DOUBLE_COLON)) { + return false; // not a "simple" static method call + } + + return $tokens[$tokens->getNextMeaningfulToken($index)]->equals('('); + } + + /** + * @param string $name + * + * @return bool + */ + private function isMagicMethodName($name) + { + return isset(self::$magicNames[$name]); + } + + /** + * @param string $name name of a magic method + * + * @return string + */ + private function getMagicMethodNameInCorrectCasing($name) + { + return self::$magicNames[$name]; + } + + /** + * @param int $index + * @param string $nameInCorrectCasing + */ + private function setTokenToCorrectCasing(Tokens $tokens, $index, $nameInCorrectCasing) + { + $tokens[$index] = new Token([T_STRING, $nameInCorrectCasing]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NativeFunctionCasingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/NativeFunctionCasingFixer.php similarity index 60% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NativeFunctionCasingFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/NativeFunctionCasingFixer.php index 2a6222b..5888895 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NativeFunctionCasingFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/NativeFunctionCasingFixer.php @@ -10,10 +10,14 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Symfony; +namespace PhpCsFixer\Fixer\Casing; -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; /** * @author SpacePossum @@ -23,7 +27,36 @@ final class NativeFunctionCasingFixer extends AbstractFixer /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function getDefinition() + { + return new FixerDefinition( + 'Function defined by PHP should be called using the correct casing.', + [new CodeSample("<?php\nSTRLEN(\$str);\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run after FunctionToConstantFixer, NoUselessSprintfFixer, PowToExponentiationFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) { static $nativeFunctionNames = null; @@ -31,8 +64,6 @@ public function fix(\SplFileInfo $file, $content) $nativeFunctionNames = $this->getNativeFunctionNames(); } - $tokens = Tokens::fromCode($content); - for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { // test if we are at a function all if (!$tokens[$index]->isGivenKind(T_STRING)) { @@ -42,41 +73,32 @@ public function fix(\SplFileInfo $file, $content) $next = $tokens->getNextMeaningfulToken($index); if (!$tokens[$next]->equals('(')) { $index = $next; + continue; } $functionNamePrefix = $tokens->getPrevMeaningfulToken($index); - if ($tokens[$functionNamePrefix]->isGivenKind(array(T_DOUBLE_COLON, T_NEW, T_OBJECT_OPERATOR, T_FUNCTION))) { + if ($tokens[$functionNamePrefix]->isGivenKind([T_DOUBLE_COLON, T_NEW, T_FUNCTION, CT::T_RETURN_REF]) || $tokens[$functionNamePrefix]->isObjectOperator()) { continue; } if ($tokens[$functionNamePrefix]->isGivenKind(T_NS_SEPARATOR)) { // skip if the call is to a constructor or to a function in a namespace other than the default $prev = $tokens->getPrevMeaningfulToken($functionNamePrefix); - if ($tokens[$prev]->isGivenKind(array(T_STRING, T_NEW))) { + if ($tokens[$prev]->isGivenKind([T_STRING, T_NEW])) { continue; } } // test if the function call is to a native PHP function $lower = strtolower($tokens[$index]->getContent()); - if (!array_key_exists($lower, $nativeFunctionNames)) { + if (!\array_key_exists($lower, $nativeFunctionNames)) { continue; } - $tokens[$index]->setContent($nativeFunctionNames[$lower]); + $tokens[$index] = new Token([T_STRING, $nativeFunctionNames[$lower]]); $index = $next; } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Function defined by PHP should be called using the correct casing.'; } /** @@ -85,7 +107,7 @@ public function getDescription() private function getNativeFunctionNames() { $allFunctions = get_defined_functions(); - $functions = array(); + $functions = []; foreach ($allFunctions['internal'] as $function) { $functions[strtolower($function)] = $function; } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php new file mode 100644 index 0000000..a97e2c2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php @@ -0,0 +1,186 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Casing; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\TypeAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class NativeFunctionTypeDeclarationCasingFixer extends AbstractFixer +{ + /** + * https://secure.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration. + * + * self PHP 5.0 + * array PHP 5.1 + * callable PHP 5.4 + * bool PHP 7.0 + * float PHP 7.0 + * int PHP 7.0 + * string PHP 7.0 + * iterable PHP 7.1 + * void PHP 7.1 + * object PHP 7.2 + * static PHP 8.0 (return type only) + * mixed PHP 8.0 + * + * @var array<string, true> + */ + private $hints; + + /** + * @var FunctionsAnalyzer + */ + private $functionsAnalyzer; + + public function __construct() + { + parent::__construct(); + + $this->hints = [ + 'array' => true, + 'callable' => true, + 'self' => true, + ]; + + if (\PHP_VERSION_ID >= 70000) { + $this->hints = array_merge( + $this->hints, + [ + 'bool' => true, + 'float' => true, + 'int' => true, + 'string' => true, + ] + ); + } + + if (\PHP_VERSION_ID >= 70100) { + $this->hints = array_merge( + $this->hints, + [ + 'iterable' => true, + 'void' => true, + ] + ); + } + + if (\PHP_VERSION_ID >= 70200) { + $this->hints = array_merge($this->hints, ['object' => true]); + } + + if (\PHP_VERSION_ID >= 80000) { + $this->hints = array_merge($this->hints, ['static' => true]); + $this->hints = array_merge($this->hints, ['mixed' => true]); + } + + $this->functionsAnalyzer = new FunctionsAnalyzer(); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Native type hints for functions should use the correct case.', + [ + new CodeSample("<?php\nclass Bar {\n public function Foo(CALLABLE \$bar)\n {\n return 1;\n }\n}\n"), + new VersionSpecificCodeSample( + "<?php\nfunction Foo(INT \$a): Bool\n{\n return true;\n}\n", + new VersionSpecification(70000) + ), + new VersionSpecificCodeSample( + "<?php\nfunction Foo(Iterable \$a): VOID\n{\n echo 'Hello world';\n}\n", + new VersionSpecification(70100) + ), + new VersionSpecificCodeSample( + "<?php\nfunction Foo(Object \$a)\n{\n return 'hi!';\n}\n", + new VersionSpecification(70200) + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_FUNCTION, T_STRING]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + if ($tokens[$index]->isGivenKind(T_FUNCTION)) { + if (\PHP_VERSION_ID >= 70000) { + $this->fixFunctionReturnType($tokens, $index); + } + + $this->fixFunctionArgumentTypes($tokens, $index); + } + } + } + + /** + * @param int $index + */ + private function fixFunctionArgumentTypes(Tokens $tokens, $index) + { + foreach ($this->functionsAnalyzer->getFunctionArguments($tokens, $index) as $argument) { + $this->fixArgumentType($tokens, $argument->getTypeAnalysis()); + } + } + + /** + * @param int $index + */ + private function fixFunctionReturnType(Tokens $tokens, $index) + { + $this->fixArgumentType($tokens, $this->functionsAnalyzer->getFunctionReturnType($tokens, $index)); + } + + private function fixArgumentType(Tokens $tokens, TypeAnalysis $type = null) + { + if (null === $type) { + return; + } + + for ($index = $type->getStartIndex(); $index <= $type->getEndIndex(); ++$index) { + if ($tokens[$tokens->getNextMeaningfulToken($index)]->isGivenKind(T_NS_SEPARATOR)) { + continue; + } + + $lowerCasedName = strtolower($tokens[$index]->getContent()); + + if (!isset($this->hints[$lowerCasedName])) { + continue; + } + + $tokens[$index] = new Token([$tokens[$index]->getId(), $lowerCasedName]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/CastSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/CastSpacesFixer.php new file mode 100644 index 0000000..7449014 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/CastSpacesFixer.php @@ -0,0 +1,129 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\CastNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class CastSpacesFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @internal + */ + const INSIDE_CAST_SPACE_REPLACE_MAP = [ + ' ' => '', + "\t" => '', + "\n" => '', + "\r" => '', + "\0" => '', + "\x0B" => '', + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'A single space or none should be between cast and variable.', + [ + new CodeSample( + "<?php\n\$bar = ( string ) \$a;\n\$foo = (int)\$b;\n" + ), + new CodeSample( + "<?php\n\$bar = ( string ) \$a;\n\$foo = (int)\$b;\n", + ['space' => 'single'] + ), + new CodeSample( + "<?php\n\$bar = ( string ) \$a;\n\$foo = (int) \$b;\n", + ['space' => 'none'] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after NoShortBoolCastFixer. + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getCastTokenKinds()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isCast()) { + continue; + } + + $tokens[$index] = new Token([ + $token->getId(), + strtr($token->getContent(), self::INSIDE_CAST_SPACE_REPLACE_MAP), + ]); + + if ('single' === $this->configuration['space']) { + // force single whitespace after cast token: + if ($tokens[$index + 1]->isWhitespace(" \t")) { + // - if next token is whitespaces that contains only spaces and tabs - override next token with single space + $tokens[$index + 1] = new Token([T_WHITESPACE, ' ']); + } elseif (!$tokens[$index + 1]->isWhitespace()) { + // - if next token is not whitespaces that contains spaces, tabs and new lines - append single space to current token + $tokens->insertAt($index + 1, new Token([T_WHITESPACE, ' '])); + } + + continue; + } + + // force no whitespace after cast token: + if ($tokens[$index + 1]->isWhitespace()) { + $tokens->clearAt($index + 1); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('space', 'spacing to apply between cast and variable.')) + ->setAllowedValues(['none', 'single']) + ->setDefault('single') + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/LowercaseCastFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/LowercaseCastFixer.php new file mode 100644 index 0000000..f774f52 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/LowercaseCastFixer.php @@ -0,0 +1,95 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\CastNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class LowercaseCastFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Cast should be written in lower case.', + [ + new VersionSpecificCodeSample( + '<?php + $a = (BOOLEAN) $b; + $a = (BOOL) $b; + $a = (INTEGER) $b; + $a = (INT) $b; + $a = (DOUBLE) $b; + $a = (FLoaT) $b; + $a = (reaL) $b; + $a = (flOAT) $b; + $a = (sTRING) $b; + $a = (ARRAy) $b; + $a = (OBJect) $b; + $a = (UNset) $b; + $a = (Binary) $b; +', + new VersionSpecification(null, 70399) + ), + new VersionSpecificCodeSample( + '<?php + $a = (BOOLEAN) $b; + $a = (BOOL) $b; + $a = (INTEGER) $b; + $a = (INT) $b; + $a = (DOUBLE) $b; + $a = (FLoaT) $b; + $a = (flOAT) $b; + $a = (sTRING) $b; + $a = (ARRAy) $b; + $a = (OBJect) $b; + $a = (UNset) $b; + $a = (Binary) $b; +', + new VersionSpecification(70400) + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getCastTokenKinds()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { + if (!$tokens[$index]->isCast()) { + continue; + } + + $tokens[$index] = new Token([$tokens[$index]->getId(), strtolower($tokens[$index]->getContent())]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/ModernizeTypesCastingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/ModernizeTypesCastingFixer.php new file mode 100644 index 0000000..6954521 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/ModernizeTypesCastingFixer.php @@ -0,0 +1,159 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\CastNotation; + +use PhpCsFixer\AbstractFunctionReferenceFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Vladimir Reznichenko <kalessil@gmail.com> + */ +final class ModernizeTypesCastingFixer extends AbstractFunctionReferenceFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replaces `intval`, `floatval`, `doubleval`, `strval` and `boolval` function calls with according type casting operator.', + [ + new CodeSample( + '<?php + $a = intval($b); + $a = floatval($b); + $a = doubleval($b); + $a = strval ($b); + $a = boolval($b); +' + ), + ], + null, + 'Risky if any of the functions `intval`, `floatval`, `doubleval`, `strval` or `boolval` are overridden.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // replacement patterns + static $replacement = [ + 'intval' => [T_INT_CAST, '(int)'], + 'floatval' => [T_DOUBLE_CAST, '(float)'], + 'doubleval' => [T_DOUBLE_CAST, '(float)'], + 'strval' => [T_STRING_CAST, '(string)'], + 'boolval' => [T_BOOL_CAST, '(bool)'], + ]; + + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + foreach ($replacement as $functionIdentity => $newToken) { + $currIndex = 0; + while (null !== $currIndex) { + // try getting function reference and translate boundaries for humans + $boundaries = $this->find($functionIdentity, $tokens, $currIndex, $tokens->count() - 1); + if (null === $boundaries) { + // next function search, as current one not found + continue 2; + } + + list($functionName, $openParenthesis, $closeParenthesis) = $boundaries; + + // analysing cursor shift + $currIndex = $openParenthesis; + + // indicator that the function is overridden + if (1 !== $argumentsAnalyzer->countArguments($tokens, $openParenthesis, $closeParenthesis)) { + continue; + } + + $paramContentEnd = $closeParenthesis; + $commaCandidate = $tokens->getPrevMeaningfulToken($paramContentEnd); + if ($tokens[$commaCandidate]->equals(',')) { + $tokens->removeTrailingWhitespace($commaCandidate); + $tokens->clearAt($commaCandidate); + $paramContentEnd = $commaCandidate; + } + + // check if something complex passed as an argument and preserve parenthesises then + $countParamTokens = 0; + for ($paramContentIndex = $openParenthesis + 1; $paramContentIndex < $paramContentEnd; ++$paramContentIndex) { + //not a space, means some sensible token + if (!$tokens[$paramContentIndex]->isGivenKind(T_WHITESPACE)) { + ++$countParamTokens; + } + } + + $preserveParenthesises = $countParamTokens > 1; + + $afterCloseParenthesisIndex = $tokens->getNextMeaningfulToken($closeParenthesis); + $afterCloseParenthesisToken = $tokens[$afterCloseParenthesisIndex]; + $wrapInParenthesises = $afterCloseParenthesisToken->equalsAny(['[', '{']) || $afterCloseParenthesisToken->isGivenKind(T_POW); + + // analyse namespace specification (root one or none) and decide what to do + $prevTokenIndex = $tokens->getPrevMeaningfulToken($functionName); + if ($tokens[$prevTokenIndex]->isGivenKind(T_NS_SEPARATOR)) { + // get rid of root namespace when it used + $tokens->removeTrailingWhitespace($prevTokenIndex); + $tokens->clearAt($prevTokenIndex); + } + + // perform transformation + $replacementSequence = [ + new Token($newToken), + new Token([T_WHITESPACE, ' ']), + ]; + if ($wrapInParenthesises) { + array_unshift($replacementSequence, new Token('(')); + } + + if (!$preserveParenthesises) { + // closing parenthesis removed with leading spaces + $tokens->removeLeadingWhitespace($closeParenthesis); + $tokens->clearAt($closeParenthesis); + + // opening parenthesis removed with trailing spaces + $tokens->removeLeadingWhitespace($openParenthesis); + $tokens->removeTrailingWhitespace($openParenthesis); + $tokens->clearAt($openParenthesis); + } else { + // we'll need to provide a space after a casting operator + $tokens->removeTrailingWhitespace($functionName); + } + + if ($wrapInParenthesises) { + $tokens->insertAt($closeParenthesis, new Token(')')); + } + + $tokens->overrideRange($functionName, $functionName, $replacementSequence); + + // nested transformations support + $currIndex = $functionName; + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/NoShortBoolCastFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/NoShortBoolCastFixer.php new file mode 100644 index 0000000..c1cdfde --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/NoShortBoolCastFixer.php @@ -0,0 +1,106 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\CastNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class NoShortBoolCastFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + * + * Must run before CastSpacesFixer. + */ + public function getPriority() + { + return -9; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Short cast `bool` using double exclamation mark should not be used.', + [new CodeSample("<?php\n\$a = !!\$b;\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound('!'); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = \count($tokens) - 1; $index > 1; --$index) { + if ($tokens[$index]->equals('!')) { + $index = $this->fixShortCast($tokens, $index); + } + } + } + + /** + * @param int $index + * + * @return int + */ + private function fixShortCast(Tokens $tokens, $index) + { + for ($i = $index - 1; $i > 1; --$i) { + if ($tokens[$i]->equals('!')) { + $this->fixShortCastToBoolCast($tokens, $i, $index); + + break; + } + + if (!$tokens[$i]->isComment() && !$tokens[$i]->isWhitespace()) { + break; + } + } + + return $i; + } + + /** + * @param int $start + * @param int $end + */ + private function fixShortCastToBoolCast(Tokens $tokens, $start, $end) + { + for (; $start <= $end; ++$start) { + if ( + !$tokens[$start]->isComment() + && !($tokens[$start]->isWhitespace() && $tokens[$start - 1]->isComment()) + ) { + $tokens->clearAt($start); + } + } + + $tokens->insertAt($start, new Token([T_BOOL_CAST, '(bool)'])); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/NoUnsetCastFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/NoUnsetCastFixer.php new file mode 100644 index 0000000..c5f2059 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/NoUnsetCastFixer.php @@ -0,0 +1,100 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\CastNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class NoUnsetCastFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Variables must be set `null` instead of using `(unset)` casting.', + [new CodeSample("<?php\n\$a = (unset) \$b;\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_UNSET_CAST); + } + + /** + * {@inheritdoc} + * + * Must run before BinaryOperatorSpacesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = \count($tokens) - 1; $index > 0; --$index) { + if ($tokens[$index]->isGivenKind(T_UNSET_CAST)) { + $this->fixUnsetCast($tokens, $index); + } + } + } + + /** + * @param int $index + */ + private function fixUnsetCast(Tokens $tokens, $index) + { + $assignmentIndex = $tokens->getPrevMeaningfulToken($index); + if (null === $assignmentIndex || !$tokens[$assignmentIndex]->equals('=')) { + return; + } + + $varIndex = $tokens->getNextMeaningfulToken($index); + if (null === $varIndex || !$tokens[$varIndex]->isGivenKind(T_VARIABLE)) { + return; + } + + $afterVar = $tokens->getNextMeaningfulToken($varIndex); + if (null === $afterVar || !$tokens[$afterVar]->equalsAny([';', [T_CLOSE_TAG]])) { + return; + } + + $nextIsWhiteSpace = $tokens[$assignmentIndex + 1]->isWhitespace(); + + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + $tokens->clearTokenAndMergeSurroundingWhitespace($varIndex); + + ++$assignmentIndex; + if (!$nextIsWhiteSpace) { + $tokens->insertAt($assignmentIndex, new Token([T_WHITESPACE, ' '])); + } + + ++$assignmentIndex; + $tokens->insertAt($assignmentIndex, new Token([T_STRING, 'null'])); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/ShortScalarCastFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/ShortScalarCastFixer.php new file mode 100644 index 0000000..8a1665b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/CastNotation/ShortScalarCastFixer.php @@ -0,0 +1,86 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\CastNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class ShortScalarCastFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Cast `(boolean)` and `(integer)` should be written as `(bool)` and `(int)`, `(double)` and `(real)` as `(float)`, `(binary)` as `(string)`.', + [ + new VersionSpecificCodeSample( + "<?php\n\$a = (boolean) \$b;\n\$a = (integer) \$b;\n\$a = (double) \$b;\n\$a = (real) \$b;\n\n\$a = (binary) \$b;\n", + new VersionSpecification(null, 70399) + ), + new VersionSpecificCodeSample( + "<?php\n\$a = (boolean) \$b;\n\$a = (integer) \$b;\n\$a = (double) \$b;\n\n\$a = (binary) \$b;\n", + new VersionSpecification(70400) + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getCastTokenKinds()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + static $castMap = [ + 'boolean' => 'bool', + 'integer' => 'int', + 'double' => 'float', + 'real' => 'float', + 'binary' => 'string', + ]; + + for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { + if (!$tokens[$index]->isCast()) { + continue; + } + + $castFrom = trim(substr($tokens[$index]->getContent(), 1, -1)); + $castFromLowered = strtolower($castFrom); + + if (!\array_key_exists($castFromLowered, $castMap)) { + continue; + } + + $tokens[$index] = new Token([ + $tokens[$index]->getId(), + str_replace($castFrom, $castMap[$castFromLowered], $tokens[$index]->getContent()), + ]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ClassAttributesSeparationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ClassAttributesSeparationFixer.php new file mode 100644 index 0000000..6e31f13 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ClassAttributesSeparationFixer.php @@ -0,0 +1,518 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use PhpCsFixer\Utils; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; +use Symfony\Component\OptionsResolver\Options; + +/** + * Make sure there is one blank line above and below class elements. + * + * The exception is when an element is the first or last item in a 'classy'. + * + * @author SpacePossum + */ +final class ClassAttributesSeparationFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @internal + */ + const SPACING_NONE = 'none'; + + /** + * @internal + */ + const SPACING_ONE = 'one'; + + /** + * @internal + */ + const SUPPORTED_SPACINGS = [self::SPACING_NONE, self::SPACING_ONE]; + + /** + * @internal + */ + const SUPPORTED_TYPES = ['const', 'method', 'property', 'trait_import']; + + /** + * @var array<string, string> + */ + private $classElementTypes = []; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->classElementTypes = []; // reset previous configuration + + foreach ($this->configuration['elements'] as $elementType => $spacing) { + $this->classElementTypes[$elementType] = $spacing; + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Class, trait and interface elements must be separated with one or none blank line.', + [ + new CodeSample( + '<?php +final class Sample +{ + protected function foo() + { + } + protected function bar() + { + } + + +} +' + ), + new CodeSample( + '<?php +class Sample +{private $a; // a is awesome + /** second in a hour */ + private $b; +} +', + ['elements' => ['property' => self::SPACING_ONE]] + ), + new CodeSample( + '<?php +class Sample +{ + const A = 1; + /** seconds in some hours */ + const B = 3600; +} +', + ['elements' => ['const' => self::SPACING_ONE]] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer, IndentationTypeFixer. + * Must run after OrderedClassElementsFixer, SingleClassElementPerStatementFixer. + */ + public function getPriority() + { + return 55; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + $class = $classStart = $classEnd = false; + + foreach (array_reverse($tokensAnalyzer->getClassyElements(true), true) as $index => $element) { + if (!isset($this->classElementTypes[$element['type']])) { + continue; // not configured to be fixed + } + + $spacing = $this->classElementTypes[$element['type']]; + + if ($element['classIndex'] !== $class) { + $class = $element['classIndex']; + $classStart = $tokens->getNextTokenOfKind($class, ['{']); + $classEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classStart); + } + + if ('method' === $element['type'] && !$tokens[$class]->isGivenKind(T_INTERFACE)) { + // method of class or trait + $attributes = $tokensAnalyzer->getMethodAttributes($index); + + $methodEnd = true === $attributes['abstract'] + ? $tokens->getNextTokenOfKind($index, [';']) + : $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $tokens->getNextTokenOfKind($index, ['{'])) + ; + + $this->fixSpaceBelowClassMethod($tokens, $classEnd, $methodEnd, $spacing); + $this->fixSpaceAboveClassElement($tokens, $classStart, $index, $spacing); + + continue; + } + + // `const`, `property` or `method` of an `interface` + $this->fixSpaceBelowClassElement($tokens, $classEnd, $tokens->getNextTokenOfKind($index, [';']), $spacing); + $this->fixSpaceAboveClassElement($tokens, $classStart, $index, $spacing); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('elements', 'Dictionary of `const|method|property|trait_import` => `none|one` values.')) + ->setNormalizer(static function (Options $options, $values) { + $deprecated = array_intersect($values, self::SUPPORTED_TYPES); + if (\count($deprecated) > 0) { + Utils::triggerDeprecation(new \RuntimeException( + 'A list of elements is deprecated, use a dictionary of `const|method|property` => `none|one` instead.' + )); + + return array_fill_keys($deprecated, self::SPACING_ONE); + } + + return $values; + }) + ->setAllowedTypes(['array']) + ->setAllowedValues([static function ($option) { + $deprecated = array_intersect($option, self::SUPPORTED_TYPES); + if (\count($deprecated) > 0) { + $option = array_fill_keys($deprecated, self::SPACING_ONE); + } + + foreach ($option as $type => $spacing) { + if (!\in_array($type, self::SUPPORTED_TYPES, true)) { + throw new InvalidOptionsException( + sprintf( + 'Unexpected element type, expected any of "%s", got "%s".', + implode('", "', self::SUPPORTED_TYPES), + \is_object($type) ? \get_class($type) : \gettype($type).'#'.$type + ) + ); + } + + if (!\in_array($spacing, self::SUPPORTED_SPACINGS, true)) { + throw new InvalidOptionsException( + sprintf( + 'Unexpected spacing for element type "%s", expected any of "%s", got "%s".', + $spacing, + implode('", "', self::SUPPORTED_SPACINGS), + \is_object($spacing) ? \get_class($spacing) : (null === $spacing ? 'null' : \gettype($spacing).'#'.$spacing) + ) + ); + } + } + + return true; + }]) + ->setDefault([ + 'const' => self::SPACING_ONE, + 'method' => self::SPACING_ONE, + 'property' => self::SPACING_ONE, + 'trait_import' => self::SPACING_ONE, + ]) + ->getOption(), + ]); + } + + /** + * Fix spacing below an element of a class, interface or trait. + * + * Deals with comments, PHPDocs and spaces above the element with respect to the position of the + * element within the class, interface or trait. + * + * @param int $classEndIndex + * @param int $elementEndIndex + * @param string $spacing + */ + private function fixSpaceBelowClassElement(Tokens $tokens, $classEndIndex, $elementEndIndex, $spacing) + { + for ($nextNotWhite = $elementEndIndex + 1;; ++$nextNotWhite) { + if (($tokens[$nextNotWhite]->isComment() || $tokens[$nextNotWhite]->isWhitespace()) && false === strpos($tokens[$nextNotWhite]->getContent(), "\n")) { + continue; + } + + break; + } + + if ($tokens[$nextNotWhite]->isWhitespace()) { + $nextNotWhite = $tokens->getNextNonWhitespace($nextNotWhite); + } + + $functionIndex = $tokens->getTokenNotOfKindsSibling($nextNotWhite - 1, 1, [T_ABSTRACT, T_FINAL, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_WHITESPACE, T_COMMENT, T_DOC_COMMENT]); + + if ($tokens[$functionIndex]->isGivenKind(T_FUNCTION)) { + $this->correctLineBreaks($tokens, $elementEndIndex, $nextNotWhite, 2); + + return; + } + + $this->correctLineBreaks($tokens, $elementEndIndex, $nextNotWhite, $nextNotWhite === $classEndIndex || self::SPACING_NONE === $spacing ? 1 : 2); + } + + /** + * Fix spacing below a method of a class or trait. + * + * Deals with comments, PHPDocs and spaces above the method with respect to the position of the + * method within the class or trait. + * + * @param int $classEndIndex + * @param int $elementEndIndex + * @param string $spacing + */ + private function fixSpaceBelowClassMethod(Tokens $tokens, $classEndIndex, $elementEndIndex, $spacing) + { + $nextNotWhite = $tokens->getNextNonWhitespace($elementEndIndex); + + $this->correctLineBreaks($tokens, $elementEndIndex, $nextNotWhite, $nextNotWhite === $classEndIndex || self::SPACING_NONE === $spacing ? 1 : 2); + } + + /** + * Fix spacing above an element of a class, interface or trait. + * + * Deals with comments, PHPDocs and spaces above the element with respect to the position of the + * element within the class, interface or trait. + * + * @param int $classStartIndex index of the class Token the element is in + * @param int $elementIndex index of the element to fix + * @param string $spacing + */ + private function fixSpaceAboveClassElement(Tokens $tokens, $classStartIndex, $elementIndex, $spacing) + { + static $methodAttr = [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_ABSTRACT, T_FINAL, T_STATIC, T_STRING, T_NS_SEPARATOR, T_VAR, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT, CT::T_TYPE_ALTERNATION]; + + $nonWhiteAbove = null; + + // find out where the element definition starts + $firstElementAttributeIndex = $elementIndex; + + for ($i = $elementIndex; $i > $classStartIndex; --$i) { + $nonWhiteAbove = $tokens->getPrevNonWhitespace($i); + + if (null !== $nonWhiteAbove && $tokens[$nonWhiteAbove]->isGivenKind($methodAttr)) { + $firstElementAttributeIndex = $nonWhiteAbove; + } else { + break; + } + } + + // deal with comments above an element + if ($tokens[$nonWhiteAbove]->isGivenKind(T_COMMENT)) { + if (1 === $firstElementAttributeIndex - $nonWhiteAbove) { + // no white space found between comment and element start + $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 1); + + return; + } + + // $tokens[$nonWhiteAbove+1] is always a white space token here + if (substr_count($tokens[$nonWhiteAbove + 1]->getContent(), "\n") > 1) { + // more than one line break, always bring it back to 2 line breaks between the element start and what is above it + $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 2); + + return; + } + + // there are 2 cases: + if ($tokens[$nonWhiteAbove - 1]->isWhitespace() && substr_count($tokens[$nonWhiteAbove - 1]->getContent(), "\n") > 0) { + // 1. The comment is meant for the element (although not a PHPDoc), + // make sure there is one line break between the element and the comment... + $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 1); + // ... and make sure there is blank line above the comment (with the exception when it is directly after a class opening) + $nonWhiteAbove = $this->findCommentBlockStart($tokens, $nonWhiteAbove); + $nonWhiteAboveComment = $tokens->getPrevNonWhitespace($nonWhiteAbove); + + $this->correctLineBreaks($tokens, $nonWhiteAboveComment, $nonWhiteAbove, $nonWhiteAboveComment === $classStartIndex ? 1 : 2); + } else { + // 2. The comment belongs to the code above the element, + // make sure there is a blank line above the element (i.e. 2 line breaks) + $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 2); + } + + return; + } + + // deal with element with a PHPDoc above it + if ($tokens[$nonWhiteAbove]->isGivenKind(T_DOC_COMMENT)) { + // there should be one linebreak between the element and the PHPDoc above it + $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 1); + + // there should be one blank line between the PHPDoc and whatever is above (with the exception when it is directly after a class opening) + $nonWhiteAbovePHPDoc = $tokens->getPrevNonWhitespace($nonWhiteAbove); + $this->correctLineBreaks($tokens, $nonWhiteAbovePHPDoc, $nonWhiteAbove, $nonWhiteAbovePHPDoc === $classStartIndex ? 1 : 2); + + return; + } + + // deal with element with an attribute above it + if ($tokens[$nonWhiteAbove]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { + // there should be one linebreak between the element and the attribute above it + $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, 1); + + // make sure there is blank line above the comment (with the exception when it is directly after a class opening) + $nonWhiteAbove = $this->findAttributeBlockStart($tokens, $nonWhiteAbove); + $nonWhiteAboveComment = $tokens->getPrevNonWhitespace($nonWhiteAbove); + + $this->correctLineBreaks($tokens, $nonWhiteAboveComment, $nonWhiteAbove, $nonWhiteAboveComment === $classStartIndex ? 1 : 2); + + return; + } + + $this->correctLineBreaks($tokens, $nonWhiteAbove, $firstElementAttributeIndex, $nonWhiteAbove === $classStartIndex || self::SPACING_NONE === $spacing ? 1 : 2); + } + + /** + * @param int $startIndex + * @param int $endIndex + * @param int $reqLineCount + */ + private function correctLineBreaks(Tokens $tokens, $startIndex, $endIndex, $reqLineCount = 2) + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + ++$startIndex; + $numbOfWhiteTokens = $endIndex - $startIndex; + + if (0 === $numbOfWhiteTokens) { + $tokens->insertAt($startIndex, new Token([T_WHITESPACE, str_repeat($lineEnding, $reqLineCount)])); + + return; + } + + $lineBreakCount = $this->getLineBreakCount($tokens, $startIndex, $endIndex); + + if ($reqLineCount === $lineBreakCount) { + return; + } + + if ($lineBreakCount < $reqLineCount) { + $tokens[$startIndex] = new Token([ + T_WHITESPACE, + str_repeat($lineEnding, $reqLineCount - $lineBreakCount).$tokens[$startIndex]->getContent(), + ]); + + return; + } + + // $lineCount = > $reqLineCount : check the one Token case first since this one will be true most of the time + if (1 === $numbOfWhiteTokens) { + $tokens[$startIndex] = new Token([ + T_WHITESPACE, + Preg::replace('/\r\n|\n/', '', $tokens[$startIndex]->getContent(), $lineBreakCount - $reqLineCount), + ]); + + return; + } + + // $numbOfWhiteTokens = > 1 + $toReplaceCount = $lineBreakCount - $reqLineCount; + + for ($i = $startIndex; $i < $endIndex && $toReplaceCount > 0; ++$i) { + $tokenLineCount = substr_count($tokens[$i]->getContent(), "\n"); + + if ($tokenLineCount > 0) { + $tokens[$i] = new Token([ + T_WHITESPACE, + Preg::replace('/\r\n|\n/', '', $tokens[$i]->getContent(), min($toReplaceCount, $tokenLineCount)), + ]); + $toReplaceCount -= $tokenLineCount; + } + } + } + + /** + * @param int $whiteSpaceStartIndex + * @param int $whiteSpaceEndIndex + * + * @return int + */ + private function getLineBreakCount(Tokens $tokens, $whiteSpaceStartIndex, $whiteSpaceEndIndex) + { + $lineCount = 0; + + for ($i = $whiteSpaceStartIndex; $i < $whiteSpaceEndIndex; ++$i) { + $lineCount += substr_count($tokens[$i]->getContent(), "\n"); + } + + return $lineCount; + } + + /** + * @param int $commentIndex + * + * @return int + */ + private function findCommentBlockStart(Tokens $tokens, $commentIndex) + { + $start = $commentIndex; + + for ($i = $commentIndex - 1; $i > 0; --$i) { + if ($tokens[$i]->isComment()) { + $start = $i; + + continue; + } + + if (!$tokens[$i]->isWhitespace() || $this->getLineBreakCount($tokens, $i, $i + 1) > 1) { + break; + } + } + + return $start; + } + + /** + * @param int $index attribute close index + * + * @return int + */ + private function findAttributeBlockStart(Tokens $tokens, $index) + { + $start = $index = $tokens->findBlockStart(Tokens::BLOCK_TYPE_ATTRIBUTE, $index); + + for ($i = $index - 1; $i > 0; --$i) { + if ($tokens[$i]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { + $start = $i = $tokens->findBlockStart(Tokens::BLOCK_TYPE_ATTRIBUTE, $i); + + continue; + } + + if (!$tokens[$i]->isWhitespace() || $this->getLineBreakCount($tokens, $i, $i + 1) > 1) { + break; + } + } + + return $start; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ClassDefinitionFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ClassDefinitionFixer.php new file mode 100644 index 0000000..d0c484c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ClassDefinitionFixer.php @@ -0,0 +1,446 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\AliasedFixerOptionBuilder; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * Fixer for part of the rules defined in PSR2 ¶4.1 Extends and Implements and PSR12 ¶8. Anonymous Classes. + * + * @author SpacePossum + */ +final class ClassDefinitionFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Whitespace around the keywords of a class, trait or interfaces definition should be one space.', + [ + new CodeSample( + '<?php + +class Foo extends Bar implements Baz, BarBaz +{ +} + +final class Foo extends Bar implements Baz, BarBaz +{ +} + +trait Foo +{ +} +' + ), + new VersionSpecificCodeSample( + '<?php + +$foo = new class extends Bar implements Baz, BarBaz {}; +', + new VersionSpecification(70100) + ), + new CodeSample( + '<?php + +class Foo +extends Bar +implements Baz, BarBaz +{} +', + ['single_line' => true] + ), + new CodeSample( + '<?php + +class Foo +extends Bar +implements Baz +{} +', + ['single_item_single_line' => true] + ), + new CodeSample( + '<?php + +interface Bar extends + Bar, BarBaz, FooBarBaz +{} +', + ['multi_line_extends_each_single_line' => true] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer. + */ + public function getPriority() + { + return 36; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // -4, one for count to index, 3 because min. of tokens for a classy location. + for ($index = $tokens->getSize() - 4; $index > 0; --$index) { + if ($tokens[$index]->isClassy()) { + $this->fixClassyDefinition($tokens, $index); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new AliasedFixerOptionBuilder( + new FixerOptionBuilder('multi_line_extends_each_single_line', 'Whether definitions should be multiline.'), + 'multiLineExtendsEachSingleLine' + )) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + (new AliasedFixerOptionBuilder( + new FixerOptionBuilder('single_item_single_line', 'Whether definitions should be single line when including a single item.'), + 'singleItemSingleLine' + )) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + (new AliasedFixerOptionBuilder( + new FixerOptionBuilder('single_line', 'Whether definitions should be single line.'), + 'singleLine' + )) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + ]); + } + + /** + * @param int $classyIndex Class definition token start index + */ + private function fixClassyDefinition(Tokens $tokens, $classyIndex) + { + $classDefInfo = $this->getClassyDefinitionInfo($tokens, $classyIndex); + + // PSR2 4.1 Lists of implements MAY be split across multiple lines, where each subsequent line is indented once. + // When doing so, the first item in the list MUST be on the next line, and there MUST be only one interface per line. + + if (false !== $classDefInfo['implements']) { + $classDefInfo['implements'] = $this->fixClassyDefinitionImplements( + $tokens, + $classDefInfo['open'], + $classDefInfo['implements'] + ); + } + + if (false !== $classDefInfo['extends']) { + $classDefInfo['extends'] = $this->fixClassyDefinitionExtends( + $tokens, + false === $classDefInfo['implements'] ? $classDefInfo['open'] : $classDefInfo['implements']['start'], + $classDefInfo['extends'] + ); + } + + // PSR2: class definition open curly brace must go on a new line. + // PSR12: anonymous class curly brace on same line if not multi line implements. + + $classDefInfo['open'] = $this->fixClassyDefinitionOpenSpacing($tokens, $classDefInfo); + if ($classDefInfo['implements']) { + $end = $classDefInfo['implements']['start']; + } elseif ($classDefInfo['extends']) { + $end = $classDefInfo['extends']['start']; + } else { + $end = $tokens->getPrevNonWhitespace($classDefInfo['open']); + } + + // 4.1 The extends and implements keywords MUST be declared on the same line as the class name. + $this->makeClassyDefinitionSingleLine( + $tokens, + $classDefInfo['anonymousClass'] ? $tokens->getPrevMeaningfulToken($classyIndex) : $classDefInfo['start'], + $end + ); + } + + /** + * @param int $classOpenIndex + * + * @return array + */ + private function fixClassyDefinitionExtends(Tokens $tokens, $classOpenIndex, array $classExtendsInfo) + { + $endIndex = $tokens->getPrevNonWhitespace($classOpenIndex); + + if ($this->configuration['single_line'] || false === $classExtendsInfo['multiLine']) { + $this->makeClassyDefinitionSingleLine($tokens, $classExtendsInfo['start'], $endIndex); + $classExtendsInfo['multiLine'] = false; + } elseif ($this->configuration['single_item_single_line'] && 1 === $classExtendsInfo['numberOfExtends']) { + $this->makeClassyDefinitionSingleLine($tokens, $classExtendsInfo['start'], $endIndex); + $classExtendsInfo['multiLine'] = false; + } elseif ($this->configuration['multi_line_extends_each_single_line'] && $classExtendsInfo['multiLine']) { + $this->makeClassyInheritancePartMultiLine($tokens, $classExtendsInfo['start'], $endIndex); + $classExtendsInfo['multiLine'] = true; + } + + return $classExtendsInfo; + } + + /** + * @param int $classOpenIndex + * + * @return array + */ + private function fixClassyDefinitionImplements(Tokens $tokens, $classOpenIndex, array $classImplementsInfo) + { + $endIndex = $tokens->getPrevNonWhitespace($classOpenIndex); + + if ($this->configuration['single_line'] || false === $classImplementsInfo['multiLine']) { + $this->makeClassyDefinitionSingleLine($tokens, $classImplementsInfo['start'], $endIndex); + $classImplementsInfo['multiLine'] = false; + } elseif ($this->configuration['single_item_single_line'] && 1 === $classImplementsInfo['numberOfImplements']) { + $this->makeClassyDefinitionSingleLine($tokens, $classImplementsInfo['start'], $endIndex); + $classImplementsInfo['multiLine'] = false; + } else { + $this->makeClassyInheritancePartMultiLine($tokens, $classImplementsInfo['start'], $endIndex); + $classImplementsInfo['multiLine'] = true; + } + + return $classImplementsInfo; + } + + /** + * @return int + */ + private function fixClassyDefinitionOpenSpacing(Tokens $tokens, array $classDefInfo) + { + if ($classDefInfo['anonymousClass']) { + if (false !== $classDefInfo['implements']) { + $spacing = $classDefInfo['implements']['multiLine'] ? $this->whitespacesConfig->getLineEnding() : ' '; + } elseif (false !== $classDefInfo['extends']) { + $spacing = $classDefInfo['extends']['multiLine'] ? $this->whitespacesConfig->getLineEnding() : ' '; + } else { + $spacing = ' '; + } + } else { + $spacing = $this->whitespacesConfig->getLineEnding(); + } + + $openIndex = $tokens->getNextTokenOfKind($classDefInfo['classy'], ['{']); + if (' ' !== $spacing && false !== strpos($tokens[$openIndex - 1]->getContent(), "\n")) { + return $openIndex; + } + + if ($tokens[$openIndex - 1]->isWhitespace()) { + if (' ' !== $spacing || !$tokens[$tokens->getPrevNonWhitespace($openIndex - 1)]->isComment()) { + $tokens[$openIndex - 1] = new Token([T_WHITESPACE, $spacing]); + } + + return $openIndex; + } + + $tokens->insertAt($openIndex, new Token([T_WHITESPACE, $spacing])); + + return $openIndex + 1; + } + + /** + * @param int $classyIndex + * + * @return array + */ + private function getClassyDefinitionInfo(Tokens $tokens, $classyIndex) + { + $openIndex = $tokens->getNextTokenOfKind($classyIndex, ['{']); + $prev = $tokens->getPrevMeaningfulToken($classyIndex); + $startIndex = $tokens[$prev]->isGivenKind([T_FINAL, T_ABSTRACT]) ? $prev : $classyIndex; + + $extends = false; + $implements = false; + $anonymousClass = false; + + if (!$tokens[$classyIndex]->isGivenKind(T_TRAIT)) { + $extends = $tokens->findGivenKind(T_EXTENDS, $classyIndex, $openIndex); + $extends = \count($extends) ? $this->getClassyInheritanceInfo($tokens, key($extends), 'numberOfExtends') : false; + + if (!$tokens[$classyIndex]->isGivenKind(T_INTERFACE)) { + $implements = $tokens->findGivenKind(T_IMPLEMENTS, $classyIndex, $openIndex); + $implements = \count($implements) ? $this->getClassyInheritanceInfo($tokens, key($implements), 'numberOfImplements') : false; + $tokensAnalyzer = new TokensAnalyzer($tokens); + $anonymousClass = $tokensAnalyzer->isAnonymousClass($classyIndex); + } + } + + return [ + 'start' => $startIndex, + 'classy' => $classyIndex, + 'open' => $openIndex, + 'extends' => $extends, + 'implements' => $implements, + 'anonymousClass' => $anonymousClass, + ]; + } + + /** + * @param int $startIndex + * @param string $label + * + * @return array + */ + private function getClassyInheritanceInfo(Tokens $tokens, $startIndex, $label) + { + $implementsInfo = ['start' => $startIndex, $label => 1, 'multiLine' => false]; + ++$startIndex; + $endIndex = $tokens->getNextTokenOfKind($startIndex, ['{', [T_IMPLEMENTS], [T_EXTENDS]]); + $endIndex = $tokens[$endIndex]->equals('{') ? $tokens->getPrevNonWhitespace($endIndex) : $endIndex; + for ($i = $startIndex; $i < $endIndex; ++$i) { + if ($tokens[$i]->equals(',')) { + ++$implementsInfo[$label]; + + continue; + } + + if (!$implementsInfo['multiLine'] && false !== strpos($tokens[$i]->getContent(), "\n")) { + $implementsInfo['multiLine'] = true; + } + } + + return $implementsInfo; + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function makeClassyDefinitionSingleLine(Tokens $tokens, $startIndex, $endIndex) + { + for ($i = $endIndex; $i >= $startIndex; --$i) { + if ($tokens[$i]->isWhitespace()) { + $prevNonWhite = $tokens->getPrevNonWhitespace($i); + $nextNonWhite = $tokens->getNextNonWhitespace($i); + + if ($tokens[$prevNonWhite]->isComment() || $tokens[$nextNonWhite]->isComment()) { + $content = $tokens[$prevNonWhite]->getContent(); + if (!('#' === $content || '//' === substr($content, 0, 2))) { + $content = $tokens[$nextNonWhite]->getContent(); + if (!('#' === $content || '//' === substr($content, 0, 2))) { + $tokens[$i] = new Token([T_WHITESPACE, ' ']); + } + } + + continue; + } + + if (!$tokens[$i - 1]->equals(',') && $tokens[$i + 1]->equalsAny([',', '(', ')']) || $tokens[$i - 1]->equals('(')) { + $tokens->clearAt($i); + + continue; + } + + $tokens[$i] = new Token([T_WHITESPACE, ' ']); + + continue; + } + + if ($tokens[$i]->equals(',') && !$tokens[$i + 1]->isWhitespace()) { + $tokens->insertAt($i + 1, new Token([T_WHITESPACE, ' '])); + + continue; + } + + if (!$tokens[$i]->isComment()) { + continue; + } + + if (!$tokens[$i + 1]->isWhitespace() && !$tokens[$i + 1]->isComment() && false === strpos($tokens[$i]->getContent(), "\n")) { + $tokens->insertAt($i + 1, new Token([T_WHITESPACE, ' '])); + } + + if (!$tokens[$i - 1]->isWhitespace() && !$tokens[$i - 1]->isComment()) { + $tokens->insertAt($i, new Token([T_WHITESPACE, ' '])); + } + } + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function makeClassyInheritancePartMultiLine(Tokens $tokens, $startIndex, $endIndex) + { + for ($i = $endIndex; $i > $startIndex; --$i) { + $previousInterfaceImplementingIndex = $tokens->getPrevTokenOfKind($i, [',', [T_IMPLEMENTS], [T_EXTENDS]]); + $breakAtIndex = $tokens->getNextMeaningfulToken($previousInterfaceImplementingIndex); + // make the part of a ',' or 'implements' single line + $this->makeClassyDefinitionSingleLine( + $tokens, + $breakAtIndex, + $i + ); + + // make sure the part is on its own line + $isOnOwnLine = false; + for ($j = $breakAtIndex; $j > $previousInterfaceImplementingIndex; --$j) { + if (false !== strpos($tokens[$j]->getContent(), "\n")) { + $isOnOwnLine = true; + + break; + } + } + + if (!$isOnOwnLine) { + if ($tokens[$breakAtIndex - 1]->isWhitespace()) { + $tokens[$breakAtIndex - 1] = new Token([ + T_WHITESPACE, + $this->whitespacesConfig->getLineEnding().$this->whitespacesConfig->getIndent(), + ]); + } else { + $tokens->insertAt($breakAtIndex, new Token([T_WHITESPACE, $this->whitespacesConfig->getLineEnding().$this->whitespacesConfig->getIndent()])); + } + } + + $i = $previousInterfaceImplementingIndex + 1; + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalClassFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalClassFixer.php new file mode 100644 index 0000000..9ee4871 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalClassFixer.php @@ -0,0 +1,60 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class FinalClassFixer extends AbstractProxyFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'All classes must be final, except abstract ones and Doctrine entities.', + [ + new CodeSample( + '<?php +class MyApp {} +' + ), + ], + 'No exception and no configuration are intentional. Beside Doctrine entities and of course abstract classes, there is no single reason not to declare all classes final. ' + .'If you want to subclass a class, mark the parent class as abstract and create two child classes, one empty if necessary: you\'ll gain much more fine grained type-hinting. ' + .'If you need to mock a standalone class, create an interface, or maybe it\'s a value-object that shouldn\'t be mocked at all. ' + .'If you need to extend a standalone class, create an interface and use the Composite pattern. ' + .'If you aren\'t ready yet for serious OOP, go with FinalInternalClassFixer, it\'s fine.', + 'Risky when subclassing non-abstract classes.' + ); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + $fixer = new FinalInternalClassFixer(); + $fixer->configure([ + 'annotation_include' => [], + 'consider_absent_docblock_as_internal_class' => true, + ]); + + return [$fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalInternalClassFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalInternalClassFixer.php new file mode 100644 index 0000000..32a9217 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalInternalClassFixer.php @@ -0,0 +1,229 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AliasedFixerOptionBuilder; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Options; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +final class FinalInternalClassFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $intersect = array_intersect_assoc( + $this->configuration['annotation_include'], + $this->configuration['annotation_exclude'] + ); + + if (\count($intersect)) { + throw new InvalidFixerConfigurationException($this->getName(), sprintf('Annotation cannot be used in both the include and exclude list, got duplicates: "%s".', implode('", "', array_keys($intersect)))); + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Internal classes should be `final`.', + [ + new CodeSample("<?php\n/**\n * @internal\n */\nclass Sample\n{\n}\n"), + new CodeSample( + "<?php\n/**\n * @CUSTOM\n */\nclass A{}\n\n/**\n * @CUSTOM\n * @not-fix\n */\nclass B{}\n", + [ + 'annotation_include' => ['@Custom'], + 'annotation_exclude' => ['@not-fix'], + ] + ), + ], + null, + 'Changing classes to `final` might cause code execution to break.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before FinalStaticAccessFixer, ProtectedToPrivateFixer, SelfStaticAccessorFixer. + * Must run after PhpUnitInternalClassFixer. + */ + public function getPriority() + { + return 67; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_CLASS); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + if (!$tokens[$index]->isGivenKind(T_CLASS) || !$this->isClassCandidate($tokens, $index)) { + continue; + } + + // make class final + $tokens->insertAt( + $index, + [ + new Token([T_FINAL, 'final']), + new Token([T_WHITESPACE, ' ']), + ] + ); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $annotationsAsserts = [static function (array $values) { + foreach ($values as $value) { + if (!\is_string($value) || '' === $value) { + return false; + } + } + + return true; + }]; + + $annotationsNormalizer = static function (Options $options, array $value) { + $newValue = []; + foreach ($value as $key) { + if ('@' === $key[0]) { + $key = substr($key, 1); + } + + $newValue[strtolower($key)] = true; + } + + return $newValue; + }; + + return new FixerConfigurationResolver([ + (new AliasedFixerOptionBuilder( + new FixerOptionBuilder('annotation_include', 'Class level annotations tags that must be set in order to fix the class. (case insensitive)'), + 'annotation-white-list' + )) + ->setAllowedTypes(['array']) + ->setAllowedValues($annotationsAsserts) + ->setDefault(['@internal']) + ->setNormalizer($annotationsNormalizer) + ->getOption(), + (new AliasedFixerOptionBuilder( + new FixerOptionBuilder('annotation_exclude', 'Class level annotations tags that must be omitted to fix the class, even if all of the white list ones are used as well. (case insensitive)'), + 'annotation-black-list' + )) + ->setAllowedTypes(['array']) + ->setAllowedValues($annotationsAsserts) + ->setDefault([ + '@final', + '@Entity', + '@ORM\Entity', + '@ORM\Mapping\Entity', + '@Mapping\Entity', + '@Document', + '@ODM\Document', + ]) + ->setNormalizer($annotationsNormalizer) + ->getOption(), + (new AliasedFixerOptionBuilder( + new FixerOptionBuilder('consider_absent_docblock_as_internal_class', 'Should classes without any DocBlock be fixed to final?'), + 'consider-absent-docblock-as-internal-class' + )) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + ]); + } + + /** + * @param int $index T_CLASS index + * + * @return bool + */ + private function isClassCandidate(Tokens $tokens, $index) + { + if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind([T_ABSTRACT, T_FINAL, T_NEW])) { + return false; // ignore class; it is abstract or already final + } + + $docToken = $tokens[$tokens->getPrevNonWhitespace($index)]; + + if (!$docToken->isGivenKind(T_DOC_COMMENT)) { + return $this->configuration['consider_absent_docblock_as_internal_class']; + } + + $doc = new DocBlock($docToken->getContent()); + $tags = []; + + foreach ($doc->getAnnotations() as $annotation) { + if (1 !== Preg::match('/@\S+(?=\s|$)/', $annotation->getContent(), $matches)) { + continue; + } + $tag = strtolower(substr(array_shift($matches), 1)); + foreach ($this->configuration['annotation_exclude'] as $tagStart => $true) { + if (0 === strpos($tag, $tagStart)) { + return false; // ignore class: class-level PHPDoc contains tag that has been excluded through configuration + } + } + + $tags[$tag] = true; + } + + foreach ($this->configuration['annotation_include'] as $tag => $true) { + if (!isset($tags[$tag])) { + return false; // ignore class: class-level PHPDoc does not contain all tags that has been included through configuration + } + } + + return true; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php new file mode 100644 index 0000000..f97da5b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php @@ -0,0 +1,168 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class FinalPublicMethodForAbstractClassFixer extends AbstractFixer +{ + /** + * @var array + */ + private $magicMethods = [ + '__construct' => true, + '__destruct' => true, + '__call' => true, + '__callstatic' => true, + '__get' => true, + '__set' => true, + '__isset' => true, + '__unset' => true, + '__sleep' => true, + '__wakeup' => true, + '__tostring' => true, + '__invoke' => true, + '__set_state' => true, + '__clone' => true, + '__debuginfo' => true, + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'All `public` methods of `abstract` classes should be `final`.', + [ + new CodeSample( + '<?php + +abstract class AbstractMachine +{ + public function start() + {} +} +' + ), + ], + 'Enforce API encapsulation in an inheritance architecture. ' + .'If you want to override a method, use the Template method pattern.', + 'Risky when overriding `public` methods of `abstract` classes.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_CLASS, T_ABSTRACT, T_PUBLIC, T_FUNCTION]); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $classes = array_keys($tokens->findGivenKind(T_CLASS)); + + while ($classIndex = array_pop($classes)) { + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($classIndex)]; + if (!$prevToken->isGivenKind(T_ABSTRACT)) { + continue; + } + + $classOpen = $tokens->getNextTokenOfKind($classIndex, ['{']); + $classClose = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classOpen); + + $this->fixClass($tokens, $classOpen, $classClose); + } + } + + /** + * @param int $classOpenIndex + * @param int $classCloseIndex + */ + private function fixClass(Tokens $tokens, $classOpenIndex, $classCloseIndex) + { + for ($index = $classCloseIndex - 1; $index > $classOpenIndex; --$index) { + // skip method contents + if ($tokens[$index]->equals('}')) { + $index = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + continue; + } + + // skip non public methods + if (!$tokens[$index]->isGivenKind(T_PUBLIC)) { + continue; + } + $nextIndex = $tokens->getNextMeaningfulToken($index); + $nextToken = $tokens[$nextIndex]; + if ($nextToken->isGivenKind(T_STATIC)) { + $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); + $nextToken = $tokens[$nextIndex]; + } + + // skip uses, attributes, constants etc + if (!$nextToken->isGivenKind(T_FUNCTION)) { + continue; + } + $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); + $nextToken = $tokens[$nextIndex]; + + // skip magic methods + if (isset($this->magicMethods[strtolower($nextToken->getContent())])) { + continue; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + $prevToken = $tokens[$prevIndex]; + if ($prevToken->isGivenKind(T_STATIC)) { + $index = $prevIndex; + $prevIndex = $tokens->getPrevMeaningfulToken($index); + $prevToken = $tokens[$prevIndex]; + } + // skip abstract or already final methods + if ($prevToken->isGivenKind([T_ABSTRACT, T_FINAL])) { + $index = $prevIndex; + + continue; + } + + $tokens->insertAt( + $index, + [ + new Token([T_FINAL, 'final']), + new Token([T_WHITESPACE, ' ']), + ] + ); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalStaticAccessFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalStaticAccessFixer.php new file mode 100644 index 0000000..56d5932 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/FinalStaticAccessFixer.php @@ -0,0 +1,75 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author ntzm + * + * @deprecated in 2.17 + */ +final class FinalStaticAccessFixer extends AbstractProxyFixer implements DeprecatedFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Converts `static` access to `self` access in `final` classes.', + [ + new CodeSample( + '<?php +final class Sample +{ + public function getFoo() + { + return static::class; + } +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after FinalInternalClassFixer, PhpUnitTestCaseStaticMethodCallsFixer. + */ + public function getPriority() + { + return parent::getPriority(); + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + return [new SelfStaticAccessorFixer()]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/MethodSeparationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/MethodSeparationFixer.php new file mode 100644 index 0000000..a89ff96 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/MethodSeparationFixer.php @@ -0,0 +1,84 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author SpacePossum + * + * @deprecated in 2.8, proxy to ClassAttributesSeparationFixer + */ +final class MethodSeparationFixer extends AbstractProxyFixer implements DeprecatedFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Methods must be separated with one blank line.', + [ + new CodeSample( + '<?php +final class Sample +{ + protected function foo() + { + } + protected function bar() + { + } +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer, IndentationTypeFixer. + * Must run after OrderedClassElementsFixer. + */ + public function getPriority() + { + return parent::getPriority(); + } + + /** + * Returns names of fixers to use instead, if any. + * + * @return string[] + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + $fixer = new ClassAttributesSeparationFixer(); + $fixer->configure(['elements' => ['method' => ClassAttributesSeparationFixer::SPACING_ONE]]); + + return [$fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoBlankLinesAfterClassOpeningFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoBlankLinesAfterClassOpeningFixer.php new file mode 100644 index 0000000..faea8c6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoBlankLinesAfterClassOpeningFixer.php @@ -0,0 +1,101 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Ceeram <ceeram@cakephp.org> + */ +final class NoBlankLinesAfterClassOpeningFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds()); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There should be no empty lines after class opening brace.', + [ + new CodeSample( + '<?php +final class Sample +{ + + protected function foo() + { + } +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after OrderedClassElementsFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isClassy()) { + continue; + } + + $startBraceIndex = $tokens->getNextTokenOfKind($index, ['{']); + if (!$tokens[$startBraceIndex + 1]->isWhitespace()) { + continue; + } + + $this->fixWhitespace($tokens, $startBraceIndex + 1); + } + } + + /** + * Cleanup a whitespace token. + * + * @param int $index + */ + private function fixWhitespace(Tokens $tokens, $index) + { + $content = $tokens[$index]->getContent(); + // if there is more than one new line in the whitespace, then we need to fix it + if (substr_count($content, "\n") > 1) { + // the final bit of the whitespace must be the next statement's indentation + $tokens[$index] = new Token([T_WHITESPACE, $this->whitespacesConfig->getLineEnding().substr($content, strrpos($content, "\n") + 1)]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoNullPropertyInitializationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoNullPropertyInitializationFixer.php new file mode 100644 index 0000000..8971a16 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoNullPropertyInitializationFixer.php @@ -0,0 +1,147 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author ntzm + */ +final class NoNullPropertyInitializationFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Properties MUST not be explicitly initialized with `null` except when they have a type declaration (PHP 7.4).', + [ + new CodeSample( + '<?php +class Foo { + public $foo = null; +} +' + ), + new CodeSample( + '<?php +class Foo { + public static $foo = null; +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_CLASS, T_TRAIT]) && $tokens->isAnyTokenKindsFound([T_PUBLIC, T_PROTECTED, T_PRIVATE, T_VAR, T_STATIC]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $inClass = []; + $classLevel = 0; + + for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { + if ($tokens[$index]->isClassy()) { + ++$classLevel; + $inClass[$classLevel] = 1; + + $index = $tokens->getNextTokenOfKind($index, ['{']); + + continue; + } + + if (0 === $classLevel) { + continue; + } + + if ($tokens[$index]->equals('{')) { + ++$inClass[$classLevel]; + + continue; + } + + if ($tokens[$index]->equals('}')) { + --$inClass[$classLevel]; + + if (0 === $inClass[$classLevel]) { + unset($inClass[$classLevel]); + --$classLevel; + } + + continue; + } + + // Ensure we are in a class but not in a method in case there are static variables defined + if (1 !== $inClass[$classLevel]) { + continue; + } + + if (!$tokens[$index]->isGivenKind([T_PUBLIC, T_PROTECTED, T_PRIVATE, T_VAR, T_STATIC])) { + continue; + } + + while (true) { + $varTokenIndex = $index = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$index]->isGivenKind(T_STATIC)) { + $varTokenIndex = $index = $tokens->getNextMeaningfulToken($index); + } + + if (!$tokens[$index]->isGivenKind(T_VARIABLE)) { + break; + } + + $index = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$index]->equals('=')) { + $index = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$index]->isGivenKind(T_NS_SEPARATOR)) { + $index = $tokens->getNextMeaningfulToken($index); + } + + if ($tokens[$index]->equals([T_STRING, 'null'], false)) { + for ($i = $varTokenIndex + 1; $i <= $index; ++$i) { + if ( + !($tokens[$i]->isWhitespace() && false !== strpos($tokens[$i]->getContent(), "\n")) + && !$tokens[$i]->isComment() + ) { + $tokens->clearAt($i); + } + } + } + + ++$index; + } + + if (!$tokens[$index]->equals(',')) { + break; + } + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/Php4ConstructorFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoPhp4ConstructorFixer.php similarity index 55% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/Php4ConstructorFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoPhp4ConstructorFixer.php index 7fd0da7..51381ec 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/Php4ConstructorFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoPhp4ConstructorFixer.php @@ -10,44 +10,94 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Contrib; +namespace PhpCsFixer\Fixer\ClassNotation; -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; /** * @author Matteo Beccati <matteo@beccati.com> */ -class Php4ConstructorFixer extends AbstractFixer +final class NoPhp4ConstructorFixer extends AbstractFixer { /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function getDefinition() { - $tokens = Tokens::fromCode($content); + return new FixerDefinition( + 'Convert PHP4-style constructors to `__construct`.', + [ + new CodeSample('<?php +class Foo +{ + public function Foo($bar) + { + } +} +'), + ], + null, + 'Risky when old style constructor being fixed is overridden or overrides parent one.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before OrderedClassElementsFixer. + */ + public function getPriority() + { + return 75; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_CLASS); + } + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); $classes = array_keys($tokens->findGivenKind(T_CLASS)); - $numClasses = count($classes); + $numClasses = \count($classes); for ($i = 0; $i < $numClasses; ++$i) { $index = $classes[$i]; // is it an an anonymous class definition? - if ($tokens->isAnonymousClass($index)) { + if ($tokensAnalyzer->isAnonymousClass($index)) { continue; } // is it inside a namespace? - $nspIndex = $tokens->getPrevTokenOfKind($index, array(array(T_NAMESPACE, 'namespace'))); + $nspIndex = $tokens->getPrevTokenOfKind($index, [[T_NAMESPACE, 'namespace']]); if (null !== $nspIndex) { $nspIndex = $tokens->getNextMeaningfulToken($nspIndex); // make sure it's not the global namespace, as PHP4 constructors are allowed in there if (!$tokens[$nspIndex]->equals('{')) { // unless it's the global namespace, the index currently points to the name - $nspIndex = $tokens->getNextTokenOfKind($nspIndex, array(';', '{')); + $nspIndex = $tokens->getNextTokenOfKind($nspIndex, [';', '{']); if ($tokens[$nspIndex]->equals(';')) { // the class is inside a (non-block) namespace, no PHP4-code should be in there @@ -71,30 +121,12 @@ public function fix(\SplFileInfo $file, $content) $classNameIndex = $tokens->getNextMeaningfulToken($index); $className = $tokens[$classNameIndex]->getContent(); - $classStart = $tokens->getNextTokenOfKind($classNameIndex, array('{')); + $classStart = $tokens->getNextTokenOfKind($classNameIndex, ['{']); $classEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classStart); $this->fixConstructor($tokens, $className, $classStart, $classEnd); $this->fixParent($tokens, $classStart, $classEnd); } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'php4_constructor'; - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Convert PHP4-style constructors to __construct. Warning! This could change code behavior.'; } /** @@ -123,7 +155,7 @@ private function fixConstructor(Tokens $tokens, $className, $classStart, $classE if (null === $php5) { // no PHP5-constructor, we can rename the old one to __construct - $tokens[$php4['nameIndex']]->setContent('__construct'); + $tokens[$php4['nameIndex']] = new Token([T_STRING, '__construct']); // in some (rare) cases we might have just created an infinite recursion issue $this->fixInfiniteRecursion($tokens, $php4['bodyIndex'], $php4['endIndex']); @@ -132,25 +164,31 @@ private function fixConstructor(Tokens $tokens, $className, $classStart, $classE } // does the PHP4-constructor only call $this->__construct($args, ...)? - list($seq, $case) = $this->getWrapperMethodSequence($tokens, '__construct', $php4['startIndex'], $php4['bodyIndex']); - if (null !== $tokens->findSequence($seq, $php4['bodyIndex'] - 1, $php4['endIndex'], $case)) { - // good, delete it! - for ($i = $php4['startIndex']; $i <= $php4['endIndex']; ++$i) { - $tokens[$i]->clear(); - } + list($sequences, $case) = $this->getWrapperMethodSequence($tokens, '__construct', $php4['startIndex'], $php4['bodyIndex']); + foreach ($sequences as $seq) { + if (null !== $tokens->findSequence($seq, $php4['bodyIndex'] - 1, $php4['endIndex'], $case)) { + // good, delete it! + for ($i = $php4['startIndex']; $i <= $php4['endIndex']; ++$i) { + $tokens->clearAt($i); + } - return; + return; + } } // does __construct only call the PHP4-constructor (with the same args)? - list($seq, $case) = $this->getWrapperMethodSequence($tokens, $className, $php4['startIndex'], $php4['bodyIndex']); - if (null !== $tokens->findSequence($seq, $php5['bodyIndex'] - 1, $php5['endIndex'], $case)) { - // that was a weird choice, but we can safely delete it and... - for ($i = $php5['startIndex']; $i <= $php5['endIndex']; ++$i) { - $tokens[$i]->clear(); + list($sequences, $case) = $this->getWrapperMethodSequence($tokens, $className, $php4['startIndex'], $php4['bodyIndex']); + foreach ($sequences as $seq) { + if (null !== $tokens->findSequence($seq, $php5['bodyIndex'] - 1, $php5['endIndex'], $case)) { + // that was a weird choice, but we can safely delete it and... + for ($i = $php5['startIndex']; $i <= $php5['endIndex']; ++$i) { + $tokens->clearAt($i); + } + // rename the PHP4 one to __construct + $tokens[$php4['nameIndex']] = new Token([T_STRING, '__construct']); + + return; } - // rename the PHP4 one to __construct - $tokens[$php4['nameIndex']]->setContent('__construct'); } } @@ -169,49 +207,49 @@ private function fixParent(Tokens $tokens, $classStart, $classEnd) $parentClass = $tokens[$parentIndex]->getContent(); // using parent::ParentClassName() or ParentClassName::ParentClassName() - $parentSeq = $tokens->findSequence(array( - array(T_STRING), - array(T_DOUBLE_COLON), - array(T_STRING, $parentClass), + $parentSeq = $tokens->findSequence([ + [T_STRING], + [T_DOUBLE_COLON], + [T_STRING, $parentClass], '(', - ), $classStart, $classEnd, array(2 => false)); + ], $classStart, $classEnd, [2 => false]); if (null !== $parentSeq) { // we only need indexes $parentSeq = array_keys($parentSeq); // match either of the possibilities - if ($tokens[$parentSeq[0]]->equalsAny(array(array(T_STRING, 'parent'), array(T_STRING, $parentClass)), false)) { + if ($tokens[$parentSeq[0]]->equalsAny([[T_STRING, 'parent'], [T_STRING, $parentClass]], false)) { // replace with parent::__construct - $tokens[$parentSeq[0]]->setContent('parent'); - $tokens[$parentSeq[2]]->setContent('__construct'); + $tokens[$parentSeq[0]] = new Token([T_STRING, 'parent']); + $tokens[$parentSeq[2]] = new Token([T_STRING, '__construct']); } } - // using $this->ParentClassName() - $parentSeq = $tokens->findSequence(array( - array(T_VARIABLE, '$this'), - array(T_OBJECT_OPERATOR), - array(T_STRING, $parentClass), - '(', - ), $classStart, $classEnd, array(2 => false)); - - if (null !== $parentSeq) { - // we only need indexes - $parentSeq = array_keys($parentSeq); - - // replace call with parent::__construct() - $tokens[$parentSeq[0]] = new Token(array( - T_STRING, - 'parent', - $tokens[$parentSeq[0]]->getLine(), - )); - $tokens[$parentSeq[1]] = new Token(array( - T_DOUBLE_COLON, - '::', - $tokens[$parentSeq[1]]->getLine(), - )); - $tokens[$parentSeq[2]]->setContent('__construct'); + foreach (Token::getObjectOperatorKinds() as $objectOperatorKind) { + // using $this->ParentClassName() + $parentSeq = $tokens->findSequence([ + [T_VARIABLE, '$this'], + [$objectOperatorKind], + [T_STRING, $parentClass], + '(', + ], $classStart, $classEnd, [2 => false]); + + if (null !== $parentSeq) { + // we only need indexes + $parentSeq = array_keys($parentSeq); + + // replace call with parent::__construct() + $tokens[$parentSeq[0]] = new Token([ + T_STRING, + 'parent', + ]); + $tokens[$parentSeq[1]] = new Token([ + T_DOUBLE_COLON, + '::', + ]); + $tokens[$parentSeq[2]] = new Token([T_STRING, '__construct']); + } } } } @@ -226,31 +264,25 @@ private function fixParent(Tokens $tokens, $classStart, $classEnd) */ private function fixInfiniteRecursion(Tokens $tokens, $start, $end) { - $seq = array( - array(T_VARIABLE, '$this'), - array(T_OBJECT_OPERATOR), - array(T_STRING, '__construct'), - ); + foreach (Token::getObjectOperatorKinds() as $objectOperatorKind) { + $seq = [ + [T_VARIABLE, '$this'], + [$objectOperatorKind], + [T_STRING, '__construct'], + ]; + + while (true) { + $callSeq = $tokens->findSequence($seq, $start, $end, [2 => false]); + + if (null === $callSeq) { + return; + } - while (true) { - $callSeq = $tokens->findSequence($seq, $start, $end, array(2 => false)); + $callSeq = array_keys($callSeq); - if (null === $callSeq) { - return; + $tokens[$callSeq[0]] = new Token([T_STRING, 'parent']); + $tokens[$callSeq[1]] = new Token([T_DOUBLE_COLON, '::']); } - - $callSeq = array_keys($callSeq); - - $tokens[$callSeq[0]] = new Token(array( - T_STRING, - 'parent', - $tokens[$callSeq[0]]->getLine(), - )); - $tokens[$callSeq[1]] = new Token(array( - T_DOUBLE_COLON, - '::', - $tokens[$callSeq[1]]->getLine(), - )); } } @@ -267,42 +299,47 @@ private function fixInfiniteRecursion(Tokens $tokens, $start, $end) */ private function getWrapperMethodSequence(Tokens $tokens, $method, $startIndex, $bodyIndex) { - // initialise sequence as { $this->{$method}( - $seq = array( - '{', - array(T_VARIABLE, '$this'), - array(T_OBJECT_OPERATOR), - array(T_STRING, $method), - '(', - ); - $case = array(3 => false); + $sequences = []; + + foreach (Token::getObjectOperatorKinds() as $objectOperatorKind) { + // initialise sequence as { $this->{$method}( + $seq = [ + '{', + [T_VARIABLE, '$this'], + [$objectOperatorKind], + [T_STRING, $method], + '(', + ]; - // parse method parameters, if any - $index = $startIndex; - while (true) { - // find the next variable name - $index = $tokens->getNextTokenOfKind($index, array(array(T_VARIABLE))); + // parse method parameters, if any + $index = $startIndex; + while (true) { + // find the next variable name + $index = $tokens->getNextTokenOfKind($index, [[T_VARIABLE]]); - if (null === $index || $index >= $bodyIndex) { - // we've reached the body already - break; - } + if (null === $index || $index >= $bodyIndex) { + // we've reached the body already + break; + } + + // append a comma if it's not the first variable + if (\count($seq) > 5) { + $seq[] = ','; + } - // append a comma if it's not the first variable - if (count($seq) > 5) { - $seq[] = ','; + // append variable name to the sequence + $seq[] = [T_VARIABLE, $tokens[$index]->getContent()]; } - // append variable name to the sequence - $seq[] = array(T_VARIABLE, $tokens[$index]->getContent()); - } + // almost done, close the sequence with ); } + $seq[] = ')'; + $seq[] = ';'; + $seq[] = '}'; - // almost done, close the sequence with ); } - $seq[] = ')'; - $seq[] = ';'; - $seq[] = '}'; + $sequences[] = $seq; + } - return array($seq, $case); + return [$sequences, [3 => false]]; } /** @@ -313,7 +350,7 @@ private function getWrapperMethodSequence(Tokens $tokens, $method, $startIndex, * @param int $startIndex the search start index * @param int $endIndex the search end index * - * @return array|null An associative array, if a match is found: + * @return null|array An associative array, if a match is found: * * - nameIndex (int): The index of the function/method name. * - startIndex (int): The index of the function/method start. @@ -324,22 +361,22 @@ private function getWrapperMethodSequence(Tokens $tokens, $method, $startIndex, */ private function findFunction(Tokens $tokens, $name, $startIndex, $endIndex) { - $function = $tokens->findSequence(array( - array(T_FUNCTION), - array(T_STRING, $name), + $function = $tokens->findSequence([ + [T_FUNCTION], + [T_STRING, $name], '(', - ), $startIndex, $endIndex, false); + ], $startIndex, $endIndex, false); if (null === $function) { - return; + return null; } // keep only the indexes $function = array_keys($function); // find previous block, saving method modifiers for later use - $possibleModifiers = array(T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_ABSTRACT, T_FINAL); - $modifiers = array(); + $possibleModifiers = [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_ABSTRACT, T_FINAL]; + $modifiers = []; $prevBlock = $tokens->getPrevMeaningfulToken($function[0]); while (null !== $prevBlock && $tokens[$prevBlock]->isGivenKind($possibleModifiers)) { @@ -350,19 +387,19 @@ private function findFunction(Tokens $tokens, $name, $startIndex, $endIndex) if (isset($modifiers[T_ABSTRACT])) { // abstract methods have no body $bodyStart = null; - $funcEnd = $tokens->getNextTokenOfKind($function[2], array(';')); + $funcEnd = $tokens->getNextTokenOfKind($function[2], [';']); } else { // find method body start and the end of the function definition - $bodyStart = $tokens->getNextTokenOfKind($function[2], array('{')); - $funcEnd = $bodyStart !== null ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $bodyStart) : null; + $bodyStart = $tokens->getNextTokenOfKind($function[2], ['{']); + $funcEnd = null !== $bodyStart ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $bodyStart) : null; } - return array( + return [ 'nameIndex' => $function[1], 'startIndex' => $prevBlock + 1, 'endIndex' => $funcEnd, 'bodyIndex' => $bodyStart, 'modifiers' => $modifiers, - ); + ]; } } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoUnneededFinalMethodFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoUnneededFinalMethodFixer.php new file mode 100644 index 0000000..2ede829 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/NoUnneededFinalMethodFixer.php @@ -0,0 +1,176 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class NoUnneededFinalMethodFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'A `final` class must not have `final` methods and `private` methods must not be `final`.', + [ + new CodeSample( + '<?php +final class Foo +{ + final public function foo1() {} + final protected function bar() {} + final private function baz() {} +} + +class Bar +{ + final private function bar1() {} +} +' + ), + new CodeSample( + '<?php +final class Foo +{ + final private function baz() {} +} + +class Bar +{ + final private function bar1() {} +} +', + ['private_methods' => false] + ), + ], + null, + 'Risky when child class overrides a `private` method.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_CLASS, T_FINAL]); + } + + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensCount = \count($tokens); + for ($index = 0; $index < $tokensCount; ++$index) { + if (!$tokens[$index]->isGivenKind(T_CLASS)) { + continue; + } + + $classOpen = $tokens->getNextTokenOfKind($index, ['{']); + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; + $classIsFinal = $prevToken->isGivenKind(T_FINAL); + + $this->fixClass($tokens, $classOpen, $classIsFinal); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('private_methods', 'Private methods of non-`final` classes must not be declared `final`.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + ]); + } + + /** + * @param int $classOpenIndex + * @param bool $classIsFinal + */ + private function fixClass(Tokens $tokens, $classOpenIndex, $classIsFinal) + { + $tokensCount = \count($tokens); + + for ($index = $classOpenIndex + 1; $index < $tokensCount; ++$index) { + // Class end + if ($tokens[$index]->equals('}')) { + return; + } + + // Skip method content + if ($tokens[$index]->equals('{')) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + continue; + } + + if (!$tokens[$index]->isGivenKind(T_FINAL)) { + continue; + } + + if (!$classIsFinal && (!$this->isPrivateMethodOtherThanConstructor($tokens, $index, $classOpenIndex) || !$this->configuration['private_methods'])) { + continue; + } + + $tokens->clearAt($index); + + ++$index; + + if ($tokens[$index]->isWhitespace()) { + $tokens->clearAt($index); + } + } + } + + /** + * @param int $index + * @param int $classOpenIndex + * + * @return bool + */ + private function isPrivateMethodOtherThanConstructor(Tokens $tokens, $index, $classOpenIndex) + { + $index = max($classOpenIndex + 1, $tokens->getPrevTokenOfKind($index, [';', '{', '}'])); + $private = false; + + while (!$tokens[$index]->isGivenKind(T_FUNCTION)) { + if ($tokens[$index]->isGivenKind(T_PRIVATE)) { + $private = true; + } + + $index = $tokens->getNextMeaningfulToken($index); + } + + return $private && '__construct' !== strtolower($tokens[$tokens->getNextMeaningfulToken($index)]->getContent()); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedClassElementsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedClassElementsFixer.php new file mode 100644 index 0000000..28e5a6f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedClassElementsFixer.php @@ -0,0 +1,527 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AliasedFixerOptionBuilder; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Gregor Harlan <gharlan@web.de> + */ +final class OrderedClassElementsFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** @internal */ + const SORT_ALPHA = 'alpha'; + + /** @internal */ + const SORT_NONE = 'none'; + + /** + * @var array Array containing all class element base types (keys) and their parent types (values) + */ + private static $typeHierarchy = [ + 'use_trait' => null, + 'public' => null, + 'protected' => null, + 'private' => null, + 'constant' => null, + 'constant_public' => ['constant', 'public'], + 'constant_protected' => ['constant', 'protected'], + 'constant_private' => ['constant', 'private'], + 'property' => null, + 'property_static' => ['property'], + 'property_public' => ['property', 'public'], + 'property_protected' => ['property', 'protected'], + 'property_private' => ['property', 'private'], + 'property_public_static' => ['property_static', 'property_public'], + 'property_protected_static' => ['property_static', 'property_protected'], + 'property_private_static' => ['property_static', 'property_private'], + 'method' => null, + 'method_abstract' => ['method'], + 'method_static' => ['method'], + 'method_public' => ['method', 'public'], + 'method_protected' => ['method', 'protected'], + 'method_private' => ['method', 'private'], + 'method_public_abstract' => ['method_abstract', 'method_public'], + 'method_protected_abstract' => ['method_abstract', 'method_protected'], + 'method_public_abstract_static' => ['method_abstract', 'method_static', 'method_public'], + 'method_protected_abstract_static' => ['method_abstract', 'method_static', 'method_protected'], + 'method_public_static' => ['method_static', 'method_public'], + 'method_protected_static' => ['method_static', 'method_protected'], + 'method_private_static' => ['method_static', 'method_private'], + ]; + + /** + * @var array Array containing special method types + */ + private static $specialTypes = [ + 'construct' => null, + 'destruct' => null, + 'magic' => null, + 'phpunit' => null, + ]; + + /** + * Array of supported sort algorithms in configuration. + * + * @var string[] + */ + private $supportedSortAlgorithms = [ + self::SORT_NONE, + self::SORT_ALPHA, + ]; + + /** + * @var array Resolved configuration array (type => position) + */ + private $typePosition; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->typePosition = []; + $pos = 0; + foreach ($this->configuration['order'] as $type) { + $this->typePosition[$type] = $pos++; + } + + foreach (self::$typeHierarchy as $type => $parents) { + if (isset($this->typePosition[$type])) { + continue; + } + + if (!$parents) { + $this->typePosition[$type] = null; + + continue; + } + + foreach ($parents as $parent) { + if (isset($this->typePosition[$parent])) { + $this->typePosition[$type] = $this->typePosition[$parent]; + + continue 2; + } + } + + $this->typePosition[$type] = null; + } + + $lastPosition = \count($this->configuration['order']); + foreach ($this->typePosition as &$pos) { + if (null === $pos) { + $pos = $lastPosition; + } + // last digit is used by phpunit method ordering + $pos *= 10; + } + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds()); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Orders the elements of classes/interfaces/traits.', + [ + new CodeSample( + '<?php +final class Example +{ + use BarTrait; + use BazTrait; + const C1 = 1; + const C2 = 2; + protected static $protStatProp; + public static $pubStatProp1; + public $pubProp1; + protected $protProp; + var $pubProp2; + private static $privStatProp; + private $privProp; + public static $pubStatProp2; + public $pubProp3; + protected function __construct() {} + private static function privStatFunc() {} + public function pubFunc1() {} + public function __toString() {} + protected function protFunc() {} + function pubFunc2() {} + public static function pubStatFunc1() {} + public function pubFunc3() {} + static function pubStatFunc2() {} + private function privFunc() {} + public static function pubStatFunc3() {} + protected static function protStatFunc() {} + public function __destruct() {} +} +' + ), + new CodeSample( + '<?php +class Example +{ + public function A(){} + private function B(){} +} +', + ['order' => ['method_private', 'method_public']] + ), + new CodeSample( + '<?php +class Example +{ + public function D(){} + public function B(){} + public function A(){} + public function C(){} +} +', + ['order' => ['method_public'], 'sort_algorithm' => 'alpha'] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before ClassAttributesSeparationFixer, MethodSeparationFixer, NoBlankLinesAfterClassOpeningFixer, SpaceAfterSemicolonFixer. + * Must run after NoPhp4ConstructorFixer, ProtectedToPrivateFixer. + */ + public function getPriority() + { + return 65; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($i = 1, $count = $tokens->count(); $i < $count; ++$i) { + if (!$tokens[$i]->isClassy()) { + continue; + } + + $i = $tokens->getNextTokenOfKind($i, ['{']); + $elements = $this->getElements($tokens, $i); + + if (0 === \count($elements)) { + continue; + } + + $sorted = $this->sortElements($elements); + $endIndex = $elements[\count($elements) - 1]['end']; + + if ($sorted !== $elements) { + $this->sortTokens($tokens, $i, $endIndex, $sorted); + } + + $i = $endIndex; + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolverRootless('order', [ + (new FixerOptionBuilder('order', 'List of strings defining order of elements.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset(array_keys(array_merge(self::$typeHierarchy, self::$specialTypes)))]) + ->setDefault([ + 'use_trait', + 'constant_public', + 'constant_protected', + 'constant_private', + 'property_public', + 'property_protected', + 'property_private', + 'construct', + 'destruct', + 'magic', + 'phpunit', + 'method_public', + 'method_protected', + 'method_private', + ]) + ->getOption(), + (new AliasedFixerOptionBuilder( + new FixerOptionBuilder('sort_algorithm', 'How multiple occurrences of same type statements should be sorted'), + 'sortAlgorithm' + )) + ->setAllowedValues($this->supportedSortAlgorithms) + ->setDefault(self::SORT_NONE) + ->getOption(), + ], $this->getName()); + } + + /** + * @param int $startIndex + * + * @return array[] + */ + private function getElements(Tokens $tokens, $startIndex) + { + static $elementTokenKinds = [CT::T_USE_TRAIT, T_CONST, T_VARIABLE, T_FUNCTION]; + + ++$startIndex; + $elements = []; + + while (true) { + $element = [ + 'start' => $startIndex, + 'visibility' => 'public', + 'abstract' => false, + 'static' => false, + ]; + + for ($i = $startIndex;; ++$i) { + $token = $tokens[$i]; + + // class end + if ($token->equals('}')) { + return $elements; + } + + if ($token->isGivenKind(T_ABSTRACT)) { + $element['abstract'] = true; + + continue; + } + + if ($token->isGivenKind(T_STATIC)) { + $element['static'] = true; + + continue; + } + + if ($token->isGivenKind([T_PROTECTED, T_PRIVATE])) { + $element['visibility'] = strtolower($token->getContent()); + + continue; + } + + if (!$token->isGivenKind($elementTokenKinds)) { + continue; + } + + $type = $this->detectElementType($tokens, $i); + if (\is_array($type)) { + $element['type'] = $type[0]; + $element['name'] = $type[1]; + } else { + $element['type'] = $type; + } + + if ('property' === $element['type']) { + $element['name'] = $tokens[$i]->getContent(); + } elseif (\in_array($element['type'], ['use_trait', 'constant', 'method', 'magic', 'construct', 'destruct'], true)) { + $element['name'] = $tokens[$tokens->getNextMeaningfulToken($i)]->getContent(); + } + + $element['end'] = $this->findElementEnd($tokens, $i); + + break; + } + + $elements[] = $element; + $startIndex = $element['end'] + 1; + } + } + + /** + * @param int $index + * + * @return array|string type or array of type and name + */ + private function detectElementType(Tokens $tokens, $index) + { + $token = $tokens[$index]; + + if ($token->isGivenKind(CT::T_USE_TRAIT)) { + return 'use_trait'; + } + + if ($token->isGivenKind(T_CONST)) { + return 'constant'; + } + + if ($token->isGivenKind(T_VARIABLE)) { + return 'property'; + } + + $nameToken = $tokens[$tokens->getNextMeaningfulToken($index)]; + + if ($nameToken->equals([T_STRING, '__construct'], false)) { + return 'construct'; + } + + if ($nameToken->equals([T_STRING, '__destruct'], false)) { + return 'destruct'; + } + + if ( + $nameToken->equalsAny([ + [T_STRING, 'setUpBeforeClass'], + [T_STRING, 'doSetUpBeforeClass'], + [T_STRING, 'tearDownAfterClass'], + [T_STRING, 'doTearDownAfterClass'], + [T_STRING, 'setUp'], + [T_STRING, 'doSetUp'], + [T_STRING, 'tearDown'], + [T_STRING, 'doTearDown'], + ], false) + ) { + return ['phpunit', strtolower($nameToken->getContent())]; + } + + if ('__' === substr($nameToken->getContent(), 0, 2)) { + return 'magic'; + } + + return 'method'; + } + + /** + * @param int $index + * + * @return int + */ + private function findElementEnd(Tokens $tokens, $index) + { + $index = $tokens->getNextTokenOfKind($index, ['{', ';']); + + if ($tokens[$index]->equals('{')) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + } + + for (++$index; $tokens[$index]->isWhitespace(" \t") || $tokens[$index]->isComment(); ++$index); + + --$index; + + return $tokens[$index]->isWhitespace() ? $index - 1 : $index; + } + + /** + * @param array[] $elements + * + * @return array[] + */ + private function sortElements(array $elements) + { + static $phpunitPositions = [ + 'setupbeforeclass' => 1, + 'dosetupbeforeclass' => 2, + 'teardownafterclass' => 3, + 'doteardownafterclass' => 4, + 'setup' => 5, + 'dosetup' => 6, + 'teardown' => 7, + 'doteardown' => 8, + ]; + + foreach ($elements as &$element) { + $type = $element['type']; + + if (\array_key_exists($type, self::$specialTypes)) { + if (isset($this->typePosition[$type])) { + $element['position'] = $this->typePosition[$type]; + if ('phpunit' === $type) { + $element['position'] += $phpunitPositions[$element['name']]; + } + + continue; + } + + $type = 'method'; + } + + if (\in_array($type, ['constant', 'property', 'method'], true)) { + $type .= '_'.$element['visibility']; + if ($element['abstract']) { + $type .= '_abstract'; + } + if ($element['static']) { + $type .= '_static'; + } + } + + $element['position'] = $this->typePosition[$type]; + } + unset($element); + + usort($elements, function (array $a, array $b) { + if ($a['position'] === $b['position']) { + return $this->sortGroupElements($a, $b); + } + + return $a['position'] > $b['position'] ? 1 : -1; + }); + + return $elements; + } + + private function sortGroupElements(array $a, array $b) + { + $selectedSortAlgorithm = $this->configuration['sort_algorithm']; + + if (self::SORT_ALPHA === $selectedSortAlgorithm) { + return strcasecmp($a['name'], $b['name']); + } + + return $a['start'] > $b['start'] ? 1 : -1; + } + + /** + * @param int $startIndex + * @param int $endIndex + * @param array[] $elements + */ + private function sortTokens(Tokens $tokens, $startIndex, $endIndex, array $elements) + { + $replaceTokens = []; + + foreach ($elements as $element) { + for ($i = $element['start']; $i <= $element['end']; ++$i) { + $replaceTokens[] = clone $tokens[$i]; + } + } + + $tokens->overrideRange($startIndex + 1, $endIndex, $replaceTokens); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedInterfacesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedInterfacesFixer.php new file mode 100644 index 0000000..e8ad880 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedInterfacesFixer.php @@ -0,0 +1,231 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dave van der Brugge <dmvdbrugge@gmail.com> + */ +final class OrderedInterfacesFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** @internal */ + const OPTION_DIRECTION = 'direction'; + + /** @internal */ + const OPTION_ORDER = 'order'; + + /** @internal */ + const DIRECTION_ASCEND = 'ascend'; + + /** @internal */ + const DIRECTION_DESCEND = 'descend'; + + /** @internal */ + const ORDER_ALPHA = 'alpha'; + + /** @internal */ + const ORDER_LENGTH = 'length'; + + /** + * Array of supported directions in configuration. + * + * @var string[] + */ + private $supportedDirectionOptions = [ + self::DIRECTION_ASCEND, + self::DIRECTION_DESCEND, + ]; + + /** + * Array of supported orders in configuration. + * + * @var string[] + */ + private $supportedOrderOptions = [ + self::ORDER_ALPHA, + self::ORDER_LENGTH, + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Orders the interfaces in an `implements` or `interface extends` clause.', + [ + new CodeSample( + "<?php\n\nfinal class ExampleA implements Gamma, Alpha, Beta {}\n\ninterface ExampleB extends Gamma, Alpha, Beta {}\n" + ), + new CodeSample( + "<?php\n\nfinal class ExampleA implements Gamma, Alpha, Beta {}\n\ninterface ExampleB extends Gamma, Alpha, Beta {}\n", + [self::OPTION_DIRECTION => self::DIRECTION_DESCEND] + ), + new CodeSample( + "<?php\n\nfinal class ExampleA implements MuchLonger, Short, Longer {}\n\ninterface ExampleB extends MuchLonger, Short, Longer {}\n", + [self::OPTION_ORDER => self::ORDER_LENGTH] + ), + new CodeSample( + "<?php\n\nfinal class ExampleA implements MuchLonger, Short, Longer {}\n\ninterface ExampleB extends MuchLonger, Short, Longer {}\n", + [ + self::OPTION_ORDER => self::ORDER_LENGTH, + self::OPTION_DIRECTION => self::DIRECTION_DESCEND, + ] + ), + ], + null, + "Risky for `implements` when specifying both an interface and its parent interface, because PHP doesn't break on `parent, child` but does on `child, parent`." + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_IMPLEMENTS) + || $tokens->isAllTokenKindsFound([T_INTERFACE, T_EXTENDS]); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_IMPLEMENTS)) { + if (!$token->isGivenKind(T_EXTENDS)) { + continue; + } + + $nameTokenIndex = $tokens->getPrevMeaningfulToken($index); + $interfaceTokenIndex = $tokens->getPrevMeaningfulToken($nameTokenIndex); + $interfaceToken = $tokens[$interfaceTokenIndex]; + + if (!$interfaceToken->isGivenKind(T_INTERFACE)) { + continue; + } + } + + $interfaceIndex = 0; + $interfaces = [['tokens' => []]]; + + $implementsStart = $index + 1; + $classStart = $tokens->getNextTokenOfKind($implementsStart, ['{']); + $implementsEnd = $tokens->getPrevNonWhitespace($classStart); + + for ($i = $implementsStart; $i <= $implementsEnd; ++$i) { + if ($tokens[$i]->equals(',')) { + ++$interfaceIndex; + $interfaces[$interfaceIndex] = ['tokens' => []]; + + continue; + } + + $interfaces[$interfaceIndex]['tokens'][] = $tokens[$i]; + } + + if (1 === \count($interfaces)) { + continue; + } + + foreach ($interfaces as $interfaceIndex => $interface) { + $interfaceTokens = Tokens::fromArray($interface['tokens'], false); + + $normalized = ''; + $actualInterfaceIndex = $interfaceTokens->getNextMeaningfulToken(-1); + + while ($interfaceTokens->offsetExists($actualInterfaceIndex)) { + $token = $interfaceTokens[$actualInterfaceIndex]; + + if (null === $token || $token->isComment() || $token->isWhitespace()) { + break; + } + + $normalized .= str_replace('\\', ' ', $token->getContent()); + ++$actualInterfaceIndex; + } + + $interfaces[$interfaceIndex]['normalized'] = $normalized; + $interfaces[$interfaceIndex]['originalIndex'] = $interfaceIndex; + } + + usort($interfaces, function (array $first, array $second) { + $score = self::ORDER_LENGTH === $this->configuration[self::OPTION_ORDER] + ? \strlen($first['normalized']) - \strlen($second['normalized']) + : strcasecmp($first['normalized'], $second['normalized']); + + if (self::DIRECTION_DESCEND === $this->configuration[self::OPTION_DIRECTION]) { + $score *= -1; + } + + return $score; + }); + + $changed = false; + + foreach ($interfaces as $interfaceIndex => $interface) { + if ($interface['originalIndex'] !== $interfaceIndex) { + $changed = true; + + break; + } + } + + if (!$changed) { + continue; + } + + $newTokens = array_shift($interfaces)['tokens']; + + foreach ($interfaces as $interface) { + array_push($newTokens, new Token(','), ...$interface['tokens']); + } + + $tokens->overrideRange($implementsStart, $implementsEnd, $newTokens); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder(self::OPTION_ORDER, 'How the interfaces should be ordered')) + ->setAllowedValues($this->supportedOrderOptions) + ->setDefault(self::ORDER_ALPHA) + ->getOption(), + (new FixerOptionBuilder(self::OPTION_DIRECTION, 'Which direction the interfaces should be ordered')) + ->setAllowedValues($this->supportedDirectionOptions) + ->setDefault(self::DIRECTION_ASCEND) + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedTraitsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedTraitsFixer.php new file mode 100644 index 0000000..675a90f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/OrderedTraitsFixer.php @@ -0,0 +1,194 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; + +final class OrderedTraitsFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Trait `use` statements must be sorted alphabetically.', + [ + new CodeSample("<?php class Foo { \nuse Z; use A; }\n"), + ], + null, + 'Risky when depending on order of the imports.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(CT::T_USE_TRAIT); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($this->findUseStatementsGroups($tokens) as $uses) { + $this->sortUseStatements($tokens, $uses); + } + } + + /** + * @return iterable<array<int, Tokens>> + */ + private function findUseStatementsGroups(Tokens $tokens) + { + $uses = []; + + for ($index = 1, $max = \count($tokens); $index < $max; ++$index) { + $token = $tokens[$index]; + + if ($token->isWhitespace() || $token->isComment()) { + continue; + } + + if (!$token->isGivenKind(CT::T_USE_TRAIT)) { + if (\count($uses) > 0) { + yield $uses; + + $uses = []; + } + + continue; + } + + $endIndex = $tokens->getNextTokenOfKind($index, [';', '{']); + + if ($tokens[$endIndex]->equals('{')) { + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $endIndex); + } + + $use = []; + + for ($i = $index; $i <= $endIndex; ++$i) { + $use[] = $tokens[$i]; + } + + $uses[$index] = Tokens::fromArray($use); + + $index = $endIndex; + } + } + + /** + * @param array<int, Tokens> $uses + */ + private function sortUseStatements(Tokens $tokens, array $uses) + { + foreach ($uses as $use) { + $this->sortMultipleTraitsInStatement($use); + } + + $this->sort($tokens, $uses); + } + + private function sortMultipleTraitsInStatement(Tokens $use) + { + $traits = []; + $indexOfName = null; + $name = []; + + for ($index = 0, $max = \count($use); $index < $max; ++$index) { + $token = $use[$index]; + + if ($token->isGivenKind([T_STRING, T_NS_SEPARATOR])) { + $name[] = $token; + + if (null === $indexOfName) { + $indexOfName = $index; + } + + continue; + } + + if ($token->equalsAny([',', ';', '{'])) { + $traits[$indexOfName] = Tokens::fromArray($name); + + $name = []; + $indexOfName = null; + } + + if ($token->equals('{')) { + $index = $use->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + } + } + + $this->sort($use, $traits); + } + + /** + * @param array<int, Tokens> $elements + */ + private function sort(Tokens $tokens, array $elements) + { + /** + * @return string + */ + $toTraitName = static function (Tokens $use) { + $string = ''; + + foreach ($use as $token) { + if ($token->equalsAny([';', '{'])) { + break; + } + + if ($token->isGivenKind([T_NS_SEPARATOR, T_STRING])) { + $string .= $token->getContent(); + } + } + + return ltrim($string, '\\'); + }; + + $sortedElements = $elements; + uasort($sortedElements, static function (Tokens $useA, Tokens $useB) use ($toTraitName) { + return strcasecmp($toTraitName($useA), $toTraitName($useB)); + }); + + $sortedElements = array_combine( + array_keys($elements), + array_values($sortedElements) + ); + + foreach (array_reverse($sortedElements, true) as $index => $tokensToInsert) { + $tokens->overrideRange( + $index, + $index + \count($elements[$index]) - 1, + $tokensToInsert + ); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ProtectedToPrivateFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ProtectedToPrivateFixer.php similarity index 53% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ProtectedToPrivateFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ProtectedToPrivateFixer.php index 1b32b5d..6c6c502 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/ProtectedToPrivateFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/ProtectedToPrivateFixer.php @@ -10,10 +10,14 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Contrib; +namespace PhpCsFixer\Fixer\ClassNotation; -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; /** * @author Filippo Tessarotto <zoeslam@gmail.com> @@ -24,47 +28,78 @@ final class ProtectedToPrivateFixer extends AbstractFixer /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function getDefinition() { - $tokens = Tokens::fromCode($content); - $end = count($tokens) - 3; // min. number of tokens to form a class candidate to fix + return new FixerDefinition( + 'Converts `protected` variables and methods to `private` where possible.', + [ + new CodeSample( + '<?php +final class Sample +{ + protected $a; + + protected function test() + { + } +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before OrderedClassElementsFixer. + * Must run after FinalInternalClassFixer. + */ + public function getPriority() + { + return 66; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_CLASS, T_FINAL, T_PROTECTED]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $end = \count($tokens) - 3; // min. number of tokens to form a class candidate to fix for ($index = 0; $index < $end; ++$index) { if (!$tokens[$index]->isGivenKind(T_CLASS)) { continue; } - $classOpen = $tokens->getNextTokenOfKind($index, array('{')); + $classOpen = $tokens->getNextTokenOfKind($index, ['{']); $classClose = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classOpen); if (!$this->skipClass($tokens, $index, $classOpen, $classClose)) { - $this->fixClass($tokens, $index, $classOpen, $classClose); + $this->fixClass($tokens, $classOpen, $classClose); } $index = $classClose; } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Converts protected variables and methods to private where possible.'; } /** - * @param Tokens $tokens - * @param int $classIndex - * @param int $classOpenIndex - * @param int $classCloseIndex + * @param int $classOpenIndex + * @param int $classCloseIndex */ - private function fixClass(Tokens $tokens, $classIndex, $classOpenIndex, $classCloseIndex) + private function fixClass(Tokens $tokens, $classOpenIndex, $classCloseIndex) { for ($index = $classOpenIndex + 1; $index < $classCloseIndex; ++$index) { if ($tokens[$index]->equals('{')) { $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + continue; } @@ -72,17 +107,16 @@ private function fixClass(Tokens $tokens, $classIndex, $classOpenIndex, $classCl continue; } - $tokens->overrideAt($index, array(T_PRIVATE, 'private')); + $tokens[$index] = new Token([T_PRIVATE, 'private']); } } /** * Decide whether or not skip the fix for given class. * - * @param Tokens $tokens - * @param int $classIndex - * @param int $classOpenIndex - * @param int $classCloseIndex + * @param int $classIndex + * @param int $classOpenIndex + * @param int $classCloseIndex * * @return bool */ @@ -99,7 +133,7 @@ private function skipClass(Tokens $tokens, $classIndex, $classOpenIndex, $classC } } - $useIndex = $tokens->getNextTokenOfKind($classIndex, array(array(T_USE))); + $useIndex = $tokens->getNextTokenOfKind($classIndex, [[CT::T_USE_TRAIT]]); return $useIndex && $useIndex < $classCloseIndex; } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SelfAccessorFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SelfAccessorFixer.php new file mode 100644 index 0000000..408f8a0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SelfAccessorFixer.php @@ -0,0 +1,191 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Gregor Harlan <gharlan@web.de> + */ +final class SelfAccessorFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Inside class or interface element `self` should be preferred to the class name itself.', + [ + new CodeSample( + '<?php +class Sample +{ + const BAZ = 1; + const BAR = Sample::BAZ; + + public function getBar() + { + return Sample::BAR; + } +} +' + ), + ], + null, + 'Risky when using dynamic calls like get_called_class() or late static binding.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_CLASS, T_INTERFACE]); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + + foreach ((new NamespacesAnalyzer())->getDeclarations($tokens) as $namespace) { + for ($index = $namespace->getScopeStartIndex(); $index < $namespace->getScopeEndIndex(); ++$index) { + if (!$tokens[$index]->isGivenKind([T_CLASS, T_INTERFACE]) || $tokensAnalyzer->isAnonymousClass($index)) { + continue; + } + + $nameIndex = $tokens->getNextTokenOfKind($index, [[T_STRING]]); + $startIndex = $tokens->getNextTokenOfKind($nameIndex, ['{']); + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startIndex); + + $name = $tokens[$nameIndex]->getContent(); + + $this->replaceNameOccurrences($tokens, $namespace->getFullName(), $name, $startIndex, $endIndex); + + $index = $endIndex; + } + } + } + + /** + * Replace occurrences of the name of the classy element by "self" (if possible). + * + * @param string $namespace + * @param string $name + * @param int $startIndex + * @param int $endIndex + */ + private function replaceNameOccurrences(Tokens $tokens, $namespace, $name, $startIndex, $endIndex) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + $insideMethodSignatureUntil = null; + + for ($i = $startIndex; $i < $endIndex; ++$i) { + if ($i === $insideMethodSignatureUntil) { + $insideMethodSignatureUntil = null; + } + + $token = $tokens[$i]; + + // skip anonymous classes + if ($token->isGivenKind(T_CLASS) && $tokensAnalyzer->isAnonymousClass($i)) { + $i = $tokens->getNextTokenOfKind($i, ['{']); + $i = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $i); + + continue; + } + + if ($token->isGivenKind(T_FUNCTION)) { + $i = $tokens->getNextTokenOfKind($i, ['(']); + $insideMethodSignatureUntil = $tokens->getNextTokenOfKind($i, ['{', ';']); + + continue; + } + + if (!$token->equals([T_STRING, $name], false)) { + continue; + } + + $nextToken = $tokens[$tokens->getNextMeaningfulToken($i)]; + if ($nextToken->isGivenKind(T_NS_SEPARATOR)) { + continue; + } + + $classStartIndex = $i; + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($i)]; + if ($prevToken->isGivenKind(T_NS_SEPARATOR)) { + $classStartIndex = $this->getClassStart($tokens, $i, $namespace); + if (null === $classStartIndex) { + continue; + } + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($classStartIndex)]; + } + if ($prevToken->isGivenKind(T_STRING) || $prevToken->isObjectOperator()) { + continue; + } + + if ( + $prevToken->isGivenKind([T_INSTANCEOF, T_NEW]) + || $nextToken->isGivenKind(T_PAAMAYIM_NEKUDOTAYIM) + || ( + null !== $insideMethodSignatureUntil + && $i < $insideMethodSignatureUntil + && $prevToken->equalsAny(['(', ',', [CT::T_TYPE_COLON], [CT::T_NULLABLE_TYPE]]) + ) + ) { + for ($j = $classStartIndex; $j < $i; ++$j) { + $tokens->clearTokenAndMergeSurroundingWhitespace($j); + } + $tokens[$i] = new Token([T_STRING, 'self']); + } + } + } + + private function getClassStart(Tokens $tokens, $index, $namespace) + { + $namespace = ('' !== $namespace ? '\\'.$namespace : '').'\\'; + + foreach (array_reverse(Preg::split('/(\\\\)/', $namespace, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)) as $piece) { + $index = $tokens->getPrevMeaningfulToken($index); + if ('\\' === $piece) { + if (!$tokens[$index]->isGivenKind(T_NS_SEPARATOR)) { + return null; + } + } elseif (!$tokens[$index]->equals([T_STRING, $piece], false)) { + return null; + } + } + + return $index; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SelfStaticAccessorFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SelfStaticAccessorFixer.php new file mode 100644 index 0000000..98ea552 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SelfStaticAccessorFixer.php @@ -0,0 +1,206 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +final class SelfStaticAccessorFixer extends AbstractFixer +{ + /** + * @var TokensAnalyzer + */ + private $tokensAnalyzer; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Inside a `final` class or anonymous class `self` should be preferred to `static`.', + [ + new CodeSample( + '<?php +final class Sample +{ + private static $A = 1; + + public function getBar() + { + return static::class.static::test().static::$A; + } + + private static function test() + { + return \'test\'; + } +} +' + ), + new CodeSample( + '<?php +final class Foo +{ + public function bar() + { + return new static(); + } +} +' + ), + new CodeSample( + '<?php +final class Foo +{ + public function isBar() + { + return $foo instanceof static; + } +} +' + ), + new VersionSpecificCodeSample( + '<?php +$a = new class() { + public function getBar() + { + return static::class; + } +}; +', + new VersionSpecification(70000) + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_CLASS, T_STATIC]) && $tokens->isAnyTokenKindsFound([T_DOUBLE_COLON, T_NEW, T_INSTANCEOF]); + } + + /** + * {@inheritdoc} + * + * Must run after FinalInternalClassFixer, FunctionToConstantFixer, PhpUnitTestCaseStaticMethodCallsFixer. + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $this->tokensAnalyzer = $tokensAnalyzer = new TokensAnalyzer($tokens); + + $classIndex = $tokens->getNextTokenOfKind(0, [[T_CLASS]]); + + while (null !== $classIndex) { + if ( + $tokens[$tokens->getPrevMeaningfulToken($classIndex)]->isGivenKind(T_FINAL) + || $tokensAnalyzer->isAnonymousClass($classIndex) + ) { + $classIndex = $this->fixClass($tokens, $classIndex); + } + + $classIndex = $tokens->getNextTokenOfKind($classIndex, [[T_CLASS]]); + } + } + + /** + * @param int $index + * + * @return int + */ + private function fixClass(Tokens $tokens, $index) + { + $index = $tokens->getNextTokenOfKind($index, ['{']); + $classOpenCount = 1; + + while ($classOpenCount > 0) { + ++$index; + + if ($tokens[$index]->equals('{')) { + ++$classOpenCount; + + continue; + } + + if ($tokens[$index]->equals('}')) { + --$classOpenCount; + + continue; + } + + if ($tokens[$index]->isGivenKind(T_FUNCTION)) { + // do not fix inside lambda + if ($this->tokensAnalyzer->isLambda($index)) { + // figure out where the lambda starts + $index = $tokens->getNextTokenOfKind($index, ['{']); + $openCount = 1; + + do { + $index = $tokens->getNextTokenOfKind($index, ['}', '{', [T_CLASS]]); + if ($tokens[$index]->equals('}')) { + --$openCount; + } elseif ($tokens[$index]->equals('{')) { + ++$openCount; + } else { + $index = $this->fixClass($tokens, $index); + } + } while ($openCount > 0); + } + + continue; + } + + if ($tokens[$index]->isGivenKind([T_NEW, T_INSTANCEOF])) { + $index = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$index]->isGivenKind(T_STATIC)) { + $tokens[$index] = new Token([T_STRING, 'self']); + } + + continue; + } + + if (!$tokens[$index]->isGivenKind(T_STATIC)) { + continue; + } + + $staticIndex = $index; + $index = $tokens->getNextMeaningfulToken($index); + + if (!$tokens[$index]->isGivenKind(T_DOUBLE_COLON)) { + continue; + } + + $tokens[$staticIndex] = new Token([T_STRING, 'self']); + } + + return $index; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SingleClassElementPerStatementFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SingleClassElementPerStatementFixer.php new file mode 100644 index 0000000..98b598e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SingleClassElementPerStatementFixer.php @@ -0,0 +1,242 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * Fixer for rules defined in PSR2 ¶4.2. + * + * @author Javier Spagnoletti <phansys@gmail.com> + * @author SpacePossum + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class SingleClassElementPerStatementFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds()); + } + + /** + * {@inheritdoc} + * + * Must run before ClassAttributesSeparationFixer. + */ + public function getPriority() + { + return 56; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There MUST NOT be more than one property or constant declared per statement.', + [ + new CodeSample( + '<?php +final class Example +{ + const FOO_1 = 1, FOO_2 = 2; + private static $bar1 = array(1,2,3), $bar2 = [1,2,3]; +} +' + ), + new CodeSample( + '<?php +final class Example +{ + const FOO_1 = 1, FOO_2 = 2; + private static $bar1 = array(1,2,3), $bar2 = [1,2,3]; +} +', + ['elements' => ['property']] + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $analyzer = new TokensAnalyzer($tokens); + $elements = array_reverse($analyzer->getClassyElements(), true); + + foreach ($elements as $index => $element) { + if (!\in_array($element['type'], $this->configuration['elements'], true)) { + continue; // not in configuration + } + + $this->fixElement($tokens, $element['type'], $index); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $values = ['const', 'property']; + + return new FixerConfigurationResolverRootless('elements', [ + (new FixerOptionBuilder('elements', 'List of strings which element should be modified.')) + ->setDefault($values) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset($values)]) + ->getOption(), + ], $this->getName()); + } + + /** + * @param string $type + * @param int $index + */ + private function fixElement(Tokens $tokens, $type, $index) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + $repeatIndex = $index; + + while (true) { + $repeatIndex = $tokens->getNextMeaningfulToken($repeatIndex); + $repeatToken = $tokens[$repeatIndex]; + + if ($tokensAnalyzer->isArray($repeatIndex)) { + if ($repeatToken->isGivenKind(T_ARRAY)) { + $repeatIndex = $tokens->getNextTokenOfKind($repeatIndex, ['(']); + $repeatIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $repeatIndex); + } else { + $repeatIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $repeatIndex); + } + + continue; + } + + if ($repeatToken->equals(';')) { + return; // no repeating found, no fixing needed + } + + if ($repeatToken->equals(',')) { + break; + } + } + + $start = $tokens->getPrevTokenOfKind($index, [';', '{', '}']); + $this->expandElement( + $tokens, + $type, + $tokens->getNextMeaningfulToken($start), + $tokens->getNextTokenOfKind($index, [';']) + ); + } + + /** + * @param string $type + * @param int $startIndex + * @param int $endIndex + */ + private function expandElement(Tokens $tokens, $type, $startIndex, $endIndex) + { + $divisionContent = null; + if ($tokens[$startIndex - 1]->isWhitespace()) { + $divisionContent = $tokens[$startIndex - 1]->getContent(); + if (Preg::match('#(\n|\r\n)#', $divisionContent, $matches)) { + $divisionContent = $matches[0].trim($divisionContent, "\r\n"); + } + } + + // iterate variables to split up + for ($i = $endIndex - 1; $i > $startIndex; --$i) { + $token = $tokens[$i]; + + if ($token->equals(')')) { + $i = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $i); + + continue; + } + + if ($token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_CLOSE)) { + $i = $tokens->findBlockStart(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $i); + + continue; + } + + if (!$tokens[$i]->equals(',')) { + continue; + } + + $tokens[$i] = new Token(';'); + if ($tokens[$i + 1]->isWhitespace()) { + $tokens->clearAt($i + 1); + } + + if (null !== $divisionContent && '' !== $divisionContent) { + $tokens->insertAt($i + 1, new Token([T_WHITESPACE, $divisionContent])); + } + + // collect modifiers + $sequence = $this->getModifiersSequences($tokens, $type, $startIndex, $endIndex); + $tokens->insertAt($i + 2, $sequence); + } + } + + /** + * @param string $type + * @param int $startIndex + * @param int $endIndex + * + * @return Token[] + */ + private function getModifiersSequences(Tokens $tokens, $type, $startIndex, $endIndex) + { + if ('property' === $type) { + $tokenKinds = [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_STATIC, T_VAR, T_STRING, T_NS_SEPARATOR, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT]; + } else { + $tokenKinds = [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_CONST]; + } + + $sequence = []; + for ($i = $startIndex; $i < $endIndex - 1; ++$i) { + if ($tokens[$i]->isComment()) { + continue; + } + + if (!$tokens[$i]->isWhitespace() && !$tokens[$i]->isGivenKind($tokenKinds)) { + break; + } + + $sequence[] = clone $tokens[$i]; + } + + return $sequence; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SingleTraitInsertPerStatementFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SingleTraitInsertPerStatementFixer.php new file mode 100644 index 0000000..be7f7d9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/SingleTraitInsertPerStatementFixer.php @@ -0,0 +1,119 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class SingleTraitInsertPerStatementFixer extends AbstractFixer +{ + public function getDefinition() + { + return new FixerDefinition( + 'Each trait `use` must be done as single statement.', + [ + new CodeSample( + '<?php +final class Example +{ + use Foo, Bar; +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer, SpaceAfterSemicolonFixer. + */ + public function getPriority() + { + return 36; + } + + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(CT::T_USE_TRAIT); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = \count($tokens) - 1; 1 < $index; --$index) { + if ($tokens[$index]->isGivenKind(CT::T_USE_TRAIT)) { + $candidates = $this->getCandidates($tokens, $index); + if (\count($candidates) > 0) { + $this->fixTraitUse($tokens, $index, $candidates); + } + } + } + } + + /** + * @param int $useTraitIndex + * @param int[] $candidates ',' indexes to fix + */ + private function fixTraitUse(Tokens $tokens, $useTraitIndex, array $candidates) + { + foreach ($candidates as $commaIndex) { + $inserts = [ + new Token([CT::T_USE_TRAIT, 'use']), + new Token([T_WHITESPACE, ' ']), + ]; + + $nextImportStartIndex = $tokens->getNextMeaningfulToken($commaIndex); + + if ($tokens[$nextImportStartIndex - 1]->isWhitespace()) { + if (1 === Preg::match('/\R/', $tokens[$nextImportStartIndex - 1]->getContent())) { + array_unshift($inserts, clone $tokens[$useTraitIndex - 1]); + } + $tokens->clearAt($nextImportStartIndex - 1); + } + + $tokens[$commaIndex] = new Token(';'); + $tokens->insertAt($nextImportStartIndex, $inserts); + } + } + + /** + * @param int $index + * + * @return int[] + */ + private function getCandidates(Tokens $tokens, $index) + { + $indexes = []; + $index = $tokens->getNextTokenOfKind($index, [',', ';', '{']); + + while (!$tokens[$index]->equals(';')) { + if ($tokens[$index]->equals('{')) { + return []; // do not fix use cases with grouping + } + + $indexes[] = $index; + $index = $tokens->getNextTokenOfKind($index, [',', ';', '{']); + } + + return array_reverse($indexes); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/VisibilityRequiredFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/VisibilityRequiredFixer.php new file mode 100644 index 0000000..fe68614 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassNotation/VisibilityRequiredFixer.php @@ -0,0 +1,201 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * Fixer for rules defined in PSR2 ¶4.3, ¶4.5. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +final class VisibilityRequiredFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Visibility MUST be declared on all properties and methods; `abstract` and `final` MUST be declared before the visibility; `static` MUST be declared after the visibility.', + [ + new CodeSample( + '<?php +class Sample +{ + var $a; + static protected $var_foo2; + + function A() + { + } +} +' + ), + new VersionSpecificCodeSample( + '<?php +class Sample +{ + const SAMPLE = 1; +} +', + new VersionSpecification(70100), + ['elements' => ['const']] + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds()); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolverRootless('elements', [ + (new FixerOptionBuilder('elements', 'The structural elements to fix (PHP >= 7.1 required for `const`).')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset(['property', 'method', 'const'])]) + ->setDefault(['property', 'method']) // @TODO v3 / PHP 7.1 add `const` + ->getOption(), + ], $this->getName()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + $propertyTypeDeclarationKinds = [T_STRING, T_NS_SEPARATOR, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT, CT::T_TYPE_ALTERNATION]; + + foreach (array_reverse($tokensAnalyzer->getClassyElements(), true) as $index => $element) { + if (!\in_array($element['type'], $this->configuration['elements'], true)) { + continue; + } + + if (\PHP_VERSION_ID < 70100 && 'const' === $element['type']) { + continue; + } + + $abstractFinalIndex = null; + $visibilityIndex = null; + $staticIndex = null; + $typeIndex = null; + $prevIndex = $tokens->getPrevMeaningfulToken($index); + $expectedKinds = [T_ABSTRACT, T_FINAL, T_PRIVATE, T_PROTECTED, T_PUBLIC, T_STATIC, T_VAR]; + + if ('property' === $element['type']) { + $expectedKinds = array_merge($expectedKinds, $propertyTypeDeclarationKinds); + } + + while ($tokens[$prevIndex]->isGivenKind($expectedKinds)) { + if ($tokens[$prevIndex]->isGivenKind([T_ABSTRACT, T_FINAL])) { + $abstractFinalIndex = $prevIndex; + } elseif ($tokens[$prevIndex]->isGivenKind(T_STATIC)) { + $staticIndex = $prevIndex; + } elseif ($tokens[$prevIndex]->isGivenKind($propertyTypeDeclarationKinds)) { + $typeIndex = $prevIndex; + } else { + $visibilityIndex = $prevIndex; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + } + + if (null !== $typeIndex) { + $index = $typeIndex; + } + + if ($tokens[$prevIndex]->equals(',')) { + continue; + } + + if (null !== $staticIndex) { + if ($this->isKeywordPlacedProperly($tokens, $staticIndex, $index)) { + $index = $staticIndex; + } else { + $this->moveTokenAndEnsureSingleSpaceFollows($tokens, $staticIndex, $index); + } + } + + if (null === $visibilityIndex) { + $tokens->insertAt($index, [new Token([T_PUBLIC, 'public']), new Token([T_WHITESPACE, ' '])]); + } else { + if ($tokens[$visibilityIndex]->isGivenKind(T_VAR)) { + $tokens[$visibilityIndex] = new Token([T_PUBLIC, 'public']); + } + if ($this->isKeywordPlacedProperly($tokens, $visibilityIndex, $index)) { + $index = $visibilityIndex; + } else { + $this->moveTokenAndEnsureSingleSpaceFollows($tokens, $visibilityIndex, $index); + } + } + + if (null === $abstractFinalIndex) { + continue; + } + + if ($this->isKeywordPlacedProperly($tokens, $abstractFinalIndex, $index)) { + continue; + } + + $this->moveTokenAndEnsureSingleSpaceFollows($tokens, $abstractFinalIndex, $index); + } + } + + /** + * @param int $keywordIndex + * @param int $comparedIndex + * + * @return bool + */ + private function isKeywordPlacedProperly(Tokens $tokens, $keywordIndex, $comparedIndex) + { + return $keywordIndex + 2 === $comparedIndex && ' ' === $tokens[$keywordIndex + 1]->getContent(); + } + + /** + * @param int $fromIndex + * @param int $toIndex + */ + private function moveTokenAndEnsureSingleSpaceFollows(Tokens $tokens, $fromIndex, $toIndex) + { + $tokens->insertAt($toIndex, [$tokens[$fromIndex], new Token([T_WHITESPACE, ' '])]); + + $tokens->clearAt($fromIndex); + if ($tokens[$fromIndex + 1]->isWhitespace()) { + $tokens->clearAt($fromIndex + 1); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassUsage/DateTimeImmutableFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassUsage/DateTimeImmutableFixer.php new file mode 100644 index 0000000..53248c1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ClassUsage/DateTimeImmutableFixer.php @@ -0,0 +1,167 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ClassUsage; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Kuba Werłos <werlos@gmail.com> + */ +final class DateTimeImmutableFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Class `DateTimeImmutable` should be used instead of `DateTime`.', + [new CodeSample("<?php\nnew DateTime();\n")], + null, + 'Risky when the code relies on modifying `DateTime` objects or if any of the `date_create*` functions are overridden.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $isInNamespace = false; + $isImported = false; // e.g. use DateTime; + + for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { + $token = $tokens[$index]; + + if ($token->isGivenKind(T_NAMESPACE)) { + $isInNamespace = true; + + continue; + } + + if ($token->isGivenKind(T_USE) && $isInNamespace) { + $nextIndex = $tokens->getNextMeaningfulToken($index); + if ('datetime' !== strtolower($tokens[$nextIndex]->getContent())) { + continue; + } + $nextNextIndex = $tokens->getNextMeaningfulToken($nextIndex); + if ($tokens[$nextNextIndex]->equals(';')) { + $isImported = true; + } + + $index = $nextNextIndex; + + continue; + } + + if (!$token->isGivenKind(T_STRING)) { + continue; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prevIndex]->isGivenKind(T_FUNCTION)) { + continue; + } + + $lowercaseContent = strtolower($token->getContent()); + + if ('datetime' === $lowercaseContent) { + $this->fixClassUsage($tokens, $index, $isInNamespace, $isImported); + $limit = $tokens->count(); // update limit, as fixing class usage may insert new token + } elseif ('date_create' === $lowercaseContent) { + $this->fixFunctionUsage($tokens, $index, 'date_create_immutable'); + } elseif ('date_create_from_format' === $lowercaseContent) { + $this->fixFunctionUsage($tokens, $index, 'date_create_immutable_from_format'); + } + } + } + + /** + * @param int $index + * @param bool $isInNamespace + * @param bool $isImported + */ + private function fixClassUsage(Tokens $tokens, $index, $isInNamespace, $isImported) + { + $nextIndex = $tokens->getNextMeaningfulToken($index); + if ($tokens[$nextIndex]->isGivenKind(T_DOUBLE_COLON)) { + $nextNextIndex = $tokens->getNextMeaningfulToken($nextIndex); + if ($tokens[$nextNextIndex]->isGivenKind(T_STRING)) { + $nextNextNextIndex = $tokens->getNextMeaningfulToken($nextNextIndex); + if (!$tokens[$nextNextNextIndex]->equals('(')) { + return; + } + } + } + + $isUsedAlone = false; // e.g. new DateTime(); + $isUsedWithLeadingBackslash = false; // e.g. new \DateTime(); + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + $prevPrevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + if (!$tokens[$prevPrevIndex]->isGivenKind(T_STRING)) { + $isUsedWithLeadingBackslash = true; + } + } elseif (!$tokens[$prevIndex]->isGivenKind(T_DOUBLE_COLON) && !$tokens[$prevIndex]->isObjectOperator()) { + $isUsedAlone = true; + } + + if ($isUsedWithLeadingBackslash || $isUsedAlone && ($isInNamespace && $isImported || !$isInNamespace)) { + $tokens[$index] = new Token([T_STRING, \DateTimeImmutable::class]); + if ($isInNamespace && $isUsedAlone) { + $tokens->insertAt($index, new Token([T_NS_SEPARATOR, '\\'])); + } + } + } + + /** + * @param int $index + * @param string $replacement + */ + private function fixFunctionUsage(Tokens $tokens, $index, $replacement) + { + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prevIndex]->isGivenKind([T_DOUBLE_COLON, T_NEW]) || $tokens[$prevIndex]->isObjectOperator()) { + return; + } + if ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + $prevPrevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + if ($tokens[$prevPrevIndex]->isGivenKind([T_NEW, T_STRING])) { + return; + } + } + + $tokens[$index] = new Token([T_STRING, $replacement]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/CommentToPhpdocFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/CommentToPhpdocFixer.php new file mode 100644 index 0000000..5e463ea --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/CommentToPhpdocFixer.php @@ -0,0 +1,240 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Comment; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\CommentsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Utils; + +/** + * @author Kuba Werłos <werlos@gmail.com> + */ +final class CommentToPhpdocFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @var string[] + */ + private $ignoredTags = []; + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_COMMENT); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + * + * Must run before GeneralPhpdocAnnotationRemoveFixer, GeneralPhpdocTagRenameFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocInlineTagFixer, PhpdocInlineTagNormalizerFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocTagCasingFixer, PhpdocTagTypeFixer, PhpdocToCommentFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run after AlignMultilineCommentFixer. + */ + public function getPriority() + { + // Should be run before all other PHPDoc fixers + return 26; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Comments with annotation should be docblock when used on structural elements.', + [ + new CodeSample("<?php /* header */ \$x = true; /* @var bool \$isFoo */ \$isFoo = true;\n"), + new CodeSample("<?php\n// @todo do something later\n\$foo = 1;\n\n// @var int \$a\n\$a = foo();\n", ['ignored_tags' => ['todo']]), + ], + null, + 'Risky as new docblocks might mean more, e.g. a Doctrine entity might have a new column in database.' + ); + } + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->ignoredTags = array_map( + static function ($tag) { + return strtolower($tag); + }, + $this->configuration['ignored_tags'] + ); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('ignored_tags', 'List of ignored tags')) + ->setAllowedTypes(['array']) + ->setDefault([]) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $commentsAnalyzer = new CommentsAnalyzer(); + + for ($index = 0, $limit = \count($tokens); $index < $limit; ++$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_COMMENT)) { + continue; + } + + if ($commentsAnalyzer->isHeaderComment($tokens, $index)) { + continue; + } + + if (!$commentsAnalyzer->isBeforeStructuralElement($tokens, $index)) { + continue; + } + + $commentIndices = $commentsAnalyzer->getCommentBlockIndices($tokens, $index); + + if ($this->isCommentCandidate($tokens, $commentIndices)) { + $this->fixComment($tokens, $commentIndices); + } + + $index = max($commentIndices); + } + } + + /** + * @param int[] $indices + * + * @return bool + */ + private function isCommentCandidate(Tokens $tokens, array $indices) + { + return array_reduce( + $indices, + function ($carry, $index) use ($tokens) { + if ($carry) { + return true; + } + if (1 !== Preg::match('~(?:#|//|/\*+|\R(?:\s*\*)?)\s*\@([a-zA-Z0-9_\\\\-]+)(?=\s|\(|$)~', $tokens[$index]->getContent(), $matches)) { + return false; + } + + return !\in_array(strtolower($matches[1]), $this->ignoredTags, true); + }, + false + ); + } + + /** + * @param int[] $indices + */ + private function fixComment(Tokens $tokens, $indices) + { + if (1 === \count($indices)) { + $this->fixCommentSingleLine($tokens, reset($indices)); + } else { + $this->fixCommentMultiLine($tokens, $indices); + } + } + + /** + * @param int $index + */ + private function fixCommentSingleLine(Tokens $tokens, $index) + { + $message = $this->getMessage($tokens[$index]->getContent()); + + if ('' !== trim(substr($message, 0, 1))) { + $message = ' '.$message; + } + + if ('' !== trim(substr($message, -1))) { + $message .= ' '; + } + + $tokens[$index] = new Token([T_DOC_COMMENT, '/**'.$message.'*/']); + } + + /** + * @param int[] $indices + */ + private function fixCommentMultiLine(Tokens $tokens, array $indices) + { + $startIndex = reset($indices); + $indent = Utils::calculateTrailingWhitespaceIndent($tokens[$startIndex - 1]); + + $newContent = '/**'.$this->whitespacesConfig->getLineEnding(); + $count = max($indices); + + for ($index = $startIndex; $index <= $count; ++$index) { + if (!$tokens[$index]->isComment()) { + continue; + } + if (false !== strpos($tokens[$index]->getContent(), '*/')) { + return; + } + $message = $this->getMessage($tokens[$index]->getContent()); + if ('' !== trim(substr($message, 0, 1))) { + $message = ' '.$message; + } + $newContent .= $indent.' *'.$message.$this->whitespacesConfig->getLineEnding(); + } + + for ($index = $startIndex; $index <= $count; ++$index) { + $tokens->clearAt($index); + } + + $newContent .= $indent.' */'; + + $tokens->insertAt($startIndex, new Token([T_DOC_COMMENT, $newContent])); + } + + private function getMessage($content) + { + if (0 === strpos($content, '#')) { + return substr($content, 1); + } + if (0 === strpos($content, '//')) { + return substr($content, 2); + } + + return rtrim(ltrim($content, '/*'), '*/'); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/HashToSlashCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/HashToSlashCommentFixer.php new file mode 100644 index 0000000..62a3161 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/HashToSlashCommentFixer.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Comment; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * Changes single comments prefixes '#' with '//'. + * + * @author SpacePossum + * + * @deprecated in 2.4, proxy to SingleLineCommentStyleFixer + */ +final class HashToSlashCommentFixer extends AbstractProxyFixer implements DeprecatedFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Single line comments should use double slashes `//` and not hash `#`.', + [new CodeSample("<?php # comment\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + $fixer = new SingleLineCommentStyleFixer(); + $fixer->configure(['comment_types' => ['hash']]); + + return [$fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/HeaderCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/HeaderCommentFixer.php new file mode 100644 index 0000000..b5a9a36 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/HeaderCommentFixer.php @@ -0,0 +1,493 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Comment; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\AliasedFixerOptionBuilder; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Options; + +/** + * @author Antonio J. García Lagar <aj@garcialagar.es> + * @author SpacePossum + */ +final class HeaderCommentFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + const HEADER_PHPDOC = 'PHPDoc'; + const HEADER_COMMENT = 'comment'; + + /** @deprecated will be removed in 3.0 */ + const HEADER_LOCATION_AFTER_OPEN = 1; + + /** @deprecated will be removed in 3.0 */ + const HEADER_LOCATION_AFTER_DECLARE_STRICT = 2; + + /** @deprecated will be removed in 3.0 */ + const HEADER_LINE_SEPARATION_BOTH = 1; + + /** @deprecated will be removed in 3.0 */ + const HEADER_LINE_SEPARATION_TOP = 2; + + /** @deprecated will be removed in 3.0 */ + const HEADER_LINE_SEPARATION_BOTTOM = 3; + + /** @deprecated will be removed in 3.0 */ + const HEADER_LINE_SEPARATION_NONE = 4; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Add, replace or remove header comment.', + [ + new CodeSample( + '<?php +declare(strict_types=1); + +namespace A\B; + +echo 1; +', + [ + 'header' => 'Made with love.', + ] + ), + new CodeSample( + '<?php +declare(strict_types=1); + +namespace A\B; + +echo 1; +', + [ + 'header' => 'Made with love.', + 'comment_type' => 'PHPDoc', + 'location' => 'after_open', + 'separate' => 'bottom', + ] + ), + new CodeSample( + '<?php +declare(strict_types=1); + +namespace A\B; + +echo 1; +', + [ + 'header' => 'Made with love.', + 'comment_type' => 'comment', + 'location' => 'after_declare_strict', + ] + ), + new CodeSample( + '<?php +declare(strict_types=1); + +/* + * Comment is not wanted here. + */ + +namespace A\B; + +echo 1; +', + [ + 'header' => '', + ] + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return isset($tokens[0]) && $tokens[0]->isGivenKind(T_OPEN_TAG) && $tokens->isMonolithicPhp(); + } + + /** + * {@inheritdoc} + * + * Must run before SingleLineCommentStyleFixer. + * Must run after DeclareStrictTypesFixer, NoBlankLinesAfterPhpdocFixer. + */ + public function getPriority() + { + // When this fixer is configured with ["separate" => "bottom", "comment_type" => "PHPDoc"] + // and the target file has no namespace or declare() construct, + // the fixed header comment gets trimmed by NoBlankLinesAfterPhpdocFixer if we run before it. + return -30; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $location = $this->configuration['location']; + $locationIndexes = []; + + foreach (['after_open', 'after_declare_strict'] as $possibleLocation) { + $locationIndex = $this->findHeaderCommentInsertionIndex($tokens, $possibleLocation); + + if (!isset($locationIndexes[$locationIndex]) || $possibleLocation === $location) { + $locationIndexes[$locationIndex] = $possibleLocation; + + continue; + } + } + + foreach (array_values($locationIndexes) as $possibleLocation) { + // figure out where the comment should be placed + $headerNewIndex = $this->findHeaderCommentInsertionIndex($tokens, $possibleLocation); + + // check if there is already a comment + $headerCurrentIndex = $this->findHeaderCommentCurrentIndex($tokens, $headerNewIndex - 1); + + if (null === $headerCurrentIndex) { + if ('' === $this->configuration['header'] || $possibleLocation !== $location) { + continue; + } + + $this->insertHeader($tokens, $headerNewIndex); + + continue; + } + + $sameComment = $this->getHeaderAsComment() === $tokens[$headerCurrentIndex]->getContent(); + $expectedLocation = $possibleLocation === $location; + + if (!$sameComment || !$expectedLocation) { + if ($expectedLocation ^ $sameComment) { + $this->removeHeader($tokens, $headerCurrentIndex); + } + + if ('' === $this->configuration['header']) { + continue; + } + + if ($possibleLocation === $location) { + $this->insertHeader($tokens, $headerNewIndex); + } + + continue; + } + + $this->fixWhiteSpaceAroundHeader($tokens, $headerCurrentIndex); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $fixerName = $this->getName(); + + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('header', 'Proper header content.')) + ->setAllowedTypes(['string']) + ->setNormalizer(static function (Options $options, $value) use ($fixerName) { + if ('' === trim($value)) { + return ''; + } + + if (false !== strpos($value, '*/')) { + throw new InvalidFixerConfigurationException($fixerName, 'Cannot use \'*/\' in header.'); + } + + return $value; + }) + ->getOption(), + (new AliasedFixerOptionBuilder( + new FixerOptionBuilder('comment_type', 'Comment syntax type.'), + 'commentType' + )) + ->setAllowedValues([self::HEADER_PHPDOC, self::HEADER_COMMENT]) + ->setDefault(self::HEADER_COMMENT) + ->getOption(), + (new FixerOptionBuilder('location', 'The location of the inserted header.')) + ->setAllowedValues(['after_open', 'after_declare_strict']) + ->setDefault('after_declare_strict') + ->getOption(), + (new FixerOptionBuilder('separate', 'Whether the header should be separated from the file content with a new line.')) + ->setAllowedValues(['both', 'top', 'bottom', 'none']) + ->setDefault('both') + ->getOption(), + ]); + } + + /** + * Enclose the given text in a comment block. + * + * @return string + */ + private function getHeaderAsComment() + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + $comment = (self::HEADER_COMMENT === $this->configuration['comment_type'] ? '/*' : '/**').$lineEnding; + $lines = explode("\n", str_replace("\r", '', $this->configuration['header'])); + + foreach ($lines as $line) { + $comment .= rtrim(' * '.$line).$lineEnding; + } + + return $comment.' */'; + } + + /** + * @param int $headerNewIndex + * + * @return null|int + */ + private function findHeaderCommentCurrentIndex(Tokens $tokens, $headerNewIndex) + { + $index = $tokens->getNextNonWhitespace($headerNewIndex); + + if (null === $index || !$tokens[$index]->isComment()) { + return null; + } + + $next = $index + 1; + + if (!isset($tokens[$next]) || \in_array($this->configuration['separate'], ['top', 'none'], true) || !$tokens[$index]->isGivenKind(T_DOC_COMMENT)) { + return $index; + } + + if ($tokens[$next]->isWhitespace()) { + if (!Preg::match('/^\h*\R\h*$/D', $tokens[$next]->getContent())) { + return $index; + } + + ++$next; + } + + if (!isset($tokens[$next]) || !$tokens[$next]->isClassy() && !$tokens[$next]->isGivenKind(T_FUNCTION)) { + return $index; + } + + return $this->getHeaderAsComment() === $tokens[$index]->getContent() ? $index : null; + } + + /** + * Find the index where the header comment must be inserted. + * + * @param string $location + * + * @return int + */ + private function findHeaderCommentInsertionIndex(Tokens $tokens, $location) + { + if ('after_open' === $location) { + return 1; + } + + $index = $tokens->getNextMeaningfulToken(0); + + if (null === $index) { + return 1; // file without meaningful tokens but an open tag, comment should always be placed directly after the open tag + } + + if (!$tokens[$index]->isGivenKind(T_DECLARE)) { + return 1; + } + + $next = $tokens->getNextMeaningfulToken($index); + + if (null === $next || !$tokens[$next]->equals('(')) { + return 1; + } + + $next = $tokens->getNextMeaningfulToken($next); + + if (null === $next || !$tokens[$next]->equals([T_STRING, 'strict_types'], false)) { + return 1; + } + + $next = $tokens->getNextMeaningfulToken($next); + + if (null === $next || !$tokens[$next]->equals('=')) { + return 1; + } + + $next = $tokens->getNextMeaningfulToken($next); + + if (null === $next || !$tokens[$next]->isGivenKind(T_LNUMBER)) { + return 1; + } + + $next = $tokens->getNextMeaningfulToken($next); + + if (null === $next || !$tokens[$next]->equals(')')) { + return 1; + } + + $next = $tokens->getNextMeaningfulToken($next); + + if (null === $next || !$tokens[$next]->equals(';')) { // don't insert after close tag + return 1; + } + + return $next + 1; + } + + /** + * @param int $headerIndex + */ + private function fixWhiteSpaceAroundHeader(Tokens $tokens, $headerIndex) + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + // fix lines after header comment + if ( + ('both' === $this->configuration['separate'] || 'bottom' === $this->configuration['separate']) + && null !== $tokens->getNextMeaningfulToken($headerIndex) + ) { + $expectedLineCount = 2; + } else { + $expectedLineCount = 1; + } + + if ($headerIndex === \count($tokens) - 1) { + $tokens->insertAt($headerIndex + 1, new Token([T_WHITESPACE, str_repeat($lineEnding, $expectedLineCount)])); + } else { + $lineBreakCount = $this->getLineBreakCount($tokens, $headerIndex, 1); + + if ($lineBreakCount < $expectedLineCount) { + $missing = str_repeat($lineEnding, $expectedLineCount - $lineBreakCount); + + if ($tokens[$headerIndex + 1]->isWhitespace()) { + $tokens[$headerIndex + 1] = new Token([T_WHITESPACE, $missing.$tokens[$headerIndex + 1]->getContent()]); + } else { + $tokens->insertAt($headerIndex + 1, new Token([T_WHITESPACE, $missing])); + } + } elseif ($lineBreakCount > $expectedLineCount && $tokens[$headerIndex + 1]->isWhitespace()) { + $newLinesToRemove = $lineBreakCount - $expectedLineCount; + $tokens[$headerIndex + 1] = new Token([ + T_WHITESPACE, + Preg::replace("/^\\R{{$newLinesToRemove}}/", '', $tokens[$headerIndex + 1]->getContent()), + ]); + } + } + + // fix lines before header comment + $expectedLineCount = 'both' === $this->configuration['separate'] || 'top' === $this->configuration['separate'] ? 2 : 1; + $prev = $tokens->getPrevNonWhitespace($headerIndex); + + $regex = '/\h$/'; + + if ($tokens[$prev]->isGivenKind(T_OPEN_TAG) && Preg::match($regex, $tokens[$prev]->getContent())) { + $tokens[$prev] = new Token([T_OPEN_TAG, Preg::replace($regex, $lineEnding, $tokens[$prev]->getContent())]); + } + + $lineBreakCount = $this->getLineBreakCount($tokens, $headerIndex, -1); + + if ($lineBreakCount < $expectedLineCount) { + // because of the way the insert index was determined for header comment there cannot be an empty token here + $tokens->insertAt($headerIndex, new Token([T_WHITESPACE, str_repeat($lineEnding, $expectedLineCount - $lineBreakCount)])); + } + } + + /** + * @param int $index + * @param int $direction + * + * @return int + */ + private function getLineBreakCount(Tokens $tokens, $index, $direction) + { + $whitespace = ''; + + for ($index += $direction; isset($tokens[$index]); $index += $direction) { + $token = $tokens[$index]; + + if ($token->isWhitespace()) { + $whitespace .= $token->getContent(); + + continue; + } + + if (-1 === $direction && $token->isGivenKind(T_OPEN_TAG)) { + $whitespace .= $token->getContent(); + } + + if ('' !== $token->getContent()) { + break; + } + } + + return substr_count($whitespace, "\n"); + } + + private function removeHeader(Tokens $tokens, $index) + { + $prevIndex = $index - 1; + $prevToken = $tokens[$prevIndex]; + $newlineRemoved = false; + + if ($prevToken->isWhitespace()) { + $content = $prevToken->getContent(); + + if (Preg::match('/\R/', $content)) { + $newlineRemoved = true; + } + + $content = Preg::replace('/\R?\h*$/', '', $content); + + if ('' === $content) { + $tokens->clearAt($prevIndex); + } else { + $tokens[$prevIndex] = new Token([T_WHITESPACE, $content]); + } + } + + $nextIndex = $index + 1; + $nextToken = isset($tokens[$nextIndex]) ? $tokens[$nextIndex] : null; + + if (!$newlineRemoved && null !== $nextToken && $nextToken->isWhitespace()) { + $content = Preg::replace('/^\R/', '', $nextToken->getContent()); + + if ('' === $content) { + $tokens->clearAt($nextIndex); + } else { + $tokens[$nextIndex] = new Token([T_WHITESPACE, $content]); + } + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } + + /** + * @param int $index + */ + private function insertHeader(Tokens $tokens, $index) + { + $tokens->insertAt($index, new Token([self::HEADER_COMMENT === $this->configuration['comment_type'] ? T_COMMENT : T_DOC_COMMENT, $this->getHeaderAsComment()])); + $this->fixWhiteSpaceAroundHeader($tokens, $index); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/MultilineCommentOpeningClosingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/MultilineCommentOpeningClosingFixer.php new file mode 100644 index 0000000..0d79ec6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/MultilineCommentOpeningClosingFixer.php @@ -0,0 +1,95 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Comment; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class MultilineCommentOpeningClosingFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'DocBlocks must start with two asterisks, multiline comments must start with a single asterisk, after the opening slash. Both must end with a single asterisk before the closing slash.', + [ + new CodeSample( + <<<'EOT' +<?php + +/****** + * Multiline comment with arbitrary asterisks count + ******/ + +/**\ + * Multiline comment that seems a DocBlock + */ + +/** + * DocBlock with arbitrary asterisk count at the end + **/ + +EOT + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_COMMENT, T_DOC_COMMENT]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + $originalContent = $token->getContent(); + + if ( + !$token->isGivenKind(T_DOC_COMMENT) + && !($token->isGivenKind(T_COMMENT) && 0 === strpos($originalContent, '/*')) + ) { + continue; + } + + $newContent = $originalContent; + + // Fix opening + if ($token->isGivenKind(T_COMMENT)) { + $newContent = Preg::replace('/^\\/\\*{2,}(?!\\/)/', '/*', $newContent); + } + + // Fix closing + $newContent = Preg::replace('/(?<!\\/)\\*{2,}\\/$/', '*/', $newContent); + + if ($newContent !== $originalContent) { + $tokens[$index] = new Token([$token->getId(), $newContent]); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/NoEmptyCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/NoEmptyCommentFixer.php new file mode 100644 index 0000000..c6873e7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/NoEmptyCommentFixer.php @@ -0,0 +1,173 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Comment; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class NoEmptyCommentFixer extends AbstractFixer +{ + const TYPE_HASH = 1; + const TYPE_DOUBLE_SLASH = 2; + const TYPE_SLASH_ASTERISK = 3; + + /** + * {@inheritdoc} + * + * Must run before NoExtraBlankLinesFixer, NoTrailingWhitespaceFixer, NoWhitespaceInBlankLineFixer. + * Must run after PhpdocToCommentFixer. + */ + public function getPriority() + { + return 2; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There should not be any empty comments.', + [new CodeSample("<?php\n//\n#\n/* */\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = 1, $count = \count($tokens); $index < $count; ++$index) { + if (!$tokens[$index]->isGivenKind(T_COMMENT)) { + continue; + } + + list($blockStart, $index, $isEmpty) = $this->getCommentBlock($tokens, $index); + if (false === $isEmpty) { + continue; + } + + for ($i = $blockStart; $i <= $index; ++$i) { + $tokens->clearTokenAndMergeSurroundingWhitespace($i); + } + } + } + + /** + * Return the start index, end index and a flag stating if the comment block is empty. + * + * @param int $index T_COMMENT index + * + * @return array + */ + private function getCommentBlock(Tokens $tokens, $index) + { + $commentType = $this->getCommentType($tokens[$index]->getContent()); + $empty = $this->isEmptyComment($tokens[$index]->getContent()); + + if (self::TYPE_SLASH_ASTERISK === $commentType) { + return [$index, $index, $empty]; + } + + $start = $index; + $count = \count($tokens); + ++$index; + + for (; $index < $count; ++$index) { + if ($tokens[$index]->isComment()) { + if ($commentType !== $this->getCommentType($tokens[$index]->getContent())) { + break; + } + + if ($empty) { // don't retest if already known the block not being empty + $empty = $this->isEmptyComment($tokens[$index]->getContent()); + } + + continue; + } + + if (!$tokens[$index]->isWhitespace() || $this->getLineBreakCount($tokens, $index, $index + 1) > 1) { + break; + } + } + + return [$start, $index - 1, $empty]; + } + + /** + * @param string $content + * + * @return int + */ + private function getCommentType($content) + { + if ('#' === $content[0]) { + return self::TYPE_HASH; + } + + if ('*' === $content[1]) { + return self::TYPE_SLASH_ASTERISK; + } + + return self::TYPE_DOUBLE_SLASH; + } + + /** + * @param int $whiteStart + * @param int $whiteEnd + * + * @return int + */ + private function getLineBreakCount(Tokens $tokens, $whiteStart, $whiteEnd) + { + $lineCount = 0; + for ($i = $whiteStart; $i < $whiteEnd; ++$i) { + $lineCount += Preg::matchAll('/\R/u', $tokens[$i]->getContent(), $matches); + } + + return $lineCount; + } + + /** + * @param string $content + * + * @return bool + */ + private function isEmptyComment($content) + { + static $mapper = [ + self::TYPE_HASH => '|^#\s*$|', // single line comment starting with '#' + self::TYPE_SLASH_ASTERISK => '|^/\*[\s\*]*\*+/$|', // comment starting with '/*' and ending with '*/' (but not a PHPDoc) + self::TYPE_DOUBLE_SLASH => '|^//\s*$|', // single line comment starting with '//' + ]; + + $type = $this->getCommentType($content); + + return 1 === Preg::match($mapper[$type], $content); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/NoTrailingWhitespaceInCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/NoTrailingWhitespaceInCommentFixer.php new file mode 100644 index 0000000..90da2d1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/NoTrailingWhitespaceInCommentFixer.php @@ -0,0 +1,85 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Comment; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NoTrailingWhitespaceInCommentFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There MUST be no trailing spaces inside comment or PHPDoc.', + [new CodeSample('<?php +// This is '.' +// a comment. '.' +')] + ); + } + + /** + * {@inheritdoc} + * + * Must run after PhpdocNoUselessInheritdocFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_COMMENT, T_DOC_COMMENT]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if ($token->isGivenKind(T_DOC_COMMENT)) { + $tokens[$index] = new Token([T_DOC_COMMENT, Preg::replace('/(*ANY)[\h]+$/m', '', $token->getContent())]); + + continue; + } + + if ($token->isGivenKind(T_COMMENT)) { + if ('/*' === substr($token->getContent(), 0, 2)) { + $tokens[$index] = new Token([T_COMMENT, Preg::replace('/(*ANY)[\h]+$/m', '', $token->getContent())]); + } elseif (isset($tokens[$index + 1]) && $tokens[$index + 1]->isWhitespace()) { + $trimmedContent = ltrim($tokens[$index + 1]->getContent(), " \t"); + if ('' !== $trimmedContent) { + $tokens[$index + 1] = new Token([T_WHITESPACE, $trimmedContent]); + } else { + $tokens->clearAt($index + 1); + } + } + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/SingleLineCommentStyleFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/SingleLineCommentStyleFixer.php new file mode 100644 index 0000000..9be26a0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Comment/SingleLineCommentStyleFixer.php @@ -0,0 +1,182 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Comment; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class SingleLineCommentStyleFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var bool + */ + private $asteriskEnabled; + + /** + * @var bool + */ + private $hashEnabled; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->asteriskEnabled = \in_array('asterisk', $this->configuration['comment_types'], true); + $this->hashEnabled = \in_array('hash', $this->configuration['comment_types'], true); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Single-line comments and multi-line comments with only one line of actual content should use the `//` syntax.', + [ + new CodeSample( + '<?php +/* asterisk comment */ +$a = 1; + +# hash comment +$b = 2; + +/* + * multi-line + * comment + */ +$c = 3; +' + ), + new CodeSample( + '<?php +/* first comment */ +$a = 1; + +/* + * second comment + */ +$b = 2; + +/* + * third + * comment + */ +$c = 3; +', + ['comment_types' => ['asterisk']] + ), + new CodeSample( + "<?php # comment\n", + ['comment_types' => ['hash']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after HeaderCommentFixer, NoUselessReturnFixer. + */ + public function getPriority() + { + return -31; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_COMMENT)) { + continue; + } + + $content = $token->getContent(); + $commentContent = substr($content, 2, -2) ?: ''; + + if ($this->hashEnabled && '#' === $content[0]) { + if (isset($content[1]) && '[' === $content[1]) { + continue; // This might be attribute on PHP8, do not change + } + + $tokens[$index] = new Token([$token->getId(), '//'.substr($content, 1)]); + + continue; + } + + if ( + !$this->asteriskEnabled + || false !== strpos($commentContent, '?>') + || '/*' !== substr($content, 0, 2) + || 1 === Preg::match('/[^\s\*].*\R.*[^\s\*]/s', $commentContent) + ) { + continue; + } + + $nextTokenIndex = $index + 1; + if (isset($tokens[$nextTokenIndex])) { + $nextToken = $tokens[$nextTokenIndex]; + if (!$nextToken->isWhitespace() || 1 !== Preg::match('/\R/', $nextToken->getContent())) { + continue; + } + + $tokens[$nextTokenIndex] = new Token([$nextToken->getId(), ltrim($nextToken->getContent(), " \t")]); + } + + $content = '//'; + if (1 === Preg::match('/[^\s\*]/', $commentContent)) { + $content = '// '.Preg::replace('/[\s\*]*([^\s\*](?:.+[^\s\*])?)[\s\*]*/', '\1', $commentContent); + } + $tokens[$index] = new Token([$token->getId(), $content]); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('comment_types', 'List of comment types to fix')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset(['asterisk', 'hash'])]) + ->setDefault(['asterisk', 'hash']) + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ConfigurableFixerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ConfigurableFixerInterface.php new file mode 100644 index 0000000..31c4b44 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ConfigurableFixerInterface.php @@ -0,0 +1,51 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer; + +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + * + * @todo Will incorporate `ConfigurationDefinitionFixerInterface` in 3.0 + */ +interface ConfigurableFixerInterface extends FixerInterface +{ + /** + * Set configuration. + * + * New configuration must override current one, not patch it. + * Using `null` makes fixer to use default configuration (or reset configuration from previously configured back + * to default one). + * + * Some fixers may have no configuration, then - simply pass null. + * Other ones may have configuration that will change behavior of fixer, + * eg `php_unit_strict` fixer allows to configure which methods should be fixed. + * Finally, some fixers need configuration to work, eg `header_comment`. + * + * @param null|array $configuration configuration depends on Fixer + * + * @throws InvalidFixerConfigurationException + */ + public function configure(array $configuration = null); + + /* + * Defines the available configuration options of the fixer. + * + * @return FixerConfigurationResolverInterface + * + * @todo uncomment at 3.0 + */ + // public function getConfigurationDefinition(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ConfigurationDefinitionFixerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ConfigurationDefinitionFixerInterface.php new file mode 100644 index 0000000..1512940 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ConfigurationDefinitionFixerInterface.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer; + +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; + +/** + * @deprecated Will be incorporated into `ConfigurableFixerInterface` in 3.0 + */ +interface ConfigurationDefinitionFixerInterface extends ConfigurableFixerInterface +{ + /** + * Defines the available configuration options of the fixer. + * + * @return FixerConfigurationResolverInterface + */ + public function getConfigurationDefinition(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ConstantNotation/NativeConstantInvocationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ConstantNotation/NativeConstantInvocationFixer.php new file mode 100644 index 0000000..4da8cbf --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ConstantNotation/NativeConstantInvocationFixer.php @@ -0,0 +1,295 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ConstantNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class NativeConstantInvocationFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var array<string, true> + */ + private $constantsToEscape = []; + + /** + * @var array<string, true> + */ + private $caseInsensitiveConstantsToEscape = []; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Add leading `\` before constant invocation of internal constant to speed up resolving. Constant name match is case-sensitive, except for `null`, `false` and `true`.', + [ + new CodeSample("<?php var_dump(PHP_VERSION, M_PI, MY_CUSTOM_PI);\n"), + new CodeSample( + '<?php +namespace space1 { + echo PHP_VERSION; +} +namespace { + echo M_PI; +} +', + ['scope' => 'namespaced'] + ), + new CodeSample( + "<?php var_dump(PHP_VERSION, M_PI, MY_CUSTOM_PI);\n", + [ + 'include' => [ + 'MY_CUSTOM_PI', + ], + ] + ), + new CodeSample( + "<?php var_dump(PHP_VERSION, M_PI, MY_CUSTOM_PI);\n", + [ + 'fix_built_in' => false, + 'include' => [ + 'MY_CUSTOM_PI', + ], + ] + ), + new CodeSample( + "<?php var_dump(PHP_VERSION, M_PI, MY_CUSTOM_PI);\n", + [ + 'exclude' => [ + 'M_PI', + ], + ] + ), + ], + null, + 'Risky when any of the constants are namespaced or overridden.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before GlobalNamespaceImportFixer. + */ + public function getPriority() + { + return 10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $uniqueConfiguredExclude = array_unique($this->configuration['exclude']); + + // Case sensitive constants handling + $constantsToEscape = array_values($this->configuration['include']); + if (true === $this->configuration['fix_built_in']) { + $getDefinedConstants = get_defined_constants(true); + unset($getDefinedConstants['user']); + foreach ($getDefinedConstants as $constants) { + $constantsToEscape = array_merge($constantsToEscape, array_keys($constants)); + } + } + $constantsToEscape = array_diff( + array_unique($constantsToEscape), + $uniqueConfiguredExclude + ); + + // Case insensitive constants handling + static $caseInsensitiveConstants = ['null', 'false', 'true']; + $caseInsensitiveConstantsToEscape = []; + foreach ($constantsToEscape as $constantIndex => $constant) { + $loweredConstant = strtolower($constant); + if (\in_array($loweredConstant, $caseInsensitiveConstants, true)) { + $caseInsensitiveConstantsToEscape[] = $loweredConstant; + unset($constantsToEscape[$constantIndex]); + } + } + + $caseInsensitiveConstantsToEscape = array_diff( + array_unique($caseInsensitiveConstantsToEscape), + array_map(static function ($function) { return strtolower($function); }, $uniqueConfiguredExclude) + ); + + // Store the cache + $this->constantsToEscape = array_fill_keys($constantsToEscape, true); + ksort($this->constantsToEscape); + + $this->caseInsensitiveConstantsToEscape = array_fill_keys($caseInsensitiveConstantsToEscape, true); + ksort($this->caseInsensitiveConstantsToEscape); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if ('all' === $this->configuration['scope']) { + $this->fixConstantInvocations($tokens, 0, \count($tokens) - 1); + + return; + } + + $namespaces = (new NamespacesAnalyzer())->getDeclarations($tokens); + + // 'scope' is 'namespaced' here + /** @var NamespaceAnalysis $namespace */ + foreach (array_reverse($namespaces) as $namespace) { + if ('' === $namespace->getFullName()) { + continue; + } + + $this->fixConstantInvocations($tokens, $namespace->getScopeStartIndex(), $namespace->getScopeEndIndex()); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $constantChecker = static function ($value) { + foreach ($value as $constantName) { + if (!\is_string($constantName) || '' === trim($constantName) || trim($constantName) !== $constantName) { + throw new InvalidOptionsException(sprintf( + 'Each element must be a non-empty, trimmed string, got "%s" instead.', + \is_object($constantName) ? \get_class($constantName) : \gettype($constantName) + )); + } + } + + return true; + }; + + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('fix_built_in', 'Whether to fix constants returned by `get_defined_constants`. User constants are not accounted in this list and must be specified in the include one.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('include', 'List of additional constants to fix.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([$constantChecker]) + ->setDefault([]) + ->getOption(), + (new FixerOptionBuilder('exclude', 'List of constants to ignore.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([$constantChecker]) + ->setDefault(['null', 'false', 'true']) + ->getOption(), + (new FixerOptionBuilder('scope', 'Only fix constant invocations that are made within a namespace or fix all.')) + ->setAllowedValues(['all', 'namespaced']) + ->setDefault('all') + ->getOption(), + (new FixerOptionBuilder('strict', 'Whether leading `\` of constant invocation not meant to have it should be removed.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) // @TODO: 3.0 change to true as default + ->getOption(), + ]); + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function fixConstantInvocations(Tokens $tokens, $startIndex, $endIndex) + { + $useDeclarations = (new NamespaceUsesAnalyzer())->getDeclarationsFromTokens($tokens); + $useConstantDeclarations = []; + foreach ($useDeclarations as $use) { + if ($use->isConstant()) { + $useConstantDeclarations[$use->getShortName()] = true; + } + } + + $tokenAnalyzer = new TokensAnalyzer($tokens); + + for ($index = $endIndex; $index > $startIndex; --$index) { + $token = $tokens[$index]; + + // test if we are at a constant call + if (!$token->isGivenKind(T_STRING)) { + continue; + } + + if (!$tokenAnalyzer->isConstantInvocation($index)) { + continue; + } + + $tokenContent = $token->getContent(); + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + + if (!isset($this->constantsToEscape[$tokenContent]) && !isset($this->caseInsensitiveConstantsToEscape[strtolower($tokenContent)])) { + if (!$this->configuration['strict']) { + continue; + } + if (!$tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + continue; + } + $prevPrevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + if ($tokens[$prevPrevIndex]->isGivenKind(T_STRING)) { + continue; + } + $tokens->clearTokenAndMergeSurroundingWhitespace($prevIndex); + + continue; + } + + if (isset($useConstantDeclarations[$tokenContent])) { + continue; + } + + if ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + continue; + } + + $tokens->insertAt($index, new Token([T_NS_SEPARATOR, '\\'])); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/ElseifFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/ElseifFixer.php new file mode 100644 index 0000000..94670ce --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/ElseifFixer.php @@ -0,0 +1,102 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR2 ¶5.1. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class ElseifFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'The keyword `elseif` should be used instead of `else if` so that all control keywords look like single words.', + [new CodeSample("<?php\nif (\$a) {\n} else if (\$b) {\n}\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer. + * Must run after NoAlternativeSyntaxFixer. + */ + public function getPriority() + { + return 40; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_IF, T_ELSE]); + } + + /** + * Replace all `else if` (T_ELSE T_IF) with `elseif` (T_ELSEIF). + * + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_ELSE)) { + continue; + } + + $ifTokenIndex = $tokens->getNextMeaningfulToken($index); + + // if next meaningful token is not T_IF - continue searching, this is not the case for fixing + if (!$tokens[$ifTokenIndex]->isGivenKind(T_IF)) { + continue; + } + + // if next meaningful token is T_IF, but uses an alternative syntax - this is not the case for fixing neither + $conditionEndBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextMeaningfulToken($ifTokenIndex)); + $afterConditionIndex = $tokens->getNextMeaningfulToken($conditionEndBraceIndex); + if ($tokens[$afterConditionIndex]->equals(':')) { + continue; + } + + // now we have T_ELSE following by T_IF with no alternative syntax so we could fix this + // 1. clear whitespaces between T_ELSE and T_IF + $tokens->clearAt($index + 1); + + // 2. change token from T_ELSE into T_ELSEIF + $tokens[$index] = new Token([T_ELSEIF, 'elseif']); + + // 3. clear succeeding T_IF + $tokens->clearAt($ifTokenIndex); + + $beforeIfTokenIndex = $tokens->getPrevNonWhitespace($ifTokenIndex); + + // 4. clear extra whitespace after T_IF in T_COMMENT,T_WHITESPACE?,T_IF,T_WHITESPACE sequence + if ($tokens[$beforeIfTokenIndex]->isComment() && $tokens[$ifTokenIndex + 1]->isWhitespace()) { + $tokens->clearAt($ifTokenIndex + 1); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/IncludeFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/IncludeFixer.php new file mode 100644 index 0000000..17de89d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/IncludeFixer.php @@ -0,0 +1,153 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\BlocksAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Sebastiaan Stok <s.stok@rollerscapes.net> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Kuba Werłos <werlos@gmail.com> + */ +final class IncludeFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Include/Require and file path should be divided with a single space. File path should not be placed under brackets.', + [ + new CodeSample( + '<?php +require ("sample1.php"); +require_once "sample2.php"; +include "sample3.php"; +include_once("sample4.php"); +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_REQUIRE, T_REQUIRE_ONCE, T_INCLUDE, T_INCLUDE_ONCE]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $this->clearIncludies($tokens, $this->findIncludies($tokens)); + } + + private function clearIncludies(Tokens $tokens, array $includies) + { + $blocksAnalyzer = new BlocksAnalyzer(); + + foreach ($includies as $includy) { + if ($includy['end'] && !$tokens[$includy['end']]->isGivenKind(T_CLOSE_TAG)) { + $afterEndIndex = $tokens->getNextNonWhitespace($includy['end']); + if (null === $afterEndIndex || !$tokens[$afterEndIndex]->isComment()) { + $tokens->removeLeadingWhitespace($includy['end']); + } + } + + $braces = $includy['braces']; + + if (null !== $braces) { + $prevIndex = $tokens->getPrevMeaningfulToken($includy['begin']); + $nextIndex = $tokens->getNextMeaningfulToken($braces['close']); + + // Include is also legal as function parameter or condition statement but requires being wrapped then. + if (!$tokens[$nextIndex]->equalsAny([';', [T_CLOSE_TAG]]) && !$blocksAnalyzer->isBlock($tokens, $prevIndex, $nextIndex)) { + continue; + } + + $this->removeWhitespaceAroundIfPossible($tokens, $braces['open']); + $this->removeWhitespaceAroundIfPossible($tokens, $braces['close']); + $tokens->clearTokenAndMergeSurroundingWhitespace($braces['open']); + $tokens->clearTokenAndMergeSurroundingWhitespace($braces['close']); + } + + $nextIndex = $tokens->getNonEmptySibling($includy['begin'], 1); + + if ($tokens[$nextIndex]->isWhitespace()) { + $tokens[$nextIndex] = new Token([T_WHITESPACE, ' ']); + } elseif (null !== $braces || $tokens[$nextIndex]->isGivenKind([T_VARIABLE, T_CONSTANT_ENCAPSED_STRING, T_COMMENT])) { + $tokens->insertAt($includy['begin'] + 1, new Token([T_WHITESPACE, ' '])); + } + } + } + + private function findIncludies(Tokens $tokens) + { + static $includyTokenKinds = [T_REQUIRE, T_REQUIRE_ONCE, T_INCLUDE, T_INCLUDE_ONCE]; + + $includies = []; + + foreach ($tokens->findGivenKind($includyTokenKinds) as $includyTokens) { + foreach ($includyTokens as $index => $token) { + $includy = [ + 'begin' => $index, + 'braces' => null, + 'end' => $tokens->getNextTokenOfKind($index, [';', [T_CLOSE_TAG]]), + ]; + + $braceOpenIndex = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$braceOpenIndex]->equals('(')) { + $braceCloseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $braceOpenIndex); + + $includy['braces'] = [ + 'open' => $braceOpenIndex, + 'close' => $braceCloseIndex, + ]; + } + + $includies[$index] = $includy; + } + } + + krsort($includies); + + return $includies; + } + + /** + * @param int $index + */ + private function removeWhitespaceAroundIfPossible(Tokens $tokens, $index) + { + $nextIndex = $tokens->getNextNonWhitespace($index); + if (null === $nextIndex || !$tokens[$nextIndex]->isComment()) { + $tokens->removeLeadingWhitespace($index); + } + + $prevIndex = $tokens->getPrevNonWhitespace($index); + if (null === $prevIndex || !$tokens[$prevIndex]->isComment()) { + $tokens->removeTrailingWhitespace($index); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoAlternativeSyntaxFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoAlternativeSyntaxFixer.php new file mode 100644 index 0000000..cc95ce7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoAlternativeSyntaxFixer.php @@ -0,0 +1,231 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Eddilbert Macharia <edd.cowan@gmail.com> + */ +final class NoAlternativeSyntaxFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replace control structure alternative syntax to use braces.', + [ + new CodeSample( + "<?php\nif(true):echo 't';else:echo 'f';endif;\n" + ), + new CodeSample( + "<?php\nwhile(true):echo 'red';endwhile;\n" + ), + new CodeSample( + "<?php\nfor(;;):echo 'xc';endfor;\n" + ), + new CodeSample( + "<?php\nforeach(array('a') as \$item):echo 'xc';endforeach;\n" + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->hasAlternativeSyntax(); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer, ElseifFixer, NoSuperfluousElseifFixer, NoUselessElseFixer, SwitchContinueToBreakFixer. + */ + public function getPriority() + { + return 42; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = \count($tokens) - 1; 0 <= $index; --$index) { + $token = $tokens[$index]; + $this->fixElseif($index, $token, $tokens); + $this->fixElse($index, $token, $tokens); + $this->fixOpenCloseControls($index, $token, $tokens); + } + } + + private function findParenthesisEnd(Tokens $tokens, $structureTokenIndex) + { + $nextIndex = $tokens->getNextMeaningfulToken($structureTokenIndex); + $nextToken = $tokens[$nextIndex]; + + // return if next token is not opening parenthesis + if (!$nextToken->equals('(')) { + return $structureTokenIndex; + } + + return $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nextIndex); + } + + /** + * Handle both extremes of the control structures. + * e.g. if(): or endif;. + * + * @param int $index the index of the token being processed + * @param Token $token the token being processed + * @param Tokens $tokens the collection of tokens + */ + private function fixOpenCloseControls($index, Token $token, Tokens $tokens) + { + if ($token->isGivenKind([T_IF, T_FOREACH, T_WHILE, T_FOR, T_SWITCH, T_DECLARE])) { + $openIndex = $tokens->getNextTokenOfKind($index, ['(']); + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); + $afterParenthesisIndex = $tokens->getNextMeaningfulToken($closeIndex); + $afterParenthesis = $tokens[$afterParenthesisIndex]; + + if (!$afterParenthesis->equals(':')) { + return; + } + + $items = []; + + if (!$tokens[$afterParenthesisIndex - 1]->isWhitespace()) { + $items[] = new Token([T_WHITESPACE, ' ']); + } + + $items[] = new Token('{'); + + if (!$tokens[$afterParenthesisIndex + 1]->isWhitespace()) { + $items[] = new Token([T_WHITESPACE, ' ']); + } + + $tokens->clearAt($afterParenthesisIndex); + $tokens->insertAt($afterParenthesisIndex, $items); + } + + if (!$token->isGivenKind([T_ENDIF, T_ENDFOREACH, T_ENDWHILE, T_ENDFOR, T_ENDSWITCH, T_ENDDECLARE])) { + return; + } + + $nextTokenIndex = $tokens->getNextMeaningfulToken($index); + $nextToken = $tokens[$nextTokenIndex]; + $tokens[$index] = new Token('}'); + + if ($nextToken->equals(';')) { + $tokens->clearAt($nextTokenIndex); + } + } + + /** + * Handle the else: cases. + * + * @param int $index the index of the token being processed + * @param Token $token the token being processed + * @param Tokens $tokens the collection of tokens + */ + private function fixElse($index, Token $token, Tokens $tokens) + { + if (!$token->isGivenKind(T_ELSE)) { + return; + } + + $tokenAfterElseIndex = $tokens->getNextMeaningfulToken($index); + $tokenAfterElse = $tokens[$tokenAfterElseIndex]; + + if (!$tokenAfterElse->equals(':')) { + return; + } + + $this->addBraces($tokens, new Token([T_ELSE, 'else']), $index, $tokenAfterElseIndex); + } + + /** + * Handle the elsif(): cases. + * + * @param int $index the index of the token being processed + * @param Token $token the token being processed + * @param Tokens $tokens the collection of tokens + */ + private function fixElseif($index, Token $token, Tokens $tokens) + { + if (!$token->isGivenKind(T_ELSEIF)) { + return; + } + + $parenthesisEndIndex = $this->findParenthesisEnd($tokens, $index); + $tokenAfterParenthesisIndex = $tokens->getNextMeaningfulToken($parenthesisEndIndex); + $tokenAfterParenthesis = $tokens[$tokenAfterParenthesisIndex]; + + if (!$tokenAfterParenthesis->equals(':')) { + return; + } + + $this->addBraces($tokens, new Token([T_ELSEIF, 'elseif']), $index, $tokenAfterParenthesisIndex); + } + + /** + * Add opening and closing braces to the else: and elseif: cases. + * + * @param Tokens $tokens the tokens collection + * @param Token $token the current token + * @param int $index the current token index + * @param int $colonIndex the index of the colon + */ + private function addBraces(Tokens $tokens, Token $token, $index, $colonIndex) + { + $items = [ + new Token('}'), + new Token([T_WHITESPACE, ' ']), + $token, + ]; + + if (!$tokens[$index + 1]->isWhitespace()) { + $items[] = new Token([T_WHITESPACE, ' ']); + } + + $tokens->clearAt($index); + $tokens->insertAt( + $index, + $items + ); + + // increment the position of the colon by number of items inserted + $colonIndex += \count($items); + + $items = [new Token('{')]; + + if (!$tokens[$colonIndex + 1]->isWhitespace()) { + $items[] = new Token([T_WHITESPACE, ' ']); + } + + $tokens->clearAt($colonIndex); + $tokens->insertAt( + $colonIndex, + $items + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoBreakCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoBreakCommentFixer.php new file mode 100644 index 0000000..f023729 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoBreakCommentFixer.php @@ -0,0 +1,368 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; +use Symfony\Component\OptionsResolver\Options; + +/** + * Fixer for rule defined in PSR2 ¶5.2. + */ +final class NoBreakCommentFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There must be a comment when fall-through is intentional in a non-empty case body.', + [ + new CodeSample( + '<?php +switch ($foo) { + case 1: + foo(); + case 2: + bar(); + // no break + break; + case 3: + baz(); +} +' + ), + new CodeSample( + '<?php +switch ($foo) { + case 1: + foo(); + case 2: + foo(); +} +', + ['comment_text' => 'some comment'] + ), + ], + 'Adds a "no break" comment before fall-through cases, and removes it if there is no fall-through.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_CASE, T_DEFAULT]); + } + + /** + * {@inheritdoc} + * + * Must run after NoUselessElseFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('comment_text', 'The text to use in the added comment and to detect it.')) + ->setAllowedTypes(['string']) + ->setAllowedValues([ + static function ($value) { + if (\is_string($value) && Preg::match('/\R/', $value)) { + throw new InvalidOptionsException('The comment text must not contain new lines.'); + } + + return true; + }, + ]) + ->setNormalizer(static function (Options $options, $value) { + return rtrim($value); + }) + ->setDefault('no break') + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = \count($tokens) - 1; $index >= 0; --$index) { + if (!$tokens[$index]->isGivenKind([T_CASE, T_DEFAULT])) { + continue; + } + + $caseColonIndex = $tokens->getNextTokenOfKind($index, [':', ';', [T_DOUBLE_ARROW]]); + + if ($tokens[$caseColonIndex]->isGivenKind(T_DOUBLE_ARROW)) { + continue; // this is "default" from "match" + } + + $this->fixCase($tokens, $caseColonIndex); + } + } + + /** + * @param int $caseColonIndex + */ + private function fixCase(Tokens $tokens, $caseColonIndex) + { + $empty = true; + $fallThrough = true; + $commentPosition = null; + + for ($i = $caseColonIndex + 1, $max = \count($tokens); $i < $max; ++$i) { + if ($tokens[$i]->isGivenKind([T_SWITCH, T_IF, T_ELSE, T_ELSEIF, T_FOR, T_FOREACH, T_WHILE, T_DO, T_FUNCTION, T_CLASS])) { + $empty = false; + $i = $this->getStructureEnd($tokens, $i); + + continue; + } + + if ($tokens[$i]->isGivenKind([T_BREAK, T_CONTINUE, T_RETURN, T_EXIT, T_GOTO])) { + $fallThrough = false; + + continue; + } + + if ($tokens[$i]->isGivenKind([T_THROW])) { + $previousIndex = $tokens->getPrevMeaningfulToken($i); + + if ($previousIndex === $caseColonIndex || $tokens[$previousIndex]->equalsAny(['{', ';', '}', [T_OPEN_TAG]])) { + $fallThrough = false; + } + + continue; + } + + if ($tokens[$i]->equals('}') || $tokens[$i]->isGivenKind(T_ENDSWITCH)) { + if (null !== $commentPosition) { + $this->removeComment($tokens, $commentPosition); + } + + break; + } + + if ($this->isNoBreakComment($tokens[$i])) { + $commentPosition = $i; + + continue; + } + + if ($tokens[$i]->isGivenKind([T_CASE, T_DEFAULT])) { + if (!$empty && $fallThrough) { + if (null !== $commentPosition && $tokens->getPrevNonWhitespace($i) !== $commentPosition) { + $this->removeComment($tokens, $commentPosition); + $commentPosition = null; + } + + if (null === $commentPosition) { + $this->insertCommentAt($tokens, $i); + } else { + $text = $this->configuration['comment_text']; + $tokens[$commentPosition] = new Token([ + $tokens[$commentPosition]->getId(), + str_ireplace($text, $text, $tokens[$commentPosition]->getContent()), + ]); + + $this->ensureNewLineAt($tokens, $commentPosition); + } + } elseif (null !== $commentPosition) { + $this->removeComment($tokens, $commentPosition); + } + + break; + } + + if (!$tokens[$i]->isGivenKind([T_COMMENT, T_WHITESPACE])) { + $empty = false; + } + } + } + + /** + * @return bool + */ + private function isNoBreakComment(Token $token) + { + if (!$token->isComment()) { + return false; + } + + $text = preg_quote($this->configuration['comment_text'], '~'); + + return 1 === Preg::match("~^((//|#)\\s*{$text}\\s*)|(/\\*\\*?\\s*{$text}\\s*\\*/)$~i", $token->getContent()); + } + + /** + * @param int $index + */ + private function insertCommentAt(Tokens $tokens, $index) + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + $newlinePosition = $this->ensureNewLineAt($tokens, $index); + $newlineToken = $tokens[$newlinePosition]; + $nbNewlines = substr_count($newlineToken->getContent(), $lineEnding); + + if ($newlineToken->isGivenKind(T_OPEN_TAG) && Preg::match('/\R/', $newlineToken->getContent())) { + ++$nbNewlines; + } elseif ($tokens[$newlinePosition - 1]->isGivenKind(T_OPEN_TAG) && Preg::match('/\R/', $tokens[$newlinePosition - 1]->getContent())) { + ++$nbNewlines; + + if (!Preg::match('/\R/', $newlineToken->getContent())) { + $tokens[$newlinePosition] = new Token([$newlineToken->getId(), $lineEnding.$newlineToken->getContent()]); + } + } + + if ($nbNewlines > 1) { + Preg::match('/^(.*?)(\R\h*)$/s', $newlineToken->getContent(), $matches); + + $indent = WhitespacesAnalyzer::detectIndent($tokens, $newlinePosition - 1); + $tokens[$newlinePosition] = new Token([$newlineToken->getId(), $matches[1].$lineEnding.$indent]); + $tokens->insertAt(++$newlinePosition, new Token([T_WHITESPACE, $matches[2]])); + } + + $tokens->insertAt($newlinePosition, new Token([T_COMMENT, '// '.$this->configuration['comment_text']])); + $this->ensureNewLineAt($tokens, $newlinePosition); + } + + /** + * @param int $position + * + * @return int The newline token position + */ + private function ensureNewLineAt(Tokens $tokens, $position) + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + $content = $lineEnding.WhitespacesAnalyzer::detectIndent($tokens, $position); + $whitespaceToken = $tokens[$position - 1]; + + if (!$whitespaceToken->isGivenKind(T_WHITESPACE)) { + if ($whitespaceToken->isGivenKind(T_OPEN_TAG)) { + $content = Preg::replace('/\R/', '', $content); + if (!Preg::match('/\R/', $whitespaceToken->getContent())) { + $tokens[$position - 1] = new Token([T_OPEN_TAG, Preg::replace('/\s+$/', $lineEnding, $whitespaceToken->getContent())]); + } + } + + if ('' !== $content) { + $tokens->insertAt($position, new Token([T_WHITESPACE, $content])); + + return $position; + } + + return $position - 1; + } + + if ($tokens[$position - 2]->isGivenKind(T_OPEN_TAG) && Preg::match('/\R/', $tokens[$position - 2]->getContent())) { + $content = Preg::replace('/^\R/', '', $content); + } + + if (!Preg::match('/\R/', $whitespaceToken->getContent())) { + $tokens[$position - 1] = new Token([T_WHITESPACE, $content]); + } + + return $position - 1; + } + + /** + * @param int $commentPosition + */ + private function removeComment(Tokens $tokens, $commentPosition) + { + if ($tokens[$tokens->getPrevNonWhitespace($commentPosition)]->isGivenKind(T_OPEN_TAG)) { + $whitespacePosition = $commentPosition + 1; + $regex = '/^\R\h*/'; + } else { + $whitespacePosition = $commentPosition - 1; + $regex = '/\R\h*$/'; + } + + $whitespaceToken = $tokens[$whitespacePosition]; + + if ($whitespaceToken->isGivenKind(T_WHITESPACE)) { + $content = Preg::replace($regex, '', $whitespaceToken->getContent()); + if ('' !== $content) { + $tokens[$whitespacePosition] = new Token([T_WHITESPACE, $content]); + } else { + $tokens->clearAt($whitespacePosition); + } + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($commentPosition); + } + + /** + * @param int $position + * + * @return int + */ + private function getStructureEnd(Tokens $tokens, $position) + { + $initialToken = $tokens[$position]; + + if ($initialToken->isGivenKind([T_FOR, T_FOREACH, T_WHILE, T_IF, T_ELSEIF, T_SWITCH, T_FUNCTION])) { + $position = $tokens->findBlockEnd( + Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, + $tokens->getNextTokenOfKind($position, ['(']) + ); + } elseif ($initialToken->isGivenKind(T_CLASS)) { + $openParenthesisPosition = $tokens->getNextMeaningfulToken($position); + if ('(' === $tokens[$openParenthesisPosition]->getContent()) { + $position = $tokens->findBlockEnd( + Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, + $openParenthesisPosition + ); + } + } + + $position = $tokens->getNextMeaningfulToken($position); + + if ('{' !== $tokens[$position]->getContent()) { + return $tokens->getNextTokenOfKind($position, [';']); + } + + $position = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $position); + + if ($initialToken->isGivenKind(T_DO)) { + $position = $tokens->findBlockEnd( + Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, + $tokens->getNextTokenOfKind($position, ['(']) + ); + + return $tokens->getNextTokenOfKind($position, [';']); + } + + return $position; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoSuperfluousElseifFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoSuperfluousElseifFixer.php new file mode 100644 index 0000000..c5eba6c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoSuperfluousElseifFixer.php @@ -0,0 +1,115 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractNoUselessElseFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +final class NoSuperfluousElseifFixer extends AbstractNoUselessElseFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_ELSE, T_ELSEIF]); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replaces superfluous `elseif` with `if`.', + [ + new CodeSample("<?php\nif (\$a) {\n return 1;\n} elseif (\$b) {\n return 2;\n}\n"), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before SimplifiedIfReturnFixer. + * Must run after NoAlternativeSyntaxFixer. + */ + public function getPriority() + { + return parent::getPriority(); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if ($this->isElseif($tokens, $index) && $this->isSuperfluousElse($tokens, $index)) { + $this->convertElseifToIf($tokens, $index); + } + } + } + + /** + * @param int $index + * + * @return bool + */ + private function isElseif(Tokens $tokens, $index) + { + return + $tokens[$index]->isGivenKind(T_ELSEIF) + || ($tokens[$index]->isGivenKind(T_ELSE) && $tokens[$tokens->getNextMeaningfulToken($index)]->isGivenKind(T_IF)) + ; + } + + /** + * @param int $index + */ + private function convertElseifToIf(Tokens $tokens, $index) + { + if ($tokens[$index]->isGivenKind(T_ELSE)) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } else { + $tokens[$index] = new Token([T_IF, 'if']); + } + + $whitespace = ''; + + for ($previous = $index - 1; $previous > 0; --$previous) { + $token = $tokens[$previous]; + if ($token->isWhitespace() && Preg::match('/(\R\N*)$/', $token->getContent(), $matches)) { + $whitespace = $matches[1]; + + break; + } + } + + if ('' === $whitespace) { + return; + } + + $previousToken = $tokens[$index - 1]; + + if (!$previousToken->isWhitespace()) { + $tokens->insertAt($index, new Token([T_WHITESPACE, $whitespace])); + } elseif (!Preg::match('/\R/', $previousToken->getContent())) { + $tokens[$index - 1] = new Token([T_WHITESPACE, $whitespace]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ListCommasFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoTrailingCommaInListCallFixer.php similarity index 65% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ListCommasFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoTrailingCommaInListCallFixer.php index 3883eb3..b08e236 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/ListCommasFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoTrailingCommaInListCallFixer.php @@ -10,31 +10,42 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Symfony; +namespace PhpCsFixer\Fixer\ControlStructure; -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; /** * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> */ -class ListCommasFixer extends AbstractFixer +final class NoTrailingCommaInListCallFixer extends AbstractFixer { /** * {@inheritdoc} */ - public function getDescription() + public function getDefinition() { - return 'Remove trailing commas in list function calls.'; + return new FixerDefinition( + 'Remove trailing commas in list function calls.', + [new CodeSample("<?php\nlist(\$a, \$b,) = foo();\n")] + ); } /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function isCandidate(Tokens $tokens) { - $tokens = Tokens::fromCode($content); + return $tokens->isTokenKindFound(T_LIST); + } + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { for ($index = $tokens->count() - 1; $index >= 0; --$index) { $token = $tokens[$index]; @@ -59,7 +70,5 @@ public function fix(\SplFileInfo $file, $content) ); } } - - return $tokens->generateCode(); } } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUnneededControlParenthesesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUnneededControlParenthesesFixer.php new file mode 100644 index 0000000..32a1e70 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUnneededControlParenthesesFixer.php @@ -0,0 +1,194 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Sullivan Senechal <soullivaneuh@gmail.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Gregor Harlan <gharlan@web.de> + */ +final class NoUnneededControlParenthesesFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + private static $loops = [ + 'break' => ['lookupTokens' => T_BREAK, 'neededSuccessors' => [';']], + 'clone' => ['lookupTokens' => T_CLONE, 'neededSuccessors' => [';', ':', ',', ')'], 'forbiddenContents' => ['?', ':']], + 'continue' => ['lookupTokens' => T_CONTINUE, 'neededSuccessors' => [';']], + 'echo_print' => ['lookupTokens' => [T_ECHO, T_PRINT], 'neededSuccessors' => [';', [T_CLOSE_TAG]]], + 'return' => ['lookupTokens' => T_RETURN, 'neededSuccessors' => [';', [T_CLOSE_TAG]]], + 'switch_case' => ['lookupTokens' => T_CASE, 'neededSuccessors' => [';', ':']], + 'yield' => ['lookupTokens' => T_YIELD, 'neededSuccessors' => [';', ')']], + ]; + + /** + * Dynamic option set on constructor. + */ + public function __construct() + { + parent::__construct(); + + // @TODO: To be moved back to compile time property declaration when PHP support of PHP CS Fixer will be 7.0+ + if (\defined('T_COALESCE')) { + self::$loops['clone']['forbiddenContents'][] = [T_COALESCE, '??']; + } + + // @TODO: To be moved back to compile time property declaration when PHP support of PHP CS Fixer will be 7.0+ + if (\defined('T_YIELD_FROM')) { + self::$loops['yield_from'] = ['lookupTokens' => T_YIELD_FROM, 'neededSuccessors' => [';', ')']]; + } + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + $types = []; + + foreach (self::$loops as $loop) { + $types[] = (array) $loop['lookupTokens']; + } + $types = array_merge(...$types); + + return $tokens->isAnyTokenKindsFound($types); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Removes unneeded parentheses around control statements.', + [ + new CodeSample( + '<?php +while ($x) { while ($y) { break (2); } } +clone($a); +while ($y) { continue (2); } +echo("foo"); +print("foo"); +return (1 + 2); +switch ($a) { case($x); } +yield(2); +' + ), + new CodeSample( + '<?php +while ($x) { while ($y) { break (2); } } +clone($a); +while ($y) { continue (2); } +echo("foo"); +print("foo"); +return (1 + 2); +switch ($a) { case($x); } +yield(2); +', + ['statements' => ['break', 'continue']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoTrailingWhitespaceFixer. + */ + public function getPriority() + { + return 30; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // Checks if specific statements are set and uses them in this case. + $loops = array_intersect_key(self::$loops, array_flip($this->configuration['statements'])); + + foreach ($tokens as $index => $token) { + if (!$token->equalsAny(['(', [CT::T_BRACE_CLASS_INSTANTIATION_OPEN]])) { + continue; + } + + $blockStartIndex = $index; + $index = $tokens->getPrevMeaningfulToken($index); + $prevToken = $tokens[$index]; + + foreach ($loops as $loop) { + if (!$prevToken->isGivenKind($loop['lookupTokens'])) { + continue; + } + + $blockEndIndex = $tokens->findBlockEnd( + $token->equals('(') ? Tokens::BLOCK_TYPE_PARENTHESIS_BRACE : Tokens::BLOCK_TYPE_BRACE_CLASS_INSTANTIATION, + $blockStartIndex + ); + $blockEndNextIndex = $tokens->getNextMeaningfulToken($blockEndIndex); + + if (!$tokens[$blockEndNextIndex]->equalsAny($loop['neededSuccessors'])) { + continue; + } + + if (\array_key_exists('forbiddenContents', $loop)) { + $forbiddenTokenIndex = $tokens->getNextTokenOfKind($blockStartIndex, $loop['forbiddenContents']); + // A forbidden token is found and is inside the parenthesis. + if (null !== $forbiddenTokenIndex && $forbiddenTokenIndex < $blockEndIndex) { + continue; + } + } + + if ($tokens[$blockStartIndex - 1]->isWhitespace() || $tokens[$blockStartIndex - 1]->isComment()) { + $tokens->clearTokenAndMergeSurroundingWhitespace($blockStartIndex); + } else { + // Adds a space to prevent broken code like `return2`. + $tokens[$blockStartIndex] = new Token([T_WHITESPACE, ' ']); + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($blockEndIndex); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolverRootless('statements', [ + (new FixerOptionBuilder('statements', 'List of control statements to fix.')) + ->setAllowedTypes(['array']) + ->setDefault([ + 'break', + 'clone', + 'continue', + 'echo_print', + 'return', + 'switch_case', + 'yield', + ]) + ->getOption(), + ], $this->getName()); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUnneededCurlyBracesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUnneededCurlyBracesFixer.php new file mode 100644 index 0000000..3a0b184 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUnneededCurlyBracesFixer.php @@ -0,0 +1,177 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class NoUnneededCurlyBracesFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Removes unneeded curly braces that are superfluous and aren\'t part of a control structure\'s body.', + [ + new CodeSample( + '<?php { + echo 1; +} + +switch ($b) { + case 1: { + break; + } +} +' + ), + new CodeSample( + '<?php +namespace Foo { + function Bar(){} +} +', + ['namespaces' => true] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoUselessElseFixer, NoUselessReturnFixer, ReturnAssignmentFixer, SimplifiedIfReturnFixer. + */ + public function getPriority() + { + return 40; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound('}'); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($this->findCurlyBraceOpen($tokens) as $index) { + if ($this->isOverComplete($tokens, $index)) { + $this->clearOverCompleteBraces($tokens, $index, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index)); + } + } + + if ($this->configuration['namespaces']) { + $this->clearIfIsOverCompleteNamespaceBlock($tokens); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('namespaces', 'Remove unneeded curly braces from bracketed namespaces.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + ]); + } + + /** + * @param int $openIndex index of `{` token + * @param int $closeIndex index of `}` token + */ + private function clearOverCompleteBraces(Tokens $tokens, $openIndex, $closeIndex) + { + $tokens->clearTokenAndMergeSurroundingWhitespace($closeIndex); + $tokens->clearTokenAndMergeSurroundingWhitespace($openIndex); + } + + private function findCurlyBraceOpen(Tokens $tokens) + { + for ($i = \count($tokens) - 1; $i > 0; --$i) { + if ($tokens[$i]->equals('{')) { + yield $i; + } + } + } + + /** + * @param int $index index of `{` token + * + * @return bool + */ + private function isOverComplete(Tokens $tokens, $index) + { + static $include = ['{', '}', [T_OPEN_TAG], ':', ';']; + + return $tokens[$tokens->getPrevMeaningfulToken($index)]->equalsAny($include); + } + + private function clearIfIsOverCompleteNamespaceBlock(Tokens $tokens) + { + if (Tokens::isLegacyMode()) { + $index = $tokens->getNextTokenOfKind(0, [[T_NAMESPACE]]); + $secondNamespaceIndex = $tokens->getNextTokenOfKind($index, [[T_NAMESPACE]]); + + if (null !== $secondNamespaceIndex) { + return; + } + } elseif (1 !== $tokens->countTokenKind(T_NAMESPACE)) { + return; // fast check, we never fix if multiple namespaces are defined + } + + $index = $tokens->getNextTokenOfKind(0, [[T_NAMESPACE]]); + + do { + $index = $tokens->getNextMeaningfulToken($index); + } while ($tokens[$index]->isGivenKind([T_STRING, T_NS_SEPARATOR])); + + if (!$tokens[$index]->equals('{')) { + return; // `;` + } + + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + $afterCloseIndex = $tokens->getNextMeaningfulToken($closeIndex); + + if (null !== $afterCloseIndex && (!$tokens[$afterCloseIndex]->isGivenKind(T_CLOSE_TAG) || null !== $tokens->getNextMeaningfulToken($afterCloseIndex))) { + return; + } + + // clear up + $tokens->clearTokenAndMergeSurroundingWhitespace($closeIndex); + $tokens[$index] = new Token(';'); + + if ($tokens[$index - 1]->isWhitespace(" \t") && !$tokens[$index - 2]->isComment()) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index - 1); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUselessElseFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUselessElseFixer.php new file mode 100644 index 0000000..67aa81c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/NoUselessElseFixer.php @@ -0,0 +1,129 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractNoUselessElseFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class NoUselessElseFixer extends AbstractNoUselessElseFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_ELSE); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There should not be useless `else` cases.', + [ + new CodeSample("<?php\nif (\$a) {\n return 1;\n} else {\n return 2;\n}\n"), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer, CombineConsecutiveUnsetsFixer, NoBreakCommentFixer, NoExtraBlankLinesFixer, NoTrailingWhitespaceFixer, NoUselessReturnFixer, NoWhitespaceInBlankLineFixer, SimplifiedIfReturnFixer. + * Must run after NoAlternativeSyntaxFixer, NoEmptyStatementFixer, NoUnneededCurlyBracesFixer. + */ + public function getPriority() + { + return parent::getPriority(); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_ELSE)) { + continue; + } + + // `else if` vs. `else` and alternative syntax `else:` checks + if ($tokens[$tokens->getNextMeaningfulToken($index)]->equalsAny([':', [T_IF]])) { + continue; + } + + // clean up `else` if it is an empty statement + $this->fixEmptyElse($tokens, $index); + if ($tokens->isEmptyAt($index)) { + continue; + } + + // clean up `else` if possible + if ($this->isSuperfluousElse($tokens, $index)) { + $this->clearElse($tokens, $index); + } + } + } + + /** + * Remove tokens part of an `else` statement if not empty (i.e. no meaningful tokens inside). + * + * @param int $index T_ELSE index + */ + private function fixEmptyElse(Tokens $tokens, $index) + { + $next = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$next]->equals('{')) { + $close = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $next); + if (1 === $close - $next) { // '{}' + $this->clearElse($tokens, $index); + } elseif ($tokens->getNextMeaningfulToken($next) === $close) { // '{/**/}' + $this->clearElse($tokens, $index); + } + + return; + } + + // short `else` + $end = $tokens->getNextTokenOfKind($index, [';', [T_CLOSE_TAG]]); + if ($next === $end) { + $this->clearElse($tokens, $index); + } + } + + /** + * @param int $index index of T_ELSE + */ + private function clearElse(Tokens $tokens, $index) + { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + + // clear T_ELSE and the '{' '}' if there are any + $next = $tokens->getNextMeaningfulToken($index); + + if (!$tokens[$next]->equals('{')) { + return; + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $next)); + $tokens->clearTokenAndMergeSurroundingWhitespace($next); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SimplifiedIfReturnFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SimplifiedIfReturnFixer.php new file mode 100644 index 0000000..0cfc654 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SimplifiedIfReturnFixer.php @@ -0,0 +1,139 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class SimplifiedIfReturnFixer extends AbstractFixer +{ + private $sequences = [ + [ + 'isNegative' => false, + 'sequence' => [ + '{', [T_RETURN], [T_STRING, 'true'], ';', '}', + [T_RETURN], [T_STRING, 'false'], ';', + ], + ], + [ + 'isNegative' => true, + 'sequence' => [ + '{', [T_RETURN], [T_STRING, 'false'], ';', '}', + [T_RETURN], [T_STRING, 'true'], ';', + ], + ], + [ + 'isNegative' => false, + 'sequence' => [ + [T_RETURN], [T_STRING, 'true'], ';', + [T_RETURN], [T_STRING, 'false'], ';', + ], + ], + [ + 'isNegative' => true, + 'sequence' => [ + [T_RETURN], [T_STRING, 'false'], ';', + [T_RETURN], [T_STRING, 'true'], ';', + ], + ], + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Simplify `if` control structures that return the boolean result of their condition.', + [new CodeSample("<?php\nif (\$foo) { return true; } return false;\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoMultilineWhitespaceBeforeSemicolonsFixer, NoSinglelineWhitespaceBeforeSemicolonsFixer. + * Must run after NoSuperfluousElseifFixer, NoUnneededCurlyBracesFixer, NoUselessElseFixer, SemicolonAfterInstructionFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_IF, T_RETURN, T_STRING]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($ifIndex = $tokens->count() - 1; 0 <= $ifIndex; --$ifIndex) { + $ifToken = $tokens[$ifIndex]; + + if (!$ifToken->isGivenKind([T_IF, T_ELSEIF])) { + continue; + } + + $startParenthesisIndex = $tokens->getNextTokenOfKind($ifIndex, ['(']); + $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex); + $firstCandidateIndex = $tokens->getNextMeaningfulToken($endParenthesisIndex); + + foreach ($this->sequences as $sequenceSpec) { + $sequenceFound = $tokens->findSequence($sequenceSpec['sequence'], $firstCandidateIndex); + + if (null === $sequenceFound) { + continue; + } + + $firstSequenceIndex = key($sequenceFound); + + if ($firstSequenceIndex !== $firstCandidateIndex) { + continue; + } + + $indexesToClear = array_keys($sequenceFound); + array_pop($indexesToClear); // Preserve last semicolon + rsort($indexesToClear); + + foreach ($indexesToClear as $index) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } + + $newTokens = [ + new Token([T_RETURN, 'return']), + new Token([T_WHITESPACE, ' ']), + ]; + + if ($sequenceSpec['isNegative']) { + $newTokens[] = new Token('!'); + } else { + $newTokens[] = new Token([T_BOOL_CAST, '(bool)']); + } + + $tokens->overrideRange($ifIndex, $ifIndex, $newTokens); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php new file mode 100644 index 0000000..e27f97f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchCaseSemicolonToColonFixer.php @@ -0,0 +1,132 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR2 ¶5.2. + * + * @author SpacePossum + */ +final class SwitchCaseSemicolonToColonFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'A case should be followed by a colon and not a semicolon.', + [ + new CodeSample( + '<?php + switch ($a) { + case 1; + break; + default; + break; + } +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after NoEmptyStatementFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_CASE, T_DEFAULT]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if ($token->isGivenKind(T_CASE)) { + $this->fixSwitchCase($tokens, $index); + } + if ($token->isGivenKind(T_DEFAULT)) { + $this->fixSwitchDefault($tokens, $index); + } + } + } + + /** + * @param int $index + */ + protected function fixSwitchCase(Tokens $tokens, $index) + { + $ternariesCount = 0; + do { + if ($tokens[$index]->equalsAny(['(', '{'])) { // skip constructs + $type = Tokens::detectBlockType($tokens[$index]); + $index = $tokens->findBlockEnd($type['type'], $index); + + continue; + } + + if ($tokens[$index]->equals('?')) { + ++$ternariesCount; + + continue; + } + + if ($tokens[$index]->equalsAny([':', ';'])) { + if (0 === $ternariesCount) { + break; + } + + --$ternariesCount; + } + } while (++$index); + + if ($tokens[$index]->equals(';')) { + $tokens[$index] = new Token(':'); + } + } + + /** + * @param int $index + */ + protected function fixSwitchDefault(Tokens $tokens, $index) + { + do { + if ($tokens[$index]->equalsAny([':', ';', [T_DOUBLE_ARROW]])) { + break; + } + } while (++$index); + + if ($tokens[$index]->equals(';')) { + $tokens[$index] = new Token(':'); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchCaseSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchCaseSpaceFixer.php new file mode 100644 index 0000000..d47492c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchCaseSpaceFixer.php @@ -0,0 +1,92 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR2 ¶5.2. + * + * @author Sullivan Senechal <soullivaneuh@gmail.com> + */ +final class SwitchCaseSpaceFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Removes extra spaces between colon and case value.', + [ + new CodeSample( + '<?php + switch($a) { + case 1 : + break; + default : + return 2; + } +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_CASE, T_DEFAULT]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind([T_CASE, T_DEFAULT])) { + continue; + } + + $ternariesCount = 0; + for ($colonIndex = $index + 1;; ++$colonIndex) { + // We have to skip ternary case for colons. + if ($tokens[$colonIndex]->equals('?')) { + ++$ternariesCount; + } + + if ($tokens[$colonIndex]->equalsAny([':', ';'])) { + if (0 === $ternariesCount) { + break; + } + + --$ternariesCount; + } + } + + $valueIndex = $tokens->getPrevNonWhitespace($colonIndex); + // skip if there is no space between the colon and previous token or is space after comment + if ($valueIndex === $colonIndex - 1 || $tokens[$valueIndex]->isComment()) { + continue; + } + + $tokens->clearAt($valueIndex + 1); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchContinueToBreakFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchContinueToBreakFixer.php new file mode 100644 index 0000000..4def5e7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/SwitchContinueToBreakFixer.php @@ -0,0 +1,269 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +final class SwitchContinueToBreakFixer extends AbstractFixer +{ + private $switchLevels = []; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Switch case must not be ended with `continue` but with `break`.', + [ + new CodeSample( + '<?php +switch ($foo) { + case 1: + continue; +} +' + ), + new CodeSample( + '<?php +switch ($foo) { + case 1: + while($bar) { + do { + continue 3; + } while(false); + + if ($foo + 1 > 3) { + continue; + } + + continue 2; + } +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after NoAlternativeSyntaxFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_SWITCH, T_CONTINUE, T_LNUMBER]) && !$tokens->hasAlternativeSyntax(); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $count = \count($tokens); + + for ($index = 1; $index < $count - 1; ++$index) { + $index = $this->doFix($tokens, $index, 0, false); + } + } + + /** + * @param int $index + * @param int $depth >= 0 + * @param bool $isInSwitch + * + * @return int + */ + private function doFix(Tokens $tokens, $index, $depth, $isInSwitch) + { + $token = $tokens[$index]; + + if ($token->isGivenKind([T_FOREACH, T_FOR, T_WHILE])) { + // go to first `(`, go to its close ')', go to first of '{', ';', '? >' + $index = $tokens->getNextTokenOfKind($index, ['(']); + $index = $tokens->getNextTokenOfKind($index, [')']); + $index = $tokens->getNextTokenOfKind($index, ['{', ';', [T_CLOSE_TAG]]); + + if (!$tokens[$index]->equals('{')) { + return $index; + } + + return $this->fixInLoop($tokens, $index, $depth + 1); + } + + if ($token->isGivenKind(T_DO)) { + return $this->fixInLoop($tokens, $tokens->getNextTokenOfKind($index, ['{']), $depth + 1); + } + + if ($token->isGivenKind(T_SWITCH)) { + return $this->fixInSwitch($tokens, $index, $depth + 1); + } + + if ($token->isGivenKind(T_CONTINUE)) { + return $this->fixContinueWhenActsAsBreak($tokens, $index, $isInSwitch, $depth); + } + + return $index; + } + + /** + * @param int $switchIndex + * @param int $depth + * + * @return int + */ + private function fixInSwitch(Tokens $tokens, $switchIndex, $depth) + { + $this->switchLevels[] = $depth; + + // figure out where the switch starts + $openIndex = $tokens->getNextTokenOfKind($switchIndex, ['{']); + + // figure out where the switch ends + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $openIndex); + + for ($index = $openIndex + 1; $index < $closeIndex; ++$index) { + $index = $this->doFix($tokens, $index, $depth, true); + } + + array_pop($this->switchLevels); + + return $closeIndex; + } + + /** + * @param int $openIndex + * @param int $depth + * + * @return int + */ + private function fixInLoop(Tokens $tokens, $openIndex, $depth) + { + $openCount = 1; + + do { + ++$openIndex; + $token = $tokens[$openIndex]; + + if ($token->equals('{')) { + ++$openCount; + + continue; + } + + if ($token->equals('}')) { + --$openCount; + + if (0 === $openCount) { + break; + } + + continue; + } + + $openIndex = $this->doFix($tokens, $openIndex, $depth, false); + } while (true); + + return $openIndex; + } + + /** + * @param int $continueIndex + * @param bool $isInSwitch + * @param int $depth + * + * @return int + */ + private function fixContinueWhenActsAsBreak(Tokens $tokens, $continueIndex, $isInSwitch, $depth) + { + $followingContinueIndex = $tokens->getNextMeaningfulToken($continueIndex); + $followingContinueToken = $tokens[$followingContinueIndex]; + + if ($isInSwitch && $followingContinueToken->equals(';')) { + $this->replaceContinueWithBreakToken($tokens, $continueIndex); // short continue 1 notation + + return $followingContinueIndex; + } + + if (!$followingContinueToken->isGivenKind(T_LNUMBER)) { + return $followingContinueIndex; + } + + $afterFollowingContinueIndex = $tokens->getNextMeaningfulToken($followingContinueIndex); + + if (!$tokens[$afterFollowingContinueIndex]->equals(';')) { + return $afterFollowingContinueIndex; // if next not is `;` return without fixing, for example `continue 1 ? ><?php + $a;` + } + + // check if continue {jump} targets a switch statement and if so fix it + + $jump = $followingContinueToken->getContent(); + $jump = str_replace('_', '', $jump); // support for numeric_literal_separator + + if (\strlen($jump) > 2 && 'x' === $jump[1]) { + $jump = hexdec($jump); // hexadecimal - 0x1 + } elseif (\strlen($jump) > 2 && 'b' === $jump[1]) { + $jump = bindec($jump); // binary - 0b1 + } elseif (\strlen($jump) > 1 && '0' === $jump[0]) { + $jump = octdec($jump); // octal 01 + } elseif (1 === Preg::match('#^\d+$#', $jump)) { // positive int + $jump = (float) $jump; // cast to float, might be a number bigger than PHP max. int value + } else { + return $afterFollowingContinueIndex; // cannot process value, ignore + } + + if ($jump > PHP_INT_MAX) { + return $afterFollowingContinueIndex; // cannot process value, ignore + } + + $jump = (int) $jump; + + if ($isInSwitch && (1 === $jump || 0 === $jump)) { + $this->replaceContinueWithBreakToken($tokens, $continueIndex); // long continue 0/1 notation + + return $afterFollowingContinueIndex; + } + + $jumpDestination = $depth - $jump + 1; + + if (\in_array($jumpDestination, $this->switchLevels, true)) { + $this->replaceContinueWithBreakToken($tokens, $continueIndex); + + return $afterFollowingContinueIndex; + } + + return $afterFollowingContinueIndex; + } + + /** + * @param int $index + */ + private function replaceContinueWithBreakToken(Tokens $tokens, $index) + { + $tokens[$index] = new Token([T_BREAK, 'break']); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/TrailingCommaInMultilineFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/TrailingCommaInMultilineFixer.php new file mode 100644 index 0000000..75db85c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/TrailingCommaInMultilineFixer.php @@ -0,0 +1,219 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerConfiguration\InvalidOptionsForEnvException; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use Symfony\Component\OptionsResolver\Options; + +/** + * @author Sebastiaan Stok <s.stok@rollerscapes.net> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Kuba Werłos <werlos@gmail.com> + */ +final class TrailingCommaInMultilineFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @internal + */ + const ELEMENTS_ARRAYS = 'arrays'; + + /** + * @internal + */ + const ELEMENTS_ARGUMENTS = 'arguments'; + + /** + * @internal + */ + const ELEMENTS_PARAMETERS = 'parameters'; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Multi-line arrays, arguments list and parameters list must have a trailing comma.', + [ + new CodeSample("<?php\narray(\n 1,\n 2\n);\n"), + new VersionSpecificCodeSample( + <<<'SAMPLE' +<?php + $x = [ + 'foo', + <<<EOD + bar + EOD + ]; + +SAMPLE + , + new VersionSpecification(70300), + ['after_heredoc' => true] + ), + new VersionSpecificCodeSample("<?php\nfoo(\n 1,\n 2\n);\n", new VersionSpecification(70300), ['elements' => [self::ELEMENTS_ARGUMENTS]]), + new VersionSpecificCodeSample("<?php\nfunction foo(\n \$x,\n \$y\n)\n{\n}\n", new VersionSpecification(80000), ['elements' => [self::ELEMENTS_PARAMETERS]]), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after NoMultilineWhitespaceAroundDoubleArrowFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN, '(']); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('after_heredoc', 'Whether a trailing comma should also be placed after heredoc end.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->setNormalizer(static function (Options $options, $value) { + if (\PHP_VERSION_ID < 70300 && $value) { + throw new InvalidOptionsForEnvException('"after_heredoc" option can only be enabled with PHP 7.3+.'); + } + + return $value; + }) + ->getOption(), + (new FixerOptionBuilder('elements', sprintf('Where to fix multiline trailing comma (PHP >= 7.3 required for `%s`, PHP >= 8.0 for `%s`).', self::ELEMENTS_ARGUMENTS, self::ELEMENTS_PARAMETERS))) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset([self::ELEMENTS_ARRAYS, self::ELEMENTS_ARGUMENTS, self::ELEMENTS_PARAMETERS])]) + ->setDefault([self::ELEMENTS_ARRAYS]) + ->setNormalizer(static function (Options $options, $value) { + if (\PHP_VERSION_ID < 70300 && \in_array(self::ELEMENTS_ARGUMENTS, $value, true)) { + throw new InvalidOptionsForEnvException(sprintf('"%s" option can only be enabled with PHP 7.3+.', self::ELEMENTS_ARGUMENTS)); + } + if (\PHP_VERSION_ID < 80000 && \in_array(self::ELEMENTS_PARAMETERS, $value, true)) { + throw new InvalidOptionsForEnvException(sprintf('"%s" option can only be enabled with PHP 8.0+.', self::ELEMENTS_PARAMETERS)); + } + + return $value; + }) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $fixArrays = \in_array(self::ELEMENTS_ARRAYS, $this->configuration['elements'], true); + $fixArguments = \in_array(self::ELEMENTS_ARGUMENTS, $this->configuration['elements'], true); + $fixParameters = \in_array(self::ELEMENTS_PARAMETERS, $this->configuration['elements'], true); + + $tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $prevIndex = $tokens->getPrevMeaningfulToken($index); + + if ( + $fixArrays + && ( + $tokens[$index]->equals('(') && $tokens[$prevIndex]->isGivenKind(T_ARRAY) // long syntax + || $tokens[$index]->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN) // short syntax + ) + ) { + $this->fixBlock($tokens, $index); + + continue; + } + + if (!$tokens[$index]->equals('(')) { + continue; + } + + $prevPrevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + + if ($fixArguments + && $tokens[$prevIndex]->equalsAny([']', [T_CLASS], [T_STRING], [T_VARIABLE]]) + && !$tokens[$prevPrevIndex]->isGivenKind(T_FUNCTION) + ) { + $this->fixBlock($tokens, $index); + + continue; + } + + if ( + $fixParameters + && ( + $tokens[$prevIndex]->isGivenKind(T_STRING) && $tokens[$prevPrevIndex]->isGivenKind(T_FUNCTION) + || $tokens[$prevIndex]->isGivenKind([T_FN, T_FUNCTION]) + ) + ) { + $this->fixBlock($tokens, $index); + } + } + } + + /** + * @param int $startIndex + */ + private function fixBlock(Tokens $tokens, $startIndex) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + if (!$tokensAnalyzer->isBlockMultiline($tokens, $startIndex)) { + return; + } + + $blockType = Tokens::detectBlockType($tokens[$startIndex]); + $endIndex = $tokens->findBlockEnd($blockType['type'], $startIndex); + + $beforeEndIndex = $tokens->getPrevMeaningfulToken($endIndex); + $beforeEndToken = $tokens[$beforeEndIndex]; + + // if there is some item between braces then add `,` after it + if ( + $startIndex !== $beforeEndIndex && !$beforeEndToken->equals(',') + && ($this->configuration['after_heredoc'] || !$beforeEndToken->isGivenKind(T_END_HEREDOC)) + ) { + $tokens->insertAt($beforeEndIndex + 1, new Token(',')); + + $endToken = $tokens[$endIndex]; + + if (!$endToken->isComment() && !$endToken->isWhitespace()) { + $tokens->ensureWhitespaceAtIndex($endIndex, 1, ' '); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/YodaStyleFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/YodaStyleFixer.php new file mode 100644 index 0000000..aecad87 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ControlStructure/YodaStyleFixer.php @@ -0,0 +1,772 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ControlStructure; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Bram Gotink <bram@gotink.me> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +final class YodaStyleFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var array<int|string, Token> + */ + private $candidatesMap; + + /** + * @var array<int|string, null|bool> + */ + private $candidateTypesConfiguration; + + /** + * @var array<int|string> + */ + private $candidateTypes; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->resolveConfiguration(); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Write conditions in Yoda style (`true`), non-Yoda style (`[\'equal\' => false, \'identical\' => false, \'less_and_greater\' => false]`) or ignore those conditions (`null`) based on configuration.', + [ + new CodeSample( + '<?php + if ($a === null) { + echo "null"; + } +' + ), + new CodeSample( + '<?php + $b = $c != 1; // equal + $a = 1 === $b; // identical + $c = $c > 3; // less than +', + [ + 'equal' => true, + 'identical' => false, + 'less_and_greater' => null, + ] + ), + new CodeSample( + '<?php +return $foo === count($bar); +', + [ + 'always_move_variable' => true, + ] + ), + new CodeSample( + '<?php + // Enforce non-Yoda style. + if (null === $a) { + echo "null"; + } +', + [ + 'equal' => false, + 'identical' => false, + 'less_and_greater' => false, + ] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after IsNullFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound($this->candidateTypes); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $this->fixTokens($tokens); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('equal', 'Style for equal (`==`, `!=`) statements.')) + ->setAllowedTypes(['bool', 'null']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('identical', 'Style for identical (`===`, `!==`) statements.')) + ->setAllowedTypes(['bool', 'null']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('less_and_greater', 'Style for less and greater than (`<`, `<=`, `>`, `>=`) statements.')) + ->setAllowedTypes(['bool', 'null']) + ->setDefault(null) + ->getOption(), + (new FixerOptionBuilder('always_move_variable', 'Whether variables should always be on non assignable side when applying Yoda style.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + ]); + } + + /** + * Finds the end of the right-hand side of the comparison at the given + * index. + * + * The right-hand side ends when an operator with a lower precedence is + * encountered or when the block level for `()`, `{}` or `[]` goes below + * zero. + * + * @param Tokens $tokens The token list + * @param int $index The index of the comparison + * + * @return int The last index of the right-hand side of the comparison + */ + private function findComparisonEnd(Tokens $tokens, $index) + { + ++$index; + $count = \count($tokens); + while ($index < $count) { + $token = $tokens[$index]; + if ($token->isGivenKind([T_WHITESPACE, T_COMMENT, T_DOC_COMMENT])) { + ++$index; + + continue; + } + + if ($this->isOfLowerPrecedence($token)) { + break; + } + + $block = Tokens::detectBlockType($token); + if (null === $block) { + ++$index; + + continue; + } + + if (!$block['isStart']) { + break; + } + + $index = $tokens->findBlockEnd($block['type'], $index) + 1; + } + + $prev = $tokens->getPrevMeaningfulToken($index); + + return $tokens[$prev]->isGivenKind(T_CLOSE_TAG) ? $tokens->getPrevMeaningfulToken($prev) : $prev; + } + + /** + * Finds the start of the left-hand side of the comparison at the given + * index. + * + * The left-hand side ends when an operator with a lower precedence is + * encountered or when the block level for `()`, `{}` or `[]` goes below + * zero. + * + * @param Tokens $tokens The token list + * @param int $index The index of the comparison + * + * @return int The first index of the left-hand side of the comparison + */ + private function findComparisonStart(Tokens $tokens, $index) + { + --$index; + $nonBlockFound = false; + + while (0 <= $index) { + $token = $tokens[$index]; + if ($token->isGivenKind([T_WHITESPACE, T_COMMENT, T_DOC_COMMENT])) { + --$index; + + continue; + } + + if ($this->isOfLowerPrecedence($token)) { + break; + } + + $block = Tokens::detectBlockType($token); + if (null === $block) { + --$index; + $nonBlockFound = true; + + continue; + } + + if ( + $block['isStart'] + || ($nonBlockFound && Tokens::BLOCK_TYPE_CURLY_BRACE === $block['type']) // closing of structure not related to the comparison + ) { + break; + } + + $index = $tokens->findBlockStart($block['type'], $index) - 1; + } + + return $tokens->getNextMeaningfulToken($index); + } + + /** + * @return Tokens + */ + private function fixTokens(Tokens $tokens) + { + for ($i = \count($tokens) - 1; $i > 1; --$i) { + if ($tokens[$i]->isGivenKind($this->candidateTypes)) { + $yoda = $this->candidateTypesConfiguration[$tokens[$i]->getId()]; + } elseif ( + ($tokens[$i]->equals('<') && \in_array('<', $this->candidateTypes, true)) + || ($tokens[$i]->equals('>') && \in_array('>', $this->candidateTypes, true)) + ) { + $yoda = $this->candidateTypesConfiguration[$tokens[$i]->getContent()]; + } else { + continue; + } + + $fixableCompareInfo = $this->getCompareFixableInfo($tokens, $i, $yoda); + if (null === $fixableCompareInfo) { + continue; + } + + $i = $this->fixTokensCompare( + $tokens, + $fixableCompareInfo['left']['start'], + $fixableCompareInfo['left']['end'], + $i, + $fixableCompareInfo['right']['start'], + $fixableCompareInfo['right']['end'] + ); + } + + return $tokens; + } + + /** + * Fixes the comparison at the given index. + * + * A comparison is considered fixed when + * - both sides are a variable (e.g. $a === $b) + * - neither side is a variable (e.g. self::CONST === 3) + * - only the right-hand side is a variable (e.g. 3 === self::$var) + * + * If the left-hand side and right-hand side of the given comparison are + * swapped, this function runs recursively on the previous left-hand-side. + * + * @param int $startLeft + * @param int $endLeft + * @param int $compareOperatorIndex + * @param int $startRight + * @param int $endRight + * + * @return int a upper bound for all non-fixed comparisons + */ + private function fixTokensCompare( + Tokens $tokens, + $startLeft, + $endLeft, + $compareOperatorIndex, + $startRight, + $endRight + ) { + $type = $tokens[$compareOperatorIndex]->getId(); + $content = $tokens[$compareOperatorIndex]->getContent(); + if (\array_key_exists($type, $this->candidatesMap)) { + $tokens[$compareOperatorIndex] = clone $this->candidatesMap[$type]; + } elseif (\array_key_exists($content, $this->candidatesMap)) { + $tokens[$compareOperatorIndex] = clone $this->candidatesMap[$content]; + } + + $right = $this->fixTokensComparePart($tokens, $startRight, $endRight); + $left = $this->fixTokensComparePart($tokens, $startLeft, $endLeft); + + for ($i = $startRight; $i <= $endRight; ++$i) { + $tokens->clearAt($i); + } + + for ($i = $startLeft; $i <= $endLeft; ++$i) { + $tokens->clearAt($i); + } + + $tokens->insertAt($startRight, $left); + $tokens->insertAt($startLeft, $right); + + return $startLeft; + } + + /** + * @param int $start + * @param int $end + * + * @return Tokens + */ + private function fixTokensComparePart(Tokens $tokens, $start, $end) + { + $newTokens = $tokens->generatePartialCode($start, $end); + $newTokens = $this->fixTokens(Tokens::fromCode(sprintf('<?php %s;', $newTokens))); + $newTokens->clearAt(\count($newTokens) - 1); + $newTokens->clearAt(0); + $newTokens->clearEmptyTokens(); + + return $newTokens; + } + + /** + * @param int $index + * @param bool $yoda + * + * @return null|array + */ + private function getCompareFixableInfo(Tokens $tokens, $index, $yoda) + { + $left = $this->getLeftSideCompareFixableInfo($tokens, $index); + $right = $this->getRightSideCompareFixableInfo($tokens, $index); + + if (!$yoda && $this->isOfLowerPrecedenceAssignment($tokens[$tokens->getNextMeaningfulToken($right['end'])])) { + return null; + } + + if ($this->isListStatement($tokens, $left['start'], $left['end']) || $this->isListStatement($tokens, $right['start'], $right['end'])) { + return null; // do not fix lists assignment inside statements + } + + $strict = $this->configuration['always_move_variable']; + + $leftSideIsVariable = $this->isVariable($tokens, $left['start'], $left['end'], $strict); + $rightSideIsVariable = $this->isVariable($tokens, $right['start'], $right['end'], $strict); + + if (!($leftSideIsVariable ^ $rightSideIsVariable)) { + return null; // both are (not) variables, do not touch + } + + if (!$strict) { // special handling for braces with not "always_move_variable" + $leftSideIsVariable = $leftSideIsVariable && !$tokens[$left['start']]->equals('('); + $rightSideIsVariable = $rightSideIsVariable && !$tokens[$right['start']]->equals('('); + } + + return ($yoda && !$leftSideIsVariable) || (!$yoda && !$rightSideIsVariable) + ? null + : ['left' => $left, 'right' => $right] + ; + } + + /** + * @param int $index + * + * @return array + */ + private function getLeftSideCompareFixableInfo(Tokens $tokens, $index) + { + return [ + 'start' => $this->findComparisonStart($tokens, $index), + 'end' => $tokens->getPrevMeaningfulToken($index), + ]; + } + + /** + * @param int $index + * + * @return array + */ + private function getRightSideCompareFixableInfo(Tokens $tokens, $index) + { + return [ + 'start' => $tokens->getNextMeaningfulToken($index), + 'end' => $this->findComparisonEnd($tokens, $index), + ]; + } + + /** + * @param int $index + * @param int $end + * + * @return bool + */ + private function isListStatement(Tokens $tokens, $index, $end) + { + for ($i = $index; $i <= $end; ++$i) { + if ($tokens[$i]->isGivenKind([T_LIST, CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN, CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE])) { + return true; + } + } + + return false; + } + + /** + * Checks whether the given token has a lower precedence than `T_IS_EQUAL` + * or `T_IS_IDENTICAL`. + * + * @param Token $token The token to check + * + * @return bool Whether the token has a lower precedence + */ + private function isOfLowerPrecedence(Token $token) + { + static $tokens; + + if (null === $tokens) { + $tokens = [ + T_BOOLEAN_AND, // && + T_BOOLEAN_OR, // || + T_CASE, // case + T_DOUBLE_ARROW, // => + T_ECHO, // echo + T_GOTO, // goto + T_LOGICAL_AND, // and + T_LOGICAL_OR, // or + T_LOGICAL_XOR, // xor + T_OPEN_TAG, // <?php + T_OPEN_TAG_WITH_ECHO, + T_PRINT, // print + T_RETURN, // return + T_THROW, // throw + T_YIELD, // yield + ]; + + // @TODO: drop condition when PHP 7.0+ is required + if (\defined('T_COALESCE')) { + $tokens[] = T_COALESCE; // ?? + } + } + + static $otherTokens = [ + // bitwise and, or, xor + '&', '|', '^', + // ternary operators + '?', ':', + // end of PHP statement + ',', ';', + ]; + + return $this->isOfLowerPrecedenceAssignment($token) || $token->isGivenKind($tokens) || $token->equalsAny($otherTokens); + } + + /** + * Checks whether the given assignment token has a lower precedence than `T_IS_EQUAL` + * or `T_IS_IDENTICAL`. + */ + private function isOfLowerPrecedenceAssignment(Token $token) + { + static $tokens; + + if (null === $tokens) { + $tokens = [ + T_AND_EQUAL, // &= + T_CONCAT_EQUAL, // .= + T_DIV_EQUAL, // /= + T_MINUS_EQUAL, // -= + T_MOD_EQUAL, // %= + T_MUL_EQUAL, // *= + T_OR_EQUAL, // |= + T_PLUS_EQUAL, // += + T_POW_EQUAL, // **= + T_SL_EQUAL, // <<= + T_SR_EQUAL, // >>= + T_XOR_EQUAL, // ^= + ]; + + // @TODO: drop condition when PHP 7.4+ is required + if (\defined('T_COALESCE_EQUAL')) { + $tokens[] = T_COALESCE_EQUAL; // ??= + } + } + + return $token->equals('=') || $token->isGivenKind($tokens); + } + + /** + * Checks whether the tokens between the given start and end describe a + * variable. + * + * @param Tokens $tokens The token list + * @param int $start The first index of the possible variable + * @param int $end The last index of the possible variable + * @param bool $strict Enable strict variable detection + * + * @return bool Whether the tokens describe a variable + */ + private function isVariable(Tokens $tokens, $start, $end, $strict) + { + $tokenAnalyzer = new TokensAnalyzer($tokens); + + if ($start === $end) { + return $tokens[$start]->isGivenKind(T_VARIABLE); + } + + if ($tokens[$start]->equals('(')) { + return true; + } + + if ($strict) { + for ($index = $start; $index <= $end; ++$index) { + if ( + $tokens[$index]->isCast() + || $tokens[$index]->isGivenKind(T_INSTANCEOF) + || $tokens[$index]->equals('!') + || $tokenAnalyzer->isBinaryOperator($index) + ) { + return false; + } + } + } + + $index = $start; + + // handle multiple braces around statement ((($a === 1))) + while ( + $tokens[$index]->equals('(') + && $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index) === $end + ) { + $index = $tokens->getNextMeaningfulToken($index); + $end = $tokens->getPrevMeaningfulToken($end); + } + + $expectString = false; + while ($index <= $end) { + $current = $tokens[$index]; + if ($current->isComment() || $current->isWhitespace() || $tokens->isEmptyAt($index)) { + ++$index; + + continue; + } + + // check if this is the last token + if ($index === $end) { + return $current->isGivenKind($expectString ? T_STRING : T_VARIABLE); + } + + if ($current->isGivenKind([T_LIST, CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN, CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE])) { + return false; + } + + $nextIndex = $tokens->getNextMeaningfulToken($index); + $next = $tokens[$nextIndex]; + + // self:: or ClassName:: + if ($current->isGivenKind(T_STRING) && $next->isGivenKind(T_DOUBLE_COLON)) { + $index = $tokens->getNextMeaningfulToken($nextIndex); + + continue; + } + + // \ClassName + if ($current->isGivenKind(T_NS_SEPARATOR) && $next->isGivenKind(T_STRING)) { + $index = $nextIndex; + + continue; + } + + // ClassName\ + if ($current->isGivenKind(T_STRING) && $next->isGivenKind(T_NS_SEPARATOR)) { + $index = $nextIndex; + + continue; + } + + // $a-> or a-> (as in $b->a->c) + if ($current->isGivenKind([T_STRING, T_VARIABLE]) && $next->isObjectOperator()) { + $index = $tokens->getNextMeaningfulToken($nextIndex); + $expectString = true; + + continue; + } + + // $a[...], a[...] (as in $c->a[$b]), $a{...} or a{...} (as in $c->a{$b}) + if ( + $current->isGivenKind($expectString ? T_STRING : T_VARIABLE) + && $next->equalsAny(['[', [CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN, '{']]) + ) { + $index = $tokens->findBlockEnd( + $next->equals('[') ? Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE : Tokens::BLOCK_TYPE_ARRAY_INDEX_CURLY_BRACE, + $nextIndex + ); + + if ($index === $end) { + return true; + } + + $index = $tokens->getNextMeaningfulToken($index); + + if (!$tokens[$index]->equalsAny(['[', [CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN, '{']]) && !$tokens[$index]->isObjectOperator()) { + return false; + } + + $index = $tokens->getNextMeaningfulToken($index); + $expectString = true; + + continue; + } + + // $a(...) or $a->b(...) + if ($strict && $current->isGivenKind([T_STRING, T_VARIABLE]) && $next->equals('(')) { + return false; + } + + // {...} (as in $a->{$b}) + if ($expectString && $current->isGivenKind(CT::T_DYNAMIC_PROP_BRACE_OPEN)) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_DYNAMIC_PROP_BRACE, $index); + if ($index === $end) { + return true; + } + + $index = $tokens->getNextMeaningfulToken($index); + + if (!$tokens[$index]->isObjectOperator()) { + return false; + } + + $index = $tokens->getNextMeaningfulToken($index); + $expectString = true; + + continue; + } + + break; + } + + return !$this->isConstant($tokens, $start, $end); + } + + private function isConstant(Tokens $tokens, $index, $end) + { + $expectArrayOnly = false; + $expectNumberOnly = false; + $expectNothing = false; + + for (; $index <= $end; ++$index) { + $token = $tokens[$index]; + + if ($token->isComment() || $token->isWhitespace()) { + continue; + } + + if ($expectNothing) { + return false; + } + + if ($expectArrayOnly) { + if ($token->equalsAny(['(', ')', [CT::T_ARRAY_SQUARE_BRACE_CLOSE]])) { + continue; + } + + return false; + } + + if ($token->isGivenKind([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN])) { + $expectArrayOnly = true; + + continue; + } + + if ($expectNumberOnly && !$token->isGivenKind([T_LNUMBER, T_DNUMBER])) { + return false; + } + + if ($token->equals('-')) { + $expectNumberOnly = true; + + continue; + } + + if ( + $token->isGivenKind([T_LNUMBER, T_DNUMBER, T_CONSTANT_ENCAPSED_STRING]) + || $token->equalsAny([[T_STRING, 'true'], [T_STRING, 'false'], [T_STRING, 'null']]) + ) { + $expectNothing = true; + + continue; + } + + return false; + } + + return true; + } + + private function resolveConfiguration() + { + $candidateTypes = []; + $this->candidatesMap = []; + + if (null !== $this->configuration['equal']) { + // `==`, `!=` and `<>` + $candidateTypes[T_IS_EQUAL] = $this->configuration['equal']; + $candidateTypes[T_IS_NOT_EQUAL] = $this->configuration['equal']; + } + + if (null !== $this->configuration['identical']) { + // `===` and `!==` + $candidateTypes[T_IS_IDENTICAL] = $this->configuration['identical']; + $candidateTypes[T_IS_NOT_IDENTICAL] = $this->configuration['identical']; + } + + if (null !== $this->configuration['less_and_greater']) { + // `<`, `<=`, `>` and `>=` + $candidateTypes[T_IS_SMALLER_OR_EQUAL] = $this->configuration['less_and_greater']; + $this->candidatesMap[T_IS_SMALLER_OR_EQUAL] = new Token([T_IS_GREATER_OR_EQUAL, '>=']); + + $candidateTypes[T_IS_GREATER_OR_EQUAL] = $this->configuration['less_and_greater']; + $this->candidatesMap[T_IS_GREATER_OR_EQUAL] = new Token([T_IS_SMALLER_OR_EQUAL, '<=']); + + $candidateTypes['<'] = $this->configuration['less_and_greater']; + $this->candidatesMap['<'] = new Token('>'); + + $candidateTypes['>'] = $this->configuration['less_and_greater']; + $this->candidatesMap['>'] = new Token('<'); + } + + $this->candidateTypesConfiguration = $candidateTypes; + $this->candidateTypes = array_keys($candidateTypes); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/DefinedFixerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DefinedFixerInterface.php new file mode 100644 index 0000000..939e718 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DefinedFixerInterface.php @@ -0,0 +1,29 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer; + +use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +interface DefinedFixerInterface extends FixerInterface +{ + /** + * Returns the definition of the fixer. + * + * @return FixerDefinitionInterface + */ + public function getDefinition(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/DeprecatedFixerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DeprecatedFixerInterface.php new file mode 100644 index 0000000..a33e632 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DeprecatedFixerInterface.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer; + +/** + * @author Kuba Werłos <werlos@gmail.com> + */ +interface DeprecatedFixerInterface extends FixerInterface +{ + /** + * Returns names of fixers to use instead, if any. + * + * @return string[] + */ + public function getSuccessorsNames(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationArrayAssignmentFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationArrayAssignmentFixer.php new file mode 100644 index 0000000..345b526 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationArrayAssignmentFixer.php @@ -0,0 +1,104 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\DoctrineAnnotation; + +use Doctrine\Common\Annotations\DocLexer; +use PhpCsFixer\AbstractDoctrineAnnotationFixer; +use PhpCsFixer\Doctrine\Annotation\Tokens; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * Forces the configured operator for assignment in arrays in Doctrine Annotations. + */ +final class DoctrineAnnotationArrayAssignmentFixer extends AbstractDoctrineAnnotationFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Doctrine annotations must use configured operator for assignment in arrays.', + [ + new CodeSample( + "<?php\n/**\n * @Foo({bar : \"baz\"})\n */\nclass Bar {}\n" + ), + new CodeSample( + "<?php\n/**\n * @Foo({bar = \"baz\"})\n */\nclass Bar {}\n", + ['operator' => ':'] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before DoctrineAnnotationSpacesFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $options = parent::createConfigurationDefinition()->getOptions(); + + $operator = new FixerOptionBuilder('operator', 'The operator to use.'); + $options[] = $operator + ->setAllowedValues(['=', ':']) + ->setDefault('=') + ->getOption() + ; + + return new FixerConfigurationResolver($options); + } + + /** + * {@inheritdoc} + */ + protected function fixAnnotations(Tokens $doctrineAnnotationTokens) + { + $scopes = []; + foreach ($doctrineAnnotationTokens as $token) { + if ($token->isType(DocLexer::T_OPEN_PARENTHESIS)) { + $scopes[] = 'annotation'; + + continue; + } + + if ($token->isType(DocLexer::T_OPEN_CURLY_BRACES)) { + $scopes[] = 'array'; + + continue; + } + + if ($token->isType([DocLexer::T_CLOSE_PARENTHESIS, DocLexer::T_CLOSE_CURLY_BRACES])) { + array_pop($scopes); + + continue; + } + + if ('array' === end($scopes) && $token->isType([DocLexer::T_EQUALS, DocLexer::T_COLON])) { + $token->setContent($this->configuration['operator']); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationBracesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationBracesFixer.php new file mode 100644 index 0000000..67753e8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationBracesFixer.php @@ -0,0 +1,123 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\DoctrineAnnotation; + +use Doctrine\Common\Annotations\DocLexer; +use PhpCsFixer\AbstractDoctrineAnnotationFixer; +use PhpCsFixer\Doctrine\Annotation\Token; +use PhpCsFixer\Doctrine\Annotation\Tokens; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * Adds braces to Doctrine annotations when missing. + */ +final class DoctrineAnnotationBracesFixer extends AbstractDoctrineAnnotationFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Doctrine annotations without arguments must use the configured syntax.', + [ + new CodeSample( + "<?php\n/**\n * @Foo()\n */\nclass Bar {}\n" + ), + new CodeSample( + "<?php\n/**\n * @Foo\n */\nclass Bar {}\n", + ['syntax' => 'with_braces'] + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver(array_merge( + parent::createConfigurationDefinition()->getOptions(), + [ + (new FixerOptionBuilder('syntax', 'Whether to add or remove braces.')) + ->setAllowedValues(['with_braces', 'without_braces']) + ->setDefault('without_braces') + ->getOption(), + ] + )); + } + + /** + * {@inheritdoc} + */ + protected function fixAnnotations(Tokens $doctrineAnnotationTokens) + { + if ('without_braces' === $this->configuration['syntax']) { + $this->removesBracesFromAnnotations($doctrineAnnotationTokens); + } else { + $this->addBracesToAnnotations($doctrineAnnotationTokens); + } + } + + private function addBracesToAnnotations(Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$tokens[$index]->isType(DocLexer::T_AT)) { + continue; + } + + $braceIndex = $tokens->getNextMeaningfulToken($index + 1); + if (null !== $braceIndex && $tokens[$braceIndex]->isType(DocLexer::T_OPEN_PARENTHESIS)) { + continue; + } + + $tokens->insertAt($index + 2, new Token(DocLexer::T_OPEN_PARENTHESIS, '(')); + $tokens->insertAt($index + 3, new Token(DocLexer::T_CLOSE_PARENTHESIS, ')')); + } + } + + private function removesBracesFromAnnotations(Tokens $tokens) + { + for ($index = 0, $max = \count($tokens); $index < $max; ++$index) { + if (!$tokens[$index]->isType(DocLexer::T_AT)) { + continue; + } + + $openBraceIndex = $tokens->getNextMeaningfulToken($index + 1); + if (null === $openBraceIndex) { + continue; + } + + if (!$tokens[$openBraceIndex]->isType(DocLexer::T_OPEN_PARENTHESIS)) { + continue; + } + + $closeBraceIndex = $tokens->getNextMeaningfulToken($openBraceIndex); + if (null === $closeBraceIndex) { + continue; + } + + if (!$tokens[$closeBraceIndex]->isType(DocLexer::T_CLOSE_PARENTHESIS)) { + continue; + } + + for ($currentIndex = $index + 2; $currentIndex <= $closeBraceIndex; ++$currentIndex) { + $tokens[$currentIndex]->clear(); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationIndentationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationIndentationFixer.php new file mode 100644 index 0000000..eed9081 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationIndentationFixer.php @@ -0,0 +1,199 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\DoctrineAnnotation; + +use Doctrine\Common\Annotations\DocLexer; +use PhpCsFixer\AbstractDoctrineAnnotationFixer; +use PhpCsFixer\Doctrine\Annotation\Tokens; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; + +final class DoctrineAnnotationIndentationFixer extends AbstractDoctrineAnnotationFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Doctrine annotations must be indented with four spaces.', + [ + new CodeSample("<?php\n/**\n * @Foo(\n * foo=\"foo\"\n * )\n */\nclass Bar {}\n"), + new CodeSample( + "<?php\n/**\n * @Foo({@Bar,\n * @Baz})\n */\nclass Bar {}\n", + ['indent_mixed_lines' => true] + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver(array_merge( + parent::createConfigurationDefinition()->getOptions(), + [ + (new FixerOptionBuilder('indent_mixed_lines', 'Whether to indent lines that have content before closing parenthesis.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + ] + )); + } + + /** + * {@inheritdoc} + */ + protected function fixAnnotations(Tokens $doctrineAnnotationTokens) + { + $annotationPositions = []; + for ($index = 0, $max = \count($doctrineAnnotationTokens); $index < $max; ++$index) { + if (!$doctrineAnnotationTokens[$index]->isType(DocLexer::T_AT)) { + continue; + } + + $annotationEndIndex = $doctrineAnnotationTokens->getAnnotationEnd($index); + if (null === $annotationEndIndex) { + return; + } + + $annotationPositions[] = [$index, $annotationEndIndex]; + $index = $annotationEndIndex; + } + + $indentLevel = 0; + foreach ($doctrineAnnotationTokens as $index => $token) { + if (!$token->isType(DocLexer::T_NONE) || false === strpos($token->getContent(), "\n")) { + continue; + } + + if (!$this->indentationCanBeFixed($doctrineAnnotationTokens, $index, $annotationPositions)) { + continue; + } + + $braces = $this->getLineBracesCount($doctrineAnnotationTokens, $index); + $delta = $braces[0] - $braces[1]; + $mixedBraces = 0 === $delta && $braces[0] > 0; + $extraIndentLevel = 0; + + if ($indentLevel > 0 && ($delta < 0 || $mixedBraces)) { + --$indentLevel; + + if ($this->configuration['indent_mixed_lines'] && $this->isClosingLineWithMeaningfulContent($doctrineAnnotationTokens, $index)) { + $extraIndentLevel = 1; + } + } + + $token->setContent(Preg::replace( + '/(\n( +\*)?) *$/', + '$1'.str_repeat(' ', 4 * ($indentLevel + $extraIndentLevel) + 1), + $token->getContent() + )); + + if ($delta > 0 || $mixedBraces) { + ++$indentLevel; + } + } + } + + /** + * @param int $index + * + * @return int[] + */ + private function getLineBracesCount(Tokens $tokens, $index) + { + $opening = 0; + $closing = 0; + + while (isset($tokens[++$index])) { + $token = $tokens[$index]; + if ($token->isType(DocLexer::T_NONE) && false !== strpos($token->getContent(), "\n")) { + break; + } + + if ($token->isType([DocLexer::T_OPEN_PARENTHESIS, DocLexer::T_OPEN_CURLY_BRACES])) { + ++$opening; + + continue; + } + + if (!$token->isType([DocLexer::T_CLOSE_PARENTHESIS, DocLexer::T_CLOSE_CURLY_BRACES])) { + continue; + } + + if ($opening > 0) { + --$opening; + } else { + ++$closing; + } + } + + return [$opening, $closing]; + } + + /** + * @param int $index + * + * @return bool + */ + private function isClosingLineWithMeaningfulContent(Tokens $tokens, $index) + { + while (isset($tokens[++$index])) { + $token = $tokens[$index]; + if ($token->isType(DocLexer::T_NONE)) { + if (false !== strpos($token->getContent(), "\n")) { + return false; + } + + continue; + } + + return !$token->isType([DocLexer::T_CLOSE_PARENTHESIS, DocLexer::T_CLOSE_CURLY_BRACES]); + } + + return false; + } + + /** + * @param int $newLineTokenIndex + * @param array<array<int>> $annotationPositions Pairs of begin and end indexes of main annotations + * + * @return bool + */ + private function indentationCanBeFixed(Tokens $tokens, $newLineTokenIndex, array $annotationPositions) + { + foreach ($annotationPositions as $position) { + if ($newLineTokenIndex >= $position[0] && $newLineTokenIndex <= $position[1]) { + return true; + } + } + + for ($index = $newLineTokenIndex + 1, $max = \count($tokens); $index < $max; ++$index) { + $token = $tokens[$index]; + + if (false !== strpos($token->getContent(), "\n")) { + return false; + } + + return $tokens[$index]->isType(DocLexer::T_AT); + } + + return false; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationSpacesFixer.php new file mode 100644 index 0000000..04d34a7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/DoctrineAnnotation/DoctrineAnnotationSpacesFixer.php @@ -0,0 +1,349 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\DoctrineAnnotation; + +use Doctrine\Common\Annotations\DocLexer; +use PhpCsFixer\AbstractDoctrineAnnotationFixer; +use PhpCsFixer\Doctrine\Annotation\Token; +use PhpCsFixer\Doctrine\Annotation\Tokens; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; + +/** + * Fixes spaces around commas and assignment operators in Doctrine annotations. + */ +final class DoctrineAnnotationSpacesFixer extends AbstractDoctrineAnnotationFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Fixes spaces in Doctrine annotations.', + [ + new CodeSample( + "<?php\n/**\n * @Foo ( )\n */\nclass Bar {}\n\n/**\n * @Foo(\"bar\" ,\"baz\")\n */\nclass Bar2 {}\n\n/**\n * @Foo(foo = \"foo\", bar = {\"foo\":\"foo\", \"bar\"=\"bar\"})\n */\nclass Bar3 {}\n" + ), + new CodeSample( + "<?php\n/**\n * @Foo(foo = \"foo\", bar = {\"foo\":\"foo\", \"bar\"=\"bar\"})\n */\nclass Bar {}\n", + ['after_array_assignments_equals' => false, 'before_array_assignments_equals' => false] + ), + ], + 'There must not be any space around parentheses; commas must be preceded by no space and followed by one space; there must be no space around named arguments assignment operator; there must be one space around array assignment operator.' + ); + } + + /** + * {@inheritdoc} + * + * Must run after DoctrineAnnotationArrayAssignmentFixer. + */ + public function getPriority() + { + return 0; + } + + public function configure(array $configuration = null) + { + parent::configure($configuration); + + if (!$this->configuration['around_argument_assignments']) { + foreach ([ + 'before_argument_assignments', + 'after_argument_assignments', + ] as $newOption) { + if (!\array_key_exists($newOption, $configuration)) { + $this->configuration[$newOption] = null; + } + } + } + + if (!$this->configuration['around_array_assignments']) { + foreach ([ + 'before_array_assignments_equals', + 'after_array_assignments_equals', + 'before_array_assignments_colon', + 'after_array_assignments_colon', + ] as $newOption) { + if (!\array_key_exists($newOption, $configuration)) { + $this->configuration[$newOption] = null; + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver(array_merge( + parent::createConfigurationDefinition()->getOptions(), + [ + (new FixerOptionBuilder('around_parentheses', 'Whether to fix spaces around parentheses.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('around_commas', 'Whether to fix spaces around commas.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('around_argument_assignments', 'Whether to fix spaces around argument assignment operator.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->setDeprecationMessage('Use options `before_argument_assignments` and `after_argument_assignments` instead.') + ->getOption(), + (new FixerOptionBuilder('before_argument_assignments', 'Whether to add, remove or ignore spaces before argument assignment operator.')) + ->setAllowedTypes(['null', 'bool']) + ->setDefault(false) + ->getOption(), + (new FixerOptionBuilder('after_argument_assignments', 'Whether to add, remove or ignore spaces after argument assignment operator.')) + ->setAllowedTypes(['null', 'bool']) + ->setDefault(false) + ->getOption(), + (new FixerOptionBuilder('around_array_assignments', 'Whether to fix spaces around array assignment operators.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->setDeprecationMessage('Use options `before_array_assignments_equals`, `after_array_assignments_equals`, `before_array_assignments_colon` and `after_array_assignments_colon` instead.') + ->getOption(), + (new FixerOptionBuilder('before_array_assignments_equals', 'Whether to add, remove or ignore spaces before array `=` assignment operator.')) + ->setAllowedTypes(['null', 'bool']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('after_array_assignments_equals', 'Whether to add, remove or ignore spaces after array assignment `=` operator.')) + ->setAllowedTypes(['null', 'bool']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('before_array_assignments_colon', 'Whether to add, remove or ignore spaces before array `:` assignment operator.')) + ->setAllowedTypes(['null', 'bool']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('after_array_assignments_colon', 'Whether to add, remove or ignore spaces after array assignment `:` operator.')) + ->setAllowedTypes(['null', 'bool']) + ->setDefault(true) + ->getOption(), + ] + )); + } + + /** + * {@inheritdoc} + */ + protected function fixAnnotations(Tokens $doctrineAnnotationTokens) + { + if ($this->configuration['around_parentheses']) { + $this->fixSpacesAroundParentheses($doctrineAnnotationTokens); + } + + if ($this->configuration['around_commas']) { + $this->fixSpacesAroundCommas($doctrineAnnotationTokens); + } + + if ( + null !== $this->configuration['before_argument_assignments'] + || null !== $this->configuration['after_argument_assignments'] + || null !== $this->configuration['before_array_assignments_equals'] + || null !== $this->configuration['after_array_assignments_equals'] + || null !== $this->configuration['before_array_assignments_colon'] + || null !== $this->configuration['after_array_assignments_colon'] + ) { + $this->fixAroundAssignments($doctrineAnnotationTokens); + } + } + + private function fixSpacesAroundParentheses(Tokens $tokens) + { + $inAnnotationUntilIndex = null; + + foreach ($tokens as $index => $token) { + if (null !== $inAnnotationUntilIndex) { + if ($index === $inAnnotationUntilIndex) { + $inAnnotationUntilIndex = null; + + continue; + } + } elseif ($tokens[$index]->isType(DocLexer::T_AT)) { + $endIndex = $tokens->getAnnotationEnd($index); + if (null !== $endIndex) { + $inAnnotationUntilIndex = $endIndex + 1; + } + + continue; + } + + if (null === $inAnnotationUntilIndex) { + continue; + } + + if (!$token->isType([DocLexer::T_OPEN_PARENTHESIS, DocLexer::T_CLOSE_PARENTHESIS])) { + continue; + } + + if ($token->isType(DocLexer::T_OPEN_PARENTHESIS)) { + $token = $tokens[$index - 1]; + if ($token->isType(DocLexer::T_NONE)) { + $token->clear(); + } + + $token = $tokens[$index + 1]; + } else { + $token = $tokens[$index - 1]; + } + + if ($token->isType(DocLexer::T_NONE)) { + if (false !== strpos($token->getContent(), "\n")) { + continue; + } + + $token->clear(); + } + } + } + + private function fixSpacesAroundCommas(Tokens $tokens) + { + $inAnnotationUntilIndex = null; + + foreach ($tokens as $index => $token) { + if (null !== $inAnnotationUntilIndex) { + if ($index === $inAnnotationUntilIndex) { + $inAnnotationUntilIndex = null; + + continue; + } + } elseif ($tokens[$index]->isType(DocLexer::T_AT)) { + $endIndex = $tokens->getAnnotationEnd($index); + if (null !== $endIndex) { + $inAnnotationUntilIndex = $endIndex; + } + + continue; + } + + if (null === $inAnnotationUntilIndex) { + continue; + } + + if (!$token->isType(DocLexer::T_COMMA)) { + continue; + } + + $token = $tokens[$index - 1]; + if ($token->isType(DocLexer::T_NONE)) { + $token->clear(); + } + + if ($index < \count($tokens) - 1 && !Preg::match('/^\s/', $tokens[$index + 1]->getContent())) { + $tokens->insertAt($index + 1, new Token(DocLexer::T_NONE, ' ')); + } + } + } + + private function fixAroundAssignments(Tokens $tokens) + { + $beforeArguments = $this->configuration['before_argument_assignments']; + $afterArguments = $this->configuration['after_argument_assignments']; + $beforeArraysEquals = $this->configuration['before_array_assignments_equals']; + $afterArraysEquals = $this->configuration['after_array_assignments_equals']; + $beforeArraysColon = $this->configuration['before_array_assignments_colon']; + $afterArraysColon = $this->configuration['after_array_assignments_colon']; + + $scopes = []; + foreach ($tokens as $index => $token) { + $endScopeType = end($scopes); + if (false !== $endScopeType && $token->isType($endScopeType)) { + array_pop($scopes); + + continue; + } + + if ($tokens[$index]->isType(DocLexer::T_AT)) { + $scopes[] = DocLexer::T_CLOSE_PARENTHESIS; + + continue; + } + + if ($tokens[$index]->isType(DocLexer::T_OPEN_CURLY_BRACES)) { + $scopes[] = DocLexer::T_CLOSE_CURLY_BRACES; + + continue; + } + + if (DocLexer::T_CLOSE_PARENTHESIS === $endScopeType && $token->isType(DocLexer::T_EQUALS)) { + $this->updateSpacesAfter($tokens, $index, $afterArguments); + $this->updateSpacesBefore($tokens, $index, $beforeArguments); + + continue; + } + + if (DocLexer::T_CLOSE_CURLY_BRACES === $endScopeType) { + if ($token->isType(DocLexer::T_EQUALS)) { + $this->updateSpacesAfter($tokens, $index, $afterArraysEquals); + $this->updateSpacesBefore($tokens, $index, $beforeArraysEquals); + + continue; + } + + if ($token->isType(DocLexer::T_COLON)) { + $this->updateSpacesAfter($tokens, $index, $afterArraysColon); + $this->updateSpacesBefore($tokens, $index, $beforeArraysColon); + } + } + } + } + + /** + * @param int $index + * @param null|bool $insert + */ + private function updateSpacesAfter(Tokens $tokens, $index, $insert) + { + $this->updateSpacesAt($tokens, $index + 1, $index + 1, $insert); + } + + /** + * @param int $index + * @param null|bool $insert + */ + private function updateSpacesBefore(Tokens $tokens, $index, $insert) + { + $this->updateSpacesAt($tokens, $index - 1, $index, $insert); + } + + /** + * @param int $index + * @param int $insertIndex + * @param null|bool $insert + */ + private function updateSpacesAt(Tokens $tokens, $index, $insertIndex, $insert) + { + if (null === $insert) { + return; + } + + $token = $tokens[$index]; + if ($insert) { + if (!$token->isType(DocLexer::T_NONE)) { + $tokens->insertAt($insertIndex, $token = new Token()); + } + + $token->setContent(' '); + } elseif ($token->isType(DocLexer::T_NONE)) { + $token->clear(); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FixerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FixerInterface.php similarity index 53% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/FixerInterface.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/FixerInterface.php index c66690b..e4f5172 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/FixerInterface.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FixerInterface.php @@ -10,50 +10,45 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS; +namespace PhpCsFixer\Fixer; + +use PhpCsFixer\Tokenizer\Tokens; /** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> * @author Fabien Potencier <fabien@symfony.com> */ interface FixerInterface { - const NONE_LEVEL = 0; - const PSR0_LEVEL = 1; - const PSR1_LEVEL = 3; - const PSR2_LEVEL = 7; - const SYMFONY_LEVEL = 15; - const CONTRIB_LEVEL = 32; - /** - * Fixes a file. + * Check if the fixer is a candidate for given Tokens collection. * - * @param \SplFileInfo $file A \SplFileInfo instance - * @param string $content The file content + * Fixer is a candidate when the collection contains tokens that may be fixed + * during fixer work. This could be considered as some kind of bloom filter. + * When this method returns true then to the Tokens collection may or may not + * need a fixing, but when this method returns false then the Tokens collection + * need no fixing for sure. * - * @return string The fixed file content + * @return bool */ - public function fix(\SplFileInfo $file, $content); + public function isCandidate(Tokens $tokens); /** - * Returns the description of the fixer. + * Check if fixer is risky or not. * - * A short one-line description of what the fixer does. + * Risky fixer could change code behavior! * - * @return string The description of the fixer + * @return bool */ - public function getDescription(); + public function isRisky(); /** - * Returns the level of CS standard. + * Fixes a file. * - * Can be one of: - * - self::PSR0_LEVEL, - * - self::PSR1_LEVEL, - * - self::PSR2_LEVEL, - * - self::SYMFONY_LEVEL, - * - self::CONTRIB_LEVEL. + * @param \SplFileInfo $file A \SplFileInfo instance + * @param Tokens $tokens Tokens collection */ - public function getLevel(); + public function fix(\SplFileInfo $file, Tokens $tokens); /** * Returns the name of the fixer. diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php new file mode 100644 index 0000000..8d3db7d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/CombineNestedDirnameFixer.php @@ -0,0 +1,234 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Gregor Harlan + */ +final class CombineNestedDirnameFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replace multiple nested calls of `dirname` by only one call with second `$level` parameter. Requires PHP >= 7.0.', + [ + new VersionSpecificCodeSample( + "<?php\ndirname(dirname(dirname(\$path)));\n", + new VersionSpecification(70000) + ), + ], + null, + 'Risky when the function `dirname` is overridden.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + * + * Must run before MethodArgumentSpaceFixer, NoSpacesInsideParenthesisFixer. + * Must run after DirConstantFixer. + */ + public function getPriority() + { + return 35; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + $dirnameInfo = $this->getDirnameInfo($tokens, $index); + + if (!$dirnameInfo) { + continue; + } + + $prev = $tokens->getPrevMeaningfulToken($dirnameInfo['indexes'][0]); + + if (!$tokens[$prev]->equals('(')) { + continue; + } + + $prev = $tokens->getPrevMeaningfulToken($prev); + + $firstArgumentEnd = $dirnameInfo['end']; + + $dirnameInfoArray = [$dirnameInfo]; + + while ($dirnameInfo = $this->getDirnameInfo($tokens, $prev, $firstArgumentEnd)) { + $dirnameInfoArray[] = $dirnameInfo; + + $prev = $tokens->getPrevMeaningfulToken($dirnameInfo['indexes'][0]); + + if (!$tokens[$prev]->equals('(')) { + break; + } + + $prev = $tokens->getPrevMeaningfulToken($prev); + $firstArgumentEnd = $dirnameInfo['end']; + } + + if (\count($dirnameInfoArray) > 1) { + $this->combineDirnames($tokens, $dirnameInfoArray); + } + + $index = $prev; + } + } + + /** + * @param int $index Index of `dirname` + * @param null|int $firstArgumentEndIndex Index of last token of first argument of `dirname` call + * + * @return array|bool `false` when it is not a (supported) `dirname` call, an array with info about the dirname call otherwise + */ + private function getDirnameInfo(Tokens $tokens, $index, $firstArgumentEndIndex = null) + { + if (!$tokens[$index]->equals([T_STRING, 'dirname'], false)) { + return false; + } + + if (!(new FunctionsAnalyzer())->isGlobalFunctionCall($tokens, $index)) { + return false; + } + + $info['indexes'] = []; + + $prev = $tokens->getPrevMeaningfulToken($index); + + if ($tokens[$prev]->isGivenKind(T_NS_SEPARATOR)) { + $info['indexes'][] = $prev; + } + + $info['indexes'][] = $index; + + // opening parenthesis "(" + $next = $tokens->getNextMeaningfulToken($index); + $info['indexes'][] = $next; + + if (null !== $firstArgumentEndIndex) { + $next = $tokens->getNextMeaningfulToken($firstArgumentEndIndex); + } else { + $next = $tokens->getNextMeaningfulToken($next); + + if ($tokens[$next]->equals(')')) { + return false; + } + + while (!$tokens[$next]->equalsAny([',', ')'])) { + $blockType = Tokens::detectBlockType($tokens[$next]); + + if ($blockType) { + $next = $tokens->findBlockEnd($blockType['type'], $next); + } + + $next = $tokens->getNextMeaningfulToken($next); + } + } + + $info['indexes'][] = $next; + + if ($tokens[$next]->equals(',')) { + $next = $tokens->getNextMeaningfulToken($next); + $info['indexes'][] = $next; + } + + if ($tokens[$next]->equals(')')) { + $info['levels'] = 1; + $info['end'] = $next; + + return $info; + } + + if (!$tokens[$next]->isGivenKind(T_LNUMBER)) { + return false; + } + + $info['secondArgument'] = $next; + $info['levels'] = (int) $tokens[$next]->getContent(); + + $next = $tokens->getNextMeaningfulToken($next); + + if ($tokens[$next]->equals(',')) { + $info['indexes'][] = $next; + $next = $tokens->getNextMeaningfulToken($next); + } + + if (!$tokens[$next]->equals(')')) { + return false; + } + + $info['indexes'][] = $next; + $info['end'] = $next; + + return $info; + } + + private function combineDirnames(Tokens $tokens, array $dirnameInfoArray) + { + $outerDirnameInfo = array_pop($dirnameInfoArray); + $levels = $outerDirnameInfo['levels']; + + foreach ($dirnameInfoArray as $dirnameInfo) { + $levels += $dirnameInfo['levels']; + + foreach ($dirnameInfo['indexes'] as $index) { + $tokens->removeLeadingWhitespace($index); + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } + } + + $levelsToken = new Token([T_LNUMBER, (string) $levels]); + + if (isset($outerDirnameInfo['secondArgument'])) { + $tokens[$outerDirnameInfo['secondArgument']] = $levelsToken; + } else { + $prev = $tokens->getPrevMeaningfulToken($outerDirnameInfo['end']); + $items = []; + if (!$tokens[$prev]->equals(',')) { + $items = [new Token(','), new Token([T_WHITESPACE, ' '])]; + } + $items[] = $levelsToken; + $tokens->insertAt($outerDirnameInfo['end'], $items); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FopenFlagOrderFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FopenFlagOrderFixer.php new file mode 100644 index 0000000..c0d7667 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FopenFlagOrderFixer.php @@ -0,0 +1,130 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFopenFlagFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class FopenFlagOrderFixer extends AbstractFopenFlagFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Order the flags in `fopen` calls, `b` and `t` must be last.', + [new CodeSample("<?php\n\$a = fopen(\$foo, 'br+');\n")], + null, + 'Risky when the function `fopen` is overridden.' + ); + } + + /** + * @param int $argumentStartIndex + * @param int $argumentEndIndex + */ + protected function fixFopenFlagToken(Tokens $tokens, $argumentStartIndex, $argumentEndIndex) + { + $argumentFlagIndex = null; + + for ($i = $argumentStartIndex; $i <= $argumentEndIndex; ++$i) { + if ($tokens[$i]->isGivenKind([T_WHITESPACE, T_COMMENT, T_DOC_COMMENT])) { + continue; + } + + if (null !== $argumentFlagIndex) { + return; // multiple meaningful tokens found, no candidate for fixing + } + + $argumentFlagIndex = $i; + } + + // check if second argument is candidate + if (null === $argumentFlagIndex || !$tokens[$argumentFlagIndex]->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) { + return; + } + + $content = $tokens[$argumentFlagIndex]->getContent(); + $contentQuote = $content[0]; // `'`, `"`, `b` or `B` + + if ('b' === $contentQuote || 'B' === $contentQuote) { + $binPrefix = $contentQuote; + $contentQuote = $content[1]; // `'` or `"` + $mode = substr($content, 2, -1); + } else { + $binPrefix = ''; + $mode = substr($content, 1, -1); + } + + $modeLength = \strlen($mode); + if ($modeLength < 2) { + return; // nothing to sort + } + + if (false === $this->isValidModeString($mode)) { + return; + } + + $split = $this->sortFlags(Preg::split('#([^\+]\+?)#', $mode, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)); + $newContent = $binPrefix.$contentQuote.implode('', $split).$contentQuote; + + if ($content !== $newContent) { + $tokens[$argumentFlagIndex] = new Token([T_CONSTANT_ENCAPSED_STRING, $newContent]); + } + } + + /** + * @param string[] $flags + * + * @return string[] + */ + private function sortFlags(array $flags) + { + usort( + $flags, + static function ($flag1, $flag2) { + if ($flag1 === $flag2) { + return 0; + } + + if ('b' === $flag1) { + return 1; + } + + if ('b' === $flag2) { + return -1; + } + + if ('t' === $flag1) { + return 1; + } + + if ('t' === $flag2) { + return -1; + } + + return $flag1 < $flag2 ? -1 : 1; + } + ); + + return $flags; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FopenFlagsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FopenFlagsFixer.php new file mode 100644 index 0000000..ea9ba96 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FopenFlagsFixer.php @@ -0,0 +1,114 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFopenFlagFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class FopenFlagsFixer extends AbstractFopenFlagFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'The flags in `fopen` calls must omit `t`, and `b` must be omitted or included consistently.', + [ + new CodeSample("<?php\n\$a = fopen(\$foo, 'rwt');\n"), + new CodeSample("<?php\n\$a = fopen(\$foo, 'rwt');\n", ['b_mode' => false]), + ], + null, + 'Risky when the function `fopen` is overridden.' + ); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('b_mode', 'The `b` flag must be used (`true`) or omitted (`false`).')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + ]); + } + + /** + * @param int $argumentStartIndex + * @param int $argumentEndIndex + */ + protected function fixFopenFlagToken(Tokens $tokens, $argumentStartIndex, $argumentEndIndex) + { + $argumentFlagIndex = null; + + for ($i = $argumentStartIndex; $i <= $argumentEndIndex; ++$i) { + if ($tokens[$i]->isGivenKind([T_WHITESPACE, T_COMMENT, T_DOC_COMMENT])) { + continue; + } + + if (null !== $argumentFlagIndex) { + return; // multiple meaningful tokens found, no candidate for fixing + } + + $argumentFlagIndex = $i; + } + + // check if second argument is candidate + if (null === $argumentFlagIndex || !$tokens[$argumentFlagIndex]->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) { + return; + } + + $content = $tokens[$argumentFlagIndex]->getContent(); + $contentQuote = $content[0]; // `'`, `"`, `b` or `B` + + if ('b' === $contentQuote || 'B' === $contentQuote) { + $binPrefix = $contentQuote; + $contentQuote = $content[1]; // `'` or `"` + $mode = substr($content, 2, -1); + } else { + $binPrefix = ''; + $mode = substr($content, 1, -1); + } + + if (false === $this->isValidModeString($mode)) { + return; + } + + $mode = str_replace('t', '', $mode); + if ($this->configuration['b_mode']) { + if (false === strpos($mode, 'b')) { + $mode .= 'b'; + } + } else { + $mode = str_replace('b', '', $mode); + } + + $newContent = $binPrefix.$contentQuote.$mode.$contentQuote; + + if ($content !== $newContent) { + $tokens[$argumentFlagIndex] = new Token([T_CONSTANT_ENCAPSED_STRING, $newContent]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FunctionDeclarationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FunctionDeclarationFixer.php new file mode 100644 index 0000000..ac61aa4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FunctionDeclarationFixer.php @@ -0,0 +1,231 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * Fixer for rules defined in PSR2 generally (¶1 and ¶6). + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class FunctionDeclarationFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @internal + */ + const SPACING_NONE = 'none'; + + /** + * @internal + */ + const SPACING_ONE = 'one'; + + private $supportedSpacings = [self::SPACING_NONE, self::SPACING_ONE]; + + /** + * @var string + */ + private $singleLineWhitespaceOptions = " \t"; + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) { + return true; + } + + return $tokens->isTokenKindFound(T_FUNCTION); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Spaces should be properly placed in a function declaration.', + [ + new CodeSample( + '<?php + +class Foo +{ + public static function bar ( $baz , $foo ) + { + return false; + } +} + +function foo ($bar, $baz) +{ + return false; +} +' + ), + new CodeSample( + '<?php +$f = function () {}; +', + ['closure_function_spacing' => self::SPACING_NONE] + ), + new VersionSpecificCodeSample( + '<?php +$f = fn () => null; +', + new VersionSpecification(70400), + ['closure_function_spacing' => self::SPACING_NONE] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before MethodArgumentSpaceFixer. + * Must run after SingleSpaceAfterConstructFixer. + */ + public function getPriority() + { + return 31; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if ( + !$token->isGivenKind(T_FUNCTION) + && (\PHP_VERSION_ID < 70400 || !$token->isGivenKind(T_FN)) + ) { + continue; + } + + $startParenthesisIndex = $tokens->getNextTokenOfKind($index, ['(', ';', [T_CLOSE_TAG]]); + if (!$tokens[$startParenthesisIndex]->equals('(')) { + continue; + } + + $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex); + $startBraceIndex = $tokens->getNextTokenOfKind($endParenthesisIndex, [';', '{', [T_DOUBLE_ARROW]]); + + // fix single-line whitespace before { or => + // eg: `function foo(){}` => `function foo() {}` + // eg: `function foo() {}` => `function foo() {}` + // eg: `fn() =>` => `fn() =>` + if ( + $tokens[$startBraceIndex]->equalsAny(['{', [T_DOUBLE_ARROW]]) + && ( + !$tokens[$startBraceIndex - 1]->isWhitespace() + || $tokens[$startBraceIndex - 1]->isWhitespace($this->singleLineWhitespaceOptions) + ) + ) { + $tokens->ensureWhitespaceAtIndex($startBraceIndex - 1, 1, ' '); + } + + $afterParenthesisIndex = $tokens->getNextNonWhitespace($endParenthesisIndex); + $afterParenthesisToken = $tokens[$afterParenthesisIndex]; + + if ($afterParenthesisToken->isGivenKind(CT::T_USE_LAMBDA)) { + // fix whitespace after CT:T_USE_LAMBDA (we might add a token, so do this before determining start and end parenthesis) + $tokens->ensureWhitespaceAtIndex($afterParenthesisIndex + 1, 0, ' '); + + $useStartParenthesisIndex = $tokens->getNextTokenOfKind($afterParenthesisIndex, ['(']); + $useEndParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $useStartParenthesisIndex); + + // remove single-line edge whitespaces inside use parentheses + $this->fixParenthesisInnerEdge($tokens, $useStartParenthesisIndex, $useEndParenthesisIndex); + + // fix whitespace before CT::T_USE_LAMBDA + $tokens->ensureWhitespaceAtIndex($afterParenthesisIndex - 1, 1, ' '); + } + + // remove single-line edge whitespaces inside parameters list parentheses + $this->fixParenthesisInnerEdge($tokens, $startParenthesisIndex, $endParenthesisIndex); + + $isLambda = $tokensAnalyzer->isLambda($index); + + // remove whitespace before ( + // eg: `function foo () {}` => `function foo() {}` + if (!$isLambda && $tokens[$startParenthesisIndex - 1]->isWhitespace() && !$tokens[$tokens->getPrevNonWhitespace($startParenthesisIndex - 1)]->isComment()) { + $tokens->clearAt($startParenthesisIndex - 1); + } + + if ($isLambda && self::SPACING_NONE === $this->configuration['closure_function_spacing']) { + // optionally remove whitespace after T_FUNCTION of a closure + // eg: `function () {}` => `function() {}` + if ($tokens[$index + 1]->isWhitespace()) { + $tokens->clearAt($index + 1); + } + } else { + // otherwise, enforce whitespace after T_FUNCTION + // eg: `function foo() {}` => `function foo() {}` + $tokens->ensureWhitespaceAtIndex($index + 1, 0, ' '); + } + + if ($isLambda) { + $prev = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prev]->isGivenKind(T_STATIC)) { + // fix whitespace after T_STATIC + // eg: `$a = static function(){};` => `$a = static function(){};` + $tokens->ensureWhitespaceAtIndex($prev + 1, 0, ' '); + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('closure_function_spacing', 'Spacing to use before open parenthesis for closures.')) + ->setDefault(self::SPACING_ONE) + ->setAllowedValues($this->supportedSpacings) + ->getOption(), + ]); + } + + private function fixParenthesisInnerEdge(Tokens $tokens, $start, $end) + { + // remove single-line whitespace before ) + if ($tokens[$end - 1]->isWhitespace($this->singleLineWhitespaceOptions)) { + $tokens->clearAt($end - 1); + } + + // remove single-line whitespace after ( + if ($tokens[$start + 1]->isWhitespace($this->singleLineWhitespaceOptions)) { + $tokens->clearAt($start + 1); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FunctionTypehintSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FunctionTypehintSpaceFixer.php new file mode 100644 index 0000000..f9b7a54 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/FunctionTypehintSpaceFixer.php @@ -0,0 +1,83 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\TypeAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class FunctionTypehintSpaceFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Ensure single space between function\'s argument and its typehint.', + [ + new CodeSample("<?php\nfunction sample(array\$a)\n{}\n"), + new CodeSample("<?php\nfunction sample(array \$a)\n{}\n"), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) { + return true; + } + + return $tokens->isTokenKindFound(T_FUNCTION); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if ( + !$token->isGivenKind(T_FUNCTION) + && (\PHP_VERSION_ID < 70400 || !$token->isGivenKind(T_FN)) + ) { + continue; + } + + $arguments = $functionsAnalyzer->getFunctionArguments($tokens, $index); + + foreach (array_reverse($arguments) as $argument) { + $type = $argument->getTypeAnalysis(); + + if (!$type instanceof TypeAnalysis) { + continue; + } + + $tokens->ensureWhitespaceAtIndex($type->getEndIndex() + 1, 0, ' '); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/ImplodeCallFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/ImplodeCallFixer.php new file mode 100644 index 0000000..a7bb4ea --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/ImplodeCallFixer.php @@ -0,0 +1,150 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Kuba Werłos <werlos@gmail.com> + */ +final class ImplodeCallFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Function `implode` must be called with 2 arguments in the documented order.', + [ + new CodeSample("<?php\nimplode(\$pieces, '');\n"), + new CodeSample("<?php\nimplode(\$pieces);\n"), + ], + null, + 'Risky when the function `implode` is overridden.' + ); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + * + * Must run before MethodArgumentSpaceFixer. + * Must run after NoAliasFunctionsFixer. + */ + public function getPriority() + { + return 37; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + + for ($index = \count($tokens) - 1; $index > 0; --$index) { + if (!$tokens[$index]->equals([T_STRING, 'implode'], false)) { + continue; + } + + if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) { + continue; + } + + $argumentsIndices = $this->getArgumentIndices($tokens, $index); + + if (1 === \count($argumentsIndices)) { + $firstArgumentIndex = key($argumentsIndices); + $tokens->insertAt($firstArgumentIndex, [ + new Token([T_CONSTANT_ENCAPSED_STRING, "''"]), + new Token(','), + new Token([T_WHITESPACE, ' ']), + ]); + + continue; + } + + if (2 === \count($argumentsIndices)) { + list($firstArgumentIndex, $secondArgumentIndex) = array_keys($argumentsIndices); + + // If the first argument is string we have nothing to do + if ($tokens[$firstArgumentIndex]->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) { + continue; + } + // If the second argument is not string we cannot make a swap + if (!$tokens[$secondArgumentIndex]->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) { + continue; + } + + // collect tokens from first argument + $firstArgumentEndIndex = $argumentsIndices[key($argumentsIndices)]; + $newSecondArgumentTokens = []; + for ($i = key($argumentsIndices); $i <= $firstArgumentEndIndex; ++$i) { + $newSecondArgumentTokens[] = clone $tokens[$i]; + $tokens->clearAt($i); + } + + $tokens->insertAt($firstArgumentIndex, clone $tokens[$secondArgumentIndex]); + + // insert above increased the second argument index + ++$secondArgumentIndex; + $tokens->clearAt($secondArgumentIndex); + $tokens->insertAt($secondArgumentIndex, $newSecondArgumentTokens); + } + } + } + + /** + * @param int $functionNameIndex + * + * @return array<int, int> In the format: startIndex => endIndex + */ + private function getArgumentIndices(Tokens $tokens, $functionNameIndex) + { + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + $openParenthesis = $tokens->getNextTokenOfKind($functionNameIndex, ['(']); + $closeParenthesis = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesis); + + $indices = []; + + foreach ($argumentsAnalyzer->getArguments($tokens, $openParenthesis, $closeParenthesis) as $startIndexCandidate => $endIndex) { + $indices[$tokens->getNextMeaningfulToken($startIndexCandidate - 1)] = $tokens->getPrevMeaningfulToken($endIndex + 1); + } + + return $indices; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/LambdaNotUsedImportFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/LambdaNotUsedImportFixer.php new file mode 100644 index 0000000..0c5c6d3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/LambdaNotUsedImportFixer.php @@ -0,0 +1,365 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author SpacePossum + */ +final class LambdaNotUsedImportFixer extends AbstractFixer +{ + /** + * @var ArgumentsAnalyzer + */ + private $argumentsAnalyzer; + + /** + * @var FunctionsAnalyzer + */ + private $functionAnalyzer; + + /** + * @var TokensAnalyzer + */ + private $tokensAnalyzer; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Lambda must not import variables it doesn\'t use.', + [new CodeSample("<?php\n\$foo = function() use (\$bar) {};\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoSpacesInsideParenthesisFixer. + */ + public function getPriority() + { + return 3; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_FUNCTION, CT::T_USE_LAMBDA]); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $this->argumentsAnalyzer = new ArgumentsAnalyzer(); + $this->functionAnalyzer = new FunctionsAnalyzer(); + $this->tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($index = $tokens->count() - 4; $index > 0; --$index) { + $lambdaUseIndex = $this->getLambdaUseIndex($tokens, $index); + + if (false !== $lambdaUseIndex) { + $this->fixLambda($tokens, $lambdaUseIndex); + } + } + } + + /** + * @param int $lambdaUseIndex + */ + private function fixLambda(Tokens $tokens, $lambdaUseIndex) + { + $lambdaUseOpenBraceIndex = $tokens->getNextTokenOfKind($lambdaUseIndex, ['(']); + $lambdaUseCloseBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $lambdaUseOpenBraceIndex); + $arguments = $this->argumentsAnalyzer->getArguments($tokens, $lambdaUseOpenBraceIndex, $lambdaUseCloseBraceIndex); + + $imports = $this->filterArguments($tokens, $arguments); + + if (0 === \count($imports)) { + return; // no imports to remove + } + + $notUsedImports = $this->findNotUsedLambdaImports($tokens, $imports, $lambdaUseCloseBraceIndex); + $notUsedImportsCount = \count($notUsedImports); + + if (0 === $notUsedImportsCount) { + return; // no not used imports found + } + + if ($notUsedImportsCount === \count($arguments)) { + $this->clearImportsAndUse($tokens, $lambdaUseIndex, $lambdaUseCloseBraceIndex); // all imports are not used + + return; + } + + $this->clearImports($tokens, array_reverse($notUsedImports)); + } + + /** + * @param int $lambdaUseCloseBraceIndex + * + * @return array + */ + private function findNotUsedLambdaImports(Tokens $tokens, array $imports, $lambdaUseCloseBraceIndex) + { + static $riskyKinds = [ + CT::T_DYNAMIC_VAR_BRACE_OPEN, + T_EVAL, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + ]; + + // figure out where the lambda starts ... + $lambdaOpenIndex = $tokens->getNextTokenOfKind($lambdaUseCloseBraceIndex, ['{']); + $curlyBracesLevel = 0; + + for ($index = $lambdaOpenIndex;; ++$index) { // go through the body of the lambda and keep count of the (possible) usages of the imported variables + $token = $tokens[$index]; + + if ($token->equals('{')) { + ++$curlyBracesLevel; + + continue; + } + + if ($token->equals('}')) { + --$curlyBracesLevel; + + if (0 === $curlyBracesLevel) { + break; + } + + continue; + } + + if ($token->isGivenKind(T_STRING) && 'compact' === strtolower($token->getContent()) && $this->functionAnalyzer->isGlobalFunctionCall($tokens, $index)) { + return []; // wouldn't touch it with a ten-foot pole + } + + if ($token->isGivenKind($riskyKinds)) { + return []; + } + + if ($token->equals('$')) { + $nextIndex = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$nextIndex]->isGivenKind(T_VARIABLE)) { + return []; // "$$a" case + } + } + + if ($token->isGivenKind(T_VARIABLE)) { + $content = $token->getContent(); + + if (isset($imports[$content])) { + unset($imports[$content]); + + if (0 === \count($imports)) { + return $imports; + } + } + } + + if ($token->isGivenKind(T_STRING_VARNAME)) { + $content = '$'.$token->getContent(); + + if (isset($imports[$content])) { + unset($imports[$content]); + + if (0 === \count($imports)) { + return $imports; + } + } + } + + if ($token->isClassy()) { // is anonymous class + // check if used as argument in the constructor of the anonymous class + $index = $tokens->getNextTokenOfKind($index, ['(', '{']); + + if ($tokens[$index]->equals('(')) { + $closeBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + $arguments = $this->argumentsAnalyzer->getArguments($tokens, $index, $closeBraceIndex); + + $imports = $this->countImportsUsedAsArgument($tokens, $imports, $arguments); + + $index = $tokens->getNextTokenOfKind($closeBraceIndex, ['{']); + } + + // skip body + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + continue; + } + + if ($token->isGivenKind(T_FUNCTION)) { + // check if used as argument + $lambdaUseOpenBraceIndex = $tokens->getNextTokenOfKind($index, ['(']); + $lambdaUseCloseBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $lambdaUseOpenBraceIndex); + $arguments = $this->argumentsAnalyzer->getArguments($tokens, $lambdaUseOpenBraceIndex, $lambdaUseCloseBraceIndex); + + $imports = $this->countImportsUsedAsArgument($tokens, $imports, $arguments); + + // check if used as import + $index = $tokens->getNextTokenOfKind($index, [[CT::T_USE_LAMBDA], '{']); + + if ($tokens[$index]->isGivenKind(CT::T_USE_LAMBDA)) { + $lambdaUseOpenBraceIndex = $tokens->getNextTokenOfKind($index, ['(']); + $lambdaUseCloseBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $lambdaUseOpenBraceIndex); + $arguments = $this->argumentsAnalyzer->getArguments($tokens, $lambdaUseOpenBraceIndex, $lambdaUseCloseBraceIndex); + + $imports = $this->countImportsUsedAsArgument($tokens, $imports, $arguments); + + $index = $tokens->getNextTokenOfKind($lambdaUseCloseBraceIndex, ['{']); + } + + // skip body + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + continue; + } + } + + return $imports; + } + + /** + * @return array + */ + private function countImportsUsedAsArgument(Tokens $tokens, array $imports, array $arguments) + { + foreach ($arguments as $start => $end) { + $info = $this->argumentsAnalyzer->getArgumentInfo($tokens, $start, $end); + $content = $info->getName(); + + if (isset($imports[$content])) { + unset($imports[$content]); + + if (0 === \count($imports)) { + return $imports; + } + } + } + + return $imports; + } + + /** + * @param int $index + * + * @return false|int + */ + private function getLambdaUseIndex(Tokens $tokens, $index) + { + if (!$tokens[$index]->isGivenKind(T_FUNCTION) || !$this->tokensAnalyzer->isLambda($index)) { + return false; + } + + $lambdaUseIndex = $tokens->getNextMeaningfulToken($index); // we are @ '(' or '&' after this + + if ($tokens[$lambdaUseIndex]->isGivenKind(CT::T_RETURN_REF)) { + $lambdaUseIndex = $tokens->getNextMeaningfulToken($lambdaUseIndex); + } + + $lambdaUseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $lambdaUseIndex); // we are @ ')' after this + $lambdaUseIndex = $tokens->getNextMeaningfulToken($lambdaUseIndex); + + if (!$tokens[$lambdaUseIndex]->isGivenKind(CT::T_USE_LAMBDA)) { + return false; + } + + return $lambdaUseIndex; + } + + /** + * @return array + */ + private function filterArguments(Tokens $tokens, array $arguments) + { + $imports = []; + + foreach ($arguments as $start => $end) { + $info = $this->argumentsAnalyzer->getArgumentInfo($tokens, $start, $end); + $argument = $info->getNameIndex(); + + if ($tokens[$tokens->getPrevMeaningfulToken($argument)]->equals('&')) { + continue; + } + + $argumentCandidate = $tokens[$argument]; + + if ('$this' === $argumentCandidate->getContent()) { + continue; + } + + if ($this->tokensAnalyzer->isSuperGlobal($argument)) { + continue; + } + + $imports[$argumentCandidate->getContent()] = $argument; + } + + return $imports; + } + + private function clearImports(Tokens $tokens, array $imports) + { + foreach ($imports as $content => $removeIndex) { + $tokens->clearTokenAndMergeSurroundingWhitespace($removeIndex); + $previousRemoveIndex = $tokens->getPrevMeaningfulToken($removeIndex); + + if ($tokens[$previousRemoveIndex]->equals(',')) { + $tokens->clearTokenAndMergeSurroundingWhitespace($previousRemoveIndex); + } elseif ($tokens[$previousRemoveIndex]->equals('(')) { + $tokens->clearTokenAndMergeSurroundingWhitespace($tokens->getNextMeaningfulToken($removeIndex)); // next is always ',' here + } + } + } + + /** + * Remove `use` and all imported variables. + * + * @param int $lambdaUseIndex + * @param int $lambdaUseCloseBraceIndex + */ + private function clearImportsAndUse(Tokens $tokens, $lambdaUseIndex, $lambdaUseCloseBraceIndex) + { + for ($i = $lambdaUseCloseBraceIndex; $i >= $lambdaUseIndex; --$i) { + if ($tokens[$i]->isComment()) { + continue; + } + + if ($tokens[$i]->isWhitespace()) { + $previousIndex = $tokens->getPrevNonWhitespace($i); + + if ($tokens[$previousIndex]->isComment()) { + continue; + } + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($i); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php new file mode 100644 index 0000000..971eca6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php @@ -0,0 +1,512 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerConfiguration\InvalidOptionsForEnvException; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Utils; +use Symfony\Component\OptionsResolver\Options; + +/** + * Fixer for rules defined in PSR2 ¶4.4, ¶4.6. + * + * @author Kuanhung Chen <ericj.tw@gmail.com> + */ +final class MethodArgumentSpaceFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * Method to insert space after comma and remove space before comma. + * + * @param int $index + */ + public function fixSpace(Tokens $tokens, $index) + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated and will be removed in 3.0.')); + $this->fixSpace2($tokens, $index); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'In method arguments and method call, there MUST NOT be a space before each comma and there MUST be one space after each comma. Argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line.', + [ + new CodeSample( + "<?php\nfunction sample(\$a=10,\$b=20,\$c=30) {}\nsample(1, 2);\n", + null + ), + new CodeSample( + "<?php\nfunction sample(\$a=10,\$b=20,\$c=30) {}\nsample(1, 2);\n", + ['keep_multiple_spaces_after_comma' => false] + ), + new CodeSample( + "<?php\nfunction sample(\$a=10,\$b=20,\$c=30) {}\nsample(1, 2);\n", + ['keep_multiple_spaces_after_comma' => true] + ), + new CodeSample( + "<?php\nfunction sample(\$a=10,\n \$b=20,\$c=30) {}\nsample(1,\n 2);\n", + ['on_multiline' => 'ensure_fully_multiline'] + ), + new CodeSample( + "<?php\nfunction sample(\n \$a=10,\n \$b=20,\n \$c=30\n) {}\nsample(\n 1,\n 2\n);\n", + ['on_multiline' => 'ensure_single_line'] + ), + new CodeSample( + "<?php\nfunction sample(\$a=10,\n \$b=20,\$c=30) {}\nsample(1, \n 2);\nsample('foo', 'foobarbaz', 'baz');\nsample('foobar', 'bar', 'baz');\n", + [ + 'on_multiline' => 'ensure_fully_multiline', + 'keep_multiple_spaces_after_comma' => true, + ] + ), + new CodeSample( + "<?php\nfunction sample(\$a=10,\n \$b=20,\$c=30) {}\nsample(1, \n 2);\nsample('foo', 'foobarbaz', 'baz');\nsample('foobar', 'bar', 'baz');\n", + [ + 'on_multiline' => 'ensure_fully_multiline', + 'keep_multiple_spaces_after_comma' => false, + ] + ), + new VersionSpecificCodeSample( + <<<'SAMPLE' +<?php +sample( + <<<EOD + foo + EOD + , + 'bar' +); + +SAMPLE + , + new VersionSpecification(70300), + ['after_heredoc' => true] + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound('('); + } + + public function configure(array $configuration = null) + { + parent::configure($configuration); + + if ($this->configuration['ensure_fully_multiline'] && 'ignore' === $this->configuration['on_multiline']) { + $this->configuration['on_multiline'] = 'ensure_fully_multiline'; + } + } + + /** + * {@inheritdoc} + * + * Must run before ArrayIndentationFixer. + * Must run after BracesFixer, CombineNestedDirnameFixer, FunctionDeclarationFixer, ImplodeCallFixer, MethodChainingIndentationFixer, NoUselessSprintfFixer, PowToExponentiationFixer. + */ + public function getPriority() + { + return 30; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $expectedTokens = [T_LIST, T_FUNCTION, CT::T_USE_LAMBDA]; + if (\PHP_VERSION_ID >= 70400) { + $expectedTokens[] = T_FN; + } + + for ($index = $tokens->count() - 1; $index > 0; --$index) { + $token = $tokens[$index]; + + if (!$token->equals('(')) { + continue; + } + + $meaningfulTokenBeforeParenthesis = $tokens[$tokens->getPrevMeaningfulToken($index)]; + if ( + $meaningfulTokenBeforeParenthesis->isKeyword() + && !$meaningfulTokenBeforeParenthesis->isGivenKind($expectedTokens) + ) { + continue; + } + + $isMultiline = $this->fixFunction($tokens, $index); + + if ( + $isMultiline + && 'ensure_fully_multiline' === $this->configuration['on_multiline'] + && !$meaningfulTokenBeforeParenthesis->isGivenKind(T_LIST) + ) { + $this->ensureFunctionFullyMultiline($tokens, $index); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('keep_multiple_spaces_after_comma', 'Whether keep multiple spaces after comma.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + (new FixerOptionBuilder( + 'ensure_fully_multiline', + 'ensure every argument of a multiline argument list is on its own line' + )) + ->setAllowedTypes(['bool']) + ->setDefault(false) // @TODO 3.0 remove + ->setDeprecationMessage('Use option `on_multiline` instead.') + ->getOption(), + (new FixerOptionBuilder( + 'on_multiline', + 'Defines how to handle function arguments lists that contain newlines.' + )) + ->setAllowedValues(['ignore', 'ensure_single_line', 'ensure_fully_multiline']) + ->setDefault('ignore') // @TODO 3.0 should be 'ensure_fully_multiline' + ->getOption(), + (new FixerOptionBuilder('after_heredoc', 'Whether the whitespace between heredoc end and comma should be removed.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->setNormalizer(static function (Options $options, $value) { + if (\PHP_VERSION_ID < 70300 && $value) { + throw new InvalidOptionsForEnvException('"after_heredoc" option can only be enabled with PHP 7.3+.'); + } + + return $value; + }) + ->getOption(), + ]); + } + + /** + * Fix arguments spacing for given function. + * + * @param Tokens $tokens Tokens to handle + * @param int $startFunctionIndex Start parenthesis position + * + * @return bool whether the function is multiline + */ + private function fixFunction(Tokens $tokens, $startFunctionIndex) + { + $endFunctionIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startFunctionIndex); + + $isMultiline = false; + + $firstWhitespaceIndex = $this->findWhitespaceIndexAfterParenthesis($tokens, $startFunctionIndex, $endFunctionIndex); + $lastWhitespaceIndex = $this->findWhitespaceIndexAfterParenthesis($tokens, $endFunctionIndex, $startFunctionIndex); + + foreach ([$firstWhitespaceIndex, $lastWhitespaceIndex] as $index) { + if (null === $index || !Preg::match('/\R/', $tokens[$index]->getContent())) { + continue; + } + + if ('ensure_single_line' !== $this->configuration['on_multiline']) { + $isMultiline = true; + + continue; + } + + $newLinesRemoved = $this->ensureSingleLine($tokens, $index); + if (!$newLinesRemoved) { + $isMultiline = true; + } + } + + for ($index = $endFunctionIndex - 1; $index > $startFunctionIndex; --$index) { + $token = $tokens[$index]; + + if ($token->equals(')')) { + $index = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + + continue; + } + + if ($token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_CLOSE)) { + $index = $tokens->findBlockStart(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $index); + + continue; + } + + if ($token->equals('}')) { + $index = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + continue; + } + + if ($token->equals(',')) { + $this->fixSpace2($tokens, $index); + if (!$isMultiline && $this->isNewline($tokens[$index + 1])) { + $isMultiline = true; + + break; + } + } + } + + return $isMultiline; + } + + /** + * @param int $startParenthesisIndex + * @param int $endParenthesisIndex + * + * @return null|int + */ + private function findWhitespaceIndexAfterParenthesis(Tokens $tokens, $startParenthesisIndex, $endParenthesisIndex) + { + $direction = $endParenthesisIndex > $startParenthesisIndex ? 1 : -1; + $startIndex = $startParenthesisIndex + $direction; + $endIndex = $endParenthesisIndex - $direction; + + for ($index = $startIndex; $index !== $endIndex; $index += $direction) { + $token = $tokens[$index]; + + if ($token->isWhitespace()) { + return $index; + } + + if (!$token->isComment()) { + break; + } + } + + return null; + } + + /** + * @param int $index + * + * @return bool Whether newlines were removed from the whitespace token + */ + private function ensureSingleLine(Tokens $tokens, $index) + { + $previousToken = $tokens[$index - 1]; + if ($previousToken->isComment() && 0 !== strpos($previousToken->getContent(), '/*')) { + return false; + } + + $content = Preg::replace('/\R\h*/', '', $tokens[$index]->getContent()); + if ('' !== $content) { + $tokens[$index] = new Token([T_WHITESPACE, $content]); + } else { + $tokens->clearAt($index); + } + + return true; + } + + /** + * @param int $startFunctionIndex + */ + private function ensureFunctionFullyMultiline(Tokens $tokens, $startFunctionIndex) + { + // find out what the indentation is + $searchIndex = $startFunctionIndex; + do { + $prevWhitespaceTokenIndex = $tokens->getPrevTokenOfKind( + $searchIndex, + [[T_WHITESPACE]] + ); + $searchIndex = $prevWhitespaceTokenIndex; + } while (null !== $prevWhitespaceTokenIndex + && false === strpos($tokens[$prevWhitespaceTokenIndex]->getContent(), "\n") + ); + + if (null === $prevWhitespaceTokenIndex) { + $existingIndentation = ''; + } else { + $existingIndentation = $tokens[$prevWhitespaceTokenIndex]->getContent(); + $lastLineIndex = strrpos($existingIndentation, "\n"); + $existingIndentation = false === $lastLineIndex + ? $existingIndentation + : substr($existingIndentation, $lastLineIndex + 1) + ; + } + + $indentation = $existingIndentation.$this->whitespacesConfig->getIndent(); + $endFunctionIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startFunctionIndex); + + $wasWhitespaceBeforeEndFunctionAddedAsNewToken = $tokens->ensureWhitespaceAtIndex( + $tokens[$endFunctionIndex - 1]->isWhitespace() ? $endFunctionIndex - 1 : $endFunctionIndex, + 0, + $this->whitespacesConfig->getLineEnding().$existingIndentation + ); + + if ($wasWhitespaceBeforeEndFunctionAddedAsNewToken) { + ++$endFunctionIndex; + } + + for ($index = $endFunctionIndex - 1; $index > $startFunctionIndex; --$index) { + $token = $tokens[$index]; + + // skip nested method calls and arrays + if ($token->equals(')')) { + $index = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + + continue; + } + + // skip nested arrays + if ($token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_CLOSE)) { + $index = $tokens->findBlockStart(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $index); + + continue; + } + + if ($token->equals('}')) { + $index = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + continue; + } + + if ($token->equals(',') && !$tokens[$tokens->getNextMeaningfulToken($index)]->equals(')')) { + $this->fixNewline($tokens, $index, $indentation); + } + } + + $this->fixNewline($tokens, $startFunctionIndex, $indentation, false); + } + + /** + * Method to insert newline after comma or opening parenthesis. + * + * @param int $index index of a comma + * @param string $indentation the indentation that should be used + * @param bool $override whether to override the existing character or not + */ + private function fixNewline(Tokens $tokens, $index, $indentation, $override = true) + { + if ($tokens[$index + 1]->isComment()) { + return; + } + + if ($tokens[$index + 2]->isComment()) { + $nextMeaningfulTokenIndex = $tokens->getNextMeaningfulToken($index + 2); + if (!$this->isNewline($tokens[$nextMeaningfulTokenIndex - 1])) { + $tokens->ensureWhitespaceAtIndex($nextMeaningfulTokenIndex, 0, $this->whitespacesConfig->getLineEnding().$indentation); + } + + return; + } + + $nextMeaningfulTokenIndex = $tokens->getNextMeaningfulToken($index); + if ($tokens[$nextMeaningfulTokenIndex]->equals(')')) { + return; + } + + $tokens->ensureWhitespaceAtIndex($index + 1, 0, $this->whitespacesConfig->getLineEnding().$indentation); + } + + /** + * Method to insert space after comma and remove space before comma. + * + * @param int $index + */ + private function fixSpace2(Tokens $tokens, $index) + { + // remove space before comma if exist + if ($tokens[$index - 1]->isWhitespace()) { + $prevIndex = $tokens->getPrevNonWhitespace($index - 1); + + if ( + !$tokens[$prevIndex]->equals(',') && !$tokens[$prevIndex]->isComment() + && ($this->configuration['after_heredoc'] || !$tokens[$prevIndex]->isGivenKind(T_END_HEREDOC)) + ) { + $tokens->clearAt($index - 1); + } + } + + $nextIndex = $index + 1; + $nextToken = $tokens[$nextIndex]; + + // Two cases for fix space after comma (exclude multiline comments) + // 1) multiple spaces after comma + // 2) no space after comma + if ($nextToken->isWhitespace()) { + $newContent = $nextToken->getContent(); + + if ('ensure_single_line' === $this->configuration['on_multiline']) { + $newContent = Preg::replace('/\R/', '', $newContent); + } + + if ( + (!$this->configuration['keep_multiple_spaces_after_comma'] || Preg::match('/\R/', $newContent)) + && !$this->isCommentLastLineToken($tokens, $index + 2) + ) { + $newContent = ltrim($newContent, " \t"); + } + + $tokens[$nextIndex] = new Token([T_WHITESPACE, '' === $newContent ? ' ' : $newContent]); + + return; + } + + if (!$this->isCommentLastLineToken($tokens, $index + 1)) { + $tokens->insertAt($index + 1, new Token([T_WHITESPACE, ' '])); + } + } + + /** + * Check if last item of current line is a comment. + * + * @param Tokens $tokens tokens to handle + * @param int $index index of token + * + * @return bool + */ + private function isCommentLastLineToken(Tokens $tokens, $index) + { + if (!$tokens[$index]->isComment() || !$tokens[$index + 1]->isWhitespace()) { + return false; + } + + $content = $tokens[$index + 1]->getContent(); + + return $content !== ltrim($content, "\r\n"); + } + + /** + * Checks if token is new line. + * + * @return bool + */ + private function isNewline(Token $token) + { + return $token->isWhitespace() && false !== strpos($token->getContent(), "\n"); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NativeFunctionInvocationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NativeFunctionInvocationFixer.php new file mode 100644 index 0000000..4e1b545 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NativeFunctionInvocationFixer.php @@ -0,0 +1,422 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; + +/** + * @author Andreas Möller <am@localheinz.com> + * @author SpacePossum + */ +final class NativeFunctionInvocationFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @internal + */ + const SET_ALL = '@all'; + + /** + * Subset of SET_INTERNAL. + * + * Change function call to functions known to be optimized by the Zend engine. + * For details: + * - @see https://github.com/php/php-src/blob/php-7.2.6/Zend/zend_compile.c "zend_try_compile_special_func" + * - @see https://github.com/php/php-src/blob/php-7.2.6/ext/opcache/Optimizer/pass1_5.c + * + * @internal + */ + const SET_COMPILER_OPTIMIZED = '@compiler_optimized'; + + /** + * @internal + */ + const SET_INTERNAL = '@internal'; + + /** + * @var callable + */ + private $functionFilter; + + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->functionFilter = $this->getFunctionFilter(); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Add leading `\` before function invocation to speed up resolving.', + [ + new CodeSample( + '<?php + +function baz($options) +{ + if (!array_key_exists("foo", $options)) { + throw new \InvalidArgumentException(); + } + + return json_encode($options); +} +' + ), + new CodeSample( + '<?php + +function baz($options) +{ + if (!array_key_exists("foo", $options)) { + throw new \InvalidArgumentException(); + } + + return json_encode($options); +} +', + [ + 'exclude' => [ + 'json_encode', + ], + ] + ), + new CodeSample( + '<?php +namespace space1 { + echo count([1]); +} +namespace { + echo count([1]); +} +', + ['scope' => 'all'] + ), + new CodeSample( + '<?php +namespace space1 { + echo count([1]); +} +namespace { + echo count([1]); +} +', + ['scope' => 'namespaced'] + ), + new CodeSample( + '<?php +myGlobalFunction(); +count(); +', + ['include' => ['myGlobalFunction']] + ), + new CodeSample( + '<?php +myGlobalFunction(); +count(); +', + ['include' => ['@all']] + ), + new CodeSample( + '<?php +myGlobalFunction(); +count(); +', + ['include' => ['@internal']] + ), + new CodeSample( + '<?php +$a .= str_repeat($a, 4); +$c = get_class($d); +', + ['include' => ['@compiler_optimized']] + ), + ], + null, + 'Risky when any of the functions are overridden.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before GlobalNamespaceImportFixer. + * Must run after BacktickToShellExecFixer, StrictParamFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if ('all' === $this->configuration['scope']) { + $this->fixFunctionCalls($tokens, $this->functionFilter, 0, \count($tokens) - 1, false); + + return; + } + + $namespaces = (new NamespacesAnalyzer())->getDeclarations($tokens); + + // 'scope' is 'namespaced' here + /** @var NamespaceAnalysis $namespace */ + foreach (array_reverse($namespaces) as $namespace) { + $this->fixFunctionCalls($tokens, $this->functionFilter, $namespace->getScopeStartIndex(), $namespace->getScopeEndIndex(), '' === $namespace->getFullName()); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('exclude', 'List of functions to ignore.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([static function (array $value) { + foreach ($value as $functionName) { + if (!\is_string($functionName) || '' === trim($functionName) || trim($functionName) !== $functionName) { + throw new InvalidOptionsException(sprintf( + 'Each element must be a non-empty, trimmed string, got "%s" instead.', + \is_object($functionName) ? \get_class($functionName) : \gettype($functionName) + )); + } + } + + return true; + }]) + ->setDefault([]) + ->getOption(), + (new FixerOptionBuilder('include', 'List of function names or sets to fix. Defined sets are `@internal` (all native functions), `@all` (all global functions) and `@compiler_optimized` (functions that are specially optimized by Zend).')) + ->setAllowedTypes(['array']) + ->setAllowedValues([static function (array $value) { + foreach ($value as $functionName) { + if (!\is_string($functionName) || '' === trim($functionName) || trim($functionName) !== $functionName) { + throw new InvalidOptionsException(sprintf( + 'Each element must be a non-empty, trimmed string, got "%s" instead.', + \is_object($functionName) ? \get_class($functionName) : \gettype($functionName) + )); + } + + $sets = [ + self::SET_ALL, + self::SET_INTERNAL, + self::SET_COMPILER_OPTIMIZED, + ]; + + if ('@' === $functionName[0] && !\in_array($functionName, $sets, true)) { + throw new InvalidOptionsException(sprintf('Unknown set "%s", known sets are "%s".', $functionName, implode('", "', $sets))); + } + } + + return true; + }]) + ->setDefault([self::SET_INTERNAL]) + ->getOption(), + (new FixerOptionBuilder('scope', 'Only fix function calls that are made within a namespace or fix all.')) + ->setAllowedValues(['all', 'namespaced']) + ->setDefault('all') + ->getOption(), + (new FixerOptionBuilder('strict', 'Whether leading `\` of function call not meant to have it should be removed.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) // @TODO: 3.0 change to true as default + ->getOption(), + ]); + } + + /** + * @param int $start + * @param int $end + * @param bool $tryToRemove + */ + private function fixFunctionCalls(Tokens $tokens, callable $functionFilter, $start, $end, $tryToRemove) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + + $tokensToInsert = []; + for ($index = $start; $index < $end; ++$index) { + if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) { + continue; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + + if (!$functionFilter($tokens[$index]->getContent()) || $tryToRemove) { + if (!$this->configuration['strict']) { + continue; + } + if ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + $tokens->clearTokenAndMergeSurroundingWhitespace($prevIndex); + } + + continue; + } + + if ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + continue; // do not bother if previous token is already namespace separator + } + + $tokensToInsert[$index] = new Token([T_NS_SEPARATOR, '\\']); + } + + $tokens->insertSlices($tokensToInsert); + } + + /** + * @return callable + */ + private function getFunctionFilter() + { + $exclude = $this->normalizeFunctionNames($this->configuration['exclude']); + + if (\in_array(self::SET_ALL, $this->configuration['include'], true)) { + if (\count($exclude) > 0) { + return static function ($functionName) use ($exclude) { + return !isset($exclude[strtolower($functionName)]); + }; + } + + return static function () { + return true; + }; + } + + $include = []; + if (\in_array(self::SET_INTERNAL, $this->configuration['include'], true)) { + $include = $this->getAllInternalFunctionsNormalized(); + } elseif (\in_array(self::SET_COMPILER_OPTIMIZED, $this->configuration['include'], true)) { + $include = $this->getAllCompilerOptimizedFunctionsNormalized(); // if `@internal` is set all compiler optimized function are already loaded + } + + foreach ($this->configuration['include'] as $additional) { + if ('@' !== $additional[0]) { + $include[strtolower($additional)] = true; + } + } + + if (\count($exclude) > 0) { + return static function ($functionName) use ($include, $exclude) { + return isset($include[strtolower($functionName)]) && !isset($exclude[strtolower($functionName)]); + }; + } + + return static function ($functionName) use ($include) { + return isset($include[strtolower($functionName)]); + }; + } + + /** + * @return array<string, true> normalized function names of which the PHP compiler optimizes + */ + private function getAllCompilerOptimizedFunctionsNormalized() + { + return $this->normalizeFunctionNames([ + // @see https://github.com/php/php-src/blob/PHP-7.4/Zend/zend_compile.c "zend_try_compile_special_func" + 'array_key_exists', + 'array_slice', + 'assert', + 'boolval', + 'call_user_func', + 'call_user_func_array', + 'chr', + 'count', + 'defined', + 'doubleval', + 'floatval', + 'func_get_args', + 'func_num_args', + 'get_called_class', + 'get_class', + 'gettype', + 'in_array', + 'intval', + 'is_array', + 'is_bool', + 'is_double', + 'is_float', + 'is_int', + 'is_integer', + 'is_long', + 'is_null', + 'is_object', + 'is_real', + 'is_resource', + 'is_string', + 'ord', + 'strlen', + 'strval', + // @see https://github.com/php/php-src/blob/php-7.2.6/ext/opcache/Optimizer/pass1_5.c + 'constant', + 'define', + 'dirname', + 'extension_loaded', + 'function_exists', + 'is_callable', + ]); + } + + /** + * @return array<string, true> normalized function names of all internal defined functions + */ + private function getAllInternalFunctionsNormalized() + { + return $this->normalizeFunctionNames(get_defined_functions()['internal']); + } + + /** + * @param string[] $functionNames + * + * @return array<string, true> all function names lower cased + */ + private function normalizeFunctionNames(array $functionNames) + { + foreach ($functionNames as $index => $functionName) { + $functionNames[strtolower($functionName)] = true; + unset($functionNames[$index]); + } + + return $functionNames; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/FunctionCallSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoSpacesAfterFunctionNameFixer.php similarity index 52% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/FunctionCallSpaceFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoSpacesAfterFunctionNameFixer.php index 1d61401..5890cf2 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/PSR2/FunctionCallSpaceFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoSpacesAfterFunctionNameFixer.php @@ -10,10 +10,13 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\PSR2; +namespace PhpCsFixer\Fixer\FunctionNotation; -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; /** * Fixer for rules defined in PSR2 ¶4.6. @@ -21,17 +24,46 @@ * @author Varga Bence <vbence@czentral.org> * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> */ -class FunctionCallSpaceFixer extends AbstractFixer +final class NoSpacesAfterFunctionNameFixer extends AbstractFixer { /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function getDefinition() { - $tokens = Tokens::fromCode($content); + return new FixerDefinition( + 'When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis.', + [new CodeSample("<?php\nrequire ('sample.php');\necho (test (3));\nexit (1);\n\$func ();\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before FunctionToConstantFixer. + * Must run after PowToExponentiationFixer. + */ + public function getPriority() + { + return 2; + } + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(array_merge($this->getFunctionyTokenKinds(), [T_STRING])); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { $functionyTokens = $this->getFunctionyTokenKinds(); $languageConstructionTokens = $this->getLanguageConstructionTokenKinds(); + $braceTypes = $this->getBraceAfterVariableKinds(); foreach ($tokens as $index => $token) { // looking for start brace @@ -39,13 +71,9 @@ public function fix(\SplFileInfo $file, $content) continue; } - // last non-whitespace token + // last non-whitespace token, can never be `null` always at least PHP open tag before it $lastTokenIndex = $tokens->getPrevNonWhitespace($index); - if (null === $lastTokenIndex) { - continue; - } - // check for ternary operator $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); $nextNonWhiteSpace = $tokens->getNextMeaningfulToken($endParenthesisIndex); @@ -65,18 +93,18 @@ public function fix(\SplFileInfo $file, $content) if (!$tokens[$possibleDefinitionIndex]->isGivenKind(T_FUNCTION)) { $this->fixFunctionCall($tokens, $index); } + } elseif ($tokens[$lastTokenIndex]->equalsAny($braceTypes)) { + $block = Tokens::detectBlockType($tokens[$lastTokenIndex]); + if ( + Tokens::BLOCK_TYPE_ARRAY_INDEX_CURLY_BRACE === $block['type'] + || Tokens::BLOCK_TYPE_DYNAMIC_VAR_BRACE === $block['type'] + || Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE === $block['type'] + || Tokens::BLOCK_TYPE_PARENTHESIS_BRACE === $block['type'] + ) { + $this->fixFunctionCall($tokens, $index); + } } } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis.'; } /** @@ -89,10 +117,25 @@ private function fixFunctionCall(Tokens $tokens, $index) { // remove space before opening brace if ($tokens[$index - 1]->isWhitespace()) { - $tokens[$index - 1]->clear(); + $tokens->clearAt($index - 1); } } + /** + * @return array<array|string> + */ + private function getBraceAfterVariableKinds() + { + static $tokens = [ + ')', + ']', + [CT::T_DYNAMIC_VAR_BRACE_CLOSE], + [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE], + ]; + + return $tokens; + } + /** * Gets the token kinds which can work as function calls. * @@ -100,25 +143,22 @@ private function fixFunctionCall(Tokens $tokens, $index) */ private function getFunctionyTokenKinds() { - static $tokens = null; - - if (null === $tokens) { - $tokens = array( - T_ARRAY, - T_ECHO, - T_EMPTY, - T_EVAL, - T_EXIT, - T_INCLUDE, - T_INCLUDE_ONCE, - T_ISSET, - T_LIST, - T_PRINT, - T_REQUIRE, - T_REQUIRE_ONCE, - T_UNSET, - ); - } + static $tokens = [ + T_ARRAY, + T_ECHO, + T_EMPTY, + T_EVAL, + T_EXIT, + T_INCLUDE, + T_INCLUDE_ONCE, + T_ISSET, + T_LIST, + T_PRINT, + T_REQUIRE, + T_REQUIRE_ONCE, + T_UNSET, + T_VARIABLE, + ]; return $tokens; } @@ -130,14 +170,14 @@ private function getFunctionyTokenKinds() */ private function getLanguageConstructionTokenKinds() { - static $languageConstructionTokens = array( + static $languageConstructionTokens = [ T_ECHO, T_PRINT, T_INCLUDE, T_INCLUDE_ONCE, T_REQUIRE, T_REQUIRE_ONCE, - ); + ]; return $languageConstructionTokens; } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoUnreachableDefaultArgumentValueFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoUnreachableDefaultArgumentValueFixer.php new file mode 100644 index 0000000..0ee4f2e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoUnreachableDefaultArgumentValueFixer.php @@ -0,0 +1,218 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Mark Scherer + * @author Lucas Manzke <lmanzke@outlook.com> + * @author Gregor Harlan <gharlan@web.de> + */ +final class NoUnreachableDefaultArgumentValueFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'In function arguments there must not be arguments with default values before non-default ones.', + [ + new CodeSample( + '<?php +function example($foo = "two words", $bar) {} +' + ), + ], + null, + 'Modifies the signature of functions; therefore risky when using systems (such as some Symfony components) that rely on those (for example through reflection).' + ); + } + + /** + * {@inheritdoc} + * + * Must run after NullableTypeDeclarationForDefaultNullValueFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) { + return true; + } + + return $tokens->isTokenKindFound(T_FUNCTION); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($i = 0, $l = $tokens->count(); $i < $l; ++$i) { + if ( + !$tokens[$i]->isGivenKind(T_FUNCTION) + && (\PHP_VERSION_ID < 70400 || !$tokens[$i]->isGivenKind(T_FN)) + ) { + continue; + } + + $startIndex = $tokens->getNextTokenOfKind($i, ['(']); + $i = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); + + $this->fixFunctionDefinition($tokens, $startIndex, $i); + } + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function fixFunctionDefinition(Tokens $tokens, $startIndex, $endIndex) + { + $lastArgumentIndex = $this->getLastNonDefaultArgumentIndex($tokens, $startIndex, $endIndex); + + if (!$lastArgumentIndex) { + return; + } + + for ($i = $lastArgumentIndex; $i > $startIndex; --$i) { + $token = $tokens[$i]; + + if ($token->isGivenKind(T_VARIABLE)) { + $lastArgumentIndex = $i; + + continue; + } + + if (!$token->equals('=') || $this->isNonNullableTypehintedNullableVariable($tokens, $i)) { + continue; + } + + $endIndex = $tokens->getPrevTokenOfKind($lastArgumentIndex, [',']); + $endIndex = $tokens->getPrevMeaningfulToken($endIndex); + $this->removeDefaultArgument($tokens, $i, $endIndex); + } + } + + /** + * @param int $startIndex + * @param int $endIndex + * + * @return null|int + */ + private function getLastNonDefaultArgumentIndex(Tokens $tokens, $startIndex, $endIndex) + { + for ($i = $endIndex - 1; $i > $startIndex; --$i) { + $token = $tokens[$i]; + + if ($token->equals('=')) { + $i = $tokens->getPrevMeaningfulToken($i); + + continue; + } + + if ($token->isGivenKind(T_VARIABLE) && !$this->isEllipsis($tokens, $i)) { + return $i; + } + } + + return null; + } + + /** + * @param int $variableIndex + * + * @return bool + */ + private function isEllipsis(Tokens $tokens, $variableIndex) + { + return $tokens[$tokens->getPrevMeaningfulToken($variableIndex)]->isGivenKind(T_ELLIPSIS); + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function removeDefaultArgument(Tokens $tokens, $startIndex, $endIndex) + { + for ($i = $startIndex; $i <= $endIndex;) { + $tokens->clearTokenAndMergeSurroundingWhitespace($i); + $this->clearWhitespacesBeforeIndex($tokens, $i); + $i = $tokens->getNextMeaningfulToken($i); + } + } + + /** + * @param int $index Index of "=" + * + * @return bool + */ + private function isNonNullableTypehintedNullableVariable(Tokens $tokens, $index) + { + $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)]; + + if (!$nextToken->equals([T_STRING, 'null'], false)) { + return false; + } + + $variableIndex = $tokens->getPrevMeaningfulToken($index); + + $searchTokens = [',', '(', [T_STRING], [CT::T_ARRAY_TYPEHINT], [T_CALLABLE]]; + $typehintKinds = [T_STRING, CT::T_ARRAY_TYPEHINT, T_CALLABLE]; + + $prevIndex = $tokens->getPrevTokenOfKind($variableIndex, $searchTokens); + + if (!$tokens[$prevIndex]->isGivenKind($typehintKinds)) { + return false; + } + + return !$tokens[$tokens->getPrevMeaningfulToken($prevIndex)]->isGivenKind(CT::T_NULLABLE_TYPE); + } + + /** + * @param int $index + */ + private function clearWhitespacesBeforeIndex(Tokens $tokens, $index) + { + $prevIndex = $tokens->getNonEmptySibling($index, -1); + if (!$tokens[$prevIndex]->isWhitespace()) { + return; + } + + $prevNonWhiteIndex = $tokens->getPrevNonWhitespace($prevIndex); + if (null === $prevNonWhiteIndex || !$tokens[$prevNonWhiteIndex]->isComment()) { + $tokens->clearTokenAndMergeSurroundingWhitespace($prevIndex); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoUselessSprintfFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoUselessSprintfFixer.php new file mode 100644 index 0000000..944420f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NoUselessSprintfFixer.php @@ -0,0 +1,118 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Tokens; + +final class NoUselessSprintfFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There must be no `sprintf` calls with only the first argument.', + [ + new CodeSample( + "<?php\n\$foo = sprintf('bar');\n" + ), + ], + null, + 'Risky when if the `sprintf` function is overridden.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + * + * Must run before MethodArgumentSpaceFixer, NativeFunctionCasingFixer, NoEmptyStatementFixer, NoExtraBlankLinesFixer, NoSpacesInsideParenthesisFixer. + */ + public function getPriority() + { + return 42; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $functionAnalyzer = new FunctionsAnalyzer(); + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + for ($index = \count($tokens) - 1; $index > 0; --$index) { + if (!$tokens[$index]->isGivenKind(T_STRING)) { + continue; + } + + if ('sprintf' !== strtolower($tokens[$index]->getContent())) { + continue; + } + + if (!$functionAnalyzer->isGlobalFunctionCall($tokens, $index)) { + continue; + } + + $openParenthesisIndex = $tokens->getNextTokenOfKind($index, ['(']); + + if ($tokens[$tokens->getNextMeaningfulToken($openParenthesisIndex)]->isGivenKind(T_ELLIPSIS)) { + continue; + } + + $closeParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesisIndex); + + if (1 !== $argumentsAnalyzer->countArguments($tokens, $openParenthesisIndex, $closeParenthesisIndex)) { + continue; + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($closeParenthesisIndex); + + $prevMeaningfulTokenIndex = $tokens->getPrevMeaningfulToken($closeParenthesisIndex); + + if ($tokens[$prevMeaningfulTokenIndex]->equals(',')) { + $tokens->clearTokenAndMergeSurroundingWhitespace($prevMeaningfulTokenIndex); + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($openParenthesisIndex); + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + + $prevMeaningfulTokenIndex = $tokens->getPrevMeaningfulToken($index); + + if ($tokens[$prevMeaningfulTokenIndex]->isGivenKind(T_NS_SEPARATOR)) { + $tokens->clearTokenAndMergeSurroundingWhitespace($prevMeaningfulTokenIndex); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php new file mode 100644 index 0000000..5a73e39 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php @@ -0,0 +1,170 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\ArgumentAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author HypeMC + */ +final class NullableTypeDeclarationForDefaultNullValueFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Adds or removes `?` before type declarations for parameters with a default `null` value.', + [ + new VersionSpecificCodeSample( + "<?php\nfunction sample(string \$str = null)\n{}\n", + new VersionSpecification(70100) + ), + new VersionSpecificCodeSample( + "<?php\nfunction sample(?string \$str = null)\n{}\n", + new VersionSpecification(70100), + ['use_nullable_type_declaration' => false] + ), + ], + 'Rule is applied only in a PHP 7.1+ environment.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + if (\PHP_VERSION_ID < 70100) { + return false; + } + + if (!$tokens->isTokenKindFound(T_VARIABLE)) { + return false; + } + + if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) { + return true; + } + + return $tokens->isTokenKindFound(T_FUNCTION); + } + + /** + * {@inheritdoc} + * + * Must run before NoUnreachableDefaultArgumentValueFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('use_nullable_type_declaration', 'Whether to add or remove `?` before type declarations for parameters with a default `null` value.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + + $tokenKinds = [T_FUNCTION]; + if (\PHP_VERSION_ID >= 70400) { + $tokenKinds[] = T_FN; + } + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind($tokenKinds)) { + continue; + } + + $arguments = $functionsAnalyzer->getFunctionArguments($tokens, $index); + + $this->fixFunctionParameters($tokens, $arguments); + } + } + + /** + * @param ArgumentAnalysis[] $arguments + */ + private function fixFunctionParameters(Tokens $tokens, array $arguments) + { + foreach (array_reverse($arguments) as $argumentInfo) { + if ( + // Skip, if the parameter + // - doesn't have a type declaration + !$argumentInfo->hasTypeAnalysis() + // type is a union + || false !== strpos($argumentInfo->getTypeAnalysis()->getName(), '|') + // - a default value is not null we can continue + || !$argumentInfo->hasDefault() || 'null' !== strtolower($argumentInfo->getDefault()) + ) { + continue; + } + + $argumentTypeInfo = $argumentInfo->getTypeAnalysis(); + + if ( + \PHP_VERSION_ID >= 80000 + && false === $this->configuration['use_nullable_type_declaration'] + ) { + $visibility = $tokens[$tokens->getPrevMeaningfulToken($argumentTypeInfo->getStartIndex())]; + + if ($visibility->isGivenKind([ + CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, + CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, + CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE, + ])) { + continue; + } + } + + if (true === $this->configuration['use_nullable_type_declaration']) { + if (!$argumentTypeInfo->isNullable() && 'mixed' !== $argumentTypeInfo->getName()) { + $tokens->insertAt($argumentTypeInfo->getStartIndex(), new Token([CT::T_NULLABLE_TYPE, '?'])); + } + } else { + if ($argumentTypeInfo->isNullable()) { + $tokens->removeTrailingWhitespace($argumentTypeInfo->getStartIndex()); + $tokens->clearTokenAndMergeSurroundingWhitespace($argumentTypeInfo->getStartIndex()); + } + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php new file mode 100644 index 0000000..7a833ca --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php @@ -0,0 +1,207 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractPhpdocToTypeDeclarationFixer; +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Jan Gantzert <jan@familie-gantzert.de> + */ +final class PhpdocToParamTypeFixer extends AbstractPhpdocToTypeDeclarationFixer +{ + /** + * @var array{int, string}[] + */ + private $excludeFuncNames = [ + [T_STRING, '__clone'], + [T_STRING, '__destruct'], + ]; + + /** + * @var array<string, true> + */ + private $skippedTypes = [ + 'mixed' => true, + 'resource' => true, + 'static' => true, + 'void' => true, + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'EXPERIMENTAL: Takes `@param` annotations of non-mixed types and adjusts accordingly the function signature. Requires PHP >= 7.0.', + [ + new VersionSpecificCodeSample( + '<?php + +/** @param string $bar */ +function my_foo($bar) +{} +', + new VersionSpecification(70000) + ), + new VersionSpecificCodeSample( + '<?php + +/** @param string|null $bar */ +function my_foo($bar) +{} +', + new VersionSpecification(70100) + ), + new VersionSpecificCodeSample( + '<?php +/** @param Foo $foo */ +function foo($foo) {} +/** @param string $foo */ +function bar($foo) {} +', + new VersionSpecification(70100), + ['scalar_types' => false] + ), + ], + null, + 'This rule is EXPERIMENTAL and [1] is not covered with backward compatibility promise. [2] `@param` annotation is mandatory for the fixer to make changes, signatures of methods without it (no docblock, inheritdocs) will not be fixed. [3] Manual actions are required if inherited signatures are not properly documented.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(T_FUNCTION); + } + + /** + * {@inheritdoc} + * + * Must run before NoSuperfluousPhpdocTagsFixer, PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 8; + } + + protected function isSkippedType($type) + { + return isset($this->skippedTypes[$type]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; 0 < $index; --$index) { + if (!$tokens[$index]->isGivenKind(T_FUNCTION)) { + continue; + } + + $funcName = $tokens->getNextMeaningfulToken($index); + if ($tokens[$funcName]->equalsAny($this->excludeFuncNames, false)) { + continue; + } + + $docCommentIndex = $this->findFunctionDocComment($tokens, $index); + + if (null === $docCommentIndex) { + continue; + } + + foreach ($this->getAnnotationsFromDocComment('param', $tokens, $docCommentIndex) as $paramTypeAnnotation) { + $typeInfo = $this->getCommonTypeFromAnnotation($paramTypeAnnotation, false); + + if (null === $typeInfo) { + continue; + } + + list($paramType, $isNullable) = $typeInfo; + + $startIndex = $tokens->getNextTokenOfKind($index, ['(']); + $variableIndex = $this->findCorrectVariable($tokens, $startIndex, $paramTypeAnnotation); + + if (null === $variableIndex) { + continue; + } + + $byRefIndex = $tokens->getPrevMeaningfulToken($variableIndex); + if ($tokens[$byRefIndex]->equals('&')) { + $variableIndex = $byRefIndex; + } + + if ($this->hasParamTypeHint($tokens, $variableIndex)) { + continue; + } + + if (!$this->isValidSyntax(sprintf('<?php function f(%s $x) {}', $paramType))) { + continue; + } + + $tokens->insertAt($variableIndex, array_merge( + $this->createTypeDeclarationTokens($paramType, $isNullable), + [new Token([T_WHITESPACE, ' '])] + )); + } + } + } + + /** + * @param int $startIndex + * @param Annotation $paramTypeAnnotation + * + * @return null|int + */ + private function findCorrectVariable(Tokens $tokens, $startIndex, $paramTypeAnnotation) + { + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startIndex); + + for ($index = $startIndex + 1; $index < $endIndex; ++$index) { + if (!$tokens[$index]->isGivenKind(T_VARIABLE)) { + continue; + } + + $variableName = $tokens[$index]->getContent(); + if ($paramTypeAnnotation->getVariableName() === $variableName) { + return $index; + } + } + + return null; + } + + /** + * Determine whether the function already has a param type hint. + * + * @param int $index The index of the end of the function definition line, EG at { or ; + * + * @return bool + */ + private function hasParamTypeHint(Tokens $tokens, $index) + { + $prevIndex = $tokens->getPrevMeaningfulToken($index); + + return !$tokens[$prevIndex]->equalsAny([',', '(']); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php new file mode 100644 index 0000000..bd539f5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php @@ -0,0 +1,244 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractPhpdocToTypeDeclarationFixer; +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +final class PhpdocToPropertyTypeFixer extends AbstractPhpdocToTypeDeclarationFixer +{ + /** + * @var array<string, true> + */ + private $skippedTypes = [ + 'mixed' => true, + 'resource' => true, + 'null' => true, + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'EXPERIMENTAL: Takes `@var` annotation of non-mixed types and adjusts accordingly the property signature. Requires PHP >= 7.4.', + [ + new VersionSpecificCodeSample( + '<?php +class Foo { + /** @var int */ + private $foo; + /** @var \Traversable */ + private $bar; +} +', + new VersionSpecification(70400) + ), + new VersionSpecificCodeSample( + '<?php +class Foo { + /** @var int */ + private $foo; + /** @var \Traversable */ + private $bar; +} +', + new VersionSpecification(70400), + ['scalar_types' => false] + ), + ], + null, + 'This rule is EXPERIMENTAL and [1] is not covered with backward compatibility promise. [2] `@var` annotation is mandatory for the fixer to make changes, signatures of properties without it (no docblock) will not be fixed. [3] Manual actions might be required for newly typed properties that are read before initialization.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + * + * Must run before NoSuperfluousPhpdocTagsFixer, PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 7; + } + + protected function isSkippedType($type) + { + return isset($this->skippedTypes[$type]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; 0 < $index; --$index) { + if ($tokens[$index]->isGivenKind([T_CLASS, T_TRAIT])) { + $this->fixClass($tokens, $index); + } + } + } + + /** + * @param int $index + */ + private function fixClass(Tokens $tokens, $index) + { + $index = $tokens->getNextTokenOfKind($index, ['{']); + $classEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + for (; $index < $classEndIndex; ++$index) { + if ($tokens[$index]->isGivenKind(T_FUNCTION)) { + $index = $tokens->getNextTokenOfKind($index, ['{', ';']); + + if ($tokens[$index]->equals('{')) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + } + + continue; + } + + if (!$tokens[$index]->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $docCommentIndex = $index; + $propertyIndexes = $this->findNextUntypedPropertiesDeclaration($tokens, $docCommentIndex); + + if ([] === $propertyIndexes) { + continue; + } + + $typeInfo = $this->resolveAppliableType( + $propertyIndexes, + $this->getAnnotationsFromDocComment('var', $tokens, $docCommentIndex) + ); + + if (null === $typeInfo) { + continue; + } + + list($propertyType, $isNullable) = $typeInfo; + + if (\in_array($propertyType, ['void', 'callable'], true)) { + continue; + } + + $newTokens = array_merge( + $this->createTypeDeclarationTokens($propertyType, $isNullable), + [new Token([T_WHITESPACE, ' '])] + ); + + $tokens->insertAt(current($propertyIndexes), $newTokens); + + $index = max($propertyIndexes) + \count($newTokens) + 1; + $classEndIndex += \count($newTokens); + } + } + + /** + * @param int $index + * + * @return array<string, int> + */ + private function findNextUntypedPropertiesDeclaration(Tokens $tokens, $index) + { + do { + $index = $tokens->getNextMeaningfulToken($index); + } while ($tokens[$index]->isGivenKind([ + T_PRIVATE, + T_PROTECTED, + T_PUBLIC, + T_STATIC, + T_VAR, + ])); + + if (!$tokens[$index]->isGivenKind(T_VARIABLE)) { + return []; + } + + $properties = []; + while (!$tokens[$index]->equals(';')) { + if ($tokens[$index]->isGivenKind(T_VARIABLE)) { + $properties[$tokens[$index]->getContent()] = $index; + } + + $index = $tokens->getNextMeaningfulToken($index); + } + + return $properties; + } + + /** + * @param array<string, int> $propertyIndexes + * @param Annotation[] $annotations + */ + private function resolveAppliableType(array $propertyIndexes, array $annotations) + { + $propertyTypes = []; + + foreach ($annotations as $annotation) { + $propertyName = $annotation->getVariableName(); + + if (null === $propertyName) { + if (1 !== \count($propertyIndexes)) { + continue; + } + + $propertyName = key($propertyIndexes); + } + + if (!isset($propertyIndexes[$propertyName])) { + continue; + } + + $typeInfo = $this->getCommonTypeFromAnnotation($annotation, false); + + if (!isset($propertyTypes[$propertyName])) { + $propertyTypes[$propertyName] = []; + } elseif ($typeInfo !== $propertyTypes[$propertyName]) { + return null; + } + + $propertyTypes[$propertyName] = $typeInfo; + } + + if (\count($propertyTypes) !== \count($propertyIndexes)) { + return null; + } + + $type = array_shift($propertyTypes); + foreach ($propertyTypes as $propertyType) { + if ($propertyType !== $type) { + return null; + } + } + + return $type; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php new file mode 100644 index 0000000..7bd21b4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php @@ -0,0 +1,218 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractPhpdocToTypeDeclarationFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class PhpdocToReturnTypeFixer extends AbstractPhpdocToTypeDeclarationFixer +{ + /** + * @var array<int, array<int, int|string>> + */ + private $excludeFuncNames = [ + [T_STRING, '__construct'], + [T_STRING, '__destruct'], + [T_STRING, '__clone'], + ]; + + /** + * @var array<string, true> + */ + private $skippedTypes = [ + 'mixed' => true, + 'resource' => true, + 'null' => true, + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'EXPERIMENTAL: Takes `@return` annotation of non-mixed types and adjusts accordingly the function signature. Requires PHP >= 7.0.', + [ + new VersionSpecificCodeSample( + '<?php + +/** @return \My\Bar */ +function my_foo() +{} +', + new VersionSpecification(70000) + ), + new VersionSpecificCodeSample( + '<?php + +/** @return void */ +function my_foo() +{} +', + new VersionSpecification(70100) + ), + new VersionSpecificCodeSample( + '<?php + +/** @return object */ +function my_foo() +{} +', + new VersionSpecification(70200) + ), + new VersionSpecificCodeSample( + '<?php +/** @return Foo */ +function foo() {} +/** @return string */ +function bar() {} +', + new VersionSpecification(70100), + ['scalar_types' => false] + ), + new VersionSpecificCodeSample( + '<?php +final class Foo { + /** + * @return static + */ + public function create($prototype) { + return new static($prototype); + } +} +', + new VersionSpecification(80000) + ), + ], + null, + 'This rule is EXPERIMENTAL and [1] is not covered with backward compatibility promise. [2] `@return` annotation is mandatory for the fixer to make changes, signatures of methods without it (no docblock, inheritdocs) will not be fixed. [3] Manual actions are required if inherited signatures are not properly documented.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) { + return true; + } + + return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(T_FUNCTION); + } + + /** + * {@inheritdoc} + * + * Must run before FullyQualifiedStrictTypesFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAlignFixer, ReturnTypeDeclarationFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 13; + } + + protected function isSkippedType($type) + { + return isset($this->skippedTypes[$type]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if (\PHP_VERSION_ID >= 80000) { + unset($this->skippedTypes['mixed']); + } + + for ($index = $tokens->count() - 1; 0 < $index; --$index) { + if ( + !$tokens[$index]->isGivenKind(T_FUNCTION) + && (\PHP_VERSION_ID < 70400 || !$tokens[$index]->isGivenKind(T_FN)) + ) { + continue; + } + + $funcName = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$funcName]->equalsAny($this->excludeFuncNames, false)) { + continue; + } + + $docCommentIndex = $this->findFunctionDocComment($tokens, $index); + if (null === $docCommentIndex) { + continue; + } + + $returnTypeAnnotation = $this->getAnnotationsFromDocComment('return', $tokens, $docCommentIndex); + if (1 !== \count($returnTypeAnnotation)) { + continue; + } + + $typeInfo = $this->getCommonTypeFromAnnotation(current($returnTypeAnnotation), true); + + if (null === $typeInfo) { + continue; + } + + list($returnType, $isNullable) = $typeInfo; + + $startIndex = $tokens->getNextTokenOfKind($index, ['{', ';']); + + if ($this->hasReturnTypeHint($tokens, $startIndex)) { + continue; + } + + if (!$this->isValidSyntax(sprintf('<?php function f():%s {}', $returnType))) { + continue; + } + + $endFuncIndex = $tokens->getPrevTokenOfKind($startIndex, [')']); + + $tokens->insertAt( + $endFuncIndex + 1, + array_merge( + [ + new Token([CT::T_TYPE_COLON, ':']), + new Token([T_WHITESPACE, ' ']), + ], + $this->createTypeDeclarationTokens($returnType, $isNullable) + ) + ); + } + } + + /** + * Determine whether the function already has a return type hint. + * + * @param int $index The index of the end of the function definition line, EG at { or ; + * + * @return bool + */ + private function hasReturnTypeHint(Tokens $tokens, $index) + { + $endFuncIndex = $tokens->getPrevTokenOfKind($index, [')']); + $nextIndex = $tokens->getNextMeaningfulToken($endFuncIndex); + + return $tokens[$nextIndex]->isGivenKind(CT::T_TYPE_COLON); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/RegularCallableCallFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/RegularCallableCallFixer.php new file mode 100644 index 0000000..0ed8f84 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/RegularCallableCallFixer.php @@ -0,0 +1,238 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class RegularCallableCallFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Callables must be called without using `call_user_func*` when possible.', + [ + new CodeSample( + '<?php + call_user_func("var_dump", 1, 2); + + call_user_func("Bar\Baz::d", 1, 2); + + call_user_func_array($callback, [1, 2]); +' + ), + new VersionSpecificCodeSample( + '<?php +call_user_func(function ($a, $b) { var_dump($a, $b); }, 1, 2); + +call_user_func(static function ($a, $b) { var_dump($a, $b); }, 1, 2); +', + new VersionSpecification(70000) + ), + ], + null, + 'Risky when the `call_user_func` or `call_user_func_array` function is overridden or when are used in constructions that should be avoided, like `call_user_func_array(\'foo\', [\'bar\' => \'baz\'])` or `call_user_func($foo, $foo = \'bar\')`.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + for ($index = $tokens->count() - 1; $index > 0; --$index) { + if (!$tokens[$index]->equalsAny([[T_STRING, 'call_user_func'], [T_STRING, 'call_user_func_array']], false)) { + continue; + } + + if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) { + continue; // redeclare/override + } + + $openParenthesis = $tokens->getNextMeaningfulToken($index); + $closeParenthesis = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesis); + $arguments = $argumentsAnalyzer->getArguments($tokens, $openParenthesis, $closeParenthesis); + + if (1 > \count($arguments)) { + return; // no arguments! + } + + $this->processCall($tokens, $index, $arguments); + } + } + + /** + * @param int $index + */ + private function processCall(Tokens $tokens, $index, array $arguments) + { + $firstArgIndex = $tokens->getNextMeaningfulToken( + $tokens->getNextMeaningfulToken($index) + ); + + /** @var Token $firstArgToken */ + $firstArgToken = $tokens[$firstArgIndex]; + + if ($firstArgToken->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) { + $afterFirstArgIndex = $tokens->getNextMeaningfulToken($firstArgIndex); + if (!$tokens[$afterFirstArgIndex]->equalsAny([',', ')'])) { + return; // first argument is an expression like `call_user_func("foo"."bar", ...)`, not supported! + } + + $newCallTokens = Tokens::fromCode('<?php '.substr(str_replace('\\\\', '\\', $firstArgToken->getContent()), 1, -1).'();'); + $newCallTokensSize = $newCallTokens->count(); + $newCallTokens->clearAt(0); + $newCallTokens->clearRange($newCallTokensSize - 3, $newCallTokensSize - 1); + $newCallTokens->clearEmptyTokens(); + + $this->replaceCallUserFuncWithCallback($tokens, $index, $newCallTokens, $firstArgIndex, $firstArgIndex); + } elseif ($firstArgToken->isGivenKind([T_FUNCTION, T_STATIC])) { + if (\PHP_VERSION_ID >= 70000) { + $firstArgEndIndex = $tokens->findBlockEnd( + Tokens::BLOCK_TYPE_CURLY_BRACE, + $tokens->getNextTokenOfKind($firstArgIndex, ['{']) + ); + + $newCallTokens = $this->getTokensSubcollection($tokens, $firstArgIndex, $firstArgEndIndex); + $newCallTokens->insertAt($newCallTokens->count(), new Token(')')); + $newCallTokens->insertAt(0, new Token('(')); + $this->replaceCallUserFuncWithCallback($tokens, $index, $newCallTokens, $firstArgIndex, $firstArgEndIndex); + } + } elseif ($firstArgToken->isGivenKind(T_VARIABLE)) { + $firstArgEndIndex = reset($arguments); + + // check if the same variable is used multiple times and if so do not fix + + foreach ($arguments as $argumentStart => $argumentEnd) { + if ($firstArgEndIndex === $argumentEnd) { + continue; + } + + for ($i = $argumentStart; $i <= $argumentEnd; ++$i) { + if ($tokens[$i]->equals($firstArgToken)) { + return; + } + } + } + + // check if complex statement and if so wrap the call in () if on PHP 7 or up, else do not fix + + $newCallTokens = $this->getTokensSubcollection($tokens, $firstArgIndex, $firstArgEndIndex); + $complex = false; + + for ($newCallIndex = \count($newCallTokens) - 1; $newCallIndex >= 0; --$newCallIndex) { + if ($newCallTokens[$newCallIndex]->isGivenKind([T_WHITESPACE, T_COMMENT, T_DOC_COMMENT, T_VARIABLE])) { + continue; + } + + $blockType = Tokens::detectBlockType($newCallTokens[$newCallIndex]); + + if (null !== $blockType && (Tokens::BLOCK_TYPE_ARRAY_INDEX_CURLY_BRACE === $blockType['type'] || Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE === $blockType['type'])) { + $newCallIndex = $newCallTokens->findBlockStart($blockType['type'], $newCallIndex); + + continue; + } + + $complex = true; + + break; + } + + if ($complex) { + if (\PHP_VERSION_ID < 70000) { + return; + } + + $newCallTokens->insertAt($newCallTokens->count(), new Token(')')); + $newCallTokens->insertAt(0, new Token('(')); + } + $this->replaceCallUserFuncWithCallback($tokens, $index, $newCallTokens, $firstArgIndex, $firstArgEndIndex); + } + } + + /** + * @param int $callIndex + * @param int $firstArgStartIndex + * @param int $firstArgEndIndex + */ + private function replaceCallUserFuncWithCallback(Tokens $tokens, $callIndex, Tokens $newCallTokens, $firstArgStartIndex, $firstArgEndIndex) + { + $tokens->clearRange($firstArgStartIndex, $firstArgEndIndex); // FRS end? + + $afterFirstArgIndex = $tokens->getNextMeaningfulToken($firstArgEndIndex); + $afterFirstArgToken = $tokens[$afterFirstArgIndex]; + + if ($afterFirstArgToken->equals(',')) { + $useEllipsis = $tokens[$callIndex]->equals([T_STRING, 'call_user_func_array']); + + if ($useEllipsis) { + $secondArgIndex = $tokens->getNextMeaningfulToken($afterFirstArgIndex); + $tokens->insertAt($secondArgIndex, new Token([T_ELLIPSIS, '...'])); + } + + $tokens->clearAt($afterFirstArgIndex); + $tokens->removeTrailingWhitespace($afterFirstArgIndex); + } + + $tokens->overrideRange($callIndex, $callIndex, $newCallTokens); + + $prevIndex = $tokens->getPrevMeaningfulToken($callIndex); + + if ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + $tokens->clearTokenAndMergeSurroundingWhitespace($prevIndex); + } + } + + private function getTokensSubcollection(Tokens $tokens, $indexStart, $indexEnd) + { + $size = $indexEnd - $indexStart + 1; + $subcollection = new Tokens($size); + + for ($i = 0; $i < $size; ++$i) { + /** @var Token $toClone */ + $toClone = $tokens[$i + $indexStart]; + $subcollection[$i] = clone $toClone; + } + + return $subcollection; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/ReturnTypeDeclarationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/ReturnTypeDeclarationFixer.php new file mode 100644 index 0000000..78340a4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/ReturnTypeDeclarationFixer.php @@ -0,0 +1,133 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class ReturnTypeDeclarationFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + $versionSpecification = new VersionSpecification(70000); + + return new FixerDefinition( + 'There should be one or no space before colon, and one space after it in return type declarations, according to configuration.', + [ + new VersionSpecificCodeSample( + "<?php\nfunction foo(int \$a):string {};\n", + $versionSpecification + ), + new VersionSpecificCodeSample( + "<?php\nfunction foo(int \$a):string {};\n", + $versionSpecification, + ['space_before' => 'none'] + ), + new VersionSpecificCodeSample( + "<?php\nfunction foo(int \$a):string {};\n", + $versionSpecification, + ['space_before' => 'one'] + ), + ], + 'Rule is applied only in a PHP 7+ environment.' + ); + } + + /** + * {@inheritdoc} + * + * Must run after PhpdocToReturnTypeFixer, VoidReturnFixer. + */ + public function getPriority() + { + return -17; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(CT::T_TYPE_COLON); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $oneSpaceBefore = 'one' === $this->configuration['space_before']; + + for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { + if (!$tokens[$index]->isGivenKind(CT::T_TYPE_COLON)) { + continue; + } + + $previousIndex = $index - 1; + $previousToken = $tokens[$previousIndex]; + + if ($previousToken->isWhitespace()) { + if (!$tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) { + if ($oneSpaceBefore) { + $tokens[$previousIndex] = new Token([T_WHITESPACE, ' ']); + } else { + $tokens->clearAt($previousIndex); + } + } + } elseif ($oneSpaceBefore) { + $tokenWasAdded = $tokens->ensureWhitespaceAtIndex($index, 0, ' '); + + if ($tokenWasAdded) { + ++$limit; + } + + ++$index; + } + + ++$index; + + $tokenWasAdded = $tokens->ensureWhitespaceAtIndex($index, 0, ' '); + + if ($tokenWasAdded) { + ++$limit; + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('space_before', 'Spacing to apply before colon.')) + ->setAllowedValues(['one', 'none']) + ->setDefault('none') + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/SingleLineThrowFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/SingleLineThrowFixer.php new file mode 100644 index 0000000..31136d8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/SingleLineThrowFixer.php @@ -0,0 +1,183 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Kuba Werłos <werlos@gmail.com> + */ +final class SingleLineThrowFixer extends AbstractFixer +{ + /** + * @internal + */ + const REMOVE_WHITESPACE_AFTER_TOKENS = ['[']; + + /** + * @internal + */ + const REMOVE_WHITESPACE_AROUND_TOKENS = ['(', [T_DOUBLE_COLON]]; + + /** + * @internal + */ + const REMOVE_WHITESPACE_BEFORE_TOKENS = [')', ']', ',', ';']; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Throwing exception must be done in single line.', + [ + new CodeSample("<?php\nthrow new Exception(\n 'Error.',\n 500\n);\n"), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_THROW); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer, ConcatSpaceFixer. + */ + public function getPriority() + { + return 36; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { + if (!$tokens[$index]->isGivenKind(T_THROW)) { + continue; + } + + $endCandidateIndex = $tokens->getNextMeaningfulToken($index); + + while (!$tokens[$endCandidateIndex]->equalsAny([')', ']', ',', ';'])) { + $blockType = Tokens::detectBlockType($tokens[$endCandidateIndex]); + if (null !== $blockType) { + if (Tokens::BLOCK_TYPE_CURLY_BRACE === $blockType['type']) { + break; + } + $endCandidateIndex = $tokens->findBlockEnd($blockType['type'], $endCandidateIndex); + } + $endCandidateIndex = $tokens->getNextMeaningfulToken($endCandidateIndex); + } + + $this->trimNewLines($tokens, $index, $tokens->getPrevMeaningfulToken($endCandidateIndex)); + } + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function trimNewLines(Tokens $tokens, $startIndex, $endIndex) + { + for ($index = $startIndex; $index < $endIndex; ++$index) { + $content = $tokens[$index]->getContent(); + + if ($tokens[$index]->isGivenKind(T_COMMENT)) { + if (0 === strpos($content, '//')) { + $content = '/*'.substr($content, 2).' */'; + $tokens->clearAt($index + 1); + } elseif (0 === strpos($content, '#')) { + $content = '/*'.substr($content, 1).' */'; + $tokens->clearAt($index + 1); + } elseif (false !== Preg::match('/\R/', $content)) { + $content = Preg::replace('/\R/', ' ', $content); + } + + $tokens[$index] = new Token([T_COMMENT, $content]); + + continue; + } + + if (!$tokens[$index]->isGivenKind(T_WHITESPACE)) { + continue; + } + + if (0 === Preg::match('/\R/', $content)) { + continue; + } + + $prevIndex = $tokens->getNonEmptySibling($index, -1); + + if ($this->isPreviousTokenToClear($tokens[$prevIndex])) { + $tokens->clearAt($index); + + continue; + } + + $nextIndex = $tokens->getNonEmptySibling($index, 1); + + if ( + $this->isNextTokenToClear($tokens[$nextIndex]) + && !$tokens[$prevIndex]->isGivenKind(T_FUNCTION) + ) { + $tokens->clearAt($index); + + continue; + } + + $tokens[$index] = new Token([T_WHITESPACE, ' ']); + } + } + + /** + * @return bool + */ + private function isPreviousTokenToClear(Token $token) + { + static $tokens = null; + + if (null === $tokens) { + $tokens = array_merge(self::REMOVE_WHITESPACE_AFTER_TOKENS, self::REMOVE_WHITESPACE_AROUND_TOKENS); + } + + return $token->equalsAny($tokens) || $token->isObjectOperator(); + } + + /** + * @return bool + */ + private function isNextTokenToClear(Token $token) + { + static $tokens = null; + + if (null === $tokens) { + $tokens = array_merge(self::REMOVE_WHITESPACE_AROUND_TOKENS, self::REMOVE_WHITESPACE_BEFORE_TOKENS); + } + + return $token->equalsAny($tokens) || $token->isObjectOperator(); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/StaticLambdaFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/StaticLambdaFixer.php new file mode 100644 index 0000000..1af6968 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/StaticLambdaFixer.php @@ -0,0 +1,186 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author SpacePossum + */ +final class StaticLambdaFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Lambdas not (indirect) referencing `$this` must be declared `static`.', + [new CodeSample("<?php\n\$a = function () use (\$b)\n{ echo \$b;\n};\n")], + null, + 'Risky when using `->bindTo` on lambdas without referencing to `$this`.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) { + return true; + } + + return $tokens->isTokenKindFound(T_FUNCTION); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $analyzer = new TokensAnalyzer($tokens); + $expectedFunctionKinds = [T_FUNCTION]; + + if (\PHP_VERSION_ID >= 70400) { + $expectedFunctionKinds[] = T_FN; + } + + for ($index = $tokens->count() - 4; $index > 0; --$index) { + if (!$tokens[$index]->isGivenKind($expectedFunctionKinds) || !$analyzer->isLambda($index)) { + continue; + } + + $prev = $tokens->getPrevMeaningfulToken($index); + + if ($tokens[$prev]->isGivenKind(T_STATIC)) { + continue; // lambda is already 'static' + } + + $argumentsStartIndex = $tokens->getNextTokenOfKind($index, ['(']); + $argumentsEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $argumentsStartIndex); + + // figure out where the lambda starts and ends + + if ($tokens[$index]->isGivenKind(T_FUNCTION)) { + $lambdaOpenIndex = $tokens->getNextTokenOfKind($argumentsEndIndex, ['{']); + $lambdaEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $lambdaOpenIndex); + } else { // T_FN + $lambdaOpenIndex = $tokens->getNextTokenOfKind($argumentsEndIndex, [[T_DOUBLE_ARROW]]); + $lambdaEndIndex = $this->findExpressionEnd($tokens, $lambdaOpenIndex); + } + + if ($this->hasPossibleReferenceToThis($tokens, $lambdaOpenIndex, $lambdaEndIndex)) { + continue; + } + + // make the lambda static + $tokens->insertAt( + $index, + [ + new Token([T_STATIC, 'static']), + new Token([T_WHITESPACE, ' ']), + ] + ); + + $index -= 4; // fixed after a lambda, closes candidate is at least 4 tokens before that + } + } + + /** + * @param int $index + * + * @return int + */ + private function findExpressionEnd(Tokens $tokens, $index) + { + $nextIndex = $tokens->getNextMeaningfulToken($index); + + while (null !== $nextIndex) { + /** @var Token $nextToken */ + $nextToken = $tokens[$nextIndex]; + + if ($nextToken->equalsAny([',', ';', [T_CLOSE_TAG]])) { + break; + } + + /** @var null|array{isStart: bool, type: int} $blockType */ + $blockType = Tokens::detectBlockType($nextToken); + + if (null !== $blockType && $blockType['isStart']) { + $nextIndex = $tokens->findBlockEnd($blockType['type'], $nextIndex); + } + + $index = $nextIndex; + $nextIndex = $tokens->getNextMeaningfulToken($index); + } + + return $index; + } + + /** + * Returns 'true' if there is a possible reference to '$this' within the given tokens index range. + * + * @param int $startIndex + * @param int $endIndex + * + * @return bool + */ + private function hasPossibleReferenceToThis(Tokens $tokens, $startIndex, $endIndex) + { + for ($i = $startIndex; $i < $endIndex; ++$i) { + if ($tokens[$i]->isGivenKind(T_VARIABLE) && '$this' === strtolower($tokens[$i]->getContent())) { + return true; // directly accessing '$this' + } + + if ($tokens[$i]->isGivenKind([ + T_INCLUDE, // loading additional symbols we cannot analyze here + T_INCLUDE_ONCE, // " + T_REQUIRE, // " + T_REQUIRE_ONCE, // " + CT::T_DYNAMIC_VAR_BRACE_OPEN, // "$h = ${$g};" case + T_EVAL, // "$c = eval('return $this;');" case + ])) { + return true; + } + + if ($tokens[$i]->equals('$')) { + $nextIndex = $tokens->getNextMeaningfulToken($i); + + if ($tokens[$nextIndex]->isGivenKind(T_VARIABLE)) { + return true; // "$$a" case + } + } + + if ($tokens[$i]->equals([T_STRING, 'parent'], false)) { + return true; // parent:: case + } + } + + return false; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/UseArrowFunctionsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/UseArrowFunctionsFixer.php new file mode 100644 index 0000000..74c0afb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/UseArrowFunctionsFixer.php @@ -0,0 +1,220 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Gregor Harlan + */ +final class UseArrowFunctionsFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Anonymous functions with one-liner return statement must use arrow functions.', + [ + new VersionSpecificCodeSample( + <<<'SAMPLE' +<?php +foo(function ($a) use ($b) { + return $a + $b; +}); + +SAMPLE + , + new VersionSpecification(70400) + ), + ], + null, + 'Risky when using `isset()` on outside variables that are not imported with `use ()`.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70400 && $tokens->isAllTokenKindsFound([T_FUNCTION, T_RETURN]); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $analyzer = new TokensAnalyzer($tokens); + + for ($index = $tokens->count() - 1; $index > 0; --$index) { + if (!$tokens[$index]->isGivenKind(T_FUNCTION) || !$analyzer->isLambda($index)) { + continue; + } + + // Find parameters end + // Abort if they are multilined + + $parametersStart = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$parametersStart]->isGivenKind(CT::T_RETURN_REF)) { + $parametersStart = $tokens->getNextMeaningfulToken($parametersStart); + } + + $parametersEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $parametersStart); + + if ($this->isMultilined($tokens, $parametersStart, $parametersEnd)) { + continue; + } + + // Find `use ()` start and end + // Abort if it contains reference variables + + $next = $tokens->getNextMeaningfulToken($parametersEnd); + + $useStart = null; + $useEnd = null; + + if ($tokens[$next]->isGivenKind(CT::T_USE_LAMBDA)) { + $useStart = $next; + + if ($tokens[$useStart - 1]->isGivenKind(T_WHITESPACE)) { + --$useStart; + } + + $next = $tokens->getNextMeaningfulToken($next); + + while (!$tokens[$next]->equals(')')) { + if ($tokens[$next]->equals('&')) { + // variables used by reference are not supported by arrow functions + continue 2; + } + + $next = $tokens->getNextMeaningfulToken($next); + } + + $useEnd = $next; + $next = $tokens->getNextMeaningfulToken($next); + } + + // Find opening brace and following `return` + // Abort if there is more than whitespace between them (like comments) + + $braceOpen = $tokens[$next]->equals('{') ? $next : $tokens->getNextTokenOfKind($next, ['{']); + $return = $braceOpen + 1; + + if ($tokens[$return]->isGivenKind(T_WHITESPACE)) { + ++$return; + } + + if (!$tokens[$return]->isGivenKind(T_RETURN)) { + continue; + } + + // Find semicolon of `return` statement + + $semicolon = $tokens->getNextTokenOfKind($return, ['{', ';']); + + if (!$tokens[$semicolon]->equals(';')) { + continue; + } + + // Find closing brace + // Abort if there is more than whitespace between semicolon and closing brace + + $braceClose = $semicolon + 1; + + if ($tokens[$braceClose]->isGivenKind(T_WHITESPACE)) { + ++$braceClose; + } + + if (!$tokens[$braceClose]->equals('}')) { + continue; + } + + // Abort if the `return` statement is multilined + + if ($this->isMultilined($tokens, $return, $semicolon)) { + continue; + } + + // Transform the function to an arrow function + + $this->transform($tokens, $index, $useStart, $useEnd, $braceOpen, $return, $semicolon, $braceClose); + } + } + + /** + * @param int $start + * @param int $end + * + * @return bool + */ + private function isMultilined(Tokens $tokens, $start, $end) + { + for ($i = $start; $i < $end; ++$i) { + if (false !== strpos($tokens[$i]->getContent(), "\n")) { + return true; + } + } + + return false; + } + + /** + * @param int $index + * @param null|int $useStart + * @param null|int $useEnd + * @param int $braceOpen + * @param int $return + * @param int $semicolon + * @param int $braceClose + */ + private function transform(Tokens $tokens, $index, $useStart, $useEnd, $braceOpen, $return, $semicolon, $braceClose) + { + $tokensToInsert = [new Token([T_DOUBLE_ARROW, '=>'])]; + if ($tokens->getNextMeaningfulToken($return) === $semicolon) { + $tokensToInsert[] = new Token([T_WHITESPACE, ' ']); + $tokensToInsert[] = new Token([T_STRING, 'null']); + } + + $tokens->clearRange($semicolon, $braceClose); + + $tokens->clearRange($braceOpen + 1, $return); + + $tokens->overrideRange($braceOpen, $braceOpen, $tokensToInsert); + + if ($useStart) { + $tokens->clearRange($useStart, $useEnd); + } + + $tokens[$index] = new Token([T_FN, 'fn']); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/VoidReturnFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/VoidReturnFixer.php new file mode 100644 index 0000000..17c1fe7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/FunctionNotation/VoidReturnFixer.php @@ -0,0 +1,264 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Mark Nielsen + */ +final class VoidReturnFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Add `void` return type to functions with missing or empty return statements, but priority is given to `@return` annotations. Requires PHP >= 7.1.', + [ + new VersionSpecificCodeSample( + "<?php\nfunction foo(\$a) {};\n", + new VersionSpecification(70100) + ), + ], + null, + 'Modifies the signature of functions.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocNoEmptyReturnFixer, ReturnTypeDeclarationFixer. + * Must run after NoSuperfluousPhpdocTagsFixer, SimplifiedNullReturnFixer. + */ + public function getPriority() + { + return 5; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70100 && $tokens->isTokenKindFound(T_FUNCTION); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // These cause syntax errors. + static $excludedFunctions = [ + [T_STRING, '__construct'], + [T_STRING, '__destruct'], + [T_STRING, '__clone'], + [T_STRING, '__isset'], + [T_STRING, '__sleep'], + [T_STRING, '__serialize'], + [T_STRING, '__set_state'], + [T_STRING, '__debugInfo'], + ]; + + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + if (!$tokens[$index]->isGivenKind(T_FUNCTION)) { + continue; + } + + $functionName = $tokens->getNextMeaningfulToken($index); + if ($tokens[$functionName]->equalsAny($excludedFunctions, false)) { + continue; + } + + $startIndex = $tokens->getNextTokenOfKind($index, ['{', ';']); + + if ($this->hasReturnTypeHint($tokens, $startIndex)) { + continue; + } + + if ($tokens[$startIndex]->equals(';')) { + // No function body defined, fallback to PHPDoc. + if ($this->hasVoidReturnAnnotation($tokens, $index)) { + $this->fixFunctionDefinition($tokens, $startIndex); + } + + continue; + } + + if ($this->hasReturnAnnotation($tokens, $index)) { + continue; + } + + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startIndex); + + if ($this->hasVoidReturn($tokens, $startIndex, $endIndex)) { + $this->fixFunctionDefinition($tokens, $startIndex); + } + } + } + + /** + * Determine whether there is a non-void return annotation in the function's PHPDoc comment. + * + * @param int $index The index of the function token + * + * @return bool + */ + private function hasReturnAnnotation(Tokens $tokens, $index) + { + foreach ($this->findReturnAnnotations($tokens, $index) as $return) { + if (['void'] !== $return->getTypes()) { + return true; + } + } + + return false; + } + + /** + * Determine whether there is a void return annotation in the function's PHPDoc comment. + * + * @param int $index The index of the function token + * + * @return bool + */ + private function hasVoidReturnAnnotation(Tokens $tokens, $index) + { + foreach ($this->findReturnAnnotations($tokens, $index) as $return) { + if (['void'] === $return->getTypes()) { + return true; + } + } + + return false; + } + + /** + * Determine whether the function already has a return type hint. + * + * @param int $index The index of the end of the function definition line, EG at { or ; + * + * @return bool + */ + private function hasReturnTypeHint(Tokens $tokens, $index) + { + $endFuncIndex = $tokens->getPrevTokenOfKind($index, [')']); + $nextIndex = $tokens->getNextMeaningfulToken($endFuncIndex); + + return $tokens[$nextIndex]->isGivenKind(CT::T_TYPE_COLON); + } + + /** + * Determine whether the function has a void return. + * + * @param int $startIndex Start of function body + * @param int $endIndex End of function body + * + * @return bool + */ + private function hasVoidReturn(Tokens $tokens, $startIndex, $endIndex) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($i = $startIndex; $i < $endIndex; ++$i) { + if ( + // skip anonymous classes + ($tokens[$i]->isGivenKind(T_CLASS) && $tokensAnalyzer->isAnonymousClass($i)) + // skip lambda functions + || ($tokens[$i]->isGivenKind(T_FUNCTION) && $tokensAnalyzer->isLambda($i)) + ) { + $i = $tokens->getNextTokenOfKind($i, ['{']); + $i = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $i); + + continue; + } + + if ($tokens[$i]->isGivenKind([T_YIELD, T_YIELD_FROM])) { + return false; // Generators cannot return void. + } + + if (!$tokens[$i]->isGivenKind(T_RETURN)) { + continue; + } + + $i = $tokens->getNextMeaningfulToken($i); + if (!$tokens[$i]->equals(';')) { + return false; + } + } + + return true; + } + + /** + * @param int $index The index of the end of the function definition line, EG at { or ; + */ + private function fixFunctionDefinition(Tokens $tokens, $index) + { + $endFuncIndex = $tokens->getPrevTokenOfKind($index, [')']); + $tokens->insertAt($endFuncIndex + 1, [ + new Token([CT::T_TYPE_COLON, ':']), + new Token([T_WHITESPACE, ' ']), + new Token([T_STRING, 'void']), + ]); + } + + /** + * Find all the return annotations in the function's PHPDoc comment. + * + * @param int $index The index of the function token + * + * @return Annotation[] + */ + private function findReturnAnnotations(Tokens $tokens, $index) + { + do { + $index = $tokens->getPrevNonWhitespace($index); + } while ($tokens[$index]->isGivenKind([ + T_ABSTRACT, + T_FINAL, + T_PRIVATE, + T_PROTECTED, + T_PUBLIC, + T_STATIC, + ])); + + if (!$tokens[$index]->isGivenKind(T_DOC_COMMENT)) { + return []; + } + + $doc = new DocBlock($tokens[$index]->getContent()); + + return $doc->getAnnotationsOfType('return'); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/FullyQualifiedStrictTypesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/FullyQualifiedStrictTypesFixer.php new file mode 100644 index 0000000..f38f9f7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/FullyQualifiedStrictTypesFixer.php @@ -0,0 +1,178 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Import; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\TypeAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Generator\NamespacedStringTokenGenerator; +use PhpCsFixer\Tokenizer\Resolver\TypeShortNameResolver; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author VeeWee <toonverwerft@gmail.com> + */ +final class FullyQualifiedStrictTypesFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Transforms imported FQCN parameters and return types in function arguments to short version.', + [ + new CodeSample( + '<?php + +use Foo\Bar; + +class SomeClass +{ + public function doSomething(\Foo\Bar $foo) + { + } +} +' + ), + new VersionSpecificCodeSample( + '<?php + +use Foo\Bar; +use Foo\Bar\Baz; + +class SomeClass +{ + public function doSomething(\Foo\Bar $foo): \Foo\Bar\Baz + { + } +} +', + new VersionSpecification(70000) + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoSuperfluousPhpdocTagsFixer. + * Must run after PhpdocToReturnTypeFixer. + */ + public function getPriority() + { + return 7; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_FUNCTION) && ( + \count((new NamespacesAnalyzer())->getDeclarations($tokens)) + || \count((new NamespaceUsesAnalyzer())->getDeclarationsFromTokens($tokens)) + ); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $lastIndex = $tokens->count() - 1; + for ($index = $lastIndex; $index >= 0; --$index) { + if (!$tokens[$index]->isGivenKind(T_FUNCTION)) { + continue; + } + + // Return types are only available since PHP 7.0 + $this->fixFunctionReturnType($tokens, $index); + $this->fixFunctionArguments($tokens, $index); + } + } + + /** + * @param int $index + */ + private function fixFunctionArguments(Tokens $tokens, $index) + { + $arguments = (new FunctionsAnalyzer())->getFunctionArguments($tokens, $index); + + foreach ($arguments as $argument) { + if (!$argument->hasTypeAnalysis()) { + continue; + } + + $this->detectAndReplaceTypeWithShortType($tokens, $argument->getTypeAnalysis()); + } + } + + /** + * @param int $index + */ + private function fixFunctionReturnType(Tokens $tokens, $index) + { + if (\PHP_VERSION_ID < 70000) { + return; + } + + $returnType = (new FunctionsAnalyzer())->getFunctionReturnType($tokens, $index); + if (!$returnType) { + return; + } + + $this->detectAndReplaceTypeWithShortType($tokens, $returnType); + } + + private function detectAndReplaceTypeWithShortType( + Tokens $tokens, + TypeAnalysis $type + ) { + if ($type->isReservedType()) { + return; + } + + $typeName = $type->getName(); + + if (0 !== strpos($typeName, '\\')) { + return; + } + + $shortType = (new TypeShortNameResolver())->resolve($tokens, $typeName); + if ($shortType === $typeName) { + return; + } + + $shortType = (new NamespacedStringTokenGenerator())->generate($shortType); + + if (true === $type->isNullable()) { + array_unshift($shortType, new Token([CT::T_NULLABLE_TYPE, '?'])); + } + + $tokens->overrideRange( + $type->getStartIndex(), + $type->getEndIndex(), + $shortType + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/GlobalNamespaceImportFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/GlobalNamespaceImportFixer.php new file mode 100644 index 0000000..2a0fe44 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/GlobalNamespaceImportFixer.php @@ -0,0 +1,751 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Import; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\ClassyAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Gregor Harlan <gharlan@web.de> + */ +final class GlobalNamespaceImportFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Imports or fully qualifies global classes/functions/constants.', + [ + new CodeSample( + '<?php + +namespace Foo; + +$d = new \DateTimeImmutable(); +' + ), + new CodeSample( + '<?php + +namespace Foo; + +if (\count($x)) { + /** @var \DateTimeImmutable $d */ + $d = new \DateTimeImmutable(); + $p = \M_PI; +} +', + ['import_classes' => true, 'import_constants' => true, 'import_functions' => true] + ), + new CodeSample( + '<?php + +namespace Foo; + +use DateTimeImmutable; +use function count; +use const M_PI; + +if (count($x)) { + /** @var DateTimeImmutable $d */ + $d = new DateTimeImmutable(); + $p = M_PI; +} +', + ['import_classes' => false, 'import_constants' => false, 'import_functions' => false] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoUnusedImportsFixer, OrderedImportsFixer. + * Must run after NativeConstantInvocationFixer, NativeFunctionInvocationFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_DOC_COMMENT, T_NS_SEPARATOR, T_USE]) + && $tokens->isTokenKindFound(T_NAMESPACE) + && (Tokens::isLegacyMode() || 1 === $tokens->countTokenKind(T_NAMESPACE)) + && $tokens->isMonolithicPhp(); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $namespaceAnalyses = (new NamespacesAnalyzer())->getDeclarations($tokens); + + if (1 !== \count($namespaceAnalyses) || '' === $namespaceAnalyses[0]->getFullName()) { + return; + } + + $useDeclarations = (new NamespaceUsesAnalyzer())->getDeclarationsFromTokens($tokens); + + $newImports = []; + + if (true === $this->configuration['import_constants']) { + $newImports['const'] = $this->importConstants($tokens, $useDeclarations); + } elseif (false === $this->configuration['import_constants']) { + $this->fullyQualifyConstants($tokens, $useDeclarations); + } + + if (true === $this->configuration['import_functions']) { + $newImports['function'] = $this->importFunctions($tokens, $useDeclarations); + } elseif (false === $this->configuration['import_functions']) { + $this->fullyQualifyFunctions($tokens, $useDeclarations); + } + + if (true === $this->configuration['import_classes']) { + $newImports['class'] = $this->importClasses($tokens, $useDeclarations); + } elseif (false === $this->configuration['import_classes']) { + $this->fullyQualifyClasses($tokens, $useDeclarations); + } + + $newImports = array_filter($newImports); + + if ($newImports) { + $this->insertImports($tokens, $newImports, $useDeclarations); + } + } + + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('import_constants', 'Whether to import, not import or ignore global constants.')) + ->setDefault(null) + ->setAllowedValues([true, false, null]) + ->getOption(), + (new FixerOptionBuilder('import_functions', 'Whether to import, not import or ignore global functions.')) + ->setDefault(null) + ->setAllowedValues([true, false, null]) + ->getOption(), + (new FixerOptionBuilder('import_classes', 'Whether to import, not import or ignore global classes.')) + ->setDefault(true) + ->setAllowedValues([true, false, null]) + ->getOption(), + ]); + } + + /** + * @param NamespaceUseAnalysis[] $useDeclarations + * + * @return array + */ + private function importConstants(Tokens $tokens, array $useDeclarations) + { + list($global, $other) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + return $declaration->isConstant(); + }, true); + + // find namespaced const declarations (`const FOO = 1`) + // and add them to the not importable names (already used) + for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { + $token = $tokens[$index]; + + if ($token->isClassy()) { + $index = $tokens->getNextTokenOfKind($index, ['{']); + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + continue; + } + + if (!$token->isGivenKind(T_CONST)) { + continue; + } + + $index = $tokens->getNextMeaningfulToken($index); + $other[$tokens[$index]->getContent()] = true; + } + + $analyzer = new TokensAnalyzer($tokens); + + $indexes = []; + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_STRING)) { + continue; + } + + $name = $token->getContent(); + + if (isset($other[$name])) { + continue; + } + + if (!$analyzer->isConstantInvocation($index)) { + continue; + } + + $nsSeparatorIndex = $tokens->getPrevMeaningfulToken($index); + if (!$tokens[$nsSeparatorIndex]->isGivenKind(T_NS_SEPARATOR)) { + if (!isset($global[$name])) { + // found an unqualified constant invocation + // add it to the not importable names (already used) + $other[$name] = true; + } + + continue; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($nsSeparatorIndex); + if ($tokens[$prevIndex]->isGivenKind([CT::T_NAMESPACE_OPERATOR, T_STRING])) { + continue; + } + + $indexes[] = $index; + } + + return $this->prepareImports($tokens, $indexes, $global, $other, true); + } + + /** + * @param NamespaceUseAnalysis[] $useDeclarations + * + * @return array + */ + private function importFunctions(Tokens $tokens, array $useDeclarations) + { + list($global, $other) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + return $declaration->isFunction(); + }, false); + + // find function declarations + // and add them to the not importable names (already used) + foreach ($this->findFunctionDeclarations($tokens, 0, $tokens->count() - 1) as $name) { + $other[strtolower($name)] = true; + } + + $analyzer = new FunctionsAnalyzer(); + + $indexes = []; + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_STRING)) { + continue; + } + + $name = strtolower($token->getContent()); + + if (isset($other[$name])) { + continue; + } + + if (!$analyzer->isGlobalFunctionCall($tokens, $index)) { + continue; + } + + $nsSeparatorIndex = $tokens->getPrevMeaningfulToken($index); + if (!$tokens[$nsSeparatorIndex]->isGivenKind(T_NS_SEPARATOR)) { + if (!isset($global[$name])) { + $other[$name] = true; + } + + continue; + } + + $indexes[] = $index; + } + + return $this->prepareImports($tokens, $indexes, $global, $other, false); + } + + /** + * @param NamespaceUseAnalysis[] $useDeclarations + * + * @return array + */ + private function importClasses(Tokens $tokens, array $useDeclarations) + { + list($global, $other) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + return $declaration->isClass(); + }, false); + + /** @var DocBlock[] $docBlocks */ + $docBlocks = []; + + // find class declarations and class usages in docblocks + // and add them to the not importable names (already used) + for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { + $token = $tokens[$index]; + + if ($token->isGivenKind(T_DOC_COMMENT)) { + $docBlocks[$index] = new DocBlock($token->getContent()); + + $this->traverseDocBlockTypes($docBlocks[$index], static function ($type) use ($global, &$other) { + if (false !== strpos($type, '\\')) { + return; + } + + $name = strtolower($type); + + if (!isset($global[$name])) { + $other[$name] = true; + } + }); + } + + if (!$token->isClassy()) { + continue; + } + + $index = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$index]->isGivenKind(T_STRING)) { + $other[strtolower($tokens[$index]->getContent())] = true; + } + } + + $analyzer = new ClassyAnalyzer(); + + $indexes = []; + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_STRING)) { + continue; + } + + $name = strtolower($token->getContent()); + + if (isset($other[$name])) { + continue; + } + + if (!$analyzer->isClassyInvocation($tokens, $index)) { + continue; + } + + $nsSeparatorIndex = $tokens->getPrevMeaningfulToken($index); + if (!$tokens[$nsSeparatorIndex]->isGivenKind(T_NS_SEPARATOR)) { + if (!isset($global[$name])) { + $other[$name] = true; + } + + continue; + } + + if ($tokens[$tokens->getPrevMeaningfulToken($nsSeparatorIndex)]->isGivenKind([CT::T_NAMESPACE_OPERATOR, T_STRING])) { + continue; + } + + $indexes[] = $index; + } + + $imports = []; + + foreach ($docBlocks as $index => $docBlock) { + $changed = $this->traverseDocBlockTypes($docBlock, static function ($type) use ($global, $other, &$imports) { + if ('\\' !== $type[0]) { + return $type; + } + + $name = substr($type, 1); + $checkName = strtolower($name); + + if (false !== strpos($checkName, '\\') || isset($other[$checkName])) { + return $type; + } + + if (isset($global[$checkName])) { + return \is_string($global[$checkName]) ? $global[$checkName] : $name; + } + + $imports[$checkName] = $name; + + return $name; + }); + + if ($changed) { + $tokens[$index] = new Token([T_DOC_COMMENT, $docBlock->getContent()]); + } + } + + return $imports + $this->prepareImports($tokens, $indexes, $global, $other, false); + } + + /** + * Removes the leading slash at the given indexes (when the name is not already used). + * + * @param int[] $indexes + * @param bool $caseSensitive + * + * @return array array keys contain the names that must be imported + */ + private function prepareImports(Tokens $tokens, array $indexes, array $global, array $other, $caseSensitive) + { + $imports = []; + + foreach ($indexes as $index) { + $name = $tokens[$index]->getContent(); + $checkName = $caseSensitive ? $name : strtolower($name); + + if (isset($other[$checkName])) { + continue; + } + + if (!isset($global[$checkName])) { + $imports[$checkName] = $name; + } elseif (\is_string($global[$checkName])) { + $tokens[$index] = new Token([T_STRING, $global[$checkName]]); + } + + $tokens->clearAt($tokens->getPrevMeaningfulToken($index)); + } + + return $imports; + } + + /** + * @param NamespaceUseAnalysis[] $useDeclarations + */ + private function insertImports(Tokens $tokens, array $imports, array $useDeclarations) + { + if ($useDeclarations) { + $useDeclaration = end($useDeclarations); + $index = $useDeclaration->getEndIndex() + 1; + } else { + $namespace = (new NamespacesAnalyzer())->getDeclarations($tokens)[0]; + $index = $namespace->getEndIndex() + 1; + } + + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + if (!$tokens[$index]->isWhitespace() || false === strpos($tokens[$index]->getContent(), "\n")) { + $tokens->insertAt($index, new Token([T_WHITESPACE, $lineEnding])); + } + + foreach ($imports as $type => $typeImports) { + foreach ($typeImports as $name) { + $items = [ + new Token([T_WHITESPACE, $lineEnding]), + new Token([T_USE, 'use']), + new Token([T_WHITESPACE, ' ']), + ]; + + if ('const' === $type) { + $items[] = new Token([CT::T_CONST_IMPORT, 'const']); + $items[] = new Token([T_WHITESPACE, ' ']); + } elseif ('function' === $type) { + $items[] = new Token([CT::T_FUNCTION_IMPORT, 'function']); + $items[] = new Token([T_WHITESPACE, ' ']); + } + + $items[] = new Token([T_STRING, $name]); + $items[] = new Token(';'); + + $tokens->insertAt($index, $items); + } + } + } + + /** + * @param NamespaceUseAnalysis[] $useDeclarations + */ + private function fullyQualifyConstants(Tokens $tokens, array $useDeclarations) + { + if (!$tokens->isTokenKindFound(CT::T_CONST_IMPORT)) { + return; + } + + list($global) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + return $declaration->isConstant() && !$declaration->isAliased(); + }, true); + + if (!$global) { + return; + } + + $analyzer = new TokensAnalyzer($tokens); + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_STRING)) { + continue; + } + + if (!isset($global[$token->getContent()])) { + continue; + } + + if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_NS_SEPARATOR)) { + continue; + } + + if (!$analyzer->isConstantInvocation($index)) { + continue; + } + + $tokens->insertAt($index, new Token([T_NS_SEPARATOR, '\\'])); + } + } + + /** + * @param NamespaceUseAnalysis[] $useDeclarations + */ + private function fullyQualifyFunctions(Tokens $tokens, array $useDeclarations) + { + if (!$tokens->isTokenKindFound(CT::T_FUNCTION_IMPORT)) { + return; + } + + list($global) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + return $declaration->isFunction() && !$declaration->isAliased(); + }, false); + + if (!$global) { + return; + } + + $analyzer = new FunctionsAnalyzer(); + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_STRING)) { + continue; + } + + if (!isset($global[strtolower($token->getContent())])) { + continue; + } + + if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_NS_SEPARATOR)) { + continue; + } + + if (!$analyzer->isGlobalFunctionCall($tokens, $index)) { + continue; + } + + $tokens->insertAt($index, new Token([T_NS_SEPARATOR, '\\'])); + } + } + + /** + * @param NamespaceUseAnalysis[] $useDeclarations + */ + private function fullyQualifyClasses(Tokens $tokens, array $useDeclarations) + { + if (!$tokens->isTokenKindFound(T_USE)) { + return; + } + + list($global) = $this->filterUseDeclarations($useDeclarations, static function (NamespaceUseAnalysis $declaration) { + return $declaration->isClass() && !$declaration->isAliased(); + }, false); + + if (!$global) { + return; + } + + $analyzer = new ClassyAnalyzer(); + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if ($token->isGivenKind(T_DOC_COMMENT)) { + $doc = new DocBlock($token->getContent()); + + $changed = $this->traverseDocBlockTypes($doc, static function ($type) use ($global) { + if (!isset($global[strtolower($type)])) { + return $type; + } + + return '\\'.$type; + }); + + if ($changed) { + $tokens[$index] = new Token([T_DOC_COMMENT, $doc->getContent()]); + } + + continue; + } + + if (!$token->isGivenKind(T_STRING)) { + continue; + } + + if (!isset($global[strtolower($token->getContent())])) { + continue; + } + + if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_NS_SEPARATOR)) { + continue; + } + + if (!$analyzer->isClassyInvocation($tokens, $index)) { + continue; + } + + $tokens->insertAt($index, new Token([T_NS_SEPARATOR, '\\'])); + } + } + + /** + * @param NamespaceUseAnalysis[] $declarations + * @param bool $caseSensitive + * + * @return array + */ + private function filterUseDeclarations(array $declarations, callable $callback, $caseSensitive) + { + $global = []; + $other = []; + + foreach ($declarations as $declaration) { + if (!$callback($declaration)) { + continue; + } + + $fullName = ltrim($declaration->getFullName(), '\\'); + + if (false !== strpos($fullName, '\\')) { + $name = $caseSensitive ? $declaration->getShortName() : strtolower($declaration->getShortName()); + $other[$name] = true; + + continue; + } + + $checkName = $caseSensitive ? $fullName : strtolower($fullName); + $alias = $declaration->getShortName(); + $global[$checkName] = $alias === $fullName ? true : $alias; + } + + return [$global, $other]; + } + + private function findFunctionDeclarations(Tokens $tokens, $start, $end) + { + for ($index = $start; $index <= $end; ++$index) { + $token = $tokens[$index]; + + if ($token->isClassy()) { + $classStart = $tokens->getNextTokenOfKind($index, ['{']); + $classEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classStart); + + for ($index = $classStart; $index <= $classEnd; ++$index) { + if (!$tokens[$index]->isGivenKind(T_FUNCTION)) { + continue; + } + + $methodStart = $tokens->getNextTokenOfKind($index, ['{', ';']); + + if ($tokens[$methodStart]->equals(';')) { + $index = $methodStart; + + continue; + } + + $methodEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $methodStart); + + foreach ($this->findFunctionDeclarations($tokens, $methodStart, $methodEnd) as $function) { + yield $function; + } + + $index = $methodEnd; + } + + continue; + } + + if (!$token->isGivenKind(T_FUNCTION)) { + continue; + } + + $index = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$index]->isGivenKind(CT::T_RETURN_REF)) { + $index = $tokens->getNextMeaningfulToken($index); + } + + if ($tokens[$index]->isGivenKind(T_STRING)) { + yield $tokens[$index]->getContent(); + } + } + } + + private function traverseDocBlockTypes(DocBlock $doc, callable $callback) + { + $annotations = $doc->getAnnotationsOfType(Annotation::getTagsWithTypes()); + + if (!$annotations) { + return false; + } + + $changed = false; + + foreach ($annotations as $annotation) { + $types = $new = $annotation->getTypes(); + + foreach ($types as $i => $fullType) { + $newFullType = $fullType; + + Preg::matchAll('/[\\\\\w]+/', $fullType, $matches, PREG_OFFSET_CAPTURE); + + foreach (array_reverse($matches[0]) as list($type, $offset)) { + $newType = $callback($type); + + if (null !== $newType && $type !== $newType) { + $newFullType = substr_replace($newFullType, $newType, $offset, \strlen($type)); + } + } + + $new[$i] = $newFullType; + } + + if ($types !== $new) { + $annotation->setTypes($new); + $changed = true; + } + } + + return $changed; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/GroupImportFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/GroupImportFixer.php new file mode 100644 index 0000000..1e69630 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/GroupImportFixer.php @@ -0,0 +1,296 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Import; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Volodymyr Kupriienko <vldmr.kuprienko@gmail.com> + */ +final class GroupImportFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There MUST be group use for the same namespaces.', + [ + new VersionSpecificCodeSample( + "<?php\nuse Foo\\Bar;\nuse Foo\\Baz;\n", + new VersionSpecification(70000) + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(T_USE); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $useWithSameNamespaces = $this->getSameNamespaces($tokens); + + if ([] === $useWithSameNamespaces) { + return; + } + + $this->removeSingleUseStatements($useWithSameNamespaces, $tokens); + $this->addGroupUseStatements($useWithSameNamespaces, $tokens); + } + + /** + * Gets namespace use analyzers with same namespaces. + * + * @return NamespaceUseAnalysis[] + */ + private function getSameNamespaces(Tokens $tokens) + { + $useDeclarations = (new NamespaceUsesAnalyzer())->getDeclarationsFromTokens($tokens); + + if (0 === \count($useDeclarations)) { + return []; + } + + $allNamespaceAndType = array_map( + function (NamespaceUseAnalysis $useDeclaration) { + return $this->getNamespaceNameWithSlash($useDeclaration).$useDeclaration->getType(); + }, + $useDeclarations + ); + + $sameNamespaces = array_filter(array_count_values($allNamespaceAndType), function ($count) { + return $count > 1; + }); + $sameNamespaces = array_keys($sameNamespaces); + + $sameNamespaceAnalysis = array_filter($useDeclarations, function ($useDeclaration) use ($sameNamespaces) { + $namespaceNameAndType = $this->getNamespaceNameWithSlash($useDeclaration).$useDeclaration->getType(); + + return \in_array($namespaceNameAndType, $sameNamespaces, true); + }); + + usort($sameNamespaceAnalysis, function (NamespaceUseAnalysis $a, NamespaceUseAnalysis $b) { + $namespaceA = $this->getNamespaceNameWithSlash($a); + $namespaceB = $this->getNamespaceNameWithSlash($b); + + return \strlen($namespaceA) - \strlen($namespaceB) ?: strcmp($a->getFullName(), $b->getFullName()); + }); + + return $sameNamespaceAnalysis; + } + + /** + * @param NamespaceUseAnalysis[] $statements + */ + private function removeSingleUseStatements(array $statements, Tokens $tokens) + { + foreach ($statements as $useDeclaration) { + $index = $useDeclaration->getStartIndex(); + $endIndex = $useDeclaration->getEndIndex(); + + $useStatementTokens = [T_USE, T_WHITESPACE, T_STRING, T_NS_SEPARATOR, T_AS, CT::T_CONST_IMPORT, CT::T_FUNCTION_IMPORT]; + + while ($index !== $endIndex) { + if ($tokens[$index]->isGivenKind($useStatementTokens)) { + $tokens->clearAt($index); + } + + ++$index; + } + + if (isset($tokens[$index]) && $tokens[$index]->equals(';')) { + $tokens->clearAt($index); + } + + ++$index; + + if (isset($tokens[$index]) && $tokens[$index]->isGivenKind(T_WHITESPACE)) { + $tokens->clearAt($index); + } + } + } + + /** + * @param NamespaceUseAnalysis[] $statements + */ + private function addGroupUseStatements(array $statements, Tokens $tokens) + { + $currentUseDeclaration = null; + $insertIndex = \array_slice($statements, -1)[0]->getEndIndex() + 1; + + foreach ($statements as $index => $useDeclaration) { + if ($this->areDeclarationsDifferent($currentUseDeclaration, $useDeclaration)) { + $currentUseDeclaration = $useDeclaration; + $insertIndex += $this->createNewGroup( + $tokens, + $insertIndex, + $useDeclaration, + $this->getNamespaceNameWithSlash($currentUseDeclaration) + ); + } else { + $newTokens = [ + new Token(','), + new Token([T_WHITESPACE, ' ']), + ]; + + if ($useDeclaration->isAliased()) { + $tokens->insertAt($insertIndex, $newTokens); + $insertIndex += \count($newTokens); + $newTokens = []; + + $insertIndex += $this->insertToGroupUseWithAlias($tokens, $insertIndex, $useDeclaration); + } + + $newTokens[] = new Token([T_STRING, $useDeclaration->getShortName()]); + + if (!isset($statements[$index + 1]) || $this->areDeclarationsDifferent($currentUseDeclaration, $statements[$index + 1])) { + $newTokens[] = new Token([CT::T_GROUP_IMPORT_BRACE_CLOSE, '}']); + $newTokens[] = new Token(';'); + $newTokens[] = new Token([T_WHITESPACE, "\n"]); + } + + $tokens->insertAt($insertIndex, $newTokens); + $insertIndex += \count($newTokens); + } + } + } + + /** + * @return string + */ + private function getNamespaceNameWithSlash(NamespaceUseAnalysis $useDeclaration) + { + $position = strrpos($useDeclaration->getFullName(), '\\'); + if (false === $position || 0 === $position) { + return $useDeclaration->getFullName(); + } + + return substr($useDeclaration->getFullName(), 0, $position + 1); + } + + /** + * Insert use with alias to the group. + * + * @param int $insertIndex + * + * @return int + */ + private function insertToGroupUseWithAlias(Tokens $tokens, $insertIndex, NamespaceUseAnalysis $useDeclaration) + { + $newTokens = [ + new Token([T_STRING, substr($useDeclaration->getFullName(), strripos($useDeclaration->getFullName(), '\\') + 1)]), + new Token([T_WHITESPACE, ' ']), + new Token([T_AS, 'as']), + new Token([T_WHITESPACE, ' ']), + ]; + + $tokens->insertAt($insertIndex, $newTokens); + + return \count($newTokens) + 1; + } + + /** + * Creates new use statement group. + * + * @param int $insertIndex + * @param string $currentNamespace + * + * @return int + */ + private function createNewGroup(Tokens $tokens, $insertIndex, NamespaceUseAnalysis $useDeclaration, $currentNamespace) + { + $insertedTokens = 0; + + if (\count($tokens) === $insertIndex) { + $tokens->setSize($insertIndex + 1); + } + + $newTokens = [ + new Token([T_USE, 'use']), + new Token([T_WHITESPACE, ' ']), + ]; + + if ($useDeclaration->isFunction() || $useDeclaration->isConstant()) { + $importStatementParams = $useDeclaration->isFunction() + ? [CT::T_FUNCTION_IMPORT, 'function'] + : [CT::T_CONST_IMPORT, 'const']; + + $newTokens[] = new Token($importStatementParams); + $newTokens[] = new Token([T_WHITESPACE, ' ']); + } + + $namespaceParts = array_filter(explode('\\', $currentNamespace)); + + foreach ($namespaceParts as $part) { + $newTokens[] = new Token([T_STRING, $part]); + $newTokens[] = new Token([T_NS_SEPARATOR, '\\']); + } + + $newTokens[] = new Token([CT::T_GROUP_IMPORT_BRACE_OPEN, '{']); + + $newTokensCount = \count($newTokens); + $tokens->insertAt($insertIndex, $newTokens); + $insertedTokens += $newTokensCount; + + $insertIndex += $newTokensCount; + + if ($useDeclaration->isAliased()) { + $inserted = $this->insertToGroupUseWithAlias($tokens, $insertIndex + 1, $useDeclaration); + $insertedTokens += $inserted; + $insertIndex += $inserted; + } + + $tokens->insertAt($insertIndex, new Token([T_STRING, $useDeclaration->getShortName()])); + ++$insertedTokens; + + return $insertedTokens; + } + + /** + * Check if namespace use analyses are different. + * + * @param null|NamespaceUseAnalysis $analysis1 + * @param null|NamespaceUseAnalysis $analysis2 + * + * @return bool + */ + private function areDeclarationsDifferent($analysis1, $analysis2) + { + if (null === $analysis1 || null === $analysis2) { + return true; + } + + $namespaceName1 = $this->getNamespaceNameWithSlash($analysis1); + $namespaceName2 = $this->getNamespaceNameWithSlash($analysis2); + + return $namespaceName1 !== $namespaceName2 || $analysis1->getType() !== $analysis2->getType(); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/NoLeadingImportSlashFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/NoLeadingImportSlashFixer.php new file mode 100644 index 0000000..a668ffa --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/NoLeadingImportSlashFixer.php @@ -0,0 +1,99 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Import; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Carlos Cirello <carlos.cirello.nl@gmail.com> + */ +final class NoLeadingImportSlashFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Remove leading slashes in `use` clauses.', + [new CodeSample("<?php\nnamespace Foo;\nuse \\Bar;\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before OrderedImportsFixer. + * Must run after NoUnusedImportsFixer, SingleImportPerStatementFixer. + */ + public function getPriority() + { + return -20; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_USE); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + $usesIndexes = $tokensAnalyzer->getImportUseIndexes(); + + foreach ($usesIndexes as $idx) { + $nextTokenIdx = $tokens->getNextMeaningfulToken($idx); + $nextToken = $tokens[$nextTokenIdx]; + + if ($nextToken->isGivenKind(T_NS_SEPARATOR)) { + $this->removeLeadingImportSlash($tokens, $nextTokenIdx); + } elseif ($nextToken->isGivenKind([CT::T_FUNCTION_IMPORT, CT::T_CONST_IMPORT])) { + $nextTokenIdx = $tokens->getNextMeaningfulToken($nextTokenIdx); + if ($tokens[$nextTokenIdx]->isGivenKind(T_NS_SEPARATOR)) { + $this->removeLeadingImportSlash($tokens, $nextTokenIdx); + } + } + } + } + + /** + * @param int $index + */ + private function removeLeadingImportSlash(Tokens $tokens, $index) + { + $previousIndex = $tokens->getPrevNonWhitespace($index); + + if ( + $previousIndex < $index - 1 + || $tokens[$previousIndex]->isComment() + ) { + $tokens->clearAt($index); + + return; + } + + $tokens[$index] = new Token([T_WHITESPACE, ' ']); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/NoUnusedImportsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/NoUnusedImportsFixer.php new file mode 100644 index 0000000..c9f64fa --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/NoUnusedImportsFixer.php @@ -0,0 +1,278 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Import; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NoUnusedImportsFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Unused `use` statements must be removed.', + [new CodeSample("<?php\nuse \\DateTime;\nuse \\Exception;\n\nnew DateTime();\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BlankLineAfterNamespaceFixer, NoExtraBlankLinesFixer, NoLeadingImportSlashFixer, SingleLineAfterImportsFixer. + * Must run after ClassKeywordRemoveFixer, GlobalNamespaceImportFixer, PhpUnitFqcnAnnotationFixer, SingleImportPerStatementFixer. + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_USE); + } + + /** + * {@inheritdoc} + */ + public function supports(\SplFileInfo $file) + { + $path = $file->getPathname(); + + /* + * @deprecated this exception will be removed on 3.0 + * some fixtures are auto-generated by Symfony and may contain unused use statements + */ + if (false !== strpos($path, \DIRECTORY_SEPARATOR.'Fixtures'.\DIRECTORY_SEPARATOR) + && false === strpos($path, \DIRECTORY_SEPARATOR.'tests'.\DIRECTORY_SEPARATOR.'Fixtures'.\DIRECTORY_SEPARATOR) + ) { + return false; + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $useDeclarations = (new NamespaceUsesAnalyzer())->getDeclarationsFromTokens($tokens); + + if (0 === \count($useDeclarations)) { + return; + } + + foreach ((new NamespacesAnalyzer())->getDeclarations($tokens) as $namespace) { + $currentNamespaceUseDeclarations = array_filter( + $useDeclarations, + static function (NamespaceUseAnalysis $useDeclaration) use ($namespace) { + return + $useDeclaration->getStartIndex() >= $namespace->getScopeStartIndex() + && $useDeclaration->getEndIndex() <= $namespace->getScopeEndIndex() + ; + } + ); + + $usagesSearchIgnoredIndexes = []; + + foreach ($currentNamespaceUseDeclarations as $useDeclaration) { + $usagesSearchIgnoredIndexes[$useDeclaration->getStartIndex()] = $useDeclaration->getEndIndex(); + } + + foreach ($currentNamespaceUseDeclarations as $useDeclaration) { + if (!$this->isImportUsed($tokens, $namespace, $usagesSearchIgnoredIndexes, $useDeclaration->getShortName())) { + $this->removeUseDeclaration($tokens, $useDeclaration); + } + } + + $this->removeUsesInSameNamespace($tokens, $currentNamespaceUseDeclarations, $namespace); + } + } + + /** + * @param array<int, int> $ignoredIndexes + * @param string $shortName + * + * @return bool + */ + private function isImportUsed(Tokens $tokens, NamespaceAnalysis $namespace, array $ignoredIndexes, $shortName) + { + $namespaceEndIndex = $namespace->getScopeEndIndex(); + for ($index = $namespace->getScopeStartIndex(); $index <= $namespaceEndIndex; ++$index) { + if (isset($ignoredIndexes[$index])) { + $index = $ignoredIndexes[$index]; + + continue; + } + + $token = $tokens[$index]; + + if ($token->isGivenKind(T_STRING)) { + $prevMeaningfulToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; + + if ($prevMeaningfulToken->isGivenKind(T_NAMESPACE)) { + $index = $tokens->getNextTokenOfKind($index, [';', '{', [T_CLOSE_TAG]]); + + continue; + } + + if ( + 0 === strcasecmp($shortName, $token->getContent()) + && !$prevMeaningfulToken->isGivenKind([T_NS_SEPARATOR, T_CONST, T_DOUBLE_COLON]) + && !$prevMeaningfulToken->isObjectOperator() + ) { + return true; + } + + continue; + } + + if ($token->isComment() + && Preg::match( + '/(?<![[:alnum:]\$])(?<!\\\\)'.$shortName.'(?![[:alnum:]])/i', + $token->getContent() + ) + ) { + return true; + } + } + + return false; + } + + private function removeUseDeclaration(Tokens $tokens, NamespaceUseAnalysis $useDeclaration) + { + for ($index = $useDeclaration->getEndIndex() - 1; $index >= $useDeclaration->getStartIndex(); --$index) { + if ($tokens[$index]->isComment()) { + continue; + } + + if (!$tokens[$index]->isWhitespace() || false === strpos($tokens[$index]->getContent(), "\n")) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + + continue; + } + + // when multi line white space keep the line feed if the previous token is a comment + $prevIndex = $tokens->getPrevNonWhitespace($index); + if ($tokens[$prevIndex]->isComment()) { + $content = $tokens[$index]->getContent(); + $tokens[$index] = new Token([T_WHITESPACE, substr($content, strrpos($content, "\n"))]); // preserve indent only + } else { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } + } + + if ($tokens[$useDeclaration->getEndIndex()]->equals(';')) { // do not remove `? >` + $tokens->clearAt($useDeclaration->getEndIndex()); + } + + // remove white space above and below where the `use` statement was + + $prevIndex = $useDeclaration->getStartIndex() - 1; + $prevToken = $tokens[$prevIndex]; + + if ($prevToken->isWhitespace()) { + $content = rtrim($prevToken->getContent(), " \t"); + + if ('' === $content) { + $tokens->clearAt($prevIndex); + } else { + $tokens[$prevIndex] = new Token([T_WHITESPACE, $content]); + } + + $prevToken = $tokens[$prevIndex]; + } + + if (!isset($tokens[$useDeclaration->getEndIndex() + 1])) { + return; + } + + $nextIndex = $tokens->getNonEmptySibling($useDeclaration->getEndIndex(), 1); + if (null === $nextIndex) { + return; + } + + $nextToken = $tokens[$nextIndex]; + + if ($nextToken->isWhitespace()) { + $content = Preg::replace( + "#^\r\n|^\n#", + '', + ltrim($nextToken->getContent(), " \t"), + 1 + ); + + if ('' !== $content) { + $tokens[$nextIndex] = new Token([T_WHITESPACE, $content]); + } else { + $tokens->clearAt($nextIndex); + } + + $nextToken = $tokens[$nextIndex]; + } + + if ($prevToken->isWhitespace() && $nextToken->isWhitespace()) { + $content = $prevToken->getContent().$nextToken->getContent(); + + if ('' !== $content) { + $tokens[$nextIndex] = new Token([T_WHITESPACE, $content]); + } else { + $tokens->clearAt($nextIndex); + } + + $tokens->clearAt($prevIndex); + } + } + + private function removeUsesInSameNamespace(Tokens $tokens, array $useDeclarations, NamespaceAnalysis $namespaceDeclaration) + { + $namespace = $namespaceDeclaration->getFullName(); + $nsLength = \strlen($namespace.'\\'); + + foreach ($useDeclarations as $useDeclaration) { + if ($useDeclaration->isAliased()) { + continue; + } + + $useDeclarationFullName = ltrim($useDeclaration->getFullName(), '\\'); + + if (0 !== strpos($useDeclarationFullName, $namespace.'\\')) { + continue; + } + + $partName = substr($useDeclarationFullName, $nsLength); + + if (false === strpos($partName, '\\')) { + $this->removeUseDeclaration($tokens, $useDeclaration); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/OrderedImportsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/OrderedImportsFixer.php new file mode 100644 index 0000000..4bc88c3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/OrderedImportsFixer.php @@ -0,0 +1,534 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Import; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\AliasedFixerOptionBuilder; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; + +/** + * @author Sebastiaan Stok <s.stok@rollerscapes.net> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + * @author Darius Matulionis <darius@matulionis.lt> + * @author Adriano Pilger <adriano.pilger@gmail.com> + */ +final class OrderedImportsFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + const IMPORT_TYPE_CLASS = 'class'; + + const IMPORT_TYPE_CONST = 'const'; + + const IMPORT_TYPE_FUNCTION = 'function'; + + const SORT_ALPHA = 'alpha'; + + const SORT_LENGTH = 'length'; + + const SORT_NONE = 'none'; + + /** + * Array of supported sort types in configuration. + * + * @var string[] + */ + private $supportedSortTypes = [self::IMPORT_TYPE_CLASS, self::IMPORT_TYPE_CONST, self::IMPORT_TYPE_FUNCTION]; + + /** + * Array of supported sort algorithms in configuration. + * + * @var string[] + */ + private $supportedSortAlgorithms = [self::SORT_ALPHA, self::SORT_LENGTH, self::SORT_NONE]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Ordering `use` statements.', + [ + new CodeSample("<?php\nuse Z; use A;\n"), + new CodeSample( + '<?php +use Acme\Bar; +use Bar1; +use Acme; +use Bar; +', + ['sort_algorithm' => self::SORT_LENGTH] + ), + new VersionSpecificCodeSample( + "<?php\nuse function AAC;\nuse const AAB;\nuse AAA;\n", + new VersionSpecification(70000) + ), + new VersionSpecificCodeSample( + '<?php +use const AAAA; +use const BBB; + +use Bar; +use AAC; +use Acme; + +use function CCC\AA; +use function DDD; +', + new VersionSpecification(70000), + [ + 'sort_algorithm' => self::SORT_LENGTH, + 'imports_order' => [ + self::IMPORT_TYPE_CONST, + self::IMPORT_TYPE_CLASS, + self::IMPORT_TYPE_FUNCTION, + ], + ] + ), + new VersionSpecificCodeSample( + '<?php +use const BBB; +use const AAAA; + +use Acme; +use AAC; +use Bar; + +use function DDD; +use function CCC\AA; +', + new VersionSpecification(70000), + [ + 'sort_algorithm' => self::SORT_ALPHA, + 'imports_order' => [ + self::IMPORT_TYPE_CONST, + self::IMPORT_TYPE_CLASS, + self::IMPORT_TYPE_FUNCTION, + ], + ] + ), + new VersionSpecificCodeSample( + '<?php +use const BBB; +use const AAAA; + +use function DDD; +use function CCC\AA; + +use Acme; +use AAC; +use Bar; +', + new VersionSpecification(70000), + [ + 'sort_algorithm' => self::SORT_NONE, + 'imports_order' => [ + self::IMPORT_TYPE_CONST, + self::IMPORT_TYPE_CLASS, + self::IMPORT_TYPE_FUNCTION, + ], + ] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after GlobalNamespaceImportFixer, NoLeadingImportSlashFixer. + */ + public function getPriority() + { + return -30; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_USE); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + $namespacesImports = $tokensAnalyzer->getImportUseIndexes(true); + + if (0 === \count($namespacesImports)) { + return; + } + + $usesOrder = []; + foreach ($namespacesImports as $uses) { + $usesOrder[] = $this->getNewOrder(array_reverse($uses), $tokens); + } + $usesOrder = array_replace(...$usesOrder); + + $usesOrder = array_reverse($usesOrder, true); + $mapStartToEnd = []; + + foreach ($usesOrder as $use) { + $mapStartToEnd[$use['startIndex']] = $use['endIndex']; + } + + // Now insert the new tokens, starting from the end + foreach ($usesOrder as $index => $use) { + $declarationTokens = Tokens::fromCode( + sprintf( + '<?php use %s%s;', + self::IMPORT_TYPE_CLASS === $use['importType'] ? '' : ' '.$use['importType'].' ', + $use['namespace'] + ) + ); + + $declarationTokens->clearRange(0, 2); // clear `<?php use ` + $declarationTokens->clearAt(\count($declarationTokens) - 1); // clear `;` + $declarationTokens->clearEmptyTokens(); + + $tokens->overrideRange($index, $mapStartToEnd[$index], $declarationTokens); + if ($use['group']) { + // a group import must start with `use` and cannot be part of comma separated import list + $prev = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prev]->equals(',')) { + $tokens[$prev] = new Token(';'); + $tokens->insertAt($prev + 1, new Token([T_USE, 'use'])); + + if (!$tokens[$prev + 2]->isWhitespace()) { + $tokens->insertAt($prev + 2, new Token([T_WHITESPACE, ' '])); + } + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $supportedSortTypes = $this->supportedSortTypes; + + return new FixerConfigurationResolver([ + (new AliasedFixerOptionBuilder( + new FixerOptionBuilder('sort_algorithm', 'whether the statements should be sorted alphabetically or by length, or not sorted'), + 'sortAlgorithm' + )) + ->setAllowedValues($this->supportedSortAlgorithms) + ->setDefault(self::SORT_ALPHA) + ->getOption(), + (new AliasedFixerOptionBuilder( + new FixerOptionBuilder('imports_order', 'Defines the order of import types.'), + 'importsOrder' + )) + ->setAllowedTypes(['array', 'null']) + ->setAllowedValues([static function ($value) use ($supportedSortTypes) { + if (null !== $value) { + $missing = array_diff($supportedSortTypes, $value); + if (\count($missing)) { + throw new InvalidOptionsException(sprintf( + 'Missing sort %s "%s".', + 1 === \count($missing) ? 'type' : 'types', + implode('", "', $missing) + )); + } + + $unknown = array_diff($value, $supportedSortTypes); + if (\count($unknown)) { + throw new InvalidOptionsException(sprintf( + 'Unknown sort %s "%s".', + 1 === \count($unknown) ? 'type' : 'types', + implode('", "', $unknown) + )); + } + } + + return true; + }]) + ->setDefault(null) + ->getOption(), + ]); + } + + /** + * This method is used for sorting the uses in a namespace. + * + * @param array<string, bool|int|string> $first + * @param array<string, bool|int|string> $second + * + * @return int + * + * @internal + */ + private function sortAlphabetically(array $first, array $second) + { + // Replace backslashes by spaces before sorting for correct sort order + $firstNamespace = str_replace('\\', ' ', $this->prepareNamespace($first['namespace'])); + $secondNamespace = str_replace('\\', ' ', $this->prepareNamespace($second['namespace'])); + + return strcasecmp($firstNamespace, $secondNamespace); + } + + /** + * This method is used for sorting the uses statements in a namespace by length. + * + * @param array<string, bool|int|string> $first + * @param array<string, bool|int|string> $second + * + * @return int + * + * @internal + */ + private function sortByLength(array $first, array $second) + { + $firstNamespace = (self::IMPORT_TYPE_CLASS === $first['importType'] ? '' : $first['importType'].' ').$this->prepareNamespace($first['namespace']); + $secondNamespace = (self::IMPORT_TYPE_CLASS === $second['importType'] ? '' : $second['importType'].' ').$this->prepareNamespace($second['namespace']); + + $firstNamespaceLength = \strlen($firstNamespace); + $secondNamespaceLength = \strlen($secondNamespace); + + if ($firstNamespaceLength === $secondNamespaceLength) { + $sortResult = strcasecmp($firstNamespace, $secondNamespace); + } else { + $sortResult = $firstNamespaceLength > $secondNamespaceLength ? 1 : -1; + } + + return $sortResult; + } + + /** + * @param string $namespace + * + * @return string + */ + private function prepareNamespace($namespace) + { + return trim(Preg::replace('%/\*(.*)\*/%s', '', $namespace)); + } + + /** + * @param int[] $uses + * + * @return array + */ + private function getNewOrder(array $uses, Tokens $tokens) + { + $indexes = []; + $originalIndexes = []; + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + for ($i = \count($uses) - 1; $i >= 0; --$i) { + $index = $uses[$i]; + + $startIndex = $tokens->getTokenNotOfKindsSibling($index + 1, 1, [T_WHITESPACE]); + $endIndex = $tokens->getNextTokenOfKind($startIndex, [';', [T_CLOSE_TAG]]); + $previous = $tokens->getPrevMeaningfulToken($endIndex); + + $group = $tokens[$previous]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_CLOSE); + if ($tokens[$startIndex]->isGivenKind(CT::T_CONST_IMPORT)) { + $type = self::IMPORT_TYPE_CONST; + $index = $tokens->getNextNonWhitespace($startIndex); + } elseif ($tokens[$startIndex]->isGivenKind(CT::T_FUNCTION_IMPORT)) { + $type = self::IMPORT_TYPE_FUNCTION; + $index = $tokens->getNextNonWhitespace($startIndex); + } else { + $type = self::IMPORT_TYPE_CLASS; + $index = $startIndex; + } + + $namespaceTokens = []; + + while ($index <= $endIndex) { + $token = $tokens[$index]; + + if ($index === $endIndex || (!$group && $token->equals(','))) { + if ($group && self::SORT_NONE !== $this->configuration['sort_algorithm']) { + // if group import, sort the items within the group definition + + // figure out where the list of namespace parts within the group def. starts + $namespaceTokensCount = \count($namespaceTokens) - 1; + $namespace = ''; + for ($k = 0; $k < $namespaceTokensCount; ++$k) { + if ($namespaceTokens[$k]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_OPEN)) { + $namespace .= '{'; + + break; + } + + $namespace .= $namespaceTokens[$k]->getContent(); + } + + // fetch all parts, split up in an array of strings, move comments to the end + $parts = []; + $firstIndent = ''; + $separator = ', '; + $lastIndent = ''; + $hasGroupTrailingComma = false; + + for ($k1 = $k + 1; $k1 < $namespaceTokensCount; ++$k1) { + $comment = ''; + $namespacePart = ''; + for ($k2 = $k1;; ++$k2) { + if ($namespaceTokens[$k2]->equalsAny([',', [CT::T_GROUP_IMPORT_BRACE_CLOSE]])) { + break; + } + + if ($namespaceTokens[$k2]->isComment()) { + $comment .= $namespaceTokens[$k2]->getContent(); + + continue; + } + + // if there is any line ending inside the group import, it should be indented properly + if ( + '' === $firstIndent + && $namespaceTokens[$k2]->isWhitespace() + && false !== strpos($namespaceTokens[$k2]->getContent(), $lineEnding) + ) { + $lastIndent = $lineEnding; + $firstIndent = $lineEnding.$this->whitespacesConfig->getIndent(); + $separator = ','.$firstIndent; + } + + $namespacePart .= $namespaceTokens[$k2]->getContent(); + } + + $namespacePart = trim($namespacePart); + if ('' === $namespacePart) { + $hasGroupTrailingComma = true; + + continue; + } + + $comment = trim($comment); + if ('' !== $comment) { + $namespacePart .= ' '.$comment; + } + + $parts[] = $namespacePart; + + $k1 = $k2; + } + + $sortedParts = $parts; + sort($parts); + + // check if the order needs to be updated, otherwise don't touch as we might change valid CS (to other valid CS). + if ($sortedParts === $parts) { + $namespace = Tokens::fromArray($namespaceTokens)->generateCode(); + } else { + $namespace .= $firstIndent.implode($separator, $parts).($hasGroupTrailingComma ? ',' : '').$lastIndent.'}'; + } + } else { + $namespace = Tokens::fromArray($namespaceTokens)->generateCode(); + } + + $indexes[$startIndex] = [ + 'namespace' => $namespace, + 'startIndex' => $startIndex, + 'endIndex' => $index - 1, + 'importType' => $type, + 'group' => $group, + ]; + + $originalIndexes[] = $startIndex; + + if ($index === $endIndex) { + break; + } + + $namespaceTokens = []; + $nextPartIndex = $tokens->getTokenNotOfKindSibling($index, 1, [[','], [T_WHITESPACE]]); + $startIndex = $nextPartIndex; + $index = $nextPartIndex; + + continue; + } + + $namespaceTokens[] = $token; + ++$index; + } + } + + // Is sort types provided, sorting by groups and each group by algorithm + if (null !== $this->configuration['imports_order']) { + // Grouping indexes by import type. + $groupedByTypes = []; + foreach ($indexes as $startIndex => $item) { + $groupedByTypes[$item['importType']][$startIndex] = $item; + } + + // Sorting each group by algorithm. + foreach ($groupedByTypes as $type => $indexes) { + $groupedByTypes[$type] = $this->sortByAlgorithm($indexes); + } + + // Ordering groups + $sortedGroups = []; + foreach ($this->configuration['imports_order'] as $type) { + if (isset($groupedByTypes[$type]) && !empty($groupedByTypes[$type])) { + foreach ($groupedByTypes[$type] as $startIndex => $item) { + $sortedGroups[$startIndex] = $item; + } + } + } + $indexes = $sortedGroups; + } else { + // Sorting only by algorithm + $indexes = $this->sortByAlgorithm($indexes); + } + + $index = -1; + $usesOrder = []; + + // Loop trough the index but use original index order + foreach ($indexes as $v) { + $usesOrder[$originalIndexes[++$index]] = $v; + } + + return $usesOrder; + } + + /** + * @param array[] $indexes + * + * @return array + */ + private function sortByAlgorithm(array $indexes) + { + if (self::SORT_ALPHA === $this->configuration['sort_algorithm']) { + uasort($indexes, [$this, 'sortAlphabetically']); + } elseif (self::SORT_LENGTH === $this->configuration['sort_algorithm']) { + uasort($indexes, [$this, 'sortByLength']); + } + + return $indexes; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/SingleImportPerStatementFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/SingleImportPerStatementFixer.php new file mode 100644 index 0000000..2e6be72 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/SingleImportPerStatementFixer.php @@ -0,0 +1,237 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Import; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * Fixer for rules defined in PSR2 ¶3. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +final class SingleImportPerStatementFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There MUST be one use keyword per declaration.', + [new CodeSample("<?php\nuse Foo, Sample, Sample\\Sample as Sample2;\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before MultilineWhitespaceBeforeSemicolonsFixer, NoLeadingImportSlashFixer, NoSinglelineWhitespaceBeforeSemicolonsFixer, NoUnusedImportsFixer, SpaceAfterSemicolonFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_USE); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + $uses = array_reverse($tokensAnalyzer->getImportUseIndexes()); + + foreach ($uses as $index) { + $endIndex = $tokens->getNextTokenOfKind($index, [';', [T_CLOSE_TAG]]); + $groupClose = $tokens->getPrevMeaningfulToken($endIndex); + + if ($tokens[$groupClose]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_CLOSE)) { + $this->fixGroupUse($tokens, $index, $endIndex); + } else { + $this->fixMultipleUse($tokens, $index, $endIndex); + } + } + } + + /** + * @param int $index + * + * @return array + */ + private function getGroupDeclaration(Tokens $tokens, $index) + { + $groupPrefix = ''; + $comment = ''; + $groupOpenIndex = null; + for ($i = $index + 1;; ++$i) { + if ($tokens[$i]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_OPEN)) { + $groupOpenIndex = $i; + + break; + } + + if ($tokens[$i]->isComment()) { + $comment .= $tokens[$i]->getContent(); + if (!$tokens[$i - 1]->isWhitespace() && !$tokens[$i + 1]->isWhitespace()) { + $groupPrefix .= ' '; + } + + continue; + } + + if ($tokens[$i]->isWhitespace()) { + $groupPrefix .= ' '; + + continue; + } + + $groupPrefix .= $tokens[$i]->getContent(); + } + + return [ + rtrim($groupPrefix), + $groupOpenIndex, + $tokens->findBlockEnd(Tokens::BLOCK_TYPE_GROUP_IMPORT_BRACE, $groupOpenIndex), + $comment, + ]; + } + + /** + * @param string $groupPrefix + * @param int $groupOpenIndex + * @param int $groupCloseIndex + * @param string $comment + * + * @return string[] + */ + private function getGroupStatements(Tokens $tokens, $groupPrefix, $groupOpenIndex, $groupCloseIndex, $comment) + { + $statements = []; + $statement = $groupPrefix; + + for ($i = $groupOpenIndex + 1; $i <= $groupCloseIndex; ++$i) { + $token = $tokens[$i]; + + if ($token->equals(',') && $tokens[$tokens->getNextMeaningfulToken($i)]->equals([CT::T_GROUP_IMPORT_BRACE_CLOSE])) { + continue; + } + + if ($token->equalsAny([',', [CT::T_GROUP_IMPORT_BRACE_CLOSE]])) { + $statements[] = 'use'.$statement.';'; + $statement = $groupPrefix; + + continue; + } + + if ($token->isWhitespace()) { + $j = $tokens->getNextMeaningfulToken($i); + + if ($tokens[$j]->equals([T_AS])) { + $statement .= ' as '; + $i += 2; + } elseif ($tokens[$j]->equals([T_FUNCTION])) { + $statement = ' function'.$statement; + $i += 2; + } elseif ($tokens[$j]->equals([T_CONST])) { + $statement = ' const'.$statement; + $i += 2; + } + + if ($token->isWhitespace(" \t") || '//' !== substr($tokens[$i - 1]->getContent(), 0, 2)) { + continue; + } + } + + $statement .= $token->getContent(); + } + + if ('' !== $comment) { + $statements[0] .= ' '.$comment; + } + + return $statements; + } + + /** + * @param int $index + * @param int $endIndex + */ + private function fixGroupUse(Tokens $tokens, $index, $endIndex) + { + list($groupPrefix, $groupOpenIndex, $groupCloseIndex, $comment) = $this->getGroupDeclaration($tokens, $index); + $statements = $this->getGroupStatements($tokens, $groupPrefix, $groupOpenIndex, $groupCloseIndex, $comment); + + if (\count($statements) < 2) { + return; + } + + $tokens->clearRange($index, $groupCloseIndex); + if ($tokens[$endIndex]->equals(';')) { + $tokens->clearAt($endIndex); + } + + $ending = $this->whitespacesConfig->getLineEnding(); + $importTokens = Tokens::fromCode('<?php '.implode($ending, $statements)); + $importTokens->clearAt(0); + $importTokens->clearEmptyTokens(); + + $tokens->insertAt($index, $importTokens); + } + + /** + * @param int $index + * @param int $endIndex + */ + private function fixMultipleUse(Tokens $tokens, $index, $endIndex) + { + $ending = $this->whitespacesConfig->getLineEnding(); + + for ($i = $endIndex - 1; $i > $index; --$i) { + if (!$tokens[$i]->equals(',')) { + continue; + } + + $tokens[$i] = new Token(';'); + $i = $tokens->getNextMeaningfulToken($i); + $tokens->insertAt($i, new Token([T_USE, 'use'])); + $tokens->insertAt($i + 1, new Token([T_WHITESPACE, ' '])); + + $indent = WhitespacesAnalyzer::detectIndent($tokens, $index); + if ($tokens[$i - 1]->isWhitespace()) { + $tokens[$i - 1] = new Token([T_WHITESPACE, $ending.$indent]); + + continue; + } + + if (false === strpos($tokens[$i - 1]->getContent(), "\n")) { + $tokens->insertAt($i, new Token([T_WHITESPACE, $ending.$indent])); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/SingleLineAfterImportsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/SingleLineAfterImportsFixer.php new file mode 100644 index 0000000..3d02cda --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Import/SingleLineAfterImportsFixer.php @@ -0,0 +1,158 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Import; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use PhpCsFixer\Utils; + +/** + * Fixer for rules defined in PSR2 ¶3. + * + * @author Ceeram <ceeram@cakephp.org> + * @author Graham Campbell <graham@alt-three.com> + */ +final class SingleLineAfterImportsFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_USE); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Each namespace use MUST go on its own line and there MUST be one blank line after the use statements block.', + [ + new CodeSample( + '<?php +namespace Foo; + +use Bar; +use Baz; +final class Example +{ +} +' + ), + new CodeSample( + '<?php +namespace Foo; + +use Bar; +use Baz; + + +final class Example +{ +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after NoUnusedImportsFixer. + */ + public function getPriority() + { + return -11; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $ending = $this->whitespacesConfig->getLineEnding(); + $tokensAnalyzer = new TokensAnalyzer($tokens); + + $added = 0; + foreach ($tokensAnalyzer->getImportUseIndexes() as $index) { + $index += $added; + $indent = ''; + + // if previous line ends with comment and current line starts with whitespace, use current indent + if ($tokens[$index - 1]->isWhitespace(" \t") && $tokens[$index - 2]->isGivenKind(T_COMMENT)) { + $indent = $tokens[$index - 1]->getContent(); + } elseif ($tokens[$index - 1]->isWhitespace()) { + $indent = Utils::calculateTrailingWhitespaceIndent($tokens[$index - 1]); + } + + $semicolonIndex = $tokens->getNextTokenOfKind($index, [';', [T_CLOSE_TAG]]); // Handle insert index for inline T_COMMENT with whitespace after semicolon + $insertIndex = $semicolonIndex; + + if ($tokens[$semicolonIndex]->isGivenKind(T_CLOSE_TAG)) { + if ($tokens[$insertIndex - 1]->isWhitespace()) { + --$insertIndex; + } + + $tokens->insertAt($insertIndex, new Token(';')); + ++$added; + } + + if ($semicolonIndex === \count($tokens) - 1) { + $tokens->insertAt($insertIndex + 1, new Token([T_WHITESPACE, $ending.$ending.$indent])); + ++$added; + } else { + $newline = $ending; + $tokens[$semicolonIndex]->isGivenKind(T_CLOSE_TAG) ? --$insertIndex : ++$insertIndex; + if ($tokens[$insertIndex]->isWhitespace(" \t") && $tokens[$insertIndex + 1]->isComment()) { + ++$insertIndex; + } + + // Increment insert index for inline T_COMMENT or T_DOC_COMMENT + if ($tokens[$insertIndex]->isComment()) { + ++$insertIndex; + } + + $afterSemicolon = $tokens->getNextMeaningfulToken($semicolonIndex); + if (null === $afterSemicolon || !$tokens[$afterSemicolon]->isGivenKind(T_USE)) { + $newline .= $ending; + } + + if ($tokens[$insertIndex]->isWhitespace()) { + $nextToken = $tokens[$insertIndex]; + if (2 === substr_count($nextToken->getContent(), "\n")) { + continue; + } + $nextMeaningfulAfterUseIndex = $tokens->getNextMeaningfulToken($insertIndex); + if (null !== $nextMeaningfulAfterUseIndex && $tokens[$nextMeaningfulAfterUseIndex]->isGivenKind(T_USE)) { + if (substr_count($nextToken->getContent(), "\n") < 1) { + $tokens[$insertIndex] = new Token([T_WHITESPACE, $newline.$indent.ltrim($nextToken->getContent())]); + } + } else { + $tokens[$insertIndex] = new Token([T_WHITESPACE, $newline.$indent.ltrim($nextToken->getContent())]); + } + } else { + $tokens->insertAt($insertIndex, new Token([T_WHITESPACE, $newline.$indent])); + ++$added; + } + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ClassKeywordRemoveFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ClassKeywordRemoveFixer.php new file mode 100644 index 0000000..ded18ab --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ClassKeywordRemoveFixer.php @@ -0,0 +1,256 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Sullivan Senechal <soullivaneuh@gmail.com> + */ +final class ClassKeywordRemoveFixer extends AbstractFixer +{ + /** + * @var string[] + */ + private $imports = []; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Converts `::class` keywords to FQCN strings.', + [ + new CodeSample( + '<?php + +use Foo\Bar\Baz; + +$className = Baz::class; +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoUnusedImportsFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(CT::T_CLASS_CONSTANT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $namespacesAnalyzer = new NamespacesAnalyzer(); + + $previousNamespaceScopeEndIndex = 0; + foreach ($namespacesAnalyzer->getDeclarations($tokens) as $declaration) { + $this->replaceClassKeywordsSection($tokens, '', $previousNamespaceScopeEndIndex, $declaration->getStartIndex()); + $this->replaceClassKeywordsSection($tokens, $declaration->getFullName(), $declaration->getStartIndex(), $declaration->getScopeEndIndex()); + $previousNamespaceScopeEndIndex = $declaration->getScopeEndIndex(); + } + + $this->replaceClassKeywordsSection($tokens, '', $previousNamespaceScopeEndIndex, $tokens->count() - 1); + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function storeImports(Tokens $tokens, $startIndex, $endIndex) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + $this->imports = []; + + /** @var int $index */ + foreach ($tokensAnalyzer->getImportUseIndexes() as $index) { + if ($index < $startIndex || $index > $endIndex) { + continue; + } + + $import = ''; + while ($index = $tokens->getNextMeaningfulToken($index)) { + if ($tokens[$index]->equalsAny([';', [CT::T_GROUP_IMPORT_BRACE_OPEN]]) || $tokens[$index]->isGivenKind(T_AS)) { + break; + } + + $import .= $tokens[$index]->getContent(); + } + + // Imports group (PHP 7 spec) + if ($tokens[$index]->isGivenKind(CT::T_GROUP_IMPORT_BRACE_OPEN)) { + $groupEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_GROUP_IMPORT_BRACE, $index); + $groupImports = array_map( + static function ($import) { + return trim($import); + }, + explode(',', $tokens->generatePartialCode($index + 1, $groupEndIndex - 1)) + ); + foreach ($groupImports as $groupImport) { + $groupImportParts = array_map(static function ($import) { + return trim($import); + }, explode(' as ', $groupImport)); + if (2 === \count($groupImportParts)) { + $this->imports[$groupImportParts[1]] = $import.$groupImportParts[0]; + } else { + $this->imports[] = $import.$groupImport; + } + } + } elseif ($tokens[$index]->isGivenKind(T_AS)) { + $aliasIndex = $tokens->getNextMeaningfulToken($index); + $alias = $tokens[$aliasIndex]->getContent(); + $this->imports[$alias] = $import; + } else { + $this->imports[] = $import; + } + } + } + + /** + * @param string $namespace + * @param int $startIndex + * @param int $endIndex + */ + private function replaceClassKeywordsSection(Tokens $tokens, $namespace, $startIndex, $endIndex) + { + if ($endIndex - $startIndex < 3) { + return; + } + + $this->storeImports($tokens, $startIndex, $endIndex); + + $ctClassTokens = $tokens->findGivenKind(CT::T_CLASS_CONSTANT, $startIndex, $endIndex); + foreach (array_reverse(array_keys($ctClassTokens)) as $classIndex) { + $this->replaceClassKeyword($tokens, $namespace, $classIndex); + } + } + + /** + * @param string $namespacePrefix + * @param int $classIndex + */ + private function replaceClassKeyword(Tokens $tokens, $namespacePrefix, $classIndex) + { + $classEndIndex = $tokens->getPrevMeaningfulToken($classIndex); + $classEndIndex = $tokens->getPrevMeaningfulToken($classEndIndex); + + if (!$tokens[$classEndIndex]->isGivenKind(T_STRING)) { + return; + } + + if ($tokens[$classEndIndex]->equalsAny([[T_STRING, 'self'], [T_STATIC, 'static'], [T_STRING, 'parent']], false)) { + return; + } + + $classBeginIndex = $classEndIndex; + while (true) { + $prev = $tokens->getPrevMeaningfulToken($classBeginIndex); + if (!$tokens[$prev]->isGivenKind([T_NS_SEPARATOR, T_STRING])) { + break; + } + + $classBeginIndex = $prev; + } + + $classString = $tokens->generatePartialCode( + $tokens[$classBeginIndex]->isGivenKind(T_NS_SEPARATOR) + ? $tokens->getNextMeaningfulToken($classBeginIndex) + : $classBeginIndex, + $classEndIndex + ); + + $classImport = false; + if ($tokens[$classBeginIndex]->isGivenKind(T_NS_SEPARATOR)) { + $namespacePrefix = ''; + } else { + foreach ($this->imports as $alias => $import) { + if ($classString === $alias) { + $classImport = $import; + + break; + } + + $classStringArray = explode('\\', $classString); + $namespaceToTest = $classStringArray[0]; + + if (0 === strcmp($namespaceToTest, substr($import, -\strlen($namespaceToTest)))) { + $classImport = $import; + + break; + } + } + } + + for ($i = $classBeginIndex; $i <= $classIndex; ++$i) { + if (!$tokens[$i]->isComment() && !($tokens[$i]->isWhitespace() && false !== strpos($tokens[$i]->getContent(), "\n"))) { + $tokens->clearAt($i); + } + } + + $tokens->insertAt($classBeginIndex, new Token([ + T_CONSTANT_ENCAPSED_STRING, + "'".$this->makeClassFQN($namespacePrefix, $classImport, $classString)."'", + ])); + } + + /** + * @param string $namespacePrefix + * @param false|string $classImport + * @param string $classString + * + * @return string + */ + private function makeClassFQN($namespacePrefix, $classImport, $classString) + { + if (false === $classImport) { + return ('' !== $namespacePrefix ? ($namespacePrefix.'\\') : '').$classString; + } + + $classStringArray = explode('\\', $classString); + $classStringLength = \count($classStringArray); + $classImportArray = explode('\\', $classImport); + $classImportLength = \count($classImportArray); + + if (1 === $classStringLength) { + return $classImport; + } + + return implode('\\', array_merge( + \array_slice($classImportArray, 0, $classImportLength - $classStringLength + 1), + $classStringArray + )); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/CombineConsecutiveIssetsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/CombineConsecutiveIssetsFixer.php new file mode 100644 index 0000000..8f40390 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/CombineConsecutiveIssetsFixer.php @@ -0,0 +1,172 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class CombineConsecutiveIssetsFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Using `isset($var) &&` multiple times should be done in one call.', + [new CodeSample("<?php\n\$a = isset(\$a) && isset(\$b);\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before MultilineWhitespaceBeforeSemicolonsFixer, NoSinglelineWhitespaceBeforeSemicolonsFixer, NoSpacesInsideParenthesisFixer, NoTrailingWhitespaceFixer, NoWhitespaceInBlankLineFixer. + */ + public function getPriority() + { + return 3; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_ISSET, T_BOOLEAN_AND]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokenCount = $tokens->count(); + + for ($index = 1; $index < $tokenCount; ++$index) { + if (!$tokens[$index]->isGivenKind(T_ISSET) + || !$tokens[$tokens->getPrevMeaningfulToken($index)]->equalsAny(['(', '{', ';', '=', [T_OPEN_TAG], [T_BOOLEAN_AND], [T_BOOLEAN_OR]])) { + continue; + } + + $issetInfo = $this->getIssetInfo($tokens, $index); + $issetCloseBraceIndex = end($issetInfo); // ')' token + $insertLocation = prev($issetInfo) + 1; // one index after the previous meaningful of ')' + + $booleanAndTokenIndex = $tokens->getNextMeaningfulToken($issetCloseBraceIndex); + + while ($tokens[$booleanAndTokenIndex]->isGivenKind(T_BOOLEAN_AND)) { + $issetIndex = $tokens->getNextMeaningfulToken($booleanAndTokenIndex); + if (!$tokens[$issetIndex]->isGivenKind(T_ISSET)) { + $index = $issetIndex; + + break; + } + + // fetch info about the 'isset' statement that we're merging + $nextIssetInfo = $this->getIssetInfo($tokens, $issetIndex); + + $nextMeaningfulTokenIndex = $tokens->getNextMeaningfulToken(end($nextIssetInfo)); + $nextMeaningfulToken = $tokens[$nextMeaningfulTokenIndex]; + + if (!$nextMeaningfulToken->equalsAny([')', '}', ';', [T_CLOSE_TAG], [T_BOOLEAN_AND], [T_BOOLEAN_OR]])) { + $index = $nextMeaningfulTokenIndex; + + break; + } + + // clone what we want to move, do not clone '(' and ')' of the 'isset' statement we're merging + $clones = $this->getTokenClones($tokens, \array_slice($nextIssetInfo, 1, -1)); + + // clean up no the tokens of the 'isset' statement we're merging + $this->clearTokens($tokens, array_merge($nextIssetInfo, [$issetIndex, $booleanAndTokenIndex])); + + // insert the tokens to create the new statement + array_unshift($clones, new Token(','), new Token([T_WHITESPACE, ' '])); + $tokens->insertAt($insertLocation, $clones); + + // correct some counts and offset based on # of tokens inserted + $numberOfTokensInserted = \count($clones); + $tokenCount += $numberOfTokensInserted; + $issetCloseBraceIndex += $numberOfTokensInserted; + $insertLocation += $numberOfTokensInserted; + + $booleanAndTokenIndex = $tokens->getNextMeaningfulToken($issetCloseBraceIndex); + } + } + } + + /** + * @param int[] $indexes + */ + private function clearTokens(Tokens $tokens, array $indexes) + { + foreach ($indexes as $index) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } + } + + /** + * @param int $index of T_ISSET + * + * @return int[] indexes of meaningful tokens belonging to the isset statement + */ + private function getIssetInfo(Tokens $tokens, $index) + { + $openIndex = $tokens->getNextMeaningfulToken($index); + + $braceOpenCount = 1; + $meaningfulTokenIndexes = [$openIndex]; + + for ($i = $openIndex + 1;; ++$i) { + if ($tokens[$i]->isWhitespace() || $tokens[$i]->isComment()) { + continue; + } + + $meaningfulTokenIndexes[] = $i; + + if ($tokens[$i]->equals(')')) { + --$braceOpenCount; + if (0 === $braceOpenCount) { + break; + } + } elseif ($tokens[$i]->equals('(')) { + ++$braceOpenCount; + } + } + + return $meaningfulTokenIndexes; + } + + /** + * @param int[] $indexes + * + * @return Token[] + */ + private function getTokenClones(Tokens $tokens, array $indexes) + { + $clones = []; + + foreach ($indexes as $i) { + $clones[] = clone $tokens[$i]; + } + + return $clones; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/CombineConsecutiveUnsetsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixer.php similarity index 69% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/CombineConsecutiveUnsetsFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixer.php index 6cc6508..7c99517 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/CombineConsecutiveUnsetsFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/CombineConsecutiveUnsetsFixer.php @@ -10,11 +10,13 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Contrib; +namespace PhpCsFixer\Fixer\LanguageConstruct; -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; /** * @author SpacePossum @@ -24,32 +26,62 @@ final class CombineConsecutiveUnsetsFixer extends AbstractFixer /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function getDefinition() + { + return new FixerDefinition( + 'Calling `unset` on multiple items should be done in one call.', + [new CodeSample("<?php\nunset(\$a); unset(\$b);\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoExtraBlankLinesFixer, NoTrailingWhitespaceFixer, NoWhitespaceInBlankLineFixer, SpaceAfterSemicolonFixer. + * Must run after NoEmptyStatementFixer, NoUnsetOnPropertyFixer, NoUselessElseFixer. + */ + public function getPriority() + { + return 24; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_UNSET); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) { - $tokens = Tokens::fromCode($content); for ($index = $tokens->count() - 1; $index >= 0; --$index) { if (!$tokens[$index]->isGivenKind(T_UNSET)) { continue; } $previousUnsetCall = $this->getPreviousUnsetCall($tokens, $index); - if (is_int($previousUnsetCall)) { + if (\is_int($previousUnsetCall)) { $index = $previousUnsetCall; + continue; } - list($previousUnset, $previousUnsetBraceStart, $previousUnsetBraceEnd, $previousUnsetSemicolon) = $previousUnsetCall; + list($previousUnset, , $previousUnsetBraceEnd) = $previousUnsetCall; // Merge the tokens inside the 'unset' call into the previous one 'unset' call. $tokensAddCount = $this->moveTokens( $tokens, - $nextUnsetContentStart = $tokens->getNextTokenOfKind($index, array('(')), + $nextUnsetContentStart = $tokens->getNextTokenOfKind($index, ['(']), $nextUnsetContentEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $nextUnsetContentStart), $previousUnsetBraceEnd - 1 ); if (!$tokens[$previousUnsetBraceEnd]->isWhitespace()) { - $tokens->insertAt($previousUnsetBraceEnd, new Token(array(T_WHITESPACE, ' '))); + $tokens->insertAt($previousUnsetBraceEnd, new Token([T_WHITESPACE, ' '])); ++$tokensAddCount; } @@ -57,7 +89,7 @@ public function fix(\SplFileInfo $file, $content) ++$tokensAddCount; // Remove 'unset', '(', ')' and (possibly) ';' from the merged 'unset' call. - $this->clearOffsetTokens($tokens, $tokensAddCount, array($index, $nextUnsetContentStart, $nextUnsetContentEnd)); + $this->clearOffsetTokens($tokens, $tokensAddCount, [$index, $nextUnsetContentStart, $nextUnsetContentEnd]); $nextUnsetSemicolon = $tokens->getNextMeaningfulToken($nextUnsetContentEnd); if (null !== $nextUnsetSemicolon && $tokens[$nextUnsetSemicolon]->equals(';')) { @@ -66,31 +98,11 @@ public function fix(\SplFileInfo $file, $content) $index = $previousUnset + 1; } - - return $tokens->generateCode(); } /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'Calling unset on multiple items should be done in one call.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should ran before SpacesAfterSemicolonFixer, WhitespacyLinesFixer, TrailingSpacesFixer and ExtraEmptyLinesFixer and after NoEmptyStatementFixer. - return 24; - } - - /** - * @param Tokens $tokens - * @param int $offset - * @param int[] $indices + * @param int $offset + * @param int[] $indices */ private function clearOffsetTokens(Tokens $tokens, $offset, array $indices) { @@ -110,10 +122,9 @@ private function clearOffsetTokens(Tokens $tokens, $offset, array $indices) * * Or the index to where the method looked for an call. * - * @param Tokens $tokens - * @param int $index + * @param int $index * - * @return int[]|int + * @return int|int[] */ private function getPreviousUnsetCall(Tokens $tokens, $index) { @@ -135,7 +146,7 @@ private function getPreviousUnsetCall(Tokens $tokens, $index) return $previousUnsetBraceEnd; } - $previousUnsetBraceStart = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $previousUnsetBraceEnd, false); + $previousUnsetBraceStart = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $previousUnsetBraceEnd); $previousUnset = $tokens->getPrevMeaningfulToken($previousUnsetBraceStart); if (null === $previousUnset) { return $index; @@ -145,19 +156,18 @@ private function getPreviousUnsetCall(Tokens $tokens, $index) return $previousUnset; } - return array( + return [ $previousUnset, $previousUnsetBraceStart, $previousUnsetBraceEnd, $previousUnsetSemicolon, - ); + ]; } /** - * @param Tokens $tokens - * @param int $start Index previous of the first token to move - * @param int $end Index of the last token to move - * @param int $to Upper boundary index + * @param int $start Index previous of the first token to move + * @param int $end Index of the last token to move + * @param int $to Upper boundary index * * @return int Number of tokens inserted */ @@ -166,14 +176,14 @@ private function moveTokens(Tokens $tokens, $start, $end, $to) $added = 0; for ($i = $start + 1; $i < $end; $i += 2) { if ($tokens[$i]->isWhitespace() && $tokens[$to + 1]->isWhitespace()) { - $tokens[$to + 1]->setContent($tokens[$to + 1]->getContent().$tokens[$i]->getContent()); + $tokens[$to + 1] = new Token([T_WHITESPACE, $tokens[$to + 1]->getContent().$tokens[$i]->getContent()]); } else { $tokens->insertAt(++$to, clone $tokens[$i]); ++$end; ++$added; } - $tokens[$i + 1]->clear(); + $tokens->clearAt($i + 1); } return $added; diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/DeclareEqualNormalizeFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/DeclareEqualNormalizeFixer.php new file mode 100644 index 0000000..2879e62 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/DeclareEqualNormalizeFixer.php @@ -0,0 +1,140 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +final class DeclareEqualNormalizeFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var string + */ + private $callback; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->callback = 'none' === $this->configuration['space'] ? 'removeWhitespaceAroundToken' : 'ensureWhitespaceAroundToken'; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Equal sign in declare statement should be surrounded by spaces or not following configuration.', + [ + new CodeSample("<?php\ndeclare(ticks = 1);\n"), + new CodeSample("<?php\ndeclare(ticks=1);\n", ['space' => 'single']), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after DeclareStrictTypesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DECLARE); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $callback = $this->callback; + for ($index = 0, $count = $tokens->count(); $index < $count - 6; ++$index) { + if (!$tokens[$index]->isGivenKind(T_DECLARE)) { + continue; + } + + while (!$tokens[++$index]->equals('=')); + + $this->{$callback}($tokens, $index); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('space', 'Spacing to apply around the equal sign.')) + ->setAllowedValues(['single', 'none']) + ->setDefault('none') + ->getOption(), + ]); + } + + /** + * @param int $index of `=` token + */ + private function ensureWhitespaceAroundToken(Tokens $tokens, $index) + { + if ($tokens[$index + 1]->isWhitespace()) { + if (' ' !== $tokens[$index + 1]->getContent()) { + $tokens[$index + 1] = new Token([T_WHITESPACE, ' ']); + } + } else { + $tokens->insertAt($index + 1, new Token([T_WHITESPACE, ' '])); + } + + if ($tokens[$index - 1]->isWhitespace()) { + if (' ' !== $tokens[$index - 1]->getContent() && !$tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) { + $tokens[$index - 1] = new Token([T_WHITESPACE, ' ']); + } + } else { + $tokens->insertAt($index, new Token([T_WHITESPACE, ' '])); + } + } + + /** + * @param int $index of `=` token + */ + private function removeWhitespaceAroundToken(Tokens $tokens, $index) + { + if (!$tokens[$tokens->getPrevNonWhitespace($index)]->isComment()) { + $tokens->removeLeadingWhitespace($index); + } + + $tokens->removeTrailingWhitespace($index); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/DirConstantFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/DirConstantFixer.php new file mode 100644 index 0000000..2d5ead8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/DirConstantFixer.php @@ -0,0 +1,131 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFunctionReferenceFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Vladimir Reznichenko <kalessil@gmail.com> + */ +final class DirConstantFixer extends AbstractFunctionReferenceFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replaces `dirname(__FILE__)` expression with equivalent `__DIR__` constant.', + [new CodeSample("<?php\n\$a = dirname(__FILE__);\n")], + null, + 'Risky when the function `dirname` is overridden.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_FILE); + } + + /** + * {@inheritdoc} + * + * Must run before CombineNestedDirnameFixer. + */ + public function getPriority() + { + return 40; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $currIndex = 0; + while (null !== $currIndex) { + $boundaries = $this->find('dirname', $tokens, $currIndex, $tokens->count() - 1); + if (null === $boundaries) { + return; + } + + list($functionNameIndex, $openParenthesis, $closeParenthesis) = $boundaries; + + // analysing cursor shift, so nested expressions kept processed + $currIndex = $openParenthesis; + + // ensure __FILE__ is in between (...) + + $fileCandidateRightIndex = $tokens->getPrevMeaningfulToken($closeParenthesis); + $trailingCommaIndex = null; + if ($tokens[$fileCandidateRightIndex]->equals(',')) { + $trailingCommaIndex = $fileCandidateRightIndex; + $fileCandidateRightIndex = $tokens->getPrevMeaningfulToken($fileCandidateRightIndex); + } + + $fileCandidateRight = $tokens[$fileCandidateRightIndex]; + if (!$fileCandidateRight->isGivenKind(T_FILE)) { + continue; + } + + $fileCandidateLeftIndex = $tokens->getNextMeaningfulToken($openParenthesis); + $fileCandidateLeft = $tokens[$fileCandidateLeftIndex]; + + if (!$fileCandidateLeft->isGivenKind(T_FILE)) { + continue; + } + + // get rid of root namespace when it used + $namespaceCandidateIndex = $tokens->getPrevMeaningfulToken($functionNameIndex); + $namespaceCandidate = $tokens[$namespaceCandidateIndex]; + if ($namespaceCandidate->isGivenKind(T_NS_SEPARATOR)) { + $tokens->removeTrailingWhitespace($namespaceCandidateIndex); + $tokens->clearAt($namespaceCandidateIndex); + } + + if (null !== $trailingCommaIndex) { + if (!$tokens[$tokens->getNextNonWhitespace($trailingCommaIndex)]->isComment()) { + $tokens->removeTrailingWhitespace($trailingCommaIndex); + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($trailingCommaIndex); + } + + // closing parenthesis removed with leading spaces + if (!$tokens[$tokens->getNextNonWhitespace($closeParenthesis)]->isComment()) { + $tokens->removeLeadingWhitespace($closeParenthesis); + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($closeParenthesis); + + // opening parenthesis removed with trailing and leading spaces + if (!$tokens[$tokens->getNextNonWhitespace($openParenthesis)]->isComment()) { + $tokens->removeLeadingWhitespace($openParenthesis); + } + + $tokens->removeTrailingWhitespace($openParenthesis); + $tokens->clearTokenAndMergeSurroundingWhitespace($openParenthesis); + + // replace constant and remove function name + $tokens[$fileCandidateLeftIndex] = new Token([T_DIR, '__DIR__']); + $tokens->clearTokenAndMergeSurroundingWhitespace($functionNameIndex); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ErrorSuppressionFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ErrorSuppressionFixer.php new file mode 100644 index 0000000..0fb2a11 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ErrorSuppressionFixer.php @@ -0,0 +1,175 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Jules Pietri <jules@heahprod.com> + * @author Kuba Werłos <werlos@gmail.com> + */ +final class ErrorSuppressionFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + const OPTION_MUTE_DEPRECATION_ERROR = 'mute_deprecation_error'; + const OPTION_NOISE_REMAINING_USAGES = 'noise_remaining_usages'; + const OPTION_NOISE_REMAINING_USAGES_EXCLUDE = 'noise_remaining_usages_exclude'; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Error control operator should be added to deprecation notices and/or removed from other cases.', + [ + new CodeSample("<?php\ntrigger_error('Warning.', E_USER_DEPRECATED);\n"), + new CodeSample( + "<?php\n@mkdir(\$dir);\n@unlink(\$path);\n", + [self::OPTION_NOISE_REMAINING_USAGES => true] + ), + new CodeSample( + "<?php\n@mkdir(\$dir);\n@unlink(\$path);\n", + [ + self::OPTION_NOISE_REMAINING_USAGES => true, + self::OPTION_NOISE_REMAINING_USAGES_EXCLUDE => ['unlink'], + ] + ), + ], + null, + 'Risky because adding/removing `@` might cause changes to code behaviour or if `trigger_error` function is overridden.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(['@', T_STRING]); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder(self::OPTION_MUTE_DEPRECATION_ERROR, 'Whether to add `@` in deprecation notices.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder(self::OPTION_NOISE_REMAINING_USAGES, 'Whether to remove `@` in remaining usages.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + (new FixerOptionBuilder(self::OPTION_NOISE_REMAINING_USAGES_EXCLUDE, 'List of global functions to exclude from removing `@`')) + ->setAllowedTypes(['array']) + ->setDefault([]) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + $excludedFunctions = array_map(static function ($function) { + return strtolower($function); + }, $this->configuration[self::OPTION_NOISE_REMAINING_USAGES_EXCLUDE]); + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if ($this->configuration[self::OPTION_NOISE_REMAINING_USAGES] && $token->equals('@')) { + $tokens->clearAt($index); + + continue; + } + + if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) { + continue; + } + + $functionIndex = $index; + $startIndex = $index; + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + $startIndex = $prevIndex; + $prevIndex = $tokens->getPrevMeaningfulToken($startIndex); + } + + $index = $prevIndex; + + if ($this->isDeprecationErrorCall($tokens, $functionIndex)) { + if (!$this->configuration[self::OPTION_MUTE_DEPRECATION_ERROR]) { + continue; + } + + if ($tokens[$prevIndex]->equals('@')) { + continue; + } + + $tokens->insertAt($startIndex, new Token('@')); + + continue; + } + + if (!$tokens[$prevIndex]->equals('@')) { + continue; + } + + if ($this->configuration[self::OPTION_NOISE_REMAINING_USAGES] && !\in_array($tokens[$functionIndex]->getContent(), $excludedFunctions, true)) { + $tokens->clearAt($index); + } + } + } + + /** + * @param int $index + * + * @return bool + */ + private function isDeprecationErrorCall(Tokens $tokens, $index) + { + if ('trigger_error' !== strtolower($tokens[$index]->getContent())) { + return false; + } + + $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextTokenOfKind($index, [T_STRING, '('])); + + $prevIndex = $tokens->getPrevMeaningfulToken($endBraceIndex); + if ($tokens[$prevIndex]->equals(',')) { + $prevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + } + + return $tokens[$prevIndex]->equals([T_STRING, 'E_USER_DEPRECATED']); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ExplicitIndirectVariableFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ExplicitIndirectVariableFixer.php new file mode 100644 index 0000000..40d8182 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/ExplicitIndirectVariableFixer.php @@ -0,0 +1,91 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class ExplicitIndirectVariableFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Add curly braces to indirect variables to make them clear to understand. Requires PHP >= 7.0.', + [ + new VersionSpecificCodeSample( + <<<'EOT' +<?php +echo $$foo; +echo $$foo['bar']; +echo $foo->$bar['baz']; +echo $foo->$callback($baz); + +EOT +, + new VersionSpecification(70000) + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(T_VARIABLE); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; $index > 1; --$index) { + $token = $tokens[$index]; + if (!$token->isGivenKind(T_VARIABLE)) { + continue; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + $prevToken = $tokens[$prevIndex]; + if (!$prevToken->equals('$') && !$prevToken->isObjectOperator()) { + continue; + } + + $openingBrace = CT::T_DYNAMIC_VAR_BRACE_OPEN; + $closingBrace = CT::T_DYNAMIC_VAR_BRACE_CLOSE; + if ($prevToken->isObjectOperator()) { + $openingBrace = CT::T_DYNAMIC_PROP_BRACE_OPEN; + $closingBrace = CT::T_DYNAMIC_PROP_BRACE_CLOSE; + } + + $tokens->overrideRange($index, $index, [ + new Token([$openingBrace, '{']), + new Token([T_VARIABLE, $token->getContent()]), + new Token([$closingBrace, '}']), + ]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/FunctionToConstantFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/FunctionToConstantFixer.php new file mode 100644 index 0000000..5222c4c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/FunctionToConstantFixer.php @@ -0,0 +1,318 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class FunctionToConstantFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var array<string, Token[]> + */ + private static $availableFunctions; + + /** + * @var array<string, Token[]> + */ + private $functionsFixMap; + + public function __construct() + { + if (null === self::$availableFunctions) { + self::$availableFunctions = [ + 'get_called_class' => [ + new Token([T_STATIC, 'static']), + new Token([T_DOUBLE_COLON, '::']), + new Token([CT::T_CLASS_CONSTANT, 'class']), + ], + 'get_class' => [new Token([T_CLASS_C, '__CLASS__'])], + 'get_class_this' => [ + new Token([T_STATIC, 'static']), + new Token([T_DOUBLE_COLON, '::']), + new Token([CT::T_CLASS_CONSTANT, 'class']), + ], + 'php_sapi_name' => [new Token([T_STRING, 'PHP_SAPI'])], + 'phpversion' => [new Token([T_STRING, 'PHP_VERSION'])], + 'pi' => [new Token([T_STRING, 'M_PI'])], + ]; + } + + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->functionsFixMap = []; + foreach ($this->configuration['functions'] as $key) { + $this->functionsFixMap[$key] = self::$availableFunctions[$key]; + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replace core functions calls returning constants with the constants.', + [ + new CodeSample( + "<?php\necho phpversion();\necho pi();\necho php_sapi_name();\nclass Foo\n{\n public function Bar()\n {\n echo get_class();\n echo get_called_class();\n }\n}\n" + ), + new CodeSample( + "<?php\necho phpversion();\necho pi();\nclass Foo\n{\n public function Bar()\n {\n echo get_class();\n get_class(\$this);\n echo get_called_class();\n }\n}\n", + ['functions' => ['get_called_class', 'get_class_this', 'phpversion']] + ), + ], + null, + 'Risky when any of the configured functions to replace are overridden.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before NativeFunctionCasingFixer, NoExtraBlankLinesFixer, NoSinglelineWhitespaceBeforeSemicolonsFixer, NoTrailingWhitespaceFixer, NoWhitespaceInBlankLineFixer, SelfStaticAccessorFixer. + * Must run after NoSpacesAfterFunctionNameFixer, NoSpacesInsideParenthesisFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $functionAnalyzer = new FunctionsAnalyzer(); + + for ($index = $tokens->count() - 4; $index > 0; --$index) { + $candidate = $this->getReplaceCandidate($tokens, $functionAnalyzer, $index); + if (null === $candidate) { + continue; + } + + $this->fixFunctionCallToConstant( + $tokens, + $index, + $candidate[0], // brace open + $candidate[1], // brace close + $candidate[2] // replacement + ); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $functionNames = array_keys(self::$availableFunctions); + + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('functions', 'List of function names to fix.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset($functionNames)]) + ->setDefault([ + 'get_class', + 'php_sapi_name', + 'phpversion', + 'pi', + // TODO on v3.0 add 'get_called_class' and `get_class_this` here + ]) + ->getOption(), + ]); + } + + /** + * @param int $index + * @param int $braceOpenIndex + * @param int $braceCloseIndex + * @param Token[] $replacements + */ + private function fixFunctionCallToConstant(Tokens $tokens, $index, $braceOpenIndex, $braceCloseIndex, array $replacements) + { + for ($i = $braceCloseIndex; $i >= $braceOpenIndex; --$i) { + if ($tokens[$i]->isGivenKind([T_WHITESPACE, T_COMMENT, T_DOC_COMMENT])) { + continue; + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($i); + } + + if ($replacements[0]->isGivenKind([T_CLASS_C, T_STATIC])) { + $prevIndex = $tokens->getPrevMeaningfulToken($index); + $prevToken = $tokens[$prevIndex]; + if ($prevToken->isGivenKind(T_NS_SEPARATOR)) { + $tokens->clearAt($prevIndex); + } + } + + $tokens->clearAt($index); + $tokens->insertAt($index, $replacements); + } + + /** + * @param int $index + * + * @return null|array + */ + private function getReplaceCandidate( + Tokens $tokens, + FunctionsAnalyzer $functionAnalyzer, + $index + ) { + if (!$tokens[$index]->isGivenKind(T_STRING)) { + return null; + } + + $lowerContent = strtolower($tokens[$index]->getContent()); + + if ('get_class' === $lowerContent) { + return $this->fixGetClassCall($tokens, $functionAnalyzer, $index); + } + + if (!isset($this->functionsFixMap[$lowerContent])) { + return null; + } + + if (!$functionAnalyzer->isGlobalFunctionCall($tokens, $index)) { + return null; + } + + // test if function call without parameters + $braceOpenIndex = $tokens->getNextMeaningfulToken($index); + if (!$tokens[$braceOpenIndex]->equals('(')) { + return null; + } + + $braceCloseIndex = $tokens->getNextMeaningfulToken($braceOpenIndex); + if (!$tokens[$braceCloseIndex]->equals(')')) { + return null; + } + + return $this->getReplacementTokenClones($lowerContent, $braceOpenIndex, $braceCloseIndex); + } + + /** + * @param int $index + * + * @return null|array + */ + private function fixGetClassCall( + Tokens $tokens, + FunctionsAnalyzer $functionAnalyzer, + $index + ) { + if (!isset($this->functionsFixMap['get_class']) && !isset($this->functionsFixMap['get_class_this'])) { + return null; + } + + if (!$functionAnalyzer->isGlobalFunctionCall($tokens, $index)) { + return null; + } + + $braceOpenIndex = $tokens->getNextMeaningfulToken($index); + $braceCloseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $braceOpenIndex); + + if ($braceCloseIndex === $tokens->getNextMeaningfulToken($braceOpenIndex)) { // no arguments passed + if (isset($this->functionsFixMap['get_class'])) { + return $this->getReplacementTokenClones('get_class', $braceOpenIndex, $braceCloseIndex); + } + } elseif (isset($this->functionsFixMap['get_class_this'])) { + $isThis = false; + + for ($i = $braceOpenIndex + 1; $i < $braceCloseIndex; ++$i) { + if ($tokens[$i]->equalsAny([[T_WHITESPACE], [T_COMMENT], [T_DOC_COMMENT], ')'])) { + continue; + } + + if ($tokens[$i]->isGivenKind(T_VARIABLE) && '$this' === strtolower($tokens[$i]->getContent())) { + $isThis = true; + + continue; + } + + if (false === $isThis && $tokens[$i]->equals('(')) { + continue; + } + + $isThis = false; + + break; + } + + if ($isThis) { + return $this->getReplacementTokenClones('get_class_this', $braceOpenIndex, $braceCloseIndex); + } + } + + return null; + } + + /** + * @param string $lowerContent + * @param int $braceOpenIndex + * @param int $braceCloseIndex + * + * @return array + */ + private function getReplacementTokenClones($lowerContent, $braceOpenIndex, $braceCloseIndex) + { + $clones = []; + foreach ($this->functionsFixMap[$lowerContent] as $token) { + $clones[] = clone $token; + } + + return [ + $braceOpenIndex, + $braceCloseIndex, + $clones, + ]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/IsNullFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/IsNullFixer.php new file mode 100644 index 0000000..410358d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/IsNullFixer.php @@ -0,0 +1,203 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Vladimir Reznichenko <kalessil@gmail.com> + */ +final class IsNullFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replaces `is_null($var)` expression with `null === $var`.', + [ + new CodeSample("<?php\n\$a = is_null(\$b);\n"), + ], + null, + 'Risky when the function `is_null` is overridden.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before YodaStyleFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + static $sequenceNeeded = [[T_STRING, 'is_null'], '(']; + $functionsAnalyzer = new FunctionsAnalyzer(); + + $currIndex = 0; + while (null !== $currIndex) { + $matches = $tokens->findSequence($sequenceNeeded, $currIndex, $tokens->count() - 1, false); + + // stop looping if didn't find any new matches + if (null === $matches) { + break; + } + + // 0 and 1 accordingly are "is_null", "(" tokens + $matches = array_keys($matches); + + // move the cursor just after the sequence + list($isNullIndex, $currIndex) = $matches; + + if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $matches[0])) { + continue; + } + + $next = $tokens->getNextMeaningfulToken($currIndex); + if ($tokens[$next]->equals(')')) { + continue; + } + + $prevTokenIndex = $tokens->getPrevMeaningfulToken($matches[0]); + + // handle function references with namespaces + if ($tokens[$prevTokenIndex]->isGivenKind(T_NS_SEPARATOR)) { + $tokens->removeTrailingWhitespace($prevTokenIndex); + $tokens->clearAt($prevTokenIndex); + + $prevTokenIndex = $tokens->getPrevMeaningfulToken($prevTokenIndex); + } + + // check if inversion being used, text comparison is due to not existing constant + $isInvertedNullCheck = false; + if ($tokens[$prevTokenIndex]->equals('!')) { + $isInvertedNullCheck = true; + + // get rid of inverting for proper transformations + $tokens->removeTrailingWhitespace($prevTokenIndex); + $tokens->clearAt($prevTokenIndex); + } + + // before getting rind of `()` around a parameter, ensure it's not assignment/ternary invariant + $referenceEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $matches[1]); + $isContainingDangerousConstructs = false; + for ($paramTokenIndex = $matches[1]; $paramTokenIndex <= $referenceEnd; ++$paramTokenIndex) { + if (\in_array($tokens[$paramTokenIndex]->getContent(), ['?', '?:', '=', '??'], true)) { + $isContainingDangerousConstructs = true; + + break; + } + } + + // edge cases: is_null() followed/preceded by ==, ===, !=, !==, <> + $parentLeftToken = $tokens[$tokens->getPrevMeaningfulToken($isNullIndex)]; + $parentRightToken = $tokens[$tokens->getNextMeaningfulToken($referenceEnd)]; + $parentOperations = [T_IS_EQUAL, T_IS_NOT_EQUAL, T_IS_IDENTICAL, T_IS_NOT_IDENTICAL]; + $wrapIntoParentheses = $parentLeftToken->isGivenKind($parentOperations) || $parentRightToken->isGivenKind($parentOperations); + + // possible trailing comma removed + $prevIndex = $tokens->getPrevMeaningfulToken($referenceEnd); + if ($tokens[$prevIndex]->equals(',')) { + $tokens->clearTokenAndMergeSurroundingWhitespace($prevIndex); + } + + if (!$isContainingDangerousConstructs) { + // closing parenthesis removed with leading spaces + $tokens->removeLeadingWhitespace($referenceEnd); + $tokens->clearAt($referenceEnd); + + // opening parenthesis removed with trailing spaces + $tokens->removeLeadingWhitespace($matches[1]); + $tokens->removeTrailingWhitespace($matches[1]); + $tokens->clearAt($matches[1]); + } + + // sequence which we'll use as a replacement + $replacement = [ + new Token([T_STRING, 'null']), + new Token([T_WHITESPACE, ' ']), + new Token($isInvertedNullCheck ? [T_IS_NOT_IDENTICAL, '!=='] : [T_IS_IDENTICAL, '===']), + new Token([T_WHITESPACE, ' ']), + ]; + + if (true === $this->configuration['use_yoda_style']) { + if ($wrapIntoParentheses) { + array_unshift($replacement, new Token('(')); + $tokens->insertAt($referenceEnd + 1, new Token(')')); + } + + $tokens->overrideRange($isNullIndex, $isNullIndex, $replacement); + } else { + $replacement = array_reverse($replacement); + if ($wrapIntoParentheses) { + $replacement[] = new Token(')'); + $tokens[$isNullIndex] = new Token('('); + } else { + $tokens->clearAt($isNullIndex); + } + + $tokens->insertAt($referenceEnd + 1, $replacement); + } + + // nested is_null calls support + $currIndex = $isNullIndex; + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + // @todo 3.0 drop `ConfigurationDefinitionFixerInterface` + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('use_yoda_style', 'Whether Yoda style conditions should be used.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->setDeprecationMessage('Use `yoda_style` fixer instead.') + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php new file mode 100644 index 0000000..19d3074 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php @@ -0,0 +1,232 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Gert de Pagter <BackEndTea@gmail.com> + */ +final class NoUnsetOnPropertyFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Properties should be set to `null` instead of using `unset`.', + [new CodeSample("<?php\nunset(\$this->a);\n")], + null, + 'Risky when relying on attributes to be removed using `unset` rather than be set to `null`.'. + ' Changing variables to `null` instead of unsetting means these still show up when looping over class variables'. + ' and reference properties remain unbroken.'. + ' With PHP 7.4, this rule might introduce `null` assignments to properties whose type declaration does not allow it.' + ); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_UNSET) + && $tokens->isAnyTokenKindsFound([T_OBJECT_OPERATOR, T_PAAMAYIM_NEKUDOTAYIM]); + } + + /** + * {@inheritdoc} + * + * Must run before CombineConsecutiveUnsetsFixer. + */ + public function getPriority() + { + return 25; + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + if (!$tokens[$index]->isGivenKind(T_UNSET)) { + continue; + } + + $unsetsInfo = $this->getUnsetsInfo($tokens, $index); + + if (!$this->isAnyUnsetToTransform($unsetsInfo)) { + continue; + } + + $isLastUnset = true; // yes, last - we reverse the array below + foreach (array_reverse($unsetsInfo) as $unsetInfo) { + $this->updateTokens($tokens, $unsetInfo, $isLastUnset); + $isLastUnset = false; + } + } + } + + /** + * @param int $index + * + * @return array<array<string, bool|int>> + */ + private function getUnsetsInfo(Tokens $tokens, $index) + { + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + $unsetStart = $tokens->getNextTokenOfKind($index, ['(']); + $unsetEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $unsetStart); + $isFirst = true; + + $unsets = []; + foreach ($argumentsAnalyzer->getArguments($tokens, $unsetStart, $unsetEnd) as $startIndex => $endIndex) { + $startIndex = $tokens->getNextMeaningfulToken($startIndex - 1); + $endIndex = $tokens->getPrevMeaningfulToken($endIndex + 1); + $unsets[] = [ + 'startIndex' => $startIndex, + 'endIndex' => $endIndex, + 'isToTransform' => $this->isProperty($tokens, $startIndex, $endIndex), + 'isFirst' => $isFirst, + ]; + $isFirst = false; + } + + return $unsets; + } + + /** + * @param int $index + * @param int $endIndex + * + * @return bool + */ + private function isProperty(Tokens $tokens, $index, $endIndex) + { + if ($tokens[$index]->isGivenKind(T_VARIABLE)) { + $nextIndex = $tokens->getNextMeaningfulToken($index); + if (null === $nextIndex || !$tokens[$nextIndex]->isGivenKind(T_OBJECT_OPERATOR)) { + return false; + } + $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); + $nextNextIndex = $tokens->getNextMeaningfulToken($nextIndex); + if (null !== $nextNextIndex && $nextNextIndex < $endIndex) { + return false; + } + + return null !== $nextIndex && $tokens[$nextIndex]->isGivenKind(T_STRING); + } + + if ($tokens[$index]->isGivenKind([T_NS_SEPARATOR, T_STRING])) { + $nextIndex = $tokens->getTokenNotOfKindsSibling($index, 1, [T_DOUBLE_COLON, T_NS_SEPARATOR, T_STRING]); + $nextNextIndex = $tokens->getNextMeaningfulToken($nextIndex); + if (null !== $nextNextIndex && $nextNextIndex < $endIndex) { + return false; + } + + return null !== $nextIndex && $tokens[$nextIndex]->isGivenKind(T_VARIABLE); + } + + return false; + } + + /** + * @param array<array<string, bool|int>> $unsetsInfo + * + * @return bool + */ + private function isAnyUnsetToTransform(array $unsetsInfo) + { + foreach ($unsetsInfo as $unsetInfo) { + if ($unsetInfo['isToTransform']) { + return true; + } + } + + return false; + } + + /** + * @param array<string, bool|int> $unsetInfo + * @param bool $isLastUnset + */ + private function updateTokens(Tokens $tokens, array $unsetInfo, $isLastUnset) + { + // if entry is first and to be transform we remove leading "unset(" + if ($unsetInfo['isFirst'] && $unsetInfo['isToTransform']) { + $braceIndex = $tokens->getPrevTokenOfKind($unsetInfo['startIndex'], ['(']); + $unsetIndex = $tokens->getPrevTokenOfKind($braceIndex, [[T_UNSET]]); + $tokens->clearTokenAndMergeSurroundingWhitespace($braceIndex); + $tokens->clearTokenAndMergeSurroundingWhitespace($unsetIndex); + } + + // if entry is last and to be transformed we remove trailing ")" + if ($isLastUnset && $unsetInfo['isToTransform']) { + $braceIndex = $tokens->getNextTokenOfKind($unsetInfo['endIndex'], [')']); + $previousIndex = $tokens->getPrevMeaningfulToken($braceIndex); + if ($tokens[$previousIndex]->equals(',')) { + $tokens->clearTokenAndMergeSurroundingWhitespace($previousIndex); // trailing ',' in function call (PHP 7.3) + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($braceIndex); + } + + // if entry is not last we replace comma with semicolon (last entry already has semicolon - from original unset) + if (!$isLastUnset) { + $commaIndex = $tokens->getNextTokenOfKind($unsetInfo['endIndex'], [',']); + $tokens[$commaIndex] = new Token(';'); + } + + // if entry is to be unset and is not last we add trailing ")" + if (!$unsetInfo['isToTransform'] && !$isLastUnset) { + $tokens->insertAt($unsetInfo['endIndex'] + 1, new Token(')')); + } + + // if entry is to be unset and is not first we add leading "unset(" + if (!$unsetInfo['isToTransform'] && !$unsetInfo['isFirst']) { + $tokens->insertAt( + $unsetInfo['startIndex'], + [ + new Token([T_UNSET, 'unset']), + new Token('('), + ] + ); + } + + // and finally + // if entry is to be transformed we add trailing " = null" + if ($unsetInfo['isToTransform']) { + $tokens->insertAt( + $unsetInfo['endIndex'] + 1, + [ + new Token([T_WHITESPACE, ' ']), + new Token('='), + new Token([T_WHITESPACE, ' ']), + new Token([T_STRING, 'null']), + ] + ); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/SilencedDeprecationErrorFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/SilencedDeprecationErrorFixer.php new file mode 100644 index 0000000..b119912 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/SilencedDeprecationErrorFixer.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author Jules Pietri <jules@heahprod.com> + * + * @deprecated + */ +final class SilencedDeprecationErrorFixer extends AbstractProxyFixer implements DeprecatedFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Ensures deprecation notices are silenced.', + [new CodeSample("<?php\ntrigger_error('Warning.', E_USER_DEPRECATED);\n")], + null, + 'Silencing of deprecation errors might cause changes to code behaviour.' + ); + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + return [new ErrorSuppressionFixer()]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixer.php new file mode 100644 index 0000000..6bdfa7e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/LanguageConstruct/SingleSpaceAfterConstructFixer.php @@ -0,0 +1,346 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\LanguageConstruct; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Andreas Möller <am@localheinz.com> + */ +final class SingleSpaceAfterConstructFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var array<string, null|int> + */ + private static $tokenMap = [ + 'abstract' => T_ABSTRACT, + 'as' => T_AS, + 'attribute' => CT::T_ATTRIBUTE_CLOSE, + 'break' => T_BREAK, + 'case' => T_CASE, + 'catch' => T_CATCH, + 'class' => T_CLASS, + 'clone' => T_CLONE, + 'comment' => T_COMMENT, + 'const' => T_CONST, + 'const_import' => CT::T_CONST_IMPORT, + 'continue' => T_CONTINUE, + 'do' => T_DO, + 'echo' => T_ECHO, + 'else' => T_ELSE, + 'elseif' => T_ELSEIF, + 'extends' => T_EXTENDS, + 'final' => T_FINAL, + 'finally' => T_FINALLY, + 'for' => T_FOR, + 'foreach' => T_FOREACH, + 'function' => T_FUNCTION, + 'function_import' => CT::T_FUNCTION_IMPORT, + 'global' => T_GLOBAL, + 'goto' => T_GOTO, + 'if' => T_IF, + 'implements' => T_IMPLEMENTS, + 'include' => T_INCLUDE, + 'include_once' => T_INCLUDE_ONCE, + 'instanceof' => T_INSTANCEOF, + 'insteadof' => T_INSTEADOF, + 'interface' => T_INTERFACE, + 'match' => null, + 'named_argument' => CT::T_NAMED_ARGUMENT_COLON, + 'namespace' => T_NAMESPACE, + 'new' => T_NEW, + 'open_tag_with_echo' => T_OPEN_TAG_WITH_ECHO, + 'php_doc' => T_DOC_COMMENT, + 'php_open' => T_OPEN_TAG, + 'print' => T_PRINT, + 'private' => T_PRIVATE, + 'protected' => T_PROTECTED, + 'public' => T_PUBLIC, + 'require' => T_REQUIRE, + 'require_once' => T_REQUIRE_ONCE, + 'return' => T_RETURN, + 'static' => T_STATIC, + 'throw' => T_THROW, + 'trait' => T_TRAIT, + 'try' => T_TRY, + 'use' => T_USE, + 'use_lambda' => CT::T_USE_LAMBDA, + 'use_trait' => CT::T_USE_TRAIT, + 'var' => T_VAR, + 'while' => T_WHILE, + 'yield' => T_YIELD, + 'yield_from' => null, + ]; + + /** + * @var array<string, int> + */ + private $fixTokenMap = []; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + // @TODO: drop condition when PHP 7.0+ is required + if (\defined('T_YIELD_FROM')) { + self::$tokenMap['yield_from'] = T_YIELD_FROM; + } + + // @TODO: drop condition when PHP 8.0+ is required + if (\defined('T_MATCH')) { + self::$tokenMap['match'] = T_MATCH; + } + + $this->fixTokenMap = []; + + foreach ($this->configuration['constructs'] as $key) { + $this->fixTokenMap[$key] = self::$tokenMap[$key]; + } + + if (isset($this->fixTokenMap['public'])) { + $this->fixTokenMap['constructor_public'] = CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC; + } + + if (isset($this->fixTokenMap['protected'])) { + $this->fixTokenMap['constructor_protected'] = CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED; + } + + if (isset($this->fixTokenMap['private'])) { + $this->fixTokenMap['constructor_private'] = CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE; + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Ensures a single space after language constructs.', + [ + new CodeSample( + '<?php + +throw new \Exception(); +' + ), + new CodeSample( + '<?php + +echo "Hello!"; +', + [ + 'constructs' => [ + 'echo', + ], + ] + ), + new VersionSpecificCodeSample( + '<?php + +yield from baz(); +', + new VersionSpecification(70000), + [ + 'constructs' => [ + 'yield_from', + ], + ] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer, FunctionDeclarationFixer. + */ + public function getPriority() + { + return 36; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(array_values($this->fixTokenMap)) && !$tokens->hasAlternativeSyntax(); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokenKinds = array_values($this->fixTokenMap); + + for ($index = $tokens->count() - 2; $index >= 0; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind($tokenKinds)) { + continue; + } + + $whitespaceTokenIndex = $index + 1; + + if ($tokens[$whitespaceTokenIndex]->equalsAny([';', ')', [CT::T_ARRAY_SQUARE_BRACE_CLOSE]])) { + continue; + } + + if ( + $token->isGivenKind(T_STATIC) + && !$tokens[$tokens->getNextMeaningfulToken($index)]->isGivenKind([T_FUNCTION, T_VARIABLE]) + ) { + continue; + } + + if ($token->isGivenKind(T_OPEN_TAG)) { + if ($tokens[$whitespaceTokenIndex]->equals([T_WHITESPACE]) && false === strpos($token->getContent(), "\n")) { + $tokens->clearAt($whitespaceTokenIndex); + } + + continue; + } + + if ($token->isGivenKind(T_CLASS) && $tokens[$tokens->getNextMeaningfulToken($index)]->equals('(')) { + continue; + } + + if ($token->isGivenKind([T_EXTENDS, T_IMPLEMENTS]) && $this->isMultilineExtendsOrImplementsWithMoreThanOneAncestor($tokens, $index)) { + continue; + } + + if ($token->isGivenKind(T_RETURN) && $this->isMultiLineReturn($tokens, $index)) { + continue; + } + + if ($token->isComment() || $token->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) { + if ($tokens[$whitespaceTokenIndex]->equals([T_WHITESPACE]) && false !== strpos($tokens[$whitespaceTokenIndex]->getContent(), "\n")) { + continue; + } + } + + if ($tokens[$whitespaceTokenIndex]->equals([T_WHITESPACE])) { + $tokens[$whitespaceTokenIndex] = new Token([T_WHITESPACE, ' ']); + } else { + $tokens->insertAt($whitespaceTokenIndex, new Token([T_WHITESPACE, ' '])); + } + + if ( + 70000 <= \PHP_VERSION_ID + && $token->isGivenKind(T_YIELD_FROM) + && 'yield from' !== strtolower($token->getContent()) + ) { + $tokens[$index] = new Token([T_YIELD_FROM, Preg::replace( + '/\s+/', + ' ', + $token->getContent() + )]); + } + } + } + + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('constructs', 'List of constructs which must be followed by a single space.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset(array_keys(self::$tokenMap))]) + ->setDefault(array_keys(self::$tokenMap)) + ->getOption(), + ]); + } + + /** + * @param int $index + * + * @return bool + */ + private function isMultiLineReturn(Tokens $tokens, $index) + { + ++$index; + $tokenFollowingReturn = $tokens[$index]; + + if ( + !$tokenFollowingReturn->isGivenKind(T_WHITESPACE) + || false === strpos($tokenFollowingReturn->getContent(), "\n") + ) { + return false; + } + + $nestedCount = 0; + + for ($indexEnd = \count($tokens) - 1, ++$index; $index < $indexEnd; ++$index) { + if (false !== strpos($tokens[$index]->getContent(), "\n")) { + return true; + } + + if ($tokens[$index]->equals('{')) { + ++$nestedCount; + } elseif ($tokens[$index]->equals('}')) { + --$nestedCount; + } elseif (0 === $nestedCount && $tokens[$index]->equalsAny([';', [T_CLOSE_TAG]])) { + break; + } + } + + return false; + } + + /** + * @param int $index + * + * @return bool + */ + private function isMultilineExtendsOrImplementsWithMoreThanOneAncestor(Tokens $tokens, $index) + { + $hasMoreThanOneAncestor = false; + + while (++$index) { + $token = $tokens[$index]; + + if ($token->equals(',')) { + $hasMoreThanOneAncestor = true; + + continue; + } + + if ($token->equals('{')) { + return false; + } + + if ($hasMoreThanOneAncestor && false !== strpos($token->getContent(), "\n")) { + return true; + } + } + + return false; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ListNotation/ListSyntaxFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ListNotation/ListSyntaxFixer.php new file mode 100644 index 0000000..57aadb6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ListNotation/ListSyntaxFixer.php @@ -0,0 +1,152 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ListNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class ListSyntaxFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var null|int + */ + private $candidateTokenKind; + + /** + * Use 'syntax' => 'long'|'short'. + * + * @param null|array<string, string> $configuration + * + * @throws InvalidFixerConfigurationException + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->candidateTokenKind = 'long' === $this->configuration['syntax'] ? CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN : T_LIST; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'List (`array` destructuring) assignment should be declared using the configured syntax. Requires PHP >= 7.1.', + [ + new VersionSpecificCodeSample( + "<?php\n[\$sample] = \$array;\n", + new VersionSpecification(70100) + ), + new VersionSpecificCodeSample( + "<?php\nlist(\$sample) = \$array;\n", + new VersionSpecification(70100), + ['syntax' => 'short'] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BinaryOperatorSpacesFixer, TernaryOperatorSpacesFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70100 && $tokens->isTokenKindFound($this->candidateTokenKind); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + if ($tokens[$index]->isGivenKind($this->candidateTokenKind)) { + if (T_LIST === $this->candidateTokenKind) { + $this->fixToShortSyntax($tokens, $index); + } else { + $this->fixToLongSyntax($tokens, $index); + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('syntax', 'Whether to use the `long` or `short` `list` syntax.')) + ->setAllowedValues(['long', 'short']) + ->setDefault('long') // TODO @3.0 change to short + ->getOption(), + ]); + } + + /** + * @param int $index + */ + private function fixToLongSyntax(Tokens $tokens, $index) + { + static $typesOfInterest = [ + [CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE], + '[', // [CT::T_ARRAY_SQUARE_BRACE_OPEN], + ]; + + $closeIndex = $tokens->getNextTokenOfKind($index, $typesOfInterest); + if (!$tokens[$closeIndex]->isGivenKind(CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE)) { + return; + } + + $tokens[$index] = new Token('('); + $tokens[$closeIndex] = new Token(')'); + $tokens->insertAt($index, new Token([T_LIST, 'list'])); + } + + /** + * @param int $index + */ + private function fixToShortSyntax(Tokens $tokens, $index) + { + $openIndex = $tokens->getNextTokenOfKind($index, ['(']); + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); + + $tokens[$openIndex] = new Token([CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN, '[']); + $tokens[$closeIndex] = new Token([CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE, ']']); + + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/BlankLineAfterNamespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/BlankLineAfterNamespaceFixer.php new file mode 100644 index 0000000..a209b89 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/BlankLineAfterNamespaceFixer.php @@ -0,0 +1,144 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\NamespaceNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR2 ¶3. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class BlankLineAfterNamespaceFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There MUST be one blank line after the namespace declaration.', + [ + new CodeSample("<?php\nnamespace Sample\\Sample;\n\n\n\$a;\n"), + new CodeSample("<?php\nnamespace Sample\\Sample;\nClass Test{}\n"), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after NoUnusedImportsFixer. + */ + public function getPriority() + { + return -20; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_NAMESPACE); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $lastIndex = $tokens->count() - 1; + + for ($index = $lastIndex; $index >= 0; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_NAMESPACE)) { + continue; + } + + $semicolonIndex = $tokens->getNextTokenOfKind($index, [';', '{', [T_CLOSE_TAG]]); + $semicolonToken = $tokens[$semicolonIndex]; + + if (!$semicolonToken->equals(';')) { + continue; + } + + $indexToEnsureBlankLineAfter = $this->getIndexToEnsureBlankLineAfter($tokens, $semicolonIndex); + $indexToEnsureBlankLine = $tokens->getNonEmptySibling($indexToEnsureBlankLineAfter, 1); + + if (null !== $indexToEnsureBlankLine && $tokens[$indexToEnsureBlankLine]->isWhitespace()) { + $tokens[$indexToEnsureBlankLine] = $this->getTokenToInsert($tokens[$indexToEnsureBlankLine]->getContent(), $indexToEnsureBlankLine === $lastIndex); + } else { + $tokens->insertAt($indexToEnsureBlankLineAfter + 1, $this->getTokenToInsert('', $indexToEnsureBlankLineAfter === $lastIndex)); + } + } + } + + /** + * @param int $index + * + * @return int + */ + private function getIndexToEnsureBlankLineAfter(Tokens $tokens, $index) + { + $indexToEnsureBlankLine = $index; + $nextIndex = $tokens->getNonEmptySibling($indexToEnsureBlankLine, 1); + + while (null !== $nextIndex) { + $token = $tokens[$nextIndex]; + + if ($token->isWhitespace()) { + if (1 === Preg::match('/\R/', $token->getContent())) { + break; + } + $nextNextIndex = $tokens->getNonEmptySibling($nextIndex, 1); + + if (!$tokens[$nextNextIndex]->isComment()) { + break; + } + } + + if (!$token->isWhitespace() && !$token->isComment()) { + break; + } + + $indexToEnsureBlankLine = $nextIndex; + $nextIndex = $tokens->getNonEmptySibling($indexToEnsureBlankLine, 1); + } + + return $indexToEnsureBlankLine; + } + + /** + * @param string $currentContent + * @param bool $isLastIndex + * + * @return Token + */ + private function getTokenToInsert($currentContent, $isLastIndex) + { + $ending = $this->whitespacesConfig->getLineEnding(); + + $emptyLines = $isLastIndex ? $ending : $ending.$ending; + $indent = 1 === Preg::match('/^.*\R( *)$/s', $currentContent, $matches) ? $matches[1] : ''; + + return new Token([T_WHITESPACE, $emptyLines.$indent]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/CleanNamespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/CleanNamespaceFixer.php new file mode 100644 index 0000000..386e6cc --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/CleanNamespaceFixer.php @@ -0,0 +1,106 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\NamespaceNotation; + +use PhpCsFixer\AbstractLinesBeforeNamespaceFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Tokens; + +final class CleanNamespaceFixer extends AbstractLinesBeforeNamespaceFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + $samples = []; + + foreach (['namespace Foo \\ Bar;', 'echo foo /* comment */ \\ bar();'] as $sample) { + $samples[] = new VersionSpecificCodeSample( + "<?php\n".$sample."\n", + new VersionSpecification(null, 80000 - 1) + ); + } + + return new FixerDefinition( + 'Namespace must not contain spacing, comments or PHPDoc.', + $samples + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID < 80000 && $tokens->isTokenKindFound(T_NS_SEPARATOR); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $count = $tokens->count(); + + for ($index = 0; $index < $count; ++$index) { + if ($tokens[$index]->isGivenKind(T_NS_SEPARATOR)) { + $previousIndex = $tokens->getPrevMeaningfulToken($index); + + $index = $this->fixNamespace( + $tokens, + $tokens[$previousIndex]->isGivenKind(T_STRING) ? $previousIndex : $index + ); + } + } + } + + /** + * @param int $index start of namespace + * + * @return int + */ + private function fixNamespace(Tokens $tokens, $index) + { + $tillIndex = $index; + + // go to the end of the namespace + while ($tokens[$tillIndex]->isGivenKind([T_NS_SEPARATOR, T_STRING])) { + $tillIndex = $tokens->getNextMeaningfulToken($tillIndex); + } + + $tillIndex = $tokens->getPrevMeaningfulToken($tillIndex); + + $spaceIndexes = []; + + for (; $index <= $tillIndex; ++$index) { + if ($tokens[$index]->isGivenKind(T_WHITESPACE)) { + $spaceIndexes[] = $index; + } elseif ($tokens[$index]->isComment()) { + $tokens->clearAt($index); + } + } + + if ($tokens[$index - 1]->isWhiteSpace()) { + array_pop($spaceIndexes); + } + + foreach ($spaceIndexes as $i) { + $tokens->clearAt($i); + } + + return $index; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixer.php new file mode 100644 index 0000000..c516a01 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/NoBlankLinesBeforeNamespaceFixer.php @@ -0,0 +1,73 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\NamespaceNotation; + +use PhpCsFixer\AbstractLinesBeforeNamespaceFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + */ +final class NoBlankLinesBeforeNamespaceFixer extends AbstractLinesBeforeNamespaceFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_NAMESPACE); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There should be no blank lines before a namespace declaration.', + [ + new CodeSample( + "<?php\n\n\n\nnamespace Example;\n" + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after BlankLineAfterOpeningTagFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_NAMESPACE)) { + continue; + } + + $this->fixLinesBeforeNamespace($tokens, $index, 0, 1); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/NoLeadingNamespaceWhitespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/NoLeadingNamespaceWhitespaceFixer.php new file mode 100644 index 0000000..ddb67ad --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/NoLeadingNamespaceWhitespaceFixer.php @@ -0,0 +1,101 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\NamespaceNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Bram Gotink <bram@gotink.me> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NoLeadingNamespaceWhitespaceFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_NAMESPACE); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'The namespace declaration line shouldn\'t contain leading whitespace.', + [ + new CodeSample( + '<?php + namespace Test8a; + namespace Test8b; +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = \count($tokens) - 1; 0 <= $index; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_NAMESPACE)) { + continue; + } + + $beforeNamespaceIndex = $index - 1; + $beforeNamespace = $tokens[$beforeNamespaceIndex]; + + if (!$beforeNamespace->isWhitespace()) { + if (!self::endsWithWhitespace($beforeNamespace->getContent())) { + $tokens->insertAt($index, new Token([T_WHITESPACE, $this->whitespacesConfig->getLineEnding()])); + } + + continue; + } + + $lastNewline = strrpos($beforeNamespace->getContent(), "\n"); + + if (false === $lastNewline) { + $beforeBeforeNamespace = $tokens[$index - 2]; + + if (self::endsWithWhitespace($beforeBeforeNamespace->getContent())) { + $tokens->clearAt($beforeNamespaceIndex); + } else { + $tokens[$beforeNamespaceIndex] = new Token([T_WHITESPACE, ' ']); + } + } else { + $tokens[$beforeNamespaceIndex] = new Token([T_WHITESPACE, substr($beforeNamespace->getContent(), 0, $lastNewline + 1)]); + } + } + } + + private static function endsWithWhitespace($str) + { + if ('' === $str) { + return false; + } + + return '' === trim(substr($str, -1)); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php new file mode 100644 index 0000000..b9180f7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php @@ -0,0 +1,68 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\NamespaceNotation; + +use PhpCsFixer\AbstractLinesBeforeNamespaceFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + */ +final class SingleBlankLineBeforeNamespaceFixer extends AbstractLinesBeforeNamespaceFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There should be exactly one blank line before a namespace declaration.', + [ + new CodeSample("<?php namespace A {}\n"), + new CodeSample("<?php\n\n\nnamespace A{}\n"), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_NAMESPACE); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return -21; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if ($token->isGivenKind(T_NAMESPACE)) { + $this->fixLinesBeforeNamespace($tokens, $index, 2, 2); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Naming/NoHomoglyphNamesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Naming/NoHomoglyphNamesFixer.php new file mode 100644 index 0000000..9f4951e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Naming/NoHomoglyphNamesFixer.php @@ -0,0 +1,244 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Naming; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Fred Cox <mcfedr@gmail.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NoHomoglyphNamesFixer extends AbstractFixer +{ + /** + * Used the program https://github.com/mcfedr/homoglyph-download + * to generate this list from + * http://homoglyphs.net/?text=abcdefghijklmnopqrstuvwxyz&lang=en&exc7=1&exc8=1&exc13=1&exc14=1. + * + * Symbols replaced include + * - Latin homoglyphs + * - IPA extensions + * - Greek and Coptic + * - Cyrillic + * - Cyrillic Supplement + * - Letterlike Symbols + * - Latin Numbers + * - Fullwidth Latin + * + * This is not the complete list of unicode homographs, but limited + * to those you are more likely to have typed/copied by accident + * + * @var array + */ + private static $replacements = [ + 'O' => '0', + '0' => '0', + 'I' => '1', + '1' => '1', + '2' => '2', + '3' => '3', + '4' => '4', + '5' => '5', + '6' => '6', + '7' => '7', + '8' => '8', + '9' => '9', + 'Α' => 'A', + 'А' => 'A', + 'A' => 'A', + 'ʙ' => 'B', + 'Β' => 'B', + 'В' => 'B', + 'B' => 'B', + 'Ϲ' => 'C', + 'С' => 'C', + 'Ⅽ' => 'C', + 'C' => 'C', + 'Ⅾ' => 'D', + 'D' => 'D', + 'Ε' => 'E', + 'Е' => 'E', + 'E' => 'E', + 'Ϝ' => 'F', + 'F' => 'F', + 'ɢ' => 'G', + 'Ԍ' => 'G', + 'G' => 'G', + 'ʜ' => 'H', + 'Η' => 'H', + 'Н' => 'H', + 'H' => 'H', + 'l' => 'I', + 'Ι' => 'I', + 'І' => 'I', + 'Ⅰ' => 'I', + 'I' => 'I', + 'Ј' => 'J', + 'J' => 'J', + 'Κ' => 'K', + 'К' => 'K', + 'K' => 'K', + 'K' => 'K', + 'ʟ' => 'L', + 'Ⅼ' => 'L', + 'L' => 'L', + 'Μ' => 'M', + 'М' => 'M', + 'Ⅿ' => 'M', + 'M' => 'M', + 'ɴ' => 'N', + 'Ν' => 'N', + 'N' => 'N', + 'Ο' => 'O', + 'О' => 'O', + 'O' => 'O', + 'Ρ' => 'P', + 'Р' => 'P', + 'P' => 'P', + 'Q' => 'Q', + 'ʀ' => 'R', + 'R' => 'R', + 'Ѕ' => 'S', + 'S' => 'S', + 'Τ' => 'T', + 'Т' => 'T', + 'T' => 'T', + 'U' => 'U', + 'Ѵ' => 'V', + 'Ⅴ' => 'V', + 'V' => 'V', + 'W' => 'W', + 'Χ' => 'X', + 'Х' => 'X', + 'Ⅹ' => 'X', + 'X' => 'X', + 'ʏ' => 'Y', + 'Υ' => 'Y', + 'Ү' => 'Y', + 'Y' => 'Y', + 'Ζ' => 'Z', + 'Z' => 'Z', + '_' => '_', + 'ɑ' => 'a', + 'а' => 'a', + 'a' => 'a', + 'Ь' => 'b', + 'b' => 'b', + 'ϲ' => 'c', + 'с' => 'c', + 'ⅽ' => 'c', + 'c' => 'c', + 'ԁ' => 'd', + 'ⅾ' => 'd', + 'd' => 'd', + 'е' => 'e', + 'e' => 'e', + 'f' => 'f', + 'ɡ' => 'g', + 'g' => 'g', + 'һ' => 'h', + 'h' => 'h', + 'ɩ' => 'i', + 'і' => 'i', + 'ⅰ' => 'i', + 'i' => 'i', + 'ј' => 'j', + 'j' => 'j', + 'k' => 'k', + 'ⅼ' => 'l', + 'l' => 'l', + 'ⅿ' => 'm', + 'm' => 'm', + 'n' => 'n', + 'ο' => 'o', + 'о' => 'o', + 'o' => 'o', + 'р' => 'p', + 'p' => 'p', + 'q' => 'q', + 'r' => 'r', + 'ѕ' => 's', + 's' => 's', + 't' => 't', + 'u' => 'u', + 'ν' => 'v', + 'ѵ' => 'v', + 'ⅴ' => 'v', + 'v' => 'v', + 'ѡ' => 'w', + 'w' => 'w', + 'х' => 'x', + 'ⅹ' => 'x', + 'x' => 'x', + 'у' => 'y', + 'y' => 'y', + 'z' => 'z', + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replace accidental usage of homoglyphs (non ascii characters) in names.', + [new CodeSample("<?php \$nаmе = 'wrong \"a\" character';\n")], + null, + 'Renames classes and cannot rename the files. You might have string references to renamed code (`$$name`).' + ); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_VARIABLE, T_STRING]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind([T_VARIABLE, T_STRING])) { + continue; + } + + $replaced = Preg::replaceCallback('/[^[:ascii:]]/u', static function ($matches) { + return isset(self::$replacements[$matches[0]]) + ? self::$replacements[$matches[0]] + : $matches[0] + ; + }, $token->getContent(), -1, $count); + + if ($count) { + $tokens->offsetSet($index, new Token([$token->getId(), $replaced])); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/AlignDoubleArrowFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/AlignDoubleArrowFixerHelper.php similarity index 64% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/AlignDoubleArrowFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/AlignDoubleArrowFixerHelper.php index 382dafe..483553c 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/AlignDoubleArrowFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/AlignDoubleArrowFixerHelper.php @@ -10,17 +10,22 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Contrib; +namespace PhpCsFixer\Fixer\Operator; -use Symfony\CS\AbstractAlignFixer; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractAlignFixerHelper; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Utils; /** * @author Carlos Cirello <carlos.cirello.nl@gmail.com> * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> * @author Graham Campbell <graham@alt-three.com> + * + * @deprecated */ -class AlignDoubleArrowFixer extends AbstractAlignFixer +final class AlignDoubleArrowFixerHelper extends AbstractAlignFixerHelper { /** * Level counter of the current nest level. @@ -29,65 +34,28 @@ class AlignDoubleArrowFixer extends AbstractAlignFixer * * @var int */ - private $currentLevel; - - /** - * Keep track of the deepest level ever achieved while - * parsing the code. Used later to replace alignment - * placeholders with spaces. - * - * @var int - */ - private $deepestLevel; + private $currentLevel = 0; - /** - * {@inheritdoc} - */ - public function fix(\SplFileInfo $file, $content) + public function __construct() { - $this->currentLevel = 0; - $this->deepestLevel = 0; - $tokens = Tokens::fromCode($content); - - $this->injectAlignmentPlaceholders($tokens, 0, count($tokens)); - - return $this->replacePlaceholder($tokens, $this->deepestLevel); + Utils::triggerDeprecation(new \RuntimeException(sprintf( + 'The "%s" class is deprecated. You should stop using it, as it will be removed in 3.0 version.', + __CLASS__ + ))); } /** * {@inheritdoc} */ - public function getDescription() - { - return 'Align double arrow symbols in consecutive lines.'; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - // should be run after the OperatorsSpacesFixer - return -10; - } - - /** - * Inject into the text placeholders of candidates of vertical alignment. - * - * @param Tokens $tokens - * @param int $startAt - * @param int $endAt - * - * @return array($code, $context_counter) - */ - private function injectAlignmentPlaceholders(Tokens $tokens, $startAt, $endAt) + protected function injectAlignmentPlaceholders(Tokens $tokens, $startAt, $endAt) { for ($index = $startAt; $index < $endAt; ++$index) { $token = $tokens[$index]; - if ($token->isGivenKind(array(T_FOREACH, T_FOR, T_WHILE, T_IF, T_SWITCH))) { + if ($token->isGivenKind([T_FOREACH, T_FOR, T_WHILE, T_IF, T_SWITCH])) { $index = $tokens->getNextMeaningfulToken($index); $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + continue; } @@ -97,40 +65,45 @@ private function injectAlignmentPlaceholders(Tokens $tokens, $startAt, $endAt) $index = $until; $this->injectArrayAlignmentPlaceholders($tokens, $from, $until); + continue; } - if ($tokens->isShortArray($index)) { + if ($token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; - if ($prevToken->isGivenKind(array(T_STRING, T_VARIABLE))) { + if ($prevToken->isGivenKind([T_STRING, T_VARIABLE])) { continue; } $from = $index; - $until = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $from); + $until = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $from); $index = $until; $this->injectArrayAlignmentPlaceholders($tokens, $from + 1, $until - 1); + continue; } if ($token->isGivenKind(T_DOUBLE_ARROW)) { $tokenContent = sprintf(self::ALIGNABLE_PLACEHOLDER, $this->currentLevel).$token->getContent(); - $nextToken = $tokens[$index + 1]; + $nextIndex = $index + 1; + $nextToken = $tokens[$nextIndex]; if (!$nextToken->isWhitespace()) { $tokenContent .= ' '; - } elseif ($nextToken->isWhitespace(array('whitespaces' => " \t"))) { - $nextToken->setContent(' '); + } elseif ($nextToken->isWhitespace(" \t")) { + $tokens[$nextIndex] = new Token([T_WHITESPACE, ' ']); } - $token->setContent($tokenContent); + $tokens[$index] = new Token([T_DOUBLE_ARROW, $tokenContent]); + continue; } if ($token->equals(';')) { ++$this->deepestLevel; ++$this->currentLevel; + continue; } @@ -140,7 +113,7 @@ private function injectAlignmentPlaceholders(Tokens $tokens, $startAt, $endAt) break; } - if ($tokens->isArray($i + 1)) { + if ($tokens[$i + 1]->isGivenKind([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN])) { $arrayStartIndex = $tokens[$i + 1]->isGivenKind(T_ARRAY) ? $tokens->getNextMeaningfulToken($i + 1) : $i + 1 @@ -160,9 +133,8 @@ private function injectAlignmentPlaceholders(Tokens $tokens, $startAt, $endAt) } /** - * @param Tokens $tokens - * @param int $from - * @param int $until + * @param int $from + * @param int $until */ private function injectArrayAlignmentPlaceholders(Tokens $tokens, $from, $until) { diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/AlignEqualsFixerHelper.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/AlignEqualsFixerHelper.php new file mode 100644 index 0000000..330c72d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/AlignEqualsFixerHelper.php @@ -0,0 +1,76 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractAlignFixerHelper; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Utils; + +/** + * @author Carlos Cirello <carlos.cirello.nl@gmail.com> + * @author Graham Campbell <graham@alt-three.com> + * + * @deprecated + */ +final class AlignEqualsFixerHelper extends AbstractAlignFixerHelper +{ + public function __construct() + { + Utils::triggerDeprecation(new \RuntimeException(sprintf( + 'The "%s" class is deprecated. You should stop using it, as it will be removed in 3.0 version.', + __CLASS__ + ))); + } + + /** + * {@inheritdoc} + */ + protected function injectAlignmentPlaceholders(Tokens $tokens, $startAt, $endAt) + { + for ($index = $startAt; $index < $endAt; ++$index) { + $token = $tokens[$index]; + + if ($token->equals('=')) { + $tokens[$index] = new Token(sprintf(self::ALIGNABLE_PLACEHOLDER, $this->deepestLevel).$token->getContent()); + + continue; + } + + if ($token->isGivenKind(T_FUNCTION)) { + ++$this->deepestLevel; + + continue; + } + + if ($token->equals('(')) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + + continue; + } + + if ($token->equals('[')) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE, $index); + + continue; + } + + if ($token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $index); + + continue; + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/BinaryOperatorSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/BinaryOperatorSpacesFixer.php new file mode 100644 index 0000000..7656967 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/BinaryOperatorSpacesFixer.php @@ -0,0 +1,870 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\Console\Command\HelpCommand; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use PhpCsFixer\Utils; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +final class BinaryOperatorSpacesFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @internal + */ + const SINGLE_SPACE = 'single_space'; + + /** + * @internal + */ + const NO_SPACE = 'no_space'; + + /** + * @internal + */ + const ALIGN = 'align'; + + /** + * @internal + */ + const ALIGN_SINGLE_SPACE = 'align_single_space'; + + /** + * @internal + */ + const ALIGN_SINGLE_SPACE_MINIMAL = 'align_single_space_minimal'; + + /** + * @internal + * @const Placeholder used as anchor for right alignment. + */ + const ALIGN_PLACEHOLDER = "\x2 ALIGNABLE%d \x3"; + + /** + * Keep track of the deepest level ever achieved while + * parsing the code. Used later to replace alignment + * placeholders with spaces. + * + * @var int + */ + private $deepestLevel; + + /** + * Level counter of the current nest level. + * So one level alignments are not mixed with + * other level ones. + * + * @var int + */ + private $currentLevel; + + private static $allowedValues = [ + self::ALIGN, + self::ALIGN_SINGLE_SPACE, + self::ALIGN_SINGLE_SPACE_MINIMAL, + self::SINGLE_SPACE, + self::NO_SPACE, + null, + ]; + + /** + * @var string[] + */ + private static $supportedOperators = [ + '=', + '*', + '/', + '%', + '<', + '>', + '|', + '^', + '+', + '-', + '&', + '&=', + '&&', + '||', + '.=', + '/=', + '=>', + '==', + '>=', + '===', + '!=', + '<>', + '!==', + '<=', + 'and', + 'or', + 'xor', + '-=', + '%=', + '*=', + '|=', + '+=', + '<<', + '<<=', + '>>', + '>>=', + '^=', + '**', + '**=', + '<=>', + '??', + '??=', + ]; + + /** + * @var TokensAnalyzer + */ + private $tokensAnalyzer; + + /** + * @var array<string, string> + */ + private $alignOperatorTokens = []; + + /** + * @var array<string, string> + */ + private $operators = []; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + if ( + null !== $configuration + && (\array_key_exists('align_equals', $configuration) || \array_key_exists('align_double_arrow', $configuration)) + ) { + $configuration = $this->resolveOldConfig($configuration); + } + + parent::configure($configuration); + + $this->operators = $this->resolveOperatorsFromConfig(); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Binary operators should be surrounded by space as configured.', + [ + new CodeSample( + "<?php\n\$a= 1 + \$b^ \$d !== \$e or \$f;\n" + ), + new CodeSample( + '<?php +$aa= 1; +$b=2; + +$c = $d xor $e; +$f -= 1; +', + ['operators' => ['=' => 'align', 'xor' => null]] + ), + new CodeSample( + '<?php +$a = $b +=$c; +$d = $ee+=$f; + +$g = $b +=$c; +$h = $ee+=$f; +', + ['operators' => ['+=' => 'align_single_space']] + ), + new CodeSample( + '<?php +$a = $b===$c; +$d = $f === $g; +$h = $i=== $j; +', + ['operators' => ['===' => 'align_single_space_minimal']] + ), + new CodeSample( + '<?php +$foo = \json_encode($bar, JSON_PRESERVE_ZERO_FRACTION | JSON_PRETTY_PRINT); +', + ['operators' => ['|' => 'no_space']] + ), + new CodeSample( + '<?php +$array = [ + "foo" => 1, + "baaaaaaaaaaar" => 11, +]; +', + ['operators' => ['=>' => 'single_space']] + ), + new CodeSample( + '<?php +$array = [ + "foo" => 12, + "baaaaaaaaaaar" => 13, +]; +', + ['operators' => ['=>' => 'align']] + ), + new CodeSample( + '<?php +$array = [ + "foo" => 12, + "baaaaaaaaaaar" => 13, +]; +', + ['operators' => ['=>' => 'align_single_space']] + ), + new CodeSample( + '<?php +$array = [ + "foo" => 12, + "baaaaaaaaaaar" => 13, +]; +', + ['operators' => ['=>' => 'align_single_space_minimal']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after ArrayIndentationFixer, ArraySyntaxFixer, ListSyntaxFixer, NoMultilineWhitespaceAroundDoubleArrowFixer, NoUnsetCastFixer, PowToExponentiationFixer, StandardizeNotEqualsFixer, StrictComparisonFixer. + */ + public function getPriority() + { + return -32; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $this->tokensAnalyzer = new TokensAnalyzer($tokens); + + // last and first tokens cannot be an operator + for ($index = $tokens->count() - 2; $index > 0; --$index) { + if (!$this->tokensAnalyzer->isBinaryOperator($index)) { + continue; + } + + if ('=' === $tokens[$index]->getContent()) { + $isDeclare = $this->isEqualPartOfDeclareStatement($tokens, $index); + if (false === $isDeclare) { + $this->fixWhiteSpaceAroundOperator($tokens, $index); + } else { + $index = $isDeclare; // skip `declare(foo ==bar)`, see `declare_equal_normalize` + } + } else { + $this->fixWhiteSpaceAroundOperator($tokens, $index); + } + + // previous of binary operator is now never an operator / previous of declare statement cannot be an operator + --$index; + } + + if (\count($this->alignOperatorTokens)) { + $this->fixAlignment($tokens, $this->alignOperatorTokens); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('default', 'Default fix strategy.')) + ->setDefault(self::SINGLE_SPACE) + ->setAllowedValues(self::$allowedValues) + ->getOption(), + (new FixerOptionBuilder('operators', 'Dictionary of `binary operator` => `fix strategy` values that differ from the default strategy.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([static function ($option) { + foreach ($option as $operator => $value) { + if (!\in_array($operator, self::$supportedOperators, true)) { + throw new InvalidOptionsException( + sprintf( + 'Unexpected "operators" key, expected any of "%s", got "%s".', + implode('", "', self::$supportedOperators), + \is_object($operator) ? \get_class($operator) : \gettype($operator).'#'.$operator + ) + ); + } + + if (!\in_array($value, self::$allowedValues, true)) { + throw new InvalidOptionsException( + sprintf( + 'Unexpected value for operator "%s", expected any of "%s", got "%s".', + $operator, + implode('", "', self::$allowedValues), + \is_object($value) ? \get_class($value) : (null === $value ? 'null' : \gettype($value).'#'.$value) + ) + ); + } + } + + return true; + }]) + ->setDefault([]) + ->getOption(), + // add deprecated options as BC layer + (new FixerOptionBuilder('align_double_arrow', 'Whether to apply, remove or ignore double arrows alignment.')) + ->setDefault(false) + ->setAllowedValues([true, false, null]) + ->setDeprecationMessage('Use options `operators` and `default` instead.') + ->getOption(), + (new FixerOptionBuilder('align_equals', 'Whether to apply, remove or ignore equals alignment.')) + ->setDefault(false) + ->setAllowedValues([true, false, null]) + ->setDeprecationMessage('Use options `operators` and `default` instead.') + ->getOption(), + ]); + } + + /** + * @param int $index + */ + private function fixWhiteSpaceAroundOperator(Tokens $tokens, $index) + { + $tokenContent = strtolower($tokens[$index]->getContent()); + + if (!\array_key_exists($tokenContent, $this->operators)) { + return; // not configured to be changed + } + + if (self::SINGLE_SPACE === $this->operators[$tokenContent]) { + $this->fixWhiteSpaceAroundOperatorToSingleSpace($tokens, $index); + + return; + } + + if (self::NO_SPACE === $this->operators[$tokenContent]) { + $this->fixWhiteSpaceAroundOperatorToNoSpace($tokens, $index); + + return; + } + + // schedule for alignment + $this->alignOperatorTokens[$tokenContent] = $this->operators[$tokenContent]; + + if (self::ALIGN === $this->operators[$tokenContent]) { + return; + } + + // fix white space after operator + if ($tokens[$index + 1]->isWhitespace()) { + if (self::ALIGN_SINGLE_SPACE_MINIMAL === $this->operators[$tokenContent]) { + $tokens[$index + 1] = new Token([T_WHITESPACE, ' ']); + } + + return; + } + + $tokens->insertAt($index + 1, new Token([T_WHITESPACE, ' '])); + } + + /** + * @param int $index + */ + private function fixWhiteSpaceAroundOperatorToSingleSpace(Tokens $tokens, $index) + { + // fix white space after operator + if ($tokens[$index + 1]->isWhitespace()) { + $content = $tokens[$index + 1]->getContent(); + if (' ' !== $content && false === strpos($content, "\n") && !$tokens[$tokens->getNextNonWhitespace($index + 1)]->isComment()) { + $tokens[$index + 1] = new Token([T_WHITESPACE, ' ']); + } + } else { + $tokens->insertAt($index + 1, new Token([T_WHITESPACE, ' '])); + } + + // fix white space before operator + if ($tokens[$index - 1]->isWhitespace()) { + $content = $tokens[$index - 1]->getContent(); + if (' ' !== $content && false === strpos($content, "\n") && !$tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) { + $tokens[$index - 1] = new Token([T_WHITESPACE, ' ']); + } + } else { + $tokens->insertAt($index, new Token([T_WHITESPACE, ' '])); + } + } + + /** + * @param int $index + */ + private function fixWhiteSpaceAroundOperatorToNoSpace(Tokens $tokens, $index) + { + // fix white space after operator + if ($tokens[$index + 1]->isWhitespace()) { + $content = $tokens[$index + 1]->getContent(); + if (false === strpos($content, "\n") && !$tokens[$tokens->getNextNonWhitespace($index + 1)]->isComment()) { + $tokens->clearAt($index + 1); + } + } + + // fix white space before operator + if ($tokens[$index - 1]->isWhitespace()) { + $content = $tokens[$index - 1]->getContent(); + if (false === strpos($content, "\n") && !$tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) { + $tokens->clearAt($index - 1); + } + } + } + + /** + * @param int $index + * + * @return false|int index of T_DECLARE where the `=` belongs to or `false` + */ + private function isEqualPartOfDeclareStatement(Tokens $tokens, $index) + { + $prevMeaningfulIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prevMeaningfulIndex]->isGivenKind(T_STRING)) { + $prevMeaningfulIndex = $tokens->getPrevMeaningfulToken($prevMeaningfulIndex); + if ($tokens[$prevMeaningfulIndex]->equals('(')) { + $prevMeaningfulIndex = $tokens->getPrevMeaningfulToken($prevMeaningfulIndex); + if ($tokens[$prevMeaningfulIndex]->isGivenKind(T_DECLARE)) { + return $prevMeaningfulIndex; + } + } + } + + return false; + } + + /** + * @return array<string, string> + */ + private function resolveOperatorsFromConfig() + { + $operators = []; + + if (null !== $this->configuration['default']) { + foreach (self::$supportedOperators as $operator) { + $operators[$operator] = $this->configuration['default']; + } + } + + foreach ($this->configuration['operators'] as $operator => $value) { + if (null === $value) { + unset($operators[$operator]); + } else { + $operators[$operator] = $value; + } + } + + // @TODO: drop condition when PHP 7.0+ is required + if (!\defined('T_SPACESHIP')) { + unset($operators['<=>']); + } + + // @TODO: drop condition when PHP 7.0+ is required + if (!\defined('T_COALESCE')) { + unset($operators['??']); + } + + // @TODO: drop condition when PHP 7.4+ is required + if (!\defined('T_COALESCE_EQUAL')) { + unset($operators['??=']); + } + + return $operators; + } + + /** + * @return array + */ + private function resolveOldConfig(array $configuration) + { + $newConfig = [ + 'operators' => [], + ]; + + foreach ($configuration as $name => $setting) { + if ('align_double_arrow' === $name) { + if (true === $configuration[$name]) { + $newConfig['operators']['=>'] = self::ALIGN; + } elseif (false === $configuration[$name]) { + $newConfig['operators']['=>'] = self::SINGLE_SPACE; + } elseif (null !== $configuration[$name]) { + throw new InvalidFixerConfigurationException( + $this->getName(), + sprintf( + 'Invalid configuration: The option "align_double_arrow" with value %s is invalid. Accepted values are: true, false, null.', + $configuration[$name] + ) + ); + } + } elseif ('align_equals' === $name) { + if (true === $configuration[$name]) { + $newConfig['operators']['='] = self::ALIGN; + } elseif (false === $configuration[$name]) { + $newConfig['operators']['='] = self::SINGLE_SPACE; + } elseif (null !== $configuration[$name]) { + throw new InvalidFixerConfigurationException( + $this->getName(), + sprintf( + 'Invalid configuration: The option "align_equals" with value %s is invalid. Accepted values are: true, false, null.', + $configuration[$name] + ) + ); + } + } else { + throw new InvalidFixerConfigurationException($this->getName(), 'Mixing old configuration with new configuration is not allowed.'); + } + } + + Utils::triggerDeprecation(new InvalidFixerConfigurationException( + $this->getName(), + sprintf( + 'Given configuration is deprecated and will be removed in 3.0. Use configuration %s as replacement for %s.', + HelpCommand::toString($newConfig), + HelpCommand::toString($configuration) + ) + )); + + return $newConfig; + } + + // Alignment logic related methods + + /** + * @param array<string, string> $toAlign + */ + private function fixAlignment(Tokens $tokens, array $toAlign) + { + $this->deepestLevel = 0; + $this->currentLevel = 0; + + foreach ($toAlign as $tokenContent => $alignStrategy) { + // This fixer works partially on Tokens and partially on string representation of code. + // During the process of fixing internal state of single Token may be affected by injecting ALIGN_PLACEHOLDER to its content. + // The placeholder will be resolved by `replacePlaceholders` method by removing placeholder or changing it into spaces. + // That way of fixing the code causes disturbances in marking Token as changed - if code is perfectly valid then placeholder + // still be injected and removed, which will cause the `changed` flag to be set. + // To handle that unwanted behavior we work on clone of Tokens collection and then override original collection with fixed collection. + $tokensClone = clone $tokens; + + if ('=>' === $tokenContent) { + $this->injectAlignmentPlaceholdersForArrow($tokensClone, 0, \count($tokens)); + } else { + $this->injectAlignmentPlaceholders($tokensClone, 0, \count($tokens), $tokenContent); + } + + // for all tokens that should be aligned but do not have anything to align with, fix spacing if needed + if (self::ALIGN_SINGLE_SPACE === $alignStrategy || self::ALIGN_SINGLE_SPACE_MINIMAL === $alignStrategy) { + if ('=>' === $tokenContent) { + for ($index = $tokens->count() - 2; $index > 0; --$index) { + if ($tokens[$index]->isGivenKind(T_DOUBLE_ARROW)) { // always binary operator, never part of declare statement + $this->fixWhiteSpaceBeforeOperator($tokensClone, $index, $alignStrategy); + } + } + } elseif ('=' === $tokenContent) { + for ($index = $tokens->count() - 2; $index > 0; --$index) { + if ('=' === $tokens[$index]->getContent() && !$this->isEqualPartOfDeclareStatement($tokens, $index) && $this->tokensAnalyzer->isBinaryOperator($index)) { + $this->fixWhiteSpaceBeforeOperator($tokensClone, $index, $alignStrategy); + } + } + } else { + for ($index = $tokens->count() - 2; $index > 0; --$index) { + $content = $tokens[$index]->getContent(); + if (strtolower($content) === $tokenContent && $this->tokensAnalyzer->isBinaryOperator($index)) { // never part of declare statement + $this->fixWhiteSpaceBeforeOperator($tokensClone, $index, $alignStrategy); + } + } + } + } + + $tokens->setCode($this->replacePlaceholders($tokensClone, $alignStrategy)); + } + } + + /** + * @param int $startAt + * @param int $endAt + * @param string $tokenContent + */ + private function injectAlignmentPlaceholders(Tokens $tokens, $startAt, $endAt, $tokenContent) + { + for ($index = $startAt; $index < $endAt; ++$index) { + $token = $tokens[$index]; + + $content = $token->getContent(); + if ( + strtolower($content) === $tokenContent + && $this->tokensAnalyzer->isBinaryOperator($index) + && ('=' !== $content || !$this->isEqualPartOfDeclareStatement($tokens, $index)) + ) { + $tokens[$index] = new Token(sprintf(self::ALIGN_PLACEHOLDER, $this->deepestLevel).$content); + + continue; + } + + if ($token->isGivenKind(T_FUNCTION)) { + ++$this->deepestLevel; + + continue; + } + + if ($token->equals('(')) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + + continue; + } + + if ($token->equals('[')) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE, $index); + + continue; + } + + if ($token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $index); + + continue; + } + } + } + + /** + * @param int $startAt + * @param int $endAt + */ + private function injectAlignmentPlaceholdersForArrow(Tokens $tokens, $startAt, $endAt) + { + for ($index = $startAt; $index < $endAt; ++$index) { + $token = $tokens[$index]; + + if ($token->isGivenKind([T_FOREACH, T_FOR, T_WHILE, T_IF, T_SWITCH])) { + $index = $tokens->getNextMeaningfulToken($index); + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + + continue; + } + + if ($token->isGivenKind(T_ARRAY)) { // don't use "$tokens->isArray()" here, short arrays are handled in the next case + $from = $tokens->getNextMeaningfulToken($index); + $until = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $from); + $index = $until; + + $this->injectArrayAlignmentPlaceholders($tokens, $from + 1, $until - 1); + + continue; + } + + if ($token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { + $from = $index; + $until = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $from); + $index = $until; + + $this->injectArrayAlignmentPlaceholders($tokens, $from + 1, $until - 1); + + continue; + } + + if ($token->isGivenKind(T_DOUBLE_ARROW)) { // no need to analyze for `isBinaryOperator` (always true), nor if part of declare statement (not valid PHP) + $tokenContent = sprintf(self::ALIGN_PLACEHOLDER, $this->currentLevel).$token->getContent(); + + $nextToken = $tokens[$index + 1]; + if (!$nextToken->isWhitespace()) { + $tokenContent .= ' '; + } elseif ($nextToken->isWhitespace(" \t")) { + $tokens[$index + 1] = new Token([T_WHITESPACE, ' ']); + } + + $tokens[$index] = new Token([T_DOUBLE_ARROW, $tokenContent]); + + continue; + } + + if ($token->equals(';')) { + ++$this->deepestLevel; + ++$this->currentLevel; + + continue; + } + + if ($token->equals(',')) { + for ($i = $index; $i < $endAt - 1; ++$i) { + if (false !== strpos($tokens[$i - 1]->getContent(), "\n")) { + break; + } + + if ($tokens[$i + 1]->isGivenKind([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN])) { + $arrayStartIndex = $tokens[$i + 1]->isGivenKind(T_ARRAY) + ? $tokens->getNextMeaningfulToken($i + 1) + : $i + 1 + ; + $blockType = Tokens::detectBlockType($tokens[$arrayStartIndex]); + $arrayEndIndex = $tokens->findBlockEnd($blockType['type'], $arrayStartIndex); + + if ($tokens->isPartialCodeMultiline($arrayStartIndex, $arrayEndIndex)) { + break; + } + } + + ++$index; + } + } + } + } + + /** + * @param int $from + * @param int $until + */ + private function injectArrayAlignmentPlaceholders(Tokens $tokens, $from, $until) + { + // Only inject placeholders for multi-line arrays + if ($tokens->isPartialCodeMultiline($from, $until)) { + ++$this->deepestLevel; + ++$this->currentLevel; + $this->injectAlignmentPlaceholdersForArrow($tokens, $from, $until); + --$this->currentLevel; + } + } + + /** + * @param int $index + * @param string $alignStrategy + */ + private function fixWhiteSpaceBeforeOperator(Tokens $tokens, $index, $alignStrategy) + { + // fix white space after operator is not needed as BinaryOperatorSpacesFixer took care of this (if strategy is _not_ ALIGN) + if (!$tokens[$index - 1]->isWhitespace()) { + $tokens->insertAt($index, new Token([T_WHITESPACE, ' '])); + + return; + } + + if (self::ALIGN_SINGLE_SPACE_MINIMAL !== $alignStrategy || $tokens[$tokens->getPrevNonWhitespace($index - 1)]->isComment()) { + return; + } + + $content = $tokens[$index - 1]->getContent(); + if (' ' !== $content && false === strpos($content, "\n")) { + $tokens[$index - 1] = new Token([T_WHITESPACE, ' ']); + } + } + + /** + * Look for group of placeholders and provide vertical alignment. + * + * @param string $alignStrategy + * + * @return string + */ + private function replacePlaceholders(Tokens $tokens, $alignStrategy) + { + $tmpCode = $tokens->generateCode(); + + for ($j = 0; $j <= $this->deepestLevel; ++$j) { + $placeholder = sprintf(self::ALIGN_PLACEHOLDER, $j); + + if (false === strpos($tmpCode, $placeholder)) { + continue; + } + + $lines = explode("\n", $tmpCode); + $groups = []; + $groupIndex = 0; + $groups[$groupIndex] = []; + + foreach ($lines as $index => $line) { + if (substr_count($line, $placeholder) > 0) { + $groups[$groupIndex][] = $index; + } else { + ++$groupIndex; + $groups[$groupIndex] = []; + } + } + + foreach ($groups as $group) { + if (\count($group) < 1) { + continue; + } + + if (self::ALIGN !== $alignStrategy) { + // move place holders to match strategy + foreach ($group as $index) { + $currentPosition = strpos($lines[$index], $placeholder); + $before = substr($lines[$index], 0, $currentPosition); + + if (self::ALIGN_SINGLE_SPACE === $alignStrategy) { + if (1 > \strlen($before) || ' ' !== substr($before, -1)) { // if last char of before-content is not ' '; add it + $before .= ' '; + } + } elseif (self::ALIGN_SINGLE_SPACE_MINIMAL === $alignStrategy) { + if (1 !== Preg::match('/^\h+$/', $before)) { // if indent; do not move, leave to other fixer + $before = rtrim($before).' '; + } + } + + $lines[$index] = $before.substr($lines[$index], $currentPosition); + } + } + + $rightmostSymbol = 0; + foreach ($group as $index) { + $rightmostSymbol = max($rightmostSymbol, strpos(utf8_decode($lines[$index]), $placeholder)); + } + + foreach ($group as $index) { + $line = $lines[$index]; + $currentSymbol = strpos(utf8_decode($line), $placeholder); + $delta = abs($rightmostSymbol - $currentSymbol); + + if ($delta > 0) { + $line = str_replace($placeholder, str_repeat(' ', $delta).$placeholder, $line); + $lines[$index] = $line; + } + } + } + + $tmpCode = str_replace($placeholder, '', implode("\n", $lines)); + } + + return $tmpCode; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/ConcatSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/ConcatSpaceFixer.php new file mode 100644 index 0000000..015828c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/ConcatSpaceFixer.php @@ -0,0 +1,164 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +final class ConcatSpaceFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var null|string + */ + private $fixCallback; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + if ('one' === $this->configuration['spacing']) { + $this->fixCallback = 'fixConcatenationToSingleSpace'; + } else { + $this->fixCallback = 'fixConcatenationToNoSpace'; + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Concatenation should be spaced according configuration.', + [ + new CodeSample( + "<?php\n\$foo = 'bar' . 3 . 'baz'.'qux';\n" + ), + new CodeSample( + "<?php\n\$foo = 'bar' . 3 . 'baz'.'qux';\n", + ['spacing' => 'none'] + ), + new CodeSample( + "<?php\n\$foo = 'bar' . 3 . 'baz'.'qux';\n", + ['spacing' => 'one'] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after SingleLineThrowFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound('.'); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $callBack = $this->fixCallback; + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + if ($tokens[$index]->equals('.')) { + $this->{$callBack}($tokens, $index); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('spacing', 'Spacing to apply around concatenation operator.')) + ->setAllowedValues(['one', 'none']) + ->setDefault('none') + ->getOption(), + ]); + } + + /** + * @param int $index index of concatenation '.' token + */ + private function fixConcatenationToNoSpace(Tokens $tokens, $index) + { + $prevNonWhitespaceToken = $tokens[$tokens->getPrevNonWhitespace($index)]; + if (!$prevNonWhitespaceToken->isGivenKind([T_LNUMBER, T_COMMENT, T_DOC_COMMENT]) || '/*' === substr($prevNonWhitespaceToken->getContent(), 0, 2)) { + $tokens->removeLeadingWhitespace($index, " \t"); + } + + if (!$tokens[$tokens->getNextNonWhitespace($index)]->isGivenKind([T_LNUMBER, T_COMMENT, T_DOC_COMMENT])) { + $tokens->removeTrailingWhitespace($index, " \t"); + } + } + + /** + * @param int $index index of concatenation '.' token + */ + private function fixConcatenationToSingleSpace(Tokens $tokens, $index) + { + $this->fixWhiteSpaceAroundConcatToken($tokens, $index, 1); + $this->fixWhiteSpaceAroundConcatToken($tokens, $index, -1); + } + + /** + * @param int $index index of concatenation '.' token + * @param int $offset 1 or -1 + */ + private function fixWhiteSpaceAroundConcatToken(Tokens $tokens, $index, $offset) + { + $offsetIndex = $index + $offset; + + if (!$tokens[$offsetIndex]->isWhitespace()) { + $tokens->insertAt($index + (1 === $offset ?: 0), new Token([T_WHITESPACE, ' '])); + + return; + } + + if (false !== strpos($tokens[$offsetIndex]->getContent(), "\n")) { + return; + } + + if ($tokens[$index + $offset * 2]->isComment()) { + return; + } + + $tokens[$offsetIndex] = new Token([T_WHITESPACE, ' ']); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/IncrementStyleFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/IncrementStyleFixer.php new file mode 100644 index 0000000..d517ed0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/IncrementStyleFixer.php @@ -0,0 +1,174 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\Fixer\AbstractIncrementOperatorFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Gregor Harlan <gharlan@web.de> + * @author Kuba Werłos <werlos@gmail.com> + */ +final class IncrementStyleFixer extends AbstractIncrementOperatorFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @internal + */ + const STYLE_PRE = 'pre'; + + /** + * @internal + */ + const STYLE_POST = 'post'; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Pre- or post-increment and decrement operators should be used if possible.', + [ + new CodeSample("<?php\n\$a++;\n\$b--;\n"), + new CodeSample( + "<?php\n++\$a;\n--\$b;\n", + ['style' => self::STYLE_POST] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after StandardizeIncrementFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_INC, T_DEC]); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('style', 'Whether to use pre- or post-increment and decrement operators.')) + ->setAllowedValues([self::STYLE_PRE, self::STYLE_POST]) + ->setDefault(self::STYLE_PRE) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind([T_INC, T_DEC])) { + continue; + } + + if (self::STYLE_PRE === $this->configuration['style'] && $tokensAnalyzer->isUnarySuccessorOperator($index)) { + $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)]; + if (!$nextToken->equalsAny([';', ')'])) { + continue; + } + + $startIndex = $this->findStart($tokens, $index); + + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($startIndex)]; + if ($prevToken->equalsAny([';', '{', '}', [T_OPEN_TAG], ')'])) { + $tokens->clearAt($index); + $tokens->insertAt($startIndex, clone $token); + } + } elseif (self::STYLE_POST === $this->configuration['style'] && $tokensAnalyzer->isUnaryPredecessorOperator($index)) { + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; + if (!$prevToken->equalsAny([';', '{', '}', [T_OPEN_TAG], ')'])) { + continue; + } + + $endIndex = $this->findEnd($tokens, $index); + + $nextToken = $tokens[$tokens->getNextMeaningfulToken($endIndex)]; + if ($nextToken->equalsAny([';', ')'])) { + $tokens->clearAt($index); + $tokens->insertAt($tokens->getNextNonWhitespace($endIndex), clone $token); + } + } + } + } + + /** + * @param int $index + * + * @return int + */ + private function findEnd(Tokens $tokens, $index) + { + $nextIndex = $tokens->getNextMeaningfulToken($index); + $nextToken = $tokens[$nextIndex]; + + while ($nextToken->equalsAny([ + '$', + '(', + '[', + [CT::T_DYNAMIC_PROP_BRACE_OPEN], + [CT::T_DYNAMIC_VAR_BRACE_OPEN], + [CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN], + [T_NS_SEPARATOR], + [T_STATIC], + [T_STRING], + [T_VARIABLE], + ])) { + $blockType = Tokens::detectBlockType($nextToken); + if (null !== $blockType) { + $nextIndex = $tokens->findBlockEnd($blockType['type'], $nextIndex); + } + $index = $nextIndex; + $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); + $nextToken = $tokens[$nextIndex]; + } + + if ($nextToken->isObjectOperator()) { + return $this->findEnd($tokens, $nextIndex); + } + + if ($nextToken->isGivenKind(T_PAAMAYIM_NEKUDOTAYIM)) { + return $this->findEnd($tokens, $tokens->getNextMeaningfulToken($nextIndex)); + } + + return $index; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/LogicalOperatorsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/LogicalOperatorsFixer.php new file mode 100644 index 0000000..30d4fc3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/LogicalOperatorsFixer.php @@ -0,0 +1,76 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Haralan Dobrev <hkdobrev@gmail.com> + */ +final class LogicalOperatorsFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Use `&&` and `||` logical operators instead of `and` and `or`.', + [ + new CodeSample( + '<?php + +if ($a == "foo" and ($b == "bar" or $c == "baz")) { +} +' + ), + ], + null, + 'Risky, because you must double-check if using and/or with lower precedence was intentional.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_LOGICAL_AND, T_LOGICAL_OR]); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if ($token->isGivenKind(T_LOGICAL_AND)) { + $tokens[$index] = new Token([T_BOOLEAN_AND, '&&']); + } elseif ($token->isGivenKind(T_LOGICAL_OR)) { + $tokens[$index] = new Token([T_BOOLEAN_OR, '||']); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NewWithBracesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NewWithBracesFixer.php similarity index 50% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NewWithBracesFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NewWithBracesFixer.php index 0c37518..50473fb 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/NewWithBracesFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NewWithBracesFixer.php @@ -10,26 +10,48 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Symfony; +namespace PhpCsFixer\Fixer\Operator; -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Token; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; /** * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> */ -class NewWithBracesFixer extends AbstractFixer +final class NewWithBracesFixer extends AbstractFixer { /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function getDefinition() + { + return new FixerDefinition( + 'All instances created with new keyword must be followed by braces.', + [new CodeSample("<?php \$x = new X;\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_NEW); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) { static $nextTokenKinds = null; if (null === $nextTokenKinds) { - $nextTokenKinds = array( + $nextTokenKinds = [ '?', ';', ',', @@ -48,37 +70,37 @@ public function fix(\SplFileInfo $file, $content) '&', '^', '|', - array(T_CLASS), - array(T_IS_SMALLER_OR_EQUAL), - array(T_IS_GREATER_OR_EQUAL), - array(T_IS_EQUAL), - array(T_IS_NOT_EQUAL), - array(T_IS_IDENTICAL), - array(T_IS_NOT_IDENTICAL), - array(T_CLOSE_TAG), - array(T_LOGICAL_AND), - array(T_LOGICAL_OR), - array(T_LOGICAL_XOR), - array(T_BOOLEAN_AND), - array(T_BOOLEAN_OR), - array(T_SL), - array(T_SR), - array(T_INSTANCEOF), - array(T_AS), - array(T_DOUBLE_ARROW), - ); - - if (defined('T_POW')) { - $nextTokenKinds[] = array(T_POW); - } - - if (defined('T_SPACESHIP')) { - $nextTokenKinds[] = array(T_SPACESHIP); + [T_CLASS], + [T_IS_SMALLER_OR_EQUAL], + [T_IS_GREATER_OR_EQUAL], + [T_IS_EQUAL], + [T_IS_NOT_EQUAL], + [T_IS_IDENTICAL], + [T_IS_NOT_IDENTICAL], + [T_CLOSE_TAG], + [T_LOGICAL_AND], + [T_LOGICAL_OR], + [T_LOGICAL_XOR], + [T_BOOLEAN_AND], + [T_BOOLEAN_OR], + [T_SL], + [T_SR], + [T_INSTANCEOF], + [T_AS], + [T_DOUBLE_ARROW], + [T_POW], + [CT::T_ARRAY_SQUARE_BRACE_OPEN], + [CT::T_ARRAY_SQUARE_BRACE_CLOSE], + [CT::T_BRACE_CLASS_INSTANTIATION_OPEN], + [CT::T_BRACE_CLASS_INSTANTIATION_CLOSE], + ]; + + // @TODO: drop condition when PHP 7.0+ is required + if (\defined('T_SPACESHIP')) { + $nextTokenKinds[] = [T_SPACESHIP]; } } - $tokens = Tokens::fromCode($content); - for ($index = $tokens->count() - 3; $index > 0; --$index) { $token = $tokens[$index]; @@ -99,42 +121,31 @@ public function fix(\SplFileInfo $file, $content) } // entrance into array index syntax - need to look for exit - while ($nextToken->equals('[')) { - $nextIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_SQUARE_BRACE, $nextIndex) + 1; + while ($nextToken->equals('[') || $nextToken->isGivenKind(CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN)) { + $nextIndex = $tokens->findBlockEnd($tokens->detectBlockType($nextToken)['type'], $nextIndex) + 1; $nextToken = $tokens[$nextIndex]; } // new statement has a gap in it - advance to the next token - if ($nextToken->isGivenKind(T_WHITESPACE)) { + if ($nextToken->isWhitespace()) { $nextIndex = $tokens->getNextNonWhitespace($nextIndex); $nextToken = $tokens[$nextIndex]; } // new statement with () - nothing to do - if ($nextToken->equals('(')) { + if ($nextToken->equals('(') || $nextToken->isObjectOperator()) { continue; } $this->insertBracesAfter($tokens, $tokens->getPrevMeaningfulToken($nextIndex)); } - - return $tokens->generateCode(); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return 'All instances created with new keyword must be followed by braces.'; } /** - * @param Tokens $tokens - * @param int $index + * @param int $index */ private function insertBracesAfter(Tokens $tokens, $index) { - $tokens->insertAt(++$index, array(new Token('('), new Token(')'))); + $tokens->insertAt(++$index, [new Token('('), new Token(')')]); } } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NotOperatorWithSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NotOperatorWithSpaceFixer.php new file mode 100644 index 0000000..d1beb31 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NotOperatorWithSpaceFixer.php @@ -0,0 +1,81 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Javier Spagnoletti <phansys@gmail.com> + */ +final class NotOperatorWithSpaceFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Logical NOT operators (`!`) should have leading and trailing whitespaces.', + [new CodeSample( + '<?php + +if (!$bar) { + echo "Help!"; +} +' + )] + ); + } + + /** + * {@inheritdoc} + * + * Must run after UnaryOperatorSpacesFixer. + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound('!'); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if ($token->equals('!')) { + if (!$tokens[$index + 1]->isWhitespace()) { + $tokens->insertAt($index + 1, new Token([T_WHITESPACE, ' '])); + } + + if (!$tokens[$index - 1]->isWhitespace()) { + $tokens->insertAt($index, new Token([T_WHITESPACE, ' '])); + } + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NotOperatorWithSuccessorSpaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NotOperatorWithSuccessorSpaceFixer.php new file mode 100644 index 0000000..feb1b8c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/NotOperatorWithSuccessorSpaceFixer.php @@ -0,0 +1,79 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Javier Spagnoletti <phansys@gmail.com> + */ +final class NotOperatorWithSuccessorSpaceFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Logical NOT operators (`!`) should have one trailing whitespace.', + [new CodeSample( + '<?php + +if (!$bar) { + echo "Help!"; +} +' + )] + ); + } + + /** + * {@inheritdoc} + * + * Must run after UnaryOperatorSpacesFixer. + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound('!'); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + + if ($token->equals('!')) { + if (!$tokens[$index + 1]->isWhitespace()) { + $tokens->insertAt($index + 1, new Token([T_WHITESPACE, ' '])); + } else { + $tokens[$index + 1] = new Token([T_WHITESPACE, ' ']); + } + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/ObjectOperatorWithoutWhitespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/ObjectOperatorWithoutWhitespaceFixer.php new file mode 100644 index 0000000..a9e5d12 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/ObjectOperatorWithoutWhitespaceFixer.php @@ -0,0 +1,68 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class ObjectOperatorWithoutWhitespaceFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There should not be space before or after object operators `->` and `?->`.', + [new CodeSample("<?php \$a -> b;\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getObjectOperatorKinds()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // [Structure] there should not be space before or after "->" or "?->" + foreach ($tokens as $index => $token) { + if (!$token->isObjectOperator()) { + continue; + } + + // clear whitespace before -> + if ($tokens[$index - 1]->isWhitespace(" \t") && !$tokens[$index - 2]->isComment()) { + $tokens->clearAt($index - 1); + } + + // clear whitespace after -> + if ($tokens[$index + 1]->isWhitespace(" \t") && !$tokens[$index + 2]->isComment()) { + $tokens->clearAt($index + 1); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/OperatorLinebreakFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/OperatorLinebreakFixer.php new file mode 100644 index 0000000..7eaf170 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/OperatorLinebreakFixer.php @@ -0,0 +1,329 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\CaseAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\GotoLabelAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\ReferenceAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\SwitchAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Kuba Werłos <werlos@gmail.com> + */ +final class OperatorLinebreakFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @internal + */ + const BOOLEAN_OPERATORS = [[T_BOOLEAN_AND], [T_BOOLEAN_OR], [T_LOGICAL_AND], [T_LOGICAL_OR], [T_LOGICAL_XOR]]; + + /** + * @var string + */ + private $position = 'beginning'; + + /** + * @var array<array<int|string>|string> + */ + private $operators = []; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Operators - when multiline - must always be at the beginning or at the end of the line.', + [ + new CodeSample('<?php +function foo() { + return $bar || + $baz; +} +'), + new CodeSample( + '<?php +function foo() { + return $bar + || $baz; +} +', + ['position' => 'end'] + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->operators = self::BOOLEAN_OPERATORS; + if (!$this->configuration['only_booleans']) { + $this->operators = array_merge($this->operators, self::getNonBooleanOperators()); + if (\PHP_VERSION_ID >= 70000) { + $this->operators[] = [T_COALESCE]; + $this->operators[] = [T_SPACESHIP]; + } + } + $this->position = $this->configuration['position']; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('only_booleans', 'whether to limit operators to only boolean ones')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + (new FixerOptionBuilder('position', 'whether to place operators at the beginning or at the end of the line')) + ->setAllowedValues(['beginning', 'end']) + ->setDefault($this->position) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $referenceAnalyzer = new ReferenceAnalyzer(); + $gotoLabelAnalyzer = new GotoLabelAnalyzer(); + + $excludedIndices = $this->getExcludedIndices($tokens); + + $index = $tokens->count(); + while ($index > 1) { + --$index; + + if (!$tokens[$index]->equalsAny($this->operators, false)) { + continue; + } + + if ($gotoLabelAnalyzer->belongsToGoToLabel($tokens, $index)) { + continue; + } + + if ($referenceAnalyzer->isReference($tokens, $index)) { + continue; + } + + if (\in_array($index, $excludedIndices, true)) { + continue; + } + + $operatorIndices = [$index]; + if ($tokens[$index]->equals(':')) { + /** @var int $prevIndex */ + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prevIndex]->equals('?')) { + $operatorIndices = [$prevIndex, $index]; + $index = $prevIndex; + } + } + + $this->fixOperatorLinebreak($tokens, $operatorIndices); + } + } + + /** + * Currently only colons from "switch". + * + * @return int[] + */ + private function getExcludedIndices(Tokens $tokens) + { + $indices = []; + for ($index = $tokens->count() - 1; $index > 0; --$index) { + if ($tokens[$index]->isGivenKind(T_SWITCH)) { + $indices = array_merge($indices, $this->getCasesColonsForSwitch($tokens, $index)); + } + } + + return $indices; + } + + /** + * @param int $switchIndex + * + * @return int[] + */ + private function getCasesColonsForSwitch(Tokens $tokens, $switchIndex) + { + return array_map( + static function (CaseAnalysis $caseAnalysis) { + return $caseAnalysis->getColonIndex(); + }, + (new SwitchAnalyzer())->getSwitchAnalysis($tokens, $switchIndex)->getCases() + ); + } + + /** + * @param int[] $operatorIndices + */ + private function fixOperatorLinebreak(Tokens $tokens, array $operatorIndices) + { + /** @var int $prevIndex */ + $prevIndex = $tokens->getPrevMeaningfulToken(min($operatorIndices)); + $indexStart = $prevIndex + 1; + + /** @var int $nextIndex */ + $nextIndex = $tokens->getNextMeaningfulToken(max($operatorIndices)); + $indexEnd = $nextIndex - 1; + + if (!$this->isMultiline($tokens, $indexStart, $indexEnd)) { + return; // operator is not surrounded by multiline whitespaces, do not touch it + } + + if ('beginning' === $this->position) { + if (!$this->isMultiline($tokens, max($operatorIndices), $indexEnd)) { + return; // operator already is placed correctly + } + $this->fixMoveToTheBeginning($tokens, $operatorIndices); + + return; + } + + if (!$this->isMultiline($tokens, $indexStart, min($operatorIndices))) { + return; // operator already is placed correctly + } + $this->fixMoveToTheEnd($tokens, $operatorIndices); + } + + /** + * @param int[] $operatorIndices + */ + private function fixMoveToTheBeginning(Tokens $tokens, array $operatorIndices) + { + /** @var int $prevIndex */ + $prevIndex = $tokens->getNonEmptySibling(min($operatorIndices), -1); + + /** @var int $nextIndex */ + $nextIndex = $tokens->getNextMeaningfulToken(max($operatorIndices)); + + for ($i = $nextIndex - 1; $i > max($operatorIndices); --$i) { + if ($tokens[$i]->isWhitespace() && 1 === Preg::match('/\R/u', $tokens[$i]->getContent())) { + $isWhitespaceBefore = $tokens[$prevIndex]->isWhitespace(); + $inserts = $this->getReplacementsAndClear($tokens, $operatorIndices, -1); + if ($isWhitespaceBefore) { + $inserts[] = new Token([T_WHITESPACE, ' ']); + } + $tokens->insertAt($nextIndex, $inserts); + + break; + } + } + } + + /** + * @param int[] $operatorIndices + */ + private function fixMoveToTheEnd(Tokens $tokens, array $operatorIndices) + { + /** @var int $prevIndex */ + $prevIndex = $tokens->getPrevMeaningfulToken(min($operatorIndices)); + + /** @var int $nextIndex */ + $nextIndex = $tokens->getNonEmptySibling(max($operatorIndices), 1); + + for ($i = $prevIndex + 1; $i < max($operatorIndices); ++$i) { + if ($tokens[$i]->isWhitespace() && 1 === Preg::match('/\R/u', $tokens[$i]->getContent())) { + $isWhitespaceAfter = $tokens[$nextIndex]->isWhitespace(); + $inserts = $this->getReplacementsAndClear($tokens, $operatorIndices, 1); + if ($isWhitespaceAfter) { + array_unshift($inserts, new Token([T_WHITESPACE, ' '])); + } + $tokens->insertAt($prevIndex + 1, $inserts); + + break; + } + } + } + + /** + * @param int[] $indices + * @param int $direction + * + * @return Token[] + */ + private function getReplacementsAndClear(Tokens $tokens, array $indices, $direction) + { + return array_map( + static function ($index) use ($tokens, $direction) { + $clone = $tokens[$index]; + if ($tokens[$index + $direction]->isWhitespace()) { + $tokens->clearAt($index + $direction); + } + $tokens->clearAt($index); + + return $clone; + }, + $indices + ); + } + + /** + * @param int $indexStart + * @param int $indexEnd + * + * @return bool + */ + private function isMultiline(Tokens $tokens, $indexStart, $indexEnd) + { + for ($index = $indexStart; $index <= $indexEnd; ++$index) { + if (false !== strpos($tokens[$index]->getContent(), "\n")) { + return true; + } + } + + return false; + } + + private static function getNonBooleanOperators() + { + return array_merge( + [ + '%', '&', '*', '+', '-', '.', '/', ':', '<', '=', '>', '?', '^', '|', + [T_AND_EQUAL], [T_CONCAT_EQUAL], [T_DIV_EQUAL], [T_DOUBLE_ARROW], [T_IS_EQUAL], [T_IS_GREATER_OR_EQUAL], + [T_IS_IDENTICAL], [T_IS_NOT_EQUAL], [T_IS_NOT_IDENTICAL], [T_IS_SMALLER_OR_EQUAL], [T_MINUS_EQUAL], + [T_MOD_EQUAL], [T_MUL_EQUAL], [T_OR_EQUAL], [T_PAAMAYIM_NEKUDOTAYIM], [T_PLUS_EQUAL], [T_POW], + [T_POW_EQUAL], [T_SL], [T_SL_EQUAL], [T_SR], [T_SR_EQUAL], [T_XOR_EQUAL], + ], + array_map(function ($id) { return [$id]; }, Token::getObjectOperatorKinds()) + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/PreIncrementFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/PreIncrementFixer.php new file mode 100644 index 0000000..04b94b6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/PreIncrementFixer.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author Gregor Harlan <gharlan@web.de> + * + * @deprecated in 2.8, proxy to IncrementStyleFixer + */ +final class PreIncrementFixer extends AbstractProxyFixer implements DeprecatedFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Pre incrementation/decrementation should be used if possible.', + [new CodeSample("<?php\n\$a++;\n\$b--;\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + $fixer = new IncrementStyleFixer(); + $fixer->configure(['style' => 'pre']); + + return [$fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/StandardizeIncrementFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/StandardizeIncrementFixer.php new file mode 100644 index 0000000..9a6ca2a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/StandardizeIncrementFixer.php @@ -0,0 +1,133 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\Fixer\AbstractIncrementOperatorFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author ntzm + */ +final class StandardizeIncrementFixer extends AbstractIncrementOperatorFixer +{ + /** + * @internal + */ + const EXPRESSION_END_TOKENS = [ + ';', + ')', + ']', + ',', + ':', + [CT::T_DYNAMIC_PROP_BRACE_CLOSE], + [CT::T_DYNAMIC_VAR_BRACE_CLOSE], + [T_CLOSE_TAG], + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Increment and decrement operators should be used if possible.', + [ + new CodeSample("<?php\n\$i += 1;\n"), + new CodeSample("<?php\n\$i -= 1;\n"), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before IncrementStyleFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_PLUS_EQUAL, T_MINUS_EQUAL]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; $index > 0; --$index) { + $expressionEnd = $tokens[$index]; + if (!$expressionEnd->equalsAny(self::EXPRESSION_END_TOKENS)) { + continue; + } + + $numberIndex = $tokens->getPrevMeaningfulToken($index); + $number = $tokens[$numberIndex]; + if (!$number->isGivenKind(T_LNUMBER) || '1' !== $number->getContent()) { + continue; + } + + $operatorIndex = $tokens->getPrevMeaningfulToken($numberIndex); + $operator = $tokens[$operatorIndex]; + if (!$operator->isGivenKind([T_PLUS_EQUAL, T_MINUS_EQUAL])) { + continue; + } + + $startIndex = $this->findStart($tokens, $operatorIndex); + + $this->clearRangeLeaveComments( + $tokens, + $tokens->getPrevMeaningfulToken($operatorIndex) + 1, + $numberIndex + ); + + $tokens->insertAt( + $startIndex, + new Token($operator->isGivenKind(T_PLUS_EQUAL) ? [T_INC, '++'] : [T_DEC, '--']) + ); + } + } + + /** + * Clear tokens in the given range unless they are comments. + * + * @param int $indexStart + * @param int $indexEnd + */ + private function clearRangeLeaveComments(Tokens $tokens, $indexStart, $indexEnd) + { + for ($i = $indexStart; $i <= $indexEnd; ++$i) { + $token = $tokens[$i]; + + if ($token->isComment()) { + continue; + } + + if ($token->isWhitespace("\n\r")) { + continue; + } + + $tokens->clearAt($i); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/StandardizeNotEqualsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/StandardizeNotEqualsFixer.php new file mode 100644 index 0000000..d240e33 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/StandardizeNotEqualsFixer.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class StandardizeNotEqualsFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replace all `<>` with `!=`.', + [new CodeSample("<?php\n\$a = \$b <> \$c;\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BinaryOperatorSpacesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_IS_NOT_EQUAL); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if ($token->isGivenKind(T_IS_NOT_EQUAL)) { + $tokens[$index] = new Token([T_IS_NOT_EQUAL, '!=']); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryOperatorSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryOperatorSpacesFixer.php new file mode 100644 index 0000000..b591580 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryOperatorSpacesFixer.php @@ -0,0 +1,188 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\CaseAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\GotoLabelAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\SwitchAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class TernaryOperatorSpacesFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Standardize spaces around ternary operator.', + [new CodeSample("<?php \$a = \$a ?1 :0;\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run after ArraySyntaxFixer, ListSyntaxFixer, TernaryToElvisOperatorFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound(['?', ':']); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $gotoLabelAnalyzer = new GotoLabelAnalyzer(); + $ternaryOperatorIndices = []; + $excludedIndices = []; + + foreach ($tokens as $index => $token) { + if ($token->isGivenKind(T_SWITCH)) { + $excludedIndices = array_merge($excludedIndices, $this->getColonIndicesForSwitch($tokens, $index)); + + continue; + } + + if (!$token->equalsAny(['?', ':'])) { + continue; + } + + if (\in_array($index, $excludedIndices, true)) { + continue; + } + + if ($this->belongsToAlternativeSyntax($tokens, $index)) { + continue; + } + + if ($gotoLabelAnalyzer->belongsToGoToLabel($tokens, $index)) { + continue; + } + + $ternaryOperatorIndices[] = $index; + } + + foreach (array_reverse($ternaryOperatorIndices) as $index) { + $token = $tokens[$index]; + + if ($token->equals('?')) { + $nextNonWhitespaceIndex = $tokens->getNextNonWhitespace($index); + + if ($tokens[$nextNonWhitespaceIndex]->equals(':')) { + // for `$a ?: $b` remove spaces between `?` and `:` + $tokens->ensureWhitespaceAtIndex($index + 1, 0, ''); + } else { + // for `$a ? $b : $c` ensure space after `?` + $this->ensureWhitespaceExistence($tokens, $index + 1, true); + } + + // for `$a ? $b : $c` ensure space before `?` + $this->ensureWhitespaceExistence($tokens, $index - 1, false); + + continue; + } + + if ($token->equals(':')) { + // for `$a ? $b : $c` ensure space after `:` + $this->ensureWhitespaceExistence($tokens, $index + 1, true); + + $prevNonWhitespaceToken = $tokens[$tokens->getPrevNonWhitespace($index)]; + + if (!$prevNonWhitespaceToken->equals('?')) { + // for `$a ? $b : $c` ensure space before `:` + $this->ensureWhitespaceExistence($tokens, $index - 1, false); + } + } + } + } + + /** + * @param int $index + * + * @return bool + */ + private function belongsToAlternativeSyntax(Tokens $tokens, $index) + { + if (!$tokens[$index]->equals(':')) { + return false; + } + + $closeParenthesisIndex = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$closeParenthesisIndex]->isGivenKind(T_ELSE)) { + return true; + } + if (!$tokens[$closeParenthesisIndex]->equals(')')) { + return false; + } + + $openParenthesisIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $closeParenthesisIndex); + + $alternativeControlStructureIndex = $tokens->getPrevMeaningfulToken($openParenthesisIndex); + + return $tokens[$alternativeControlStructureIndex]->isGivenKind([T_DECLARE, T_ELSEIF, T_FOR, T_FOREACH, T_IF, T_SWITCH, T_WHILE]); + } + + /** + * @param int $switchIndex + * + * @return int[] + */ + private function getColonIndicesForSwitch(Tokens $tokens, $switchIndex) + { + return array_map( + static function (CaseAnalysis $caseAnalysis) { + return $caseAnalysis->getColonIndex(); + }, + (new SwitchAnalyzer())->getSwitchAnalysis($tokens, $switchIndex)->getCases() + ); + } + + /** + * @param int $index + * @param bool $after + */ + private function ensureWhitespaceExistence(Tokens $tokens, $index, $after) + { + if ($tokens[$index]->isWhitespace()) { + if ( + false === strpos($tokens[$index]->getContent(), "\n") + && !$tokens[$index - 1]->isComment() + ) { + $tokens[$index] = new Token([T_WHITESPACE, ' ']); + } + + return; + } + + $index += $after ? 0 : 1; + $tokens->insertAt($index, new Token([T_WHITESPACE, ' '])); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryToElvisOperatorFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryToElvisOperatorFixer.php new file mode 100644 index 0000000..dd1e333 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryToElvisOperatorFixer.php @@ -0,0 +1,270 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class TernaryToElvisOperatorFixer extends AbstractFixer +{ + /** + * @internal + * + * Lower precedence and other valid preceding tokens. + * + * Ordered by most common types first. + * + * @var array + */ + const VALID_BEFORE_ENDTYPES = [ + '=', + [T_OPEN_TAG], + [T_OPEN_TAG_WITH_ECHO], + '(', + ',', + ';', + '[', + '{', + '}', + [CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN], + [T_AND_EQUAL], // &= + [T_CONCAT_EQUAL], // .= + [T_DIV_EQUAL], // /= + [T_MINUS_EQUAL], // -= + [T_MOD_EQUAL], // %= + [T_MUL_EQUAL], // *= + [T_OR_EQUAL], // |= + [T_PLUS_EQUAL], // += + [T_POW_EQUAL], // **= + [T_SL_EQUAL], // <<= + [T_SR_EQUAL], // >>= + [T_XOR_EQUAL], // ^= + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Use the Elvis operator `?:` where possible.', + [ + new CodeSample( + "<?php\n\$foo = \$foo ? \$foo : 1;\n" + ), + new CodeSample( + "<?php \$foo = \$bar[a()] ? \$bar[a()] : 1; # \"risky\" sample, \"a()\" only gets called once after fixing\n" + ), + ], + null, + 'Risky when relying on functions called on both sides of the `?` operator.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoTrailingWhitespaceFixer, TernaryOperatorSpacesFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound('?'); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $blockEdgeDefinitions = Tokens::getBlockEdgeDefinitions(); + + for ($index = \count($tokens) - 5; $index > 1; --$index) { + if (!$tokens[$index]->equals('?')) { + continue; + } + + $nextIndex = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$nextIndex]->equals(':')) { + continue; // Elvis is alive! + } + + // get and check what is before the `?` operator + + $beforeOperator = $this->getBeforeOperator($tokens, $index, $blockEdgeDefinitions); + + if (null === $beforeOperator) { + continue; // contains something we cannot fix because of priorities + } + + // get what is after the `?` token + + $afterOperator = $this->getAfterOperator($tokens, $index); + + // if before and after the `?` operator are the same (in meaningful matter), clear after + + if ($this->rangeEqualsRange($tokens, $beforeOperator, $afterOperator)) { + $this->clearMeaningfulFromRange($tokens, $afterOperator); + } + } + } + + /** + * @param int $index + * + * @return null|array null if contains ++/-- operator + */ + private function getBeforeOperator(Tokens $tokens, $index, array $blockEdgeDefinitions) + { + $index = $tokens->getPrevMeaningfulToken($index); + $before = ['end' => $index]; + + while (!$tokens[$index]->equalsAny(self::VALID_BEFORE_ENDTYPES)) { + if ($tokens[$index]->isGivenKind([T_INC, T_DEC])) { + return null; + } + + $blockType = Tokens::detectBlockType($tokens[$index]); + + if (null === $blockType || $blockType['isStart']) { + $before['start'] = $index; + $index = $tokens->getPrevMeaningfulToken($index); + + continue; + } + + $blockType = $blockEdgeDefinitions[$blockType['type']]; + $openCount = 1; + + do { + $index = $tokens->getPrevMeaningfulToken($index); + + if ($tokens[$index]->isGivenKind([T_INC, T_DEC])) { + return null; + } + + if ($tokens[$index]->equals($blockType['start'])) { + ++$openCount; + + continue; + } + + if ($tokens[$index]->equals($blockType['end'])) { + --$openCount; + } + } while (1 >= $openCount); + + $before['start'] = $index; + $index = $tokens->getPrevMeaningfulToken($index); + } + + if (!isset($before['start'])) { + return null; + } + + return $before; + } + + /** + * @param int $index + * + * @return array + */ + private function getAfterOperator(Tokens $tokens, $index) + { + $index = $tokens->getNextMeaningfulToken($index); + $after = ['start' => $index]; + + while (!$tokens[$index]->equals(':')) { + $blockType = Tokens::detectBlockType($tokens[$index]); + + if (null !== $blockType) { + $index = $tokens->findBlockEnd($blockType['type'], $index); + } + + $after['end'] = $index; + $index = $tokens->getNextMeaningfulToken($index); + } + + return $after; + } + + /** + * Meaningful compare of tokens within ranges. + * + * @return bool + */ + private function rangeEqualsRange(Tokens $tokens, array $range1, array $range2) + { + $leftStart = $range1['start']; + $leftEnd = $range1['end']; + + while ($tokens[$leftStart]->equals('(') && $tokens[$leftEnd]->equals(')')) { + $leftStart = $tokens->getNextMeaningfulToken($leftStart); + $leftEnd = $tokens->getPrevMeaningfulToken($leftEnd); + } + + $rightStart = $range2['start']; + $rightEnd = $range2['end']; + + while ($tokens[$rightStart]->equals('(') && $tokens[$rightEnd]->equals(')')) { + $rightStart = $tokens->getNextMeaningfulToken($rightStart); + $rightEnd = $tokens->getPrevMeaningfulToken($rightEnd); + } + + while ($leftStart <= $leftEnd && $rightStart <= $rightEnd) { + if ( + !$tokens[$leftStart]->equals($tokens[$rightStart]) + && !($tokens[$leftStart]->equalsAny(['[', [CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN]]) && $tokens[$rightStart]->equalsAny(['[', [CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN]])) + && !($tokens[$leftStart]->equalsAny([']', [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE]]) && $tokens[$rightStart]->equalsAny([']', [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE]])) + ) { + return false; + } + + $leftStart = $tokens->getNextMeaningfulToken($leftStart); + $rightStart = $tokens->getNextMeaningfulToken($rightStart); + } + + return $leftStart > $leftEnd && $rightStart > $rightEnd; + } + + private function clearMeaningfulFromRange(Tokens $tokens, array $range) + { + // $range['end'] must be meaningful! + for ($i = $range['end']; $i >= $range['start']; $i = $tokens->getPrevMeaningfulToken($i)) { + $tokens->clearTokenAndMergeSurroundingWhitespace($i); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryToNullCoalescingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryToNullCoalescingFixer.php new file mode 100644 index 0000000..932b7f9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/TernaryToNullCoalescingFixer.php @@ -0,0 +1,215 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class TernaryToNullCoalescingFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Use `null` coalescing operator `??` where possible. Requires PHP >= 7.0.', + [ + new VersionSpecificCodeSample( + "<?php\n\$sample = isset(\$a) ? \$a : \$b;\n", + new VersionSpecification(70000) + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(T_ISSET); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $issetIndexes = array_keys($tokens->findGivenKind(T_ISSET)); + while ($issetIndex = array_pop($issetIndexes)) { + $this->fixIsset($tokens, $issetIndex); + } + } + + /** + * @param int $index of `T_ISSET` token + */ + private function fixIsset(Tokens $tokens, $index) + { + $prevTokenIndex = $tokens->getPrevMeaningfulToken($index); + if ($this->isHigherPrecedenceAssociativityOperator($tokens[$prevTokenIndex])) { + return; + } + + $startBraceIndex = $tokens->getNextTokenOfKind($index, ['(']); + $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startBraceIndex); + + $ternaryQuestionMarkIndex = $tokens->getNextMeaningfulToken($endBraceIndex); + if (!$tokens[$ternaryQuestionMarkIndex]->equals('?')) { + return; // we are not in a ternary operator + } + + // search what is inside the isset() + $issetTokens = $this->getMeaningfulSequence($tokens, $startBraceIndex, $endBraceIndex); + if ($this->hasChangingContent($issetTokens)) { + return; // some weird stuff inside the isset + } + + // search what is inside the middle argument of ternary operator + $ternaryColonIndex = $tokens->getNextTokenOfKind($ternaryQuestionMarkIndex, [':']); + $ternaryFirstOperandTokens = $this->getMeaningfulSequence($tokens, $ternaryQuestionMarkIndex, $ternaryColonIndex); + + if ($issetTokens->generateCode() !== $ternaryFirstOperandTokens->generateCode()) { + return; // regardless of non-meaningful tokens, the operands are different + } + + $ternaryFirstOperandIndex = $tokens->getNextMeaningfulToken($ternaryQuestionMarkIndex); + + // preserve comments and spaces + $comments = []; + $commentStarted = false; + for ($loopIndex = $index; $loopIndex < $ternaryFirstOperandIndex; ++$loopIndex) { + if ($tokens[$loopIndex]->isComment()) { + $comments[] = $tokens[$loopIndex]; + $commentStarted = true; + } elseif ($commentStarted) { + if ($tokens[$loopIndex]->isWhitespace()) { + $comments[] = $tokens[$loopIndex]; + } + + $commentStarted = false; + } + } + + $tokens[$ternaryColonIndex] = new Token([T_COALESCE, '??']); + $tokens->overrideRange($index, $ternaryFirstOperandIndex - 1, $comments); + } + + /** + * Get the sequence of meaningful tokens and returns a new Tokens instance. + * + * @param int $start start index + * @param int $end end index + * + * @return Tokens + */ + private function getMeaningfulSequence(Tokens $tokens, $start, $end) + { + $sequence = []; + $index = $start; + while ($index < $end) { + $index = $tokens->getNextMeaningfulToken($index); + if ($index >= $end || null === $index) { + break; + } + + $sequence[] = $tokens[$index]; + } + + return Tokens::fromArray($sequence); + } + + /** + * Check if the requested token is an operator computed + * before the ternary operator along with the `isset()`. + * + * @return bool + */ + private function isHigherPrecedenceAssociativityOperator(Token $token) + { + static $operatorsPerId = [ + T_ARRAY_CAST => true, + T_BOOLEAN_AND => true, + T_BOOLEAN_OR => true, + T_BOOL_CAST => true, + T_COALESCE => true, + T_DEC => true, + T_DOUBLE_CAST => true, + T_INC => true, + T_INT_CAST => true, + T_IS_EQUAL => true, + T_IS_GREATER_OR_EQUAL => true, + T_IS_IDENTICAL => true, + T_IS_NOT_EQUAL => true, + T_IS_NOT_IDENTICAL => true, + T_IS_SMALLER_OR_EQUAL => true, + T_OBJECT_CAST => true, + T_POW => true, + T_SL => true, + T_SPACESHIP => true, + T_SR => true, + T_STRING_CAST => true, + T_UNSET_CAST => true, + ]; + + static $operatorsPerContent = [ + '!', + '%', + '&', + '*', + '+', + '-', + '/', + ':', + '^', + '|', + '~', + '.', + ]; + + return isset($operatorsPerId[$token->getId()]) || $token->equalsAny($operatorsPerContent); + } + + /** + * Check if the `isset()` content may change if called multiple times. + * + * @param Tokens $tokens The original token list + * + * @return bool + */ + private function hasChangingContent(Tokens $tokens) + { + static $operatorsPerId = [ + T_DEC, + T_INC, + T_YIELD, + T_YIELD_FROM, + ]; + + foreach ($tokens as $token) { + if ($token->isGivenKind($operatorsPerId) || $token->equals('(')) { + return true; + } + } + + return false; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/UnaryOperatorSpacesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/UnaryOperatorSpacesFixer.php new file mode 100644 index 0000000..697cc6d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Operator/UnaryOperatorSpacesFixer.php @@ -0,0 +1,78 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Operator; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Gregor Harlan <gharlan@web.de> + */ +final class UnaryOperatorSpacesFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Unary operators should be placed adjacent to their operands.', + [new CodeSample("<?php\n\$sample ++;\n-- \$sample;\n\$sample = ! ! \$a;\n\$sample = ~ \$c;\nfunction & foo(){}\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NotOperatorWithSpaceFixer, NotOperatorWithSuccessorSpaceFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + if ($tokensAnalyzer->isUnarySuccessorOperator($index)) { + if (!$tokens[$tokens->getPrevNonWhitespace($index)]->isComment()) { + $tokens->removeLeadingWhitespace($index); + } + + continue; + } + + if ($tokensAnalyzer->isUnaryPredecessorOperator($index)) { + $tokens->removeTrailingWhitespace($index); + + continue; + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/BlankLineAfterOpeningTagFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/BlankLineAfterOpeningTagFixer.php new file mode 100644 index 0000000..871c149 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/BlankLineAfterOpeningTagFixer.php @@ -0,0 +1,98 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpTag; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Ceeram <ceeram@cakephp.org> + */ +final class BlankLineAfterOpeningTagFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Ensure there is no code on the same line as the PHP open tag and it is followed by a blank line.', + [new CodeSample("<?php \$a = 1;\n\$b = 1;\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoBlankLinesBeforeNamespaceFixer. + * Must run after DeclareStrictTypesFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_OPEN_TAG); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + // ignore files with short open tag and ignore non-monolithic files + if (!$tokens[0]->isGivenKind(T_OPEN_TAG) || !$tokens->isMonolithicPhp()) { + return; + } + + $newlineFound = false; + /** @var Token $token */ + foreach ($tokens as $token) { + if ($token->isWhitespace() && false !== strpos($token->getContent(), "\n")) { + $newlineFound = true; + + break; + } + } + + // ignore one-line files + if (!$newlineFound) { + return; + } + + $token = $tokens[0]; + + if (false === strpos($token->getContent(), "\n")) { + $tokens[0] = new Token([$token->getId(), rtrim($token->getContent()).$lineEnding]); + } + + if (false === strpos($tokens[1]->getContent(), "\n")) { + if ($tokens[1]->isWhitespace()) { + $tokens[1] = new Token([T_WHITESPACE, $lineEnding.$tokens[1]->getContent()]); + } else { + $tokens->insertAt(1, new Token([T_WHITESPACE, $lineEnding])); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/EchoTagSyntaxFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/EchoTagSyntaxFixer.php new file mode 100644 index 0000000..b66a36f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/EchoTagSyntaxFixer.php @@ -0,0 +1,275 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpTag; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Michele Locati <michele@locati.it> + */ +final class EchoTagSyntaxFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** @internal */ + const OPTION_FORMAT = 'format'; + + /** @internal */ + const OPTION_SHORTEN_SIMPLE_STATEMENTS_ONLY = 'shorten_simple_statements_only'; + + /** @internal */ + const OPTION_LONG_FUNCTION = 'long_function'; + + /** @internal */ + const FORMAT_SHORT = 'short'; + + /** @internal */ + const FORMAT_LONG = 'long'; + + /** @internal */ + const LONG_FUNCTION_ECHO = 'echo'; + + /** @internal */ + const LONG_FUNCTION_PRINT = 'print'; + + /** @internal */ + const SUPPORTED_FORMAT_OPTIONS = [ + self::FORMAT_LONG, + self::FORMAT_SHORT, + ]; + + /** @internal */ + const SUPPORTED_LONGFUNCTION_OPTIONS = [ + self::LONG_FUNCTION_ECHO, + self::LONG_FUNCTION_PRINT, + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + $sample = <<<'EOT' +<?=1?> +<?php print '2' . '3'; ?> +<?php /* comment */ echo '2' . '3'; ?> +<?php print '2' . '3'; someFunction(); ?> + +EOT + ; + + return new FixerDefinition( + 'Replaces short-echo `<?=` with long format `<?php echo`/`<?php print` syntax, or vice-versa.', + [ + new CodeSample($sample), + new CodeSample($sample, [self::OPTION_FORMAT => self::FORMAT_LONG]), + new CodeSample($sample, [self::OPTION_FORMAT => self::FORMAT_LONG, self::OPTION_LONG_FUNCTION => self::LONG_FUNCTION_PRINT]), + new CodeSample($sample, [self::OPTION_FORMAT => self::FORMAT_SHORT]), + new CodeSample($sample, [self::OPTION_FORMAT => self::FORMAT_SHORT, self::OPTION_SHORTEN_SIMPLE_STATEMENTS_ONLY => false]), + ], + null + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoMixedEchoPrintFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + if (self::FORMAT_SHORT === $this->configuration[self::OPTION_FORMAT]) { + return $tokens->isAnyTokenKindsFound([T_ECHO, T_PRINT]); + } + + return $tokens->isTokenKindFound(T_OPEN_TAG_WITH_ECHO); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder(self::OPTION_FORMAT, 'The desired language construct.')) + ->setAllowedValues(self::SUPPORTED_FORMAT_OPTIONS) + ->setDefault(self::FORMAT_LONG) + ->getOption(), + (new FixerOptionBuilder(self::OPTION_LONG_FUNCTION, 'The function to be used to expand the short echo tags')) + ->setAllowedValues(self::SUPPORTED_LONGFUNCTION_OPTIONS) + ->setDefault(self::LONG_FUNCTION_ECHO) + ->getOption(), + (new FixerOptionBuilder(self::OPTION_SHORTEN_SIMPLE_STATEMENTS_ONLY, 'Render short-echo tags only in case of simple code')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if (self::FORMAT_SHORT === $this->configuration[self::OPTION_FORMAT]) { + $this->longToShort($tokens); + } else { + $this->shortToLong($tokens); + } + } + + private function longToShort(Tokens $tokens) + { + $skipWhenComplexCode = $this->configuration[self::OPTION_SHORTEN_SIMPLE_STATEMENTS_ONLY]; + $count = $tokens->count(); + + for ($index = 0; $index < $count; ++$index) { + if (!$tokens[$index]->isGivenKind(T_OPEN_TAG)) { + continue; + } + + $nextMeaningful = $tokens->getNextMeaningfulToken($index); + + if (null === $nextMeaningful) { + return; + } + + if (!$tokens[$nextMeaningful]->isGivenKind([T_ECHO, T_PRINT])) { + $index = $nextMeaningful; + + continue; + } + + if ($skipWhenComplexCode && $this->isComplexCode($tokens, $nextMeaningful + 1)) { + $index = $nextMeaningful; + + continue; + } + + $newTokens = $this->buildLongToShortTokens($tokens, $index, $nextMeaningful); + $tokens->overrideRange($index, $nextMeaningful, $newTokens); + $count = $tokens->count(); + } + } + + private function shortToLong(Tokens $tokens) + { + if (self::LONG_FUNCTION_PRINT === $this->configuration[self::OPTION_LONG_FUNCTION]) { + $echoToken = [T_PRINT, 'print']; + } else { + $echoToken = [T_ECHO, 'echo']; + } + + $index = -1; + + while (true) { + $index = $tokens->getNextTokenOfKind($index, [[T_OPEN_TAG_WITH_ECHO]]); + + if (null === $index) { + return; + } + + $replace = [new Token([T_OPEN_TAG, '<?php ']), new Token($echoToken)]; + + if (!$tokens[$index + 1]->isWhitespace()) { + $replace[] = new Token([T_WHITESPACE, ' ']); + } + + $tokens->overrideRange($index, $index, $replace); + ++$index; + } + } + + /** + * Check if $tokens, starting at $index, contains "complex code", that is, the content + * of the echo tag contains more than a simple "echo something". + * + * This is done by a very quick test: if the tag contains non-whitespace tokens after + * a semicolon, we consider it as "complex". + * + * @param int $index + * + * @return bool + * + * @example `<?php echo 1 ?>` is false (not complex) + * @example `<?php echo 'hello' . 'world'; ?>` is false (not "complex") + * @example `<?php echo 2; $set = 3 ?>` is true ("complex") + */ + private function isComplexCode(Tokens $tokens, $index) + { + $semicolonFound = false; + + for ($count = $tokens->count(); $index < $count; ++$index) { + $token = $tokens[$index]; + + if ($token->isGivenKind(T_CLOSE_TAG)) { + return false; + } + + if (';' === $token->getContent()) { + $semicolonFound = true; + } elseif ($semicolonFound && !$token->isWhitespace()) { + return true; + } + } + + return false; + } + + /** + * Builds the list of tokens that replace a long echo sequence. + * + * @param int $openTagIndex + * @param int $echoTagIndex + * + * @return Token[] + */ + private function buildLongToShortTokens(Tokens $tokens, $openTagIndex, $echoTagIndex) + { + $result = [new Token([T_OPEN_TAG_WITH_ECHO, '<?='])]; + + $start = $tokens->getNextNonWhitespace($openTagIndex); + + if ($start === $echoTagIndex) { + // No non-whitespace tokens between $openTagIndex and $echoTagIndex + return $result; + } + + // Find the last non-whitespace index before $echoTagIndex + $end = $echoTagIndex - 1; + + while ($tokens[$end]->isWhitespace()) { + --$end; + } + + // Copy the non-whitespace tokens between $openTagIndex and $echoTagIndex + for ($index = $start; $index <= $end; ++$index) { + $result[] = clone $tokens[$index]; + } + + return $result; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/FullOpeningTagFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/FullOpeningTagFixer.php new file mode 100644 index 0000000..4d1a518 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/FullOpeningTagFixer.php @@ -0,0 +1,131 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpTag; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR1 ¶2.1. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class FullOpeningTagFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHP code must use the long `<?php` tags or short-echo `<?=` tags and not other tag variations.', + [ + new CodeSample( + '<? + +echo "Hello!"; +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + // must run before all Token-based fixers + return 98; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $content = $tokens->generateCode(); + + // replace all <? with <?php to replace all short open tags even without short_open_tag option enabled + $newContent = Preg::replace('/<\?(?:phP|pHp|pHP|Php|PhP|PHp|PHP)?(\s|$)/', '<?php$1', $content, -1, $count); + + if (!$count) { + return; + } + + /* the following code is magic to revert previous replacements which should NOT be replaced, for example incorrectly replacing + * > echo '<? '; + * with + * > echo '<?php '; + */ + $newTokens = Tokens::fromCode($newContent); + + $tokensOldContentLength = 0; + + foreach ($newTokens as $index => $token) { + if ($token->isGivenKind(T_OPEN_TAG)) { + $tokenContent = $token->getContent(); + + if ('<?php' !== strtolower(substr($content, $tokensOldContentLength, 5))) { + $tokenContent = '<? '; + } + + $tokensOldContentLength += \strlen($tokenContent); + + continue; + } + + if ($token->isGivenKind([T_COMMENT, T_DOC_COMMENT, T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_STRING])) { + $tokenContent = ''; + $tokenContentLength = 0; + $parts = explode('<?php', $token->getContent()); + $iLast = \count($parts) - 1; + + foreach ($parts as $i => $part) { + $tokenContent .= $part; + $tokenContentLength += \strlen($part); + + if ($i !== $iLast) { + $originalTokenContent = substr($content, $tokensOldContentLength + $tokenContentLength, 5); + if ('<?php' === strtolower($originalTokenContent)) { + $tokenContent .= $originalTokenContent; + $tokenContentLength += 5; + } else { + $tokenContent .= '<?'; + $tokenContentLength += 2; + } + } + } + + $newTokens[$index] = new Token([$token->getId(), $tokenContent]); + $token = $newTokens[$index]; + } + + $tokensOldContentLength += \strlen($token->getContent()); + } + + $tokens->overrideRange(0, $tokens->count() - 1, $newTokens); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php new file mode 100644 index 0000000..5eef330 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php @@ -0,0 +1,77 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpTag; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Ceeram <ceeram@cakephp.org> + */ +final class LinebreakAfterOpeningTagFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Ensure there is no code on the same line as the PHP open tag.', + [new CodeSample("<?php \$a = 1;\n\$b = 3;\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_OPEN_TAG); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // ignore files with short open tag and ignore non-monolithic files + if (!$tokens[0]->isGivenKind(T_OPEN_TAG) || !$tokens->isMonolithicPhp()) { + return; + } + + // ignore if linebreak already present + if (false !== strpos($tokens[0]->getContent(), "\n")) { + return; + } + + $newlineFound = false; + foreach ($tokens as $token) { + if ($token->isWhitespace() && false !== strpos($token->getContent(), "\n")) { + $newlineFound = true; + + break; + } + } + + // ignore one-line files + if (!$newlineFound) { + return; + } + + $tokens[0] = new Token([T_OPEN_TAG, rtrim($tokens[0]->getContent()).$this->whitespacesConfig->getLineEnding()]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoClosingTagFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoClosingTagFixer.php new file mode 100644 index 0000000..8b19366 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoClosingTagFixer.php @@ -0,0 +1,69 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpTag; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR2 ¶2.2. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NoClosingTagFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'The closing `?>` tag MUST be omitted from files containing only PHP.', + [new CodeSample("<?php\nclass Sample\n{\n}\n?>\n")] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_CLOSE_TAG); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if (\count($tokens) < 2 || !$tokens->isMonolithicPhp() || !$tokens->isTokenKindFound(T_CLOSE_TAG)) { + return; + } + + $closeTags = $tokens->findGivenKind(T_CLOSE_TAG); + $index = key($closeTags); + + if (isset($tokens[$index - 1]) && $tokens[$index - 1]->isWhitespace()) { + $tokens->clearAt($index - 1); + } + $tokens->clearAt($index); + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + if (!$tokens[$prevIndex]->equalsAny([';', '}', [T_OPEN_TAG]])) { + $tokens->insertAt($prevIndex + 1, new Token(';')); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoShortEchoTagFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoShortEchoTagFixer.php new file mode 100644 index 0000000..49ae209 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoShortEchoTagFixer.php @@ -0,0 +1,63 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpTag; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author Vincent Klaiber <hello@vinkla.com> + * + * @deprecated proxy to EchoTagSyntaxFixer + */ +final class NoShortEchoTagFixer extends AbstractProxyFixer implements DeprecatedFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Replaces short-echo `<?=` with long format `<?php echo` syntax.', + [new CodeSample("<?= \"foo\";\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoMixedEchoPrintFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + return [new EchoTagSyntaxFixer()]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitConstructFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitConstructFixer.php new file mode 100644 index 0000000..1881f4c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitConstructFixer.php @@ -0,0 +1,218 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpUnitConstructFixer extends AbstractPhpUnitFixer implements ConfigurationDefinitionFixerInterface +{ + private static $assertionFixers = [ + 'assertSame' => 'fixAssertPositive', + 'assertEquals' => 'fixAssertPositive', + 'assertNotEquals' => 'fixAssertNegative', + 'assertNotSame' => 'fixAssertNegative', + ]; + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHPUnit assertion method calls like `->assertSame(true, $foo)` should be written with dedicated method like `->assertTrue($foo)`.', + [ + new CodeSample( + '<?php +final class FooTest extends \PHPUnit_Framework_TestCase { + public function testSomething() { + $this->assertEquals(false, $b); + $this->assertSame(true, $a); + $this->assertNotEquals(null, $c); + $this->assertNotSame(null, $d); + } +} +' + ), + new CodeSample( + '<?php +final class FooTest extends \PHPUnit_Framework_TestCase { + public function testSomething() { + $this->assertEquals(false, $b); + $this->assertSame(true, $a); + $this->assertNotEquals(null, $c); + $this->assertNotSame(null, $d); + } +} +', + ['assertions' => ['assertSame', 'assertNotSame']] + ), + ], + null, + 'Fixer could be risky if one is overriding PHPUnit\'s native methods.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpUnitDedicateAssertFixer. + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + // no assertions to be fixed - fast return + if (empty($this->configuration['assertions'])) { + return; + } + + foreach ($this->configuration['assertions'] as $assertionMethod) { + $assertionFixer = self::$assertionFixers[$assertionMethod]; + + for ($index = $startIndex; $index < $endIndex; ++$index) { + $index = $this->{$assertionFixer}($tokens, $index, $assertionMethod); + + if (null === $index) { + break; + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolverRootless('assertions', [ + (new FixerOptionBuilder('assertions', 'List of assertion methods to fix.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset(array_keys(self::$assertionFixers))]) + ->setDefault([ + 'assertEquals', + 'assertSame', + 'assertNotEquals', + 'assertNotSame', + ]) + ->getOption(), + ], $this->getName()); + } + + /** + * @param int $index + * @param string $method + * + * @return null|int + */ + private function fixAssertNegative(Tokens $tokens, $index, $method) + { + static $map = [ + 'false' => 'assertNotFalse', + 'null' => 'assertNotNull', + 'true' => 'assertNotTrue', + ]; + + return $this->fixAssert($map, $tokens, $index, $method); + } + + /** + * @param int $index + * @param string $method + * + * @return null|int + */ + private function fixAssertPositive(Tokens $tokens, $index, $method) + { + static $map = [ + 'false' => 'assertFalse', + 'null' => 'assertNull', + 'true' => 'assertTrue', + ]; + + return $this->fixAssert($map, $tokens, $index, $method); + } + + /** + * @param array<string, string> $map + * @param int $index + * @param string $method + * + * @return null|int + */ + private function fixAssert(array $map, Tokens $tokens, $index, $method) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + + $sequence = $tokens->findSequence( + [ + [T_STRING, $method], + '(', + ], + $index + ); + + if (null === $sequence) { + return null; + } + + $sequenceIndexes = array_keys($sequence); + if (!$functionsAnalyzer->isTheSameClassCall($tokens, $sequenceIndexes[0])) { + return null; + } + + $sequenceIndexes[2] = $tokens->getNextMeaningfulToken($sequenceIndexes[1]); + $firstParameterToken = $tokens[$sequenceIndexes[2]]; + + if (!$firstParameterToken->isNativeConstant()) { + return $sequenceIndexes[2]; + } + + $sequenceIndexes[3] = $tokens->getNextMeaningfulToken($sequenceIndexes[2]); + + // return if first method argument is an expression, not value + if (!$tokens[$sequenceIndexes[3]]->equals(',')) { + return $sequenceIndexes[3]; + } + + $tokens[$sequenceIndexes[0]] = new Token([T_STRING, $map[strtolower($firstParameterToken->getContent())]]); + $tokens->clearRange($sequenceIndexes[2], $tokens->getNextNonWhitespace($sequenceIndexes[3]) - 1); + + return $sequenceIndexes[3]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php new file mode 100644 index 0000000..749e83c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php @@ -0,0 +1,451 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpUnitDedicateAssertFixer extends AbstractPhpUnitFixer implements ConfigurationDefinitionFixerInterface +{ + private static $fixMap = [ + 'array_key_exists' => ['assertArrayNotHasKey', 'assertArrayHasKey'], + 'empty' => ['assertNotEmpty', 'assertEmpty'], + 'file_exists' => ['assertFileNotExists', 'assertFileExists'], + 'is_array' => true, + 'is_bool' => true, + 'is_callable' => true, + 'is_dir' => ['assertDirectoryNotExists', 'assertDirectoryExists'], + 'is_double' => true, + 'is_float' => true, + 'is_infinite' => ['assertFinite', 'assertInfinite'], + 'is_int' => true, + 'is_integer' => true, + 'is_long' => true, + 'is_nan' => [false, 'assertNan'], + 'is_null' => ['assertNotNull', 'assertNull'], + 'is_numeric' => true, + 'is_object' => true, + 'is_readable' => ['assertNotIsReadable', 'assertIsReadable'], + 'is_real' => true, + 'is_resource' => true, + 'is_scalar' => true, + 'is_string' => true, + 'is_writable' => ['assertNotIsWritable', 'assertIsWritable'], + ]; + + /** + * @var string[] + */ + private $functions = []; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + if (isset($this->configuration['functions'])) { + $this->functions = $this->configuration['functions']; + + return; + } + + // assertions added in 3.0: assertArrayNotHasKey assertArrayHasKey assertFileNotExists assertFileExists assertNotNull, assertNull + $this->functions = [ + 'array_key_exists', + 'file_exists', + 'is_null', + ]; + + if (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_3_5)) { + // assertions added in 3.5: assertInternalType assertNotEmpty assertEmpty + $this->functions = array_merge($this->functions, [ + 'empty', + 'is_array', + 'is_bool', + 'is_boolean', + 'is_callable', + 'is_double', + 'is_float', + 'is_int', + 'is_integer', + 'is_long', + 'is_numeric', + 'is_object', + 'is_real', + 'is_resource', + 'is_scalar', + 'is_string', + ]); + } + + if (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_5_0)) { + // assertions added in 5.0: assertFinite assertInfinite assertNan + $this->functions = array_merge($this->functions, [ + 'is_infinite', + 'is_nan', + ]); + } + + if (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_5_6)) { + // assertions added in 5.6: assertDirectoryExists assertDirectoryNotExists assertIsReadable assertNotIsReadable assertIsWritable assertNotIsWritable + $this->functions = array_merge($this->functions, [ + 'is_dir', + 'is_readable', + 'is_writable', + ]); + } + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHPUnit assertions like `assertInternalType`, `assertFileExists`, should be used over `assertTrue`.', + [ + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testSomeTest() + { + $this->assertTrue(is_float( $a), "my message"); + $this->assertTrue(is_nan($a)); + } +} +' + ), + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testSomeTest() + { + $this->assertTrue(is_dir($a)); + $this->assertTrue(is_writable($a)); + $this->assertTrue(is_readable($a)); + } +} +', + ['target' => PhpUnitTargetVersion::VERSION_5_6] + ), + ], + null, + 'Fixer could be risky if one is overriding PHPUnit\'s native methods.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpUnitDedicateAssertInternalTypeFixer. + * Must run after NoAliasFunctionsFixer, PhpUnitConstructFixer. + */ + public function getPriority() + { + return -15; + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + foreach ($this->getPreviousAssertCall($tokens, $startIndex, $endIndex) as $assertCall) { + // test and fix for assertTrue/False to dedicated asserts + if ('asserttrue' === $assertCall['loweredName'] || 'assertfalse' === $assertCall['loweredName']) { + $this->fixAssertTrueFalse($tokens, $assertCall); + + continue; + } + + if ( + 'assertsame' === $assertCall['loweredName'] + || 'assertnotsame' === $assertCall['loweredName'] + || 'assertequals' === $assertCall['loweredName'] + || 'assertnotequals' === $assertCall['loweredName'] + ) { + $this->fixAssertSameEquals($tokens, $assertCall); + + continue; + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $values = [ + 'array_key_exists', + 'empty', + 'file_exists', + 'is_array', + 'is_bool', + 'is_callable', + 'is_double', + 'is_float', + 'is_infinite', + 'is_int', + 'is_integer', + 'is_long', + 'is_nan', + 'is_null', + 'is_numeric', + 'is_object', + 'is_real', + 'is_resource', + 'is_scalar', + 'is_string', + ]; + + sort($values); + + return new FixerConfigurationResolverRootless('functions', [ + (new FixerOptionBuilder('functions', 'List of assertions to fix (overrides `target`).')) + ->setAllowedTypes(['null', 'array']) + ->setAllowedValues([ + null, + new AllowedValueSubset($values), + ]) + ->setDefault(null) + ->setDeprecationMessage('Use option `target` instead.') + ->getOption(), + (new FixerOptionBuilder('target', 'Target version of PHPUnit.')) + ->setAllowedTypes(['string']) + ->setAllowedValues([ + PhpUnitTargetVersion::VERSION_3_0, + PhpUnitTargetVersion::VERSION_3_5, + PhpUnitTargetVersion::VERSION_5_0, + PhpUnitTargetVersion::VERSION_5_6, + PhpUnitTargetVersion::VERSION_NEWEST, + ]) + ->setDefault(PhpUnitTargetVersion::VERSION_5_0) // @TODO 3.x: change to `VERSION_NEWEST` + ->getOption(), + ], $this->getName()); + } + + private function fixAssertTrueFalse(Tokens $tokens, array $assertCall) + { + $testDefaultNamespaceTokenIndex = false; + $testIndex = $tokens->getNextMeaningfulToken($assertCall['openBraceIndex']); + + if (!$tokens[$testIndex]->isGivenKind([T_EMPTY, T_STRING])) { + if (!$tokens[$testIndex]->isGivenKind(T_NS_SEPARATOR)) { + return; + } + + $testDefaultNamespaceTokenIndex = $testIndex; + $testIndex = $tokens->getNextMeaningfulToken($testIndex); + } + + $testOpenIndex = $tokens->getNextMeaningfulToken($testIndex); + if (!$tokens[$testOpenIndex]->equals('(')) { + return; + } + + $testCloseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $testOpenIndex); + + $assertCallCloseIndex = $tokens->getNextMeaningfulToken($testCloseIndex); + if (!$tokens[$assertCallCloseIndex]->equalsAny([')', ','])) { + return; + } + + $isPositive = 'asserttrue' === $assertCall['loweredName']; + + $content = strtolower($tokens[$testIndex]->getContent()); + if (!\in_array($content, $this->functions, true)) { + return; + } + + if (\is_array(self::$fixMap[$content])) { + if (false !== self::$fixMap[$content][$isPositive]) { + $tokens[$assertCall['index']] = new Token([T_STRING, self::$fixMap[$content][$isPositive]]); + $this->removeFunctionCall($tokens, $testDefaultNamespaceTokenIndex, $testIndex, $testOpenIndex, $testCloseIndex); + } + + return; + } + + $type = substr($content, 3); + + $tokens[$assertCall['index']] = new Token([T_STRING, $isPositive ? 'assertInternalType' : 'assertNotInternalType']); + $tokens[$testIndex] = new Token([T_CONSTANT_ENCAPSED_STRING, "'".$type."'"]); + $tokens[$testOpenIndex] = new Token(','); + + $tokens->clearTokenAndMergeSurroundingWhitespace($testCloseIndex); + $commaIndex = $tokens->getPrevMeaningfulToken($testCloseIndex); + if ($tokens[$commaIndex]->equals(',')) { + $tokens->removeTrailingWhitespace($commaIndex); + $tokens->clearAt($commaIndex); + } + + if (!$tokens[$testOpenIndex + 1]->isWhitespace()) { + $tokens->insertAt($testOpenIndex + 1, new Token([T_WHITESPACE, ' '])); + } + + if (false !== $testDefaultNamespaceTokenIndex) { + $tokens->clearTokenAndMergeSurroundingWhitespace($testDefaultNamespaceTokenIndex); + } + } + + private function fixAssertSameEquals(Tokens $tokens, array $assertCall) + { + // @ $this->/self::assertEquals/Same([$nextIndex]) + $expectedIndex = $tokens->getNextMeaningfulToken($assertCall['openBraceIndex']); + + // do not fix + // let $a = [1,2]; $b = "2"; + // "$this->assertEquals("2", count($a)); $this->assertEquals($b, count($a)); $this->assertEquals(2.1, count($a));" + + if (!$tokens[$expectedIndex]->isGivenKind(T_LNUMBER)) { + return; + } + + // @ $this->/self::assertEquals/Same([$nextIndex,$commaIndex]) + $commaIndex = $tokens->getNextMeaningfulToken($expectedIndex); + if (!$tokens[$commaIndex]->equals(',')) { + return; + } + + // @ $this->/self::assertEquals/Same([$nextIndex,$commaIndex,$countCallIndex]) + $countCallIndex = $tokens->getNextMeaningfulToken($commaIndex); + if ($tokens[$countCallIndex]->isGivenKind(T_NS_SEPARATOR)) { + $defaultNamespaceTokenIndex = $countCallIndex; + $countCallIndex = $tokens->getNextMeaningfulToken($countCallIndex); + } else { + $defaultNamespaceTokenIndex = false; + } + + if (!$tokens[$countCallIndex]->isGivenKind(T_STRING)) { + return; + } + + $lowerContent = strtolower($tokens[$countCallIndex]->getContent()); + if ('count' !== $lowerContent && 'sizeof' !== $lowerContent) { + return; // not a call to "count" or "sizeOf" + } + + // @ $this->/self::assertEquals/Same([$nextIndex,$commaIndex,[$defaultNamespaceTokenIndex,]$countCallIndex,$countCallOpenBraceIndex]) + $countCallOpenBraceIndex = $tokens->getNextMeaningfulToken($countCallIndex); + if (!$tokens[$countCallOpenBraceIndex]->equals('(')) { + return; + } + + $countCallCloseBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $countCallOpenBraceIndex); + + $afterCountCallCloseBraceIndex = $tokens->getNextMeaningfulToken($countCallCloseBraceIndex); + if (!$tokens[$afterCountCallCloseBraceIndex]->equalsAny([')', ','])) { + return; + } + + $this->removeFunctionCall( + $tokens, + $defaultNamespaceTokenIndex, + $countCallIndex, + $countCallOpenBraceIndex, + $countCallCloseBraceIndex + ); + + $tokens[$assertCall['index']] = new Token([ + T_STRING, + false === strpos($assertCall['loweredName'], 'not', 6) ? 'assertCount' : 'assertNotCount', + ]); + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function getPreviousAssertCall(Tokens $tokens, $startIndex, $endIndex) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + + for ($index = $endIndex; $index > $startIndex; --$index) { + $index = $tokens->getPrevTokenOfKind($index, [[T_STRING]]); + if (null === $index) { + return; + } + + // test if "assert" something call + $loweredContent = strtolower($tokens[$index]->getContent()); + if ('assert' !== substr($loweredContent, 0, 6)) { + continue; + } + + // test candidate for simple calls like: ([\]+'some fixable call'(...)) + $openBraceIndex = $tokens->getNextMeaningfulToken($index); + if (!$tokens[$openBraceIndex]->equals('(')) { + continue; + } + + if (!$functionsAnalyzer->isTheSameClassCall($tokens, $index)) { + continue; + } + + yield [ + 'index' => $index, + 'loweredName' => $loweredContent, + 'openBraceIndex' => $openBraceIndex, + 'closeBraceIndex' => $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openBraceIndex), + ]; + } + } + + /** + * @param false|int $callNSIndex + * @param int $callIndex + * @param int $openIndex + * @param int $closeIndex + */ + private function removeFunctionCall(Tokens $tokens, $callNSIndex, $callIndex, $openIndex, $closeIndex) + { + $tokens->clearTokenAndMergeSurroundingWhitespace($callIndex); + if (false !== $callNSIndex) { + $tokens->clearTokenAndMergeSurroundingWhitespace($callNSIndex); + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($openIndex); + $commaIndex = $tokens->getPrevMeaningfulToken($closeIndex); + if ($tokens[$commaIndex]->equals(',')) { + $tokens->removeTrailingWhitespace($commaIndex); + $tokens->clearAt($commaIndex); + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($closeIndex); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDedicateAssertInternalTypeFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDedicateAssertInternalTypeFixer.php new file mode 100644 index 0000000..558fddd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDedicateAssertInternalTypeFixer.php @@ -0,0 +1,192 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class PhpUnitDedicateAssertInternalTypeFixer extends AbstractPhpUnitFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var array + */ + private $typeToDedicatedAssertMap = [ + 'array' => 'assertIsArray', + 'boolean' => 'assertIsBool', + 'bool' => 'assertIsBool', + 'double' => 'assertIsFloat', + 'float' => 'assertIsFloat', + 'integer' => 'assertIsInt', + 'int' => 'assertIsInt', + 'null' => 'assertNull', + 'numeric' => 'assertIsNumeric', + 'object' => 'assertIsObject', + 'real' => 'assertIsFloat', + 'resource' => 'assertIsResource', + 'string' => 'assertIsString', + 'scalar' => 'assertIsScalar', + 'callable' => 'assertIsCallable', + 'iterable' => 'assertIsIterable', + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHPUnit assertions like `assertIsArray` should be used over `assertInternalType`.', + [ + new CodeSample( + '<?php +final class MyTest extends \PHPUnit\Framework\TestCase +{ + public function testMe() + { + $this->assertInternalType("array", $var); + $this->assertInternalType("boolean", $var); + } +} +' + ), + new CodeSample( + '<?php +final class MyTest extends \PHPUnit\Framework\TestCase +{ + public function testMe() + { + $this->assertInternalType("array", $var); + $this->assertInternalType("boolean", $var); + } +} +', + ['target' => PhpUnitTargetVersion::VERSION_7_5] + ), + ], + null, + 'Risky when PHPUnit methods are overridden or when project has PHPUnit incompatibilities.' + ); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + * + * Must run after PhpUnitDedicateAssertFixer. + */ + public function getPriority() + { + return -16; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('target', 'Target version of PHPUnit.')) + ->setAllowedTypes(['string']) + ->setAllowedValues([PhpUnitTargetVersion::VERSION_7_5, PhpUnitTargetVersion::VERSION_NEWEST]) + ->setDefault(PhpUnitTargetVersion::VERSION_NEWEST) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $anonymousClassIndexes = []; + $tokenAnalyzer = new TokensAnalyzer($tokens); + for ($index = $startIndex; $index < $endIndex; ++$index) { + if (!$tokens[$index]->isClassy() || !$tokenAnalyzer->isAnonymousClass($index)) { + continue; + } + + $openingBraceIndex = $tokens->getNextTokenOfKind($index, ['{']); + $closingBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $openingBraceIndex); + + $anonymousClassIndexes[$closingBraceIndex] = $openingBraceIndex; + } + + for ($index = $endIndex - 1; $index > $startIndex; --$index) { + if (isset($anonymousClassIndexes[$index])) { + $index = $anonymousClassIndexes[$index]; + + continue; + } + + if (!$tokens[$index]->isGivenKind(T_STRING)) { + continue; + } + + $functionName = strtolower($tokens[$index]->getContent()); + if ('assertinternaltype' !== $functionName && 'assertnotinternaltype' !== $functionName) { + continue; + } + + $bracketTokenIndex = $tokens->getNextMeaningfulToken($index); + if (!$tokens[$bracketTokenIndex]->equals('(')) { + continue; + } + + $expectedTypeTokenIndex = $tokens->getNextMeaningfulToken($bracketTokenIndex); + $expectedTypeToken = $tokens[$expectedTypeTokenIndex]; + if (!$expectedTypeToken->equals([T_CONSTANT_ENCAPSED_STRING])) { + continue; + } + + $expectedType = trim($expectedTypeToken->getContent(), '\'"'); + if (!isset($this->typeToDedicatedAssertMap[$expectedType])) { + continue; + } + + $commaTokenIndex = $tokens->getNextMeaningfulToken($expectedTypeTokenIndex); + if (!$tokens[$commaTokenIndex]->equals(',')) { + continue; + } + + $newAssertion = $this->typeToDedicatedAssertMap[$expectedType]; + if ('assertnotinternaltype' === $functionName) { + $newAssertion = str_replace('Is', 'IsNot', $newAssertion); + $newAssertion = str_replace('Null', 'NotNull', $newAssertion); + } + + $nextMeaningfulTokenIndex = $tokens->getNextMeaningfulToken($commaTokenIndex); + + $tokens->overrideRange($index, $nextMeaningfulTokenIndex - 1, [ + new Token([T_STRING, $newAssertion]), + new Token('('), + ]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitExpectationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitExpectationFixer.php new file mode 100644 index 0000000..c28627e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitExpectationFixer.php @@ -0,0 +1,290 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpUnitExpectationFixer extends AbstractPhpUnitFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @var array<string, string> + */ + private $methodMap = []; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->methodMap = [ + 'setExpectedException' => 'expectExceptionMessage', + ]; + + if (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_5_6)) { + $this->methodMap['setExpectedExceptionRegExp'] = 'expectExceptionMessageRegExp'; + } + + if (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_8_4)) { + $this->methodMap['setExpectedExceptionRegExp'] = 'expectExceptionMessageMatches'; + $this->methodMap['expectExceptionMessageRegExp'] = 'expectExceptionMessageMatches'; + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Usages of `->setExpectedException*` methods MUST be replaced by `->expectException*` methods.', + [ + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testFoo() + { + $this->setExpectedException("RuntimeException", "Msg", 123); + foo(); + } + + public function testBar() + { + $this->setExpectedExceptionRegExp("RuntimeException", "/Msg.*/", 123); + bar(); + } +} +' + ), + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testFoo() + { + $this->setExpectedException("RuntimeException", null, 123); + foo(); + } + + public function testBar() + { + $this->setExpectedExceptionRegExp("RuntimeException", "/Msg.*/", 123); + bar(); + } +} +', + ['target' => PhpUnitTargetVersion::VERSION_8_4] + ), + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testFoo() + { + $this->setExpectedException("RuntimeException", null, 123); + foo(); + } + + public function testBar() + { + $this->setExpectedExceptionRegExp("RuntimeException", "/Msg.*/", 123); + bar(); + } +} +', + ['target' => PhpUnitTargetVersion::VERSION_5_6] + ), + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testFoo() + { + $this->setExpectedException("RuntimeException", "Msg", 123); + foo(); + } + + public function testBar() + { + $this->setExpectedExceptionRegExp("RuntimeException", "/Msg.*/", 123); + bar(); + } +} +', + ['target' => PhpUnitTargetVersion::VERSION_5_2] + ), + ], + null, + 'Risky when PHPUnit classes are overridden or not accessible, or when project has PHPUnit incompatibilities.' + ); + } + + /** + * {@inheritdoc} + * + * Must run after PhpUnitNoExpectationAnnotationFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('target', 'Target version of PHPUnit.')) + ->setAllowedTypes(['string']) + ->setAllowedValues([PhpUnitTargetVersion::VERSION_5_2, PhpUnitTargetVersion::VERSION_5_6, PhpUnitTargetVersion::VERSION_8_4, PhpUnitTargetVersion::VERSION_NEWEST]) + ->setDefault(PhpUnitTargetVersion::VERSION_NEWEST) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + foreach (Token::getObjectOperatorKinds() as $objectOperator) { + $this->applyPhpUnitClassFixWithObjectOperator($tokens, $startIndex, $endIndex, $objectOperator); + } + } + + /** + * @param int $startIndex + * @param int $endIndex + * @param int $objectOperator + */ + private function applyPhpUnitClassFixWithObjectOperator(Tokens $tokens, $startIndex, $endIndex, $objectOperator) + { + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + $oldMethodSequence = [ + [T_VARIABLE, '$this'], + [$objectOperator], + [T_STRING], + ]; + + for ($index = $startIndex; $startIndex < $endIndex; ++$index) { + $match = $tokens->findSequence($oldMethodSequence, $index); + + if (null === $match) { + return; + } + + list($thisIndex, , $index) = array_keys($match); + + if (!isset($this->methodMap[$tokens[$index]->getContent()])) { + continue; + } + + $openIndex = $tokens->getNextTokenOfKind($index, ['(']); + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); + $commaIndex = $tokens->getPrevMeaningfulToken($closeIndex); + if ($tokens[$commaIndex]->equals(',')) { + $tokens->removeTrailingWhitespace($commaIndex); + $tokens->clearAt($commaIndex); + } + + $arguments = $argumentsAnalyzer->getArguments($tokens, $openIndex, $closeIndex); + $argumentsCnt = \count($arguments); + + $argumentsReplacements = ['expectException', $this->methodMap[$tokens[$index]->getContent()], 'expectExceptionCode']; + + $indent = $this->whitespacesConfig->getLineEnding().WhitespacesAnalyzer::detectIndent($tokens, $thisIndex); + + $isMultilineWhitespace = false; + + for ($cnt = $argumentsCnt - 1; $cnt >= 1; --$cnt) { + $argStart = array_keys($arguments)[$cnt]; + $argBefore = $tokens->getPrevMeaningfulToken($argStart); + + if ('expectExceptionMessage' === $argumentsReplacements[$cnt]) { + $paramIndicatorIndex = $tokens->getNextMeaningfulToken($argBefore); + $afterParamIndicatorIndex = $tokens->getNextMeaningfulToken($paramIndicatorIndex); + + if ( + $tokens[$paramIndicatorIndex]->equals([T_STRING, 'null'], false) + && $tokens[$afterParamIndicatorIndex]->equals(')') + ) { + if ($tokens[$argBefore + 1]->isWhitespace()) { + $tokens->clearTokenAndMergeSurroundingWhitespace($argBefore + 1); + } + $tokens->clearTokenAndMergeSurroundingWhitespace($argBefore); + $tokens->clearTokenAndMergeSurroundingWhitespace($paramIndicatorIndex); + + continue; + } + } + + $isMultilineWhitespace = $isMultilineWhitespace || ($tokens[$argStart]->isWhitespace() && !$tokens[$argStart]->isWhitespace(" \t")); + $tokensOverrideArgStart = [ + new Token([T_WHITESPACE, $indent]), + new Token([T_VARIABLE, '$this']), + new Token([T_OBJECT_OPERATOR, '->']), + new Token([T_STRING, $argumentsReplacements[$cnt]]), + new Token('('), + ]; + $tokensOverrideArgBefore = [ + new Token(')'), + new Token(';'), + ]; + + if ($isMultilineWhitespace) { + $tokensOverrideArgStart[] = new Token([T_WHITESPACE, $indent.$this->whitespacesConfig->getIndent()]); + array_unshift($tokensOverrideArgBefore, new Token([T_WHITESPACE, $indent])); + } + + if ($tokens[$argStart]->isWhitespace()) { + $tokens->overrideRange($argStart, $argStart, $tokensOverrideArgStart); + } else { + $tokens->insertAt($argStart, $tokensOverrideArgStart); + } + + $tokens->overrideRange($argBefore, $argBefore, $tokensOverrideArgBefore); + } + + $methodName = 'expectException'; + if ('expectExceptionMessageRegExp' === $tokens[$index]->getContent()) { + $methodName = $this->methodMap[$tokens[$index]->getContent()]; + } + $tokens[$index] = new Token([T_STRING, $methodName]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitFqcnAnnotationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitFqcnAnnotationFixer.php new file mode 100644 index 0000000..9a997b1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitFqcnAnnotationFixer.php @@ -0,0 +1,93 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Roland Franssen <franssen.roland@gmail.com> + */ +final class PhpUnitFqcnAnnotationFixer extends AbstractPhpUnitFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHPUnit annotations should be a FQCNs including a root namespace.', + [new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException InvalidArgumentException + * @covers Project\NameSpace\Something + * @coversDefaultClass Project\Default + * @uses Project\Test\Util + */ + public function testSomeTest() + { + } +} +' + )] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoUnusedImportsFixer, PhpdocOrderByValueFixer. + */ + public function getPriority() + { + return -9; + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $prevDocCommentIndex = $tokens->getPrevTokenOfKind($startIndex, [[T_DOC_COMMENT]]); + + if (null !== $prevDocCommentIndex) { + $startIndex = $prevDocCommentIndex; + } + + $this->fixPhpUnitClass($tokens, $startIndex, $endIndex); + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function fixPhpUnitClass(Tokens $tokens, $startIndex, $endIndex) + { + for ($index = $startIndex; $index < $endIndex; ++$index) { + if ($tokens[$index]->isGivenKind(T_DOC_COMMENT)) { + $tokens[$index] = new Token([T_DOC_COMMENT, Preg::replace( + '~^(\s*\*\s*@(?:expectedException|covers|coversDefaultClass|uses)\h+)(?!(?:self|static)::)(\w.*)$~m', + '$1\\\\$2', + $tokens[$index]->getContent() + )]); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitInternalClassFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitInternalClassFixer.php new file mode 100644 index 0000000..473ac51 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitInternalClassFixer.php @@ -0,0 +1,173 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\Line; +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Gert de Pagter <BackEndTea@gmail.com> + */ +final class PhpUnitInternalClassFixer extends AbstractPhpUnitFixer implements WhitespacesAwareFixerInterface, ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'All PHPUnit test classes should be marked as internal.', + [ + new CodeSample("<?php\nclass MyTest extends TestCase {}\n"), + new CodeSample( + "<?php\nclass MyTest extends TestCase {}\nfinal class FinalTest extends TestCase {}\nabstract class AbstractTest extends TestCase {}\n", + ['types' => ['final']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before FinalInternalClassFixer. + */ + public function getPriority() + { + return 68; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $types = ['normal', 'final', 'abstract']; + + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('types', 'What types of classes to mark as internal')) + ->setAllowedValues([(new AllowedValueSubset($types))]) + ->setAllowedTypes(['array']) + ->setDefault(['normal', 'final']) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $classIndex = $tokens->getPrevTokenOfKind($startIndex, [[T_CLASS]]); + + if (!$this->isAllowedByConfiguration($tokens, $classIndex)) { + return; + } + + $docBlockIndex = $this->getDocBlockIndex($tokens, $classIndex); + + if ($this->isPHPDoc($tokens, $docBlockIndex)) { + $this->updateDocBlockIfNeeded($tokens, $docBlockIndex); + } else { + $this->createDocBlock($tokens, $docBlockIndex); + } + } + + /** + * @param int $i + * + * @return bool + */ + private function isAllowedByConfiguration(Tokens $tokens, $i) + { + $typeIndex = $tokens->getPrevMeaningfulToken($i); + if ($tokens[$typeIndex]->isGivenKind(T_FINAL)) { + return \in_array('final', $this->configuration['types'], true); + } + + if ($tokens[$typeIndex]->isGivenKind(T_ABSTRACT)) { + return \in_array('abstract', $this->configuration['types'], true); + } + + return \in_array('normal', $this->configuration['types'], true); + } + + private function createDocBlock(Tokens $tokens, $docBlockIndex) + { + $lineEnd = $this->whitespacesConfig->getLineEnding(); + $originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $tokens->getNextNonWhitespace($docBlockIndex)); + $toInsert = [ + new Token([T_DOC_COMMENT, '/**'.$lineEnd."{$originalIndent} * @internal".$lineEnd."{$originalIndent} */"]), + new Token([T_WHITESPACE, $lineEnd.$originalIndent]), + ]; + $index = $tokens->getNextMeaningfulToken($docBlockIndex); + $tokens->insertAt($index, $toInsert); + } + + private function updateDocBlockIfNeeded(Tokens $tokens, $docBlockIndex) + { + $doc = new DocBlock($tokens[$docBlockIndex]->getContent()); + if (!empty($doc->getAnnotationsOfType('internal'))) { + return; + } + $doc = $this->makeDocBlockMultiLineIfNeeded($doc, $tokens, $docBlockIndex); + $lines = $this->addInternalAnnotation($doc, $tokens, $docBlockIndex); + $lines = implode('', $lines); + + $tokens[$docBlockIndex] = new Token([T_DOC_COMMENT, $lines]); + } + + /** + * @param int $docBlockIndex + * + * @return Line[] + */ + private function addInternalAnnotation(DocBlock $docBlock, Tokens $tokens, $docBlockIndex) + { + $lines = $docBlock->getLines(); + $originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $docBlockIndex); + $lineEnd = $this->whitespacesConfig->getLineEnding(); + array_splice($lines, -1, 0, $originalIndent.' *'.$lineEnd.$originalIndent.' * @internal'.$lineEnd); + + return $lines; + } + + /** + * @param int $docBlockIndex + * + * @return DocBlock + */ + private function makeDocBlockMultiLineIfNeeded(DocBlock $doc, Tokens $tokens, $docBlockIndex) + { + $lines = $doc->getLines(); + if (1 === \count($lines) && empty($doc->getAnnotationsOfType('internal'))) { + $indent = WhitespacesAnalyzer::detectIndent($tokens, $tokens->getNextNonWhitespace($docBlockIndex)); + $doc->makeMultiLine($indent, $this->whitespacesConfig->getLineEnding()); + + return $doc; + } + + return $doc; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMethodCasingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMethodCasingFixer.php new file mode 100644 index 0000000..e424918 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMethodCasingFixer.php @@ -0,0 +1,233 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\Line; +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use PhpCsFixer\Utils; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class PhpUnitMethodCasingFixer extends AbstractPhpUnitFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @internal + */ + const CAMEL_CASE = 'camel_case'; + + /** + * @internal + */ + const SNAKE_CASE = 'snake_case'; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Enforce camel (or snake) case for PHPUnit test methods, following configuration.', + [ + new CodeSample( + '<?php +class MyTest extends \\PhpUnit\\FrameWork\\TestCase +{ + public function test_my_code() {} +} +' + ), + new CodeSample( + '<?php +class MyTest extends \\PhpUnit\\FrameWork\\TestCase +{ + public function testMyCode() {} +} +', + ['case' => self::SNAKE_CASE] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after PhpUnitTestAnnotationFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('case', 'Apply camel or snake case to test methods')) + ->setAllowedValues([self::CAMEL_CASE, self::SNAKE_CASE]) + ->setDefault(self::CAMEL_CASE) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + for ($index = $endIndex - 1; $index > $startIndex; --$index) { + if (!$this->isTestMethod($tokens, $index)) { + continue; + } + + $functionNameIndex = $tokens->getNextMeaningfulToken($index); + $functionName = $tokens[$functionNameIndex]->getContent(); + $newFunctionName = $this->updateMethodCasing($functionName); + + if ($newFunctionName !== $functionName) { + $tokens[$functionNameIndex] = new Token([T_STRING, $newFunctionName]); + } + + $docBlockIndex = $this->getDocBlockIndex($tokens, $index); + + if ($this->isPHPDoc($tokens, $docBlockIndex)) { + $this->updateDocBlock($tokens, $docBlockIndex); + } + } + } + + /** + * @param string $functionName + * + * @return string + */ + private function updateMethodCasing($functionName) + { + $parts = explode('::', $functionName); + + $functionNamePart = array_pop($parts); + + if (self::CAMEL_CASE === $this->configuration['case']) { + $newFunctionNamePart = $functionNamePart; + $newFunctionNamePart = ucwords($newFunctionNamePart, '_'); + $newFunctionNamePart = str_replace('_', '', $newFunctionNamePart); + $newFunctionNamePart = lcfirst($newFunctionNamePart); + } else { + $newFunctionNamePart = Utils::camelCaseToUnderscore($functionNamePart); + } + + $parts[] = $newFunctionNamePart; + + return implode('::', $parts); + } + + /** + * @param int $index + * + * @return bool + */ + private function isTestMethod(Tokens $tokens, $index) + { + // Check if we are dealing with a (non abstract, non lambda) function + if (!$this->isMethod($tokens, $index)) { + return false; + } + + // if the function name starts with test it's a test + $functionNameIndex = $tokens->getNextMeaningfulToken($index); + $functionName = $tokens[$functionNameIndex]->getContent(); + + if ($this->startsWith('test', $functionName)) { + return true; + } + + $docBlockIndex = $this->getDocBlockIndex($tokens, $index); + + return + $this->isPHPDoc($tokens, $docBlockIndex) // If the function doesn't have test in its name, and no doc block, it's not a test + && false !== strpos($tokens[$docBlockIndex]->getContent(), '@test') + ; + } + + /** + * @param int $index + * + * @return bool + */ + private function isMethod(Tokens $tokens, $index) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + + return $tokens[$index]->isGivenKind(T_FUNCTION) && !$tokensAnalyzer->isLambda($index); + } + + /** + * @param string $needle + * @param string $haystack + * + * @return bool + */ + private function startsWith($needle, $haystack) + { + return substr($haystack, 0, \strlen($needle)) === $needle; + } + + /** + * @param int $docBlockIndex + */ + private function updateDocBlock(Tokens $tokens, $docBlockIndex) + { + $doc = new DocBlock($tokens[$docBlockIndex]->getContent()); + $lines = $doc->getLines(); + + $docBlockNeedsUpdate = false; + for ($inc = 0; $inc < \count($lines); ++$inc) { + $lineContent = $lines[$inc]->getContent(); + if (false === strpos($lineContent, '@depends')) { + continue; + } + + $newLineContent = Preg::replaceCallback('/(@depends\s+)(.+)(\b)/', function (array $matches) { + return sprintf( + '%s%s%s', + $matches[1], + $this->updateMethodCasing($matches[2]), + $matches[3] + ); + }, $lineContent); + + if ($newLineContent !== $lineContent) { + $lines[$inc] = new Line($newLineContent); + $docBlockNeedsUpdate = true; + } + } + + if ($docBlockNeedsUpdate) { + $lines = implode('', $lines); + $tokens[$docBlockIndex] = new Token([T_DOC_COMMENT, $lines]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMockFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMockFixer.php new file mode 100644 index 0000000..bd19d75 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMockFixer.php @@ -0,0 +1,138 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpUnitMockFixer extends AbstractPhpUnitFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var bool + */ + private $fixCreatePartialMock; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Usages of `->getMock` and `->getMockWithoutInvokingTheOriginalConstructor` methods MUST be replaced by `->createMock` or `->createPartialMock` methods.', + [ + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testFoo() + { + $mock = $this->getMockWithoutInvokingTheOriginalConstructor("Foo"); + $mock1 = $this->getMock("Foo"); + $mock1 = $this->getMock("Bar", ["aaa"]); + $mock1 = $this->getMock("Baz", ["aaa"], ["argument"]); // version with more than 2 params is not supported + } +} +' + ), + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testFoo() + { + $mock1 = $this->getMock("Foo"); + $mock1 = $this->getMock("Bar", ["aaa"]); // version with multiple params is not supported + } +} +', + ['target' => PhpUnitTargetVersion::VERSION_5_4] + ), + ], + null, + 'Risky when PHPUnit classes are overridden or not accessible, or when project has PHPUnit incompatibilities.' + ); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->fixCreatePartialMock = PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_5_5); + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + for ($index = $startIndex; $index < $endIndex; ++$index) { + if (!$tokens[$index]->isObjectOperator()) { + continue; + } + + $index = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$index]->equals([T_STRING, 'getMockWithoutInvokingTheOriginalConstructor'], false)) { + $tokens[$index] = new Token([T_STRING, 'createMock']); + } elseif ($tokens[$index]->equals([T_STRING, 'getMock'], false)) { + $openingParenthesis = $tokens->getNextMeaningfulToken($index); + $closingParenthesis = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openingParenthesis); + + $argumentsCount = $argumentsAnalyzer->countArguments($tokens, $openingParenthesis, $closingParenthesis); + + if (1 === $argumentsCount) { + $tokens[$index] = new Token([T_STRING, 'createMock']); + } elseif (2 === $argumentsCount && true === $this->fixCreatePartialMock) { + $tokens[$index] = new Token([T_STRING, 'createPartialMock']); + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('target', 'Target version of PHPUnit.')) + ->setAllowedTypes(['string']) + ->setAllowedValues([PhpUnitTargetVersion::VERSION_5_4, PhpUnitTargetVersion::VERSION_5_5, PhpUnitTargetVersion::VERSION_NEWEST]) + ->setDefault(PhpUnitTargetVersion::VERSION_NEWEST) + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixer.php new file mode 100644 index 0000000..5fe2c15 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitMockShortWillReturnFixer.php @@ -0,0 +1,124 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Michał Adamski <michal.adamski@gmail.com> + * @author Kuba Werłos <werlos@gmail.com> + */ +final class PhpUnitMockShortWillReturnFixer extends AbstractPhpUnitFixer +{ + /** + * @internal + */ + const RETURN_METHODS_MAP = [ + 'returnargument' => 'willReturnArgument', + 'returncallback' => 'willReturnCallback', + 'returnself' => 'willReturnSelf', + 'returnvalue' => 'willReturn', + 'returnvaluemap' => 'willReturnMap', + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Usage of PHPUnit\'s mock e.g. `->will($this->returnValue(..))` must be replaced by its shorter equivalent such as `->willReturn(...)`.', + [ + new CodeSample('<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testSomeTest() + { + $someMock = $this->createMock(Some::class); + $someMock->method("some")->will($this->returnSelf()); + $someMock->method("some")->will($this->returnValue("example")); + $someMock->method("some")->will($this->returnArgument(2)); + $someMock->method("some")->will($this->returnCallback("str_rot13")); + $someMock->method("some")->will($this->returnValueMap(["a","b","c"])); + } +} +'), + ], + null, + 'Risky when PHPUnit classes are overridden or not accessible, or when project has PHPUnit incompatibilities.' + ); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + + for ($index = $startIndex; $index < $endIndex; ++$index) { + if (!$tokens[$index]->isObjectOperator()) { + continue; + } + + $functionToReplaceIndex = $tokens->getNextMeaningfulToken($index); + if (!$tokens[$functionToReplaceIndex]->equals([T_STRING, 'will'], false)) { + continue; + } + + $functionToReplaceOpeningBraceIndex = $tokens->getNextMeaningfulToken($functionToReplaceIndex); + if (!$tokens[$functionToReplaceOpeningBraceIndex]->equals('(')) { + continue; + } + + $classReferenceIndex = $tokens->getNextMeaningfulToken($functionToReplaceOpeningBraceIndex); + $objectOperatorIndex = $tokens->getNextMeaningfulToken($classReferenceIndex); + $functionToRemoveIndex = $tokens->getNextMeaningfulToken($objectOperatorIndex); + + if (!$functionsAnalyzer->isTheSameClassCall($tokens, $functionToRemoveIndex)) { + continue; + } + + if (!\array_key_exists(strtolower($tokens[$functionToRemoveIndex]->getContent()), self::RETURN_METHODS_MAP)) { + continue; + } + + $openingBraceIndex = $tokens->getNextMeaningfulToken($functionToRemoveIndex); + if (!$tokens[$openingBraceIndex]->equals('(')) { + continue; + } + + $closingBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openingBraceIndex); + + $tokens[$functionToReplaceIndex] = new Token([T_STRING, self::RETURN_METHODS_MAP[strtolower($tokens[$functionToRemoveIndex]->getContent())]]); + $tokens->clearTokenAndMergeSurroundingWhitespace($classReferenceIndex); + $tokens->clearTokenAndMergeSurroundingWhitespace($objectOperatorIndex); + $tokens->clearTokenAndMergeSurroundingWhitespace($functionToRemoveIndex); + $tokens->clearTokenAndMergeSurroundingWhitespace($openingBraceIndex); + $tokens->clearTokenAndMergeSurroundingWhitespace($closingBraceIndex); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php new file mode 100644 index 0000000..2a341cd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php @@ -0,0 +1,230 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpUnitNamespacedFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var string + */ + private $originalClassRegEx; + + /** + * Class Mappings. + * + * * [original classname => new classname] Some classes which match the + * original class regular expression do not have a same-compound name- + * space class and need a dedicated translation table. This trans- + * lation table is defined in @see configure. + * + * @var array|string[] Class Mappings + */ + private $classMap; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + $codeSample = '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testSomething() + { + PHPUnit_Framework_Assert::assertTrue(true); + } +} +'; + + return new FixerDefinition( + 'PHPUnit classes MUST be used in namespaced version, e.g. `\PHPUnit\Framework\TestCase` instead of `\PHPUnit_Framework_TestCase`.', + [ + new CodeSample($codeSample), + new CodeSample($codeSample, ['target' => PhpUnitTargetVersion::VERSION_4_8]), + ], + "PHPUnit v6 has finally fully switched to namespaces.\n" + ."You could start preparing the upgrade by switching from non-namespaced TestCase to namespaced one.\n" + .'Forward compatibility layer (`\PHPUnit\Framework\TestCase` class) was backported to PHPUnit v4.8.35 and PHPUnit v5.4.0.'."\n" + .'Extended forward compatibility layer (`PHPUnit\Framework\Assert`, `PHPUnit\Framework\BaseTestListener`, `PHPUnit\Framework\TestListener` classes) was introduced in v5.7.0.'."\n", + 'Risky when PHPUnit classes are overridden or not accessible, or when project has PHPUnit incompatibilities.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + if (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_6_0)) { + $this->originalClassRegEx = '/^PHPUnit_\w+$/i'; + // @noinspection ClassConstantCanBeUsedInspection + $this->classMap = [ + 'PHPUnit_Extensions_PhptTestCase' => 'PHPUnit\Runner\PhptTestCase', + 'PHPUnit_Framework_Constraint' => 'PHPUnit\Framework\Constraint\Constraint', + 'PHPUnit_Framework_Constraint_StringMatches' => 'PHPUnit\Framework\Constraint\StringMatchesFormatDescription', + 'PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider' => 'PHPUnit\Framework\Constraint\JsonMatchesErrorMessageProvider', + 'PHPUnit_Framework_Constraint_PCREMatch' => 'PHPUnit\Framework\Constraint\RegularExpression', + 'PHPUnit_Framework_Constraint_ExceptionMessageRegExp' => 'PHPUnit\Framework\Constraint\ExceptionMessageRegularExpression', + 'PHPUnit_Framework_Constraint_And' => 'PHPUnit\Framework\Constraint\LogicalAnd', + 'PHPUnit_Framework_Constraint_Or' => 'PHPUnit\Framework\Constraint\LogicalOr', + 'PHPUnit_Framework_Constraint_Not' => 'PHPUnit\Framework\Constraint\LogicalNot', + 'PHPUnit_Framework_Constraint_Xor' => 'PHPUnit\Framework\Constraint\LogicalXor', + 'PHPUnit_Framework_Error' => 'PHPUnit\Framework\Error\Error', + 'PHPUnit_Framework_TestSuite_DataProvider' => 'PHPUnit\Framework\DataProviderTestSuite', + 'PHPUnit_Framework_MockObject_Invocation_Static' => 'PHPUnit\Framework\MockObject\Invocation\StaticInvocation', + 'PHPUnit_Framework_MockObject_Invocation_Object' => 'PHPUnit\Framework\MockObject\Invocation\ObjectInvocation', + 'PHPUnit_Framework_MockObject_Stub_Return' => 'PHPUnit\Framework\MockObject\Stub\ReturnStub', + 'PHPUnit_Runner_Filter_Group_Exclude' => 'PHPUnit\Runner\Filter\ExcludeGroupFilterIterator', + 'PHPUnit_Runner_Filter_Group_Include' => 'PHPUnit\Runner\Filter\IncludeGroupFilterIterator', + 'PHPUnit_Runner_Filter_Test' => 'PHPUnit\Runner\Filter\NameFilterIterator', + 'PHPUnit_Util_PHP' => 'PHPUnit\Util\PHP\AbstractPhpProcess', + 'PHPUnit_Util_PHP_Default' => 'PHPUnit\Util\PHP\DefaultPhpProcess', + 'PHPUnit_Util_PHP_Windows' => 'PHPUnit\Util\PHP\WindowsPhpProcess', + 'PHPUnit_Util_Regex' => 'PHPUnit\Util\RegularExpression', + 'PHPUnit_Util_TestDox_ResultPrinter_XML' => 'PHPUnit\Util\TestDox\XmlResultPrinter', + 'PHPUnit_Util_TestDox_ResultPrinter_HTML' => 'PHPUnit\Util\TestDox\HtmlResultPrinter', + 'PHPUnit_Util_TestDox_ResultPrinter_Text' => 'PHPUnit\Util\TestDox\TextResultPrinter', + 'PHPUnit_Util_TestSuiteIterator' => 'PHPUnit\Framework\TestSuiteIterator', + 'PHPUnit_Util_XML' => 'PHPUnit\Util\Xml', + ]; + } elseif (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_5_7)) { + $this->originalClassRegEx = '/^PHPUnit_Framework_TestCase|PHPUnit_Framework_Assert|PHPUnit_Framework_BaseTestListener|PHPUnit_Framework_TestListener$/i'; + $this->classMap = []; + } else { + $this->originalClassRegEx = '/^PHPUnit_Framework_TestCase$/i'; + $this->classMap = []; + } + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $importedOriginalClassesMap = []; + $currIndex = 0; + + while (null !== $currIndex) { + $currIndex = $tokens->getNextTokenOfKind($currIndex, [[T_STRING]]); + + if (null === $currIndex) { + break; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($currIndex); + if ($tokens[$prevIndex]->isGivenKind([T_CONST, T_DOUBLE_COLON])) { + continue; + } + + $originalClass = $tokens[$currIndex]->getContent(); + + if (1 !== Preg::match($this->originalClassRegEx, $originalClass)) { + ++$currIndex; + + continue; + } + + $substituteTokens = $this->generateReplacement($originalClass); + + $tokens->clearAt($currIndex); + $tokens->insertAt( + $currIndex, + isset($importedOriginalClassesMap[$originalClass]) ? $substituteTokens[$substituteTokens->getSize() - 1] : $substituteTokens + ); + + $prevIndex = $tokens->getPrevMeaningfulToken($currIndex); + if ($tokens[$prevIndex]->isGivenKind(T_USE)) { + $importedOriginalClassesMap[$originalClass] = true; + } elseif ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + $prevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + + if ($tokens[$prevIndex]->isGivenKind(T_USE)) { + $importedOriginalClassesMap[$originalClass] = true; + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('target', 'Target version of PHPUnit.')) + ->setAllowedTypes(['string']) + ->setAllowedValues([PhpUnitTargetVersion::VERSION_4_8, PhpUnitTargetVersion::VERSION_5_7, PhpUnitTargetVersion::VERSION_6_0, PhpUnitTargetVersion::VERSION_NEWEST]) + ->setDefault(PhpUnitTargetVersion::VERSION_NEWEST) + ->getOption(), + ]); + } + + /** + * @param string $originalClassName + * + * @return Tokens + */ + private function generateReplacement($originalClassName) + { + $delimiter = '_'; + $string = $originalClassName; + + if (isset($this->classMap[$originalClassName])) { + $delimiter = '\\'; + $string = $this->classMap[$originalClassName]; + } + + $parts = explode($delimiter, $string); + + $tokensArray = []; + while (!empty($parts)) { + $tokensArray[] = new Token([T_STRING, array_shift($parts)]); + if (!empty($parts)) { + $tokensArray[] = new Token([T_NS_SEPARATOR, '\\']); + } + } + + return Tokens::fromArray($tokensArray); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitNoExpectationAnnotationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitNoExpectationAnnotationFixer.php new file mode 100644 index 0000000..8914797 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitNoExpectationAnnotationFixer.php @@ -0,0 +1,274 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpUnitNoExpectationAnnotationFixer extends AbstractPhpUnitFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @var bool + */ + private $fixMessageRegExp; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->fixMessageRegExp = PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_4_3); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Usages of `@expectedException*` annotations MUST be replaced by `->setExpectedException*` methods.', + [ + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException FooException + * @expectedExceptionMessageRegExp /foo.*$/ + * @expectedExceptionCode 123 + */ + function testAaa() + { + aaa(); + } +} +' + ), + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException FooException + * @expectedExceptionCode 123 + */ + function testBbb() + { + bbb(); + } + + /** + * @expectedException FooException + * @expectedExceptionMessageRegExp /foo.*$/ + */ + function testCcc() + { + ccc(); + } +} +', + ['target' => PhpUnitTargetVersion::VERSION_3_2] + ), + ], + null, + 'Risky when PHPUnit classes are overridden or not accessible, or when project has PHPUnit incompatibilities.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoEmptyPhpdocFixer, PhpUnitExpectationFixer. + */ + public function getPriority() + { + return 10; + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('target', 'Target version of PHPUnit.')) + ->setAllowedTypes(['string']) + ->setAllowedValues([PhpUnitTargetVersion::VERSION_3_2, PhpUnitTargetVersion::VERSION_4_3, PhpUnitTargetVersion::VERSION_NEWEST]) + ->setDefault(PhpUnitTargetVersion::VERSION_NEWEST) + ->getOption(), + (new FixerOptionBuilder('use_class_const', 'Use ::class notation.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($i = $endIndex - 1; $i > $startIndex; --$i) { + if (!$tokens[$i]->isGivenKind(T_FUNCTION) || $tokensAnalyzer->isLambda($i)) { + continue; + } + + $functionIndex = $i; + $docBlockIndex = $i; + + // ignore abstract functions + $braceIndex = $tokens->getNextTokenOfKind($functionIndex, [';', '{']); + if (!$tokens[$braceIndex]->equals('{')) { + continue; + } + + do { + $docBlockIndex = $tokens->getPrevNonWhitespace($docBlockIndex); + } while ($tokens[$docBlockIndex]->isGivenKind([T_PUBLIC, T_PROTECTED, T_PRIVATE, T_FINAL, T_ABSTRACT, T_COMMENT])); + + if (!$tokens[$docBlockIndex]->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $doc = new DocBlock($tokens[$docBlockIndex]->getContent()); + $annotations = []; + + foreach ($doc->getAnnotationsOfType([ + 'expectedException', + 'expectedExceptionCode', + 'expectedExceptionMessage', + 'expectedExceptionMessageRegExp', + ]) as $annotation) { + $tag = $annotation->getTag()->getName(); + $content = $this->extractContentFromAnnotation($annotation); + $annotations[$tag] = $content; + $annotation->remove(); + } + + if (!isset($annotations['expectedException'])) { + continue; + } + if (!$this->fixMessageRegExp && isset($annotations['expectedExceptionMessageRegExp'])) { + continue; + } + + $originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $docBlockIndex); + + $paramList = $this->annotationsToParamList($annotations); + + $newMethodsCode = '<?php $this->' + .(isset($annotations['expectedExceptionMessageRegExp']) ? 'setExpectedExceptionRegExp' : 'setExpectedException') + .'(' + .implode(', ', $paramList) + .');'; + $newMethods = Tokens::fromCode($newMethodsCode); + $newMethods[0] = new Token([ + T_WHITESPACE, + $this->whitespacesConfig->getLineEnding().$originalIndent.$this->whitespacesConfig->getIndent(), + ]); + + // apply changes + $docContent = $doc->getContent(); + if ('' === $docContent) { + $docContent = '/** */'; + } + $tokens[$docBlockIndex] = new Token([T_DOC_COMMENT, $docContent]); + $tokens->insertAt($braceIndex + 1, $newMethods); + + $whitespaceIndex = $braceIndex + $newMethods->getSize() + 1; + $tokens[$whitespaceIndex] = new Token([ + T_WHITESPACE, + $this->whitespacesConfig->getLineEnding().$tokens[$whitespaceIndex]->getContent(), + ]); + + $i = $docBlockIndex; + } + } + + /** + * @return string + */ + private function extractContentFromAnnotation(Annotation $annotation) + { + $tag = $annotation->getTag()->getName(); + + if (1 !== Preg::match('/@'.$tag.'\s+(.+)$/s', $annotation->getContent(), $matches)) { + return ''; + } + + $content = Preg::replace('/\*+\/$/', '', $matches[1]); + + if (Preg::match('/\R/u', $content)) { + $content = Preg::replace('/\s*\R+\s*\*\s*/u', ' ', $content); + } + + return rtrim($content); + } + + private function annotationsToParamList(array $annotations) + { + $params = []; + $exceptionClass = ltrim($annotations['expectedException'], '\\'); + if (false !== strpos($exceptionClass, '*')) { + $exceptionClass = substr($exceptionClass, 0, strpos($exceptionClass, '*')); + } + $exceptionClass = trim($exceptionClass); + + if ($this->configuration['use_class_const']) { + $params[] = "\\{$exceptionClass}::class"; + } else { + $params[] = "'{$exceptionClass}'"; + } + + if (isset($annotations['expectedExceptionMessage'])) { + $params[] = var_export($annotations['expectedExceptionMessage'], true); + } elseif (isset($annotations['expectedExceptionMessageRegExp'])) { + $params[] = var_export($annotations['expectedExceptionMessageRegExp'], true); + } elseif (isset($annotations['expectedExceptionCode'])) { + $params[] = 'null'; + } + + if (isset($annotations['expectedExceptionCode'])) { + $params[] = $annotations['expectedExceptionCode']; + } + + return $params; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitOrderedCoversFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitOrderedCoversFixer.php new file mode 100644 index 0000000..9193608 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitOrderedCoversFixer.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\Fixer\Phpdoc\PhpdocOrderByValueFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @deprecated since 2.16, replaced by PhpdocOrderByValueFixer + * + * @todo To be removed at 3.0 + * + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class PhpUnitOrderedCoversFixer extends AbstractProxyFixer implements DeprecatedFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Order `@covers` annotation of PHPUnit tests.', + [ + new CodeSample( + '<?php +/** + * @covers Foo + * @covers Bar + */ +final class MyTest extends \PHPUnit_Framework_TestCase +{} +' + ), + ] + ); + } + + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + protected function createProxyFixers() + { + $fixer = new PhpdocOrderByValueFixer(); + + $fixer->configure([ + 'annotations' => [ + 'covers', + ], + ]); + + return [ + $fixer, + ]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitSetUpTearDownVisibilityFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitSetUpTearDownVisibilityFixer.php new file mode 100644 index 0000000..1c43a95 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitSetUpTearDownVisibilityFixer.php @@ -0,0 +1,119 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Gert de Pagter + */ +final class PhpUnitSetUpTearDownVisibilityFixer extends AbstractPhpUnitFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Changes the visibility of the `setUp()` and `tearDown()` functions of PHPUnit to `protected`, to match the PHPUnit TestCase.', + [ + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + private $hello; + public function setUp() + { + $this->hello = "hello"; + } + + public function tearDown() + { + $this->hello = null; + } +} +' + ), + ], + null, + 'This fixer may change functions named `setUp()` or `tearDown()` outside of PHPUnit tests, '. + 'when a class is wrongly seen as a PHPUnit test.' + ); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $counter = 0; + $tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($i = $endIndex - 1; $i > $startIndex; --$i) { + if (2 === $counter) { + break; // we've seen both method we are interested in, so stop analyzing this class + } + + if (!$this->isSetupOrTearDownMethod($tokens, $i)) { + continue; + } + + ++$counter; + $visibility = $tokensAnalyzer->getMethodAttributes($i)['visibility']; + + if (T_PUBLIC === $visibility) { + $index = $tokens->getPrevTokenOfKind($i, [[T_PUBLIC]]); + $tokens[$index] = new Token([T_PROTECTED, 'protected']); + + continue; + } + + if (null === $visibility) { + $tokens->insertAt($i, [new Token([T_PROTECTED, 'protected']), new Token([T_WHITESPACE, ' '])]); + } + } + } + + /** + * @param int $index + * + * @return bool + */ + private function isSetupOrTearDownMethod(Tokens $tokens, $index) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + + $isMethod = $tokens[$index]->isGivenKind(T_FUNCTION) && !$tokensAnalyzer->isLambda($index); + if (!$isMethod) { + return false; + } + + $functionNameIndex = $tokens->getNextMeaningfulToken($index); + $functionName = strtolower($tokens[$functionNameIndex]->getContent()); + + return 'setup' === $functionName || 'teardown' === $functionName; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitSizeClassFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitSizeClassFixer.php new file mode 100644 index 0000000..f571024 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitSizeClassFixer.php @@ -0,0 +1,206 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\Line; +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Jefersson Nathan <malukenho.dev@gmail.com> + */ +final class PhpUnitSizeClassFixer extends AbstractPhpUnitFixer implements WhitespacesAwareFixerInterface, ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'All PHPUnit test cases should have `@small`, `@medium` or `@large` annotation to enable run time limits.', + [ + new CodeSample("<?php\nclass MyTest extends TestCase {}\n"), + new CodeSample("<?php\nclass MyTest extends TestCase {}\n", ['group' => 'medium']), + ], + 'The special groups [small, medium, large] provides a way to identify tests that are taking long to be executed.' + ); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('group', 'Define a specific group to be used in case no group is already in use')) + ->setAllowedValues(['small', 'medium', 'large']) + ->setDefault('small') + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $classIndex = $tokens->getPrevTokenOfKind($startIndex, [[T_CLASS]]); + + if ($this->isAbstractClass($tokens, $classIndex)) { + return; + } + + $docBlockIndex = $this->getDocBlockIndex($tokens, $classIndex); + + if ($this->isPHPDoc($tokens, $docBlockIndex)) { + $this->updateDocBlockIfNeeded($tokens, $docBlockIndex); + } else { + $this->createDocBlock($tokens, $docBlockIndex); + } + } + + /** + * @param int $i + * + * @return bool + */ + private function isAbstractClass(Tokens $tokens, $i) + { + $typeIndex = $tokens->getPrevMeaningfulToken($i); + + return $tokens[$typeIndex]->isGivenKind(T_ABSTRACT); + } + + private function createDocBlock(Tokens $tokens, $docBlockIndex) + { + $lineEnd = $this->whitespacesConfig->getLineEnding(); + $originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $tokens->getNextNonWhitespace($docBlockIndex)); + $group = $this->configuration['group']; + $toInsert = [ + new Token([T_DOC_COMMENT, '/**'.$lineEnd."{$originalIndent} * @".$group.$lineEnd."{$originalIndent} */"]), + new Token([T_WHITESPACE, $lineEnd.$originalIndent]), + ]; + $index = $tokens->getNextMeaningfulToken($docBlockIndex); + $tokens->insertAt($index, $toInsert); + } + + private function updateDocBlockIfNeeded(Tokens $tokens, $docBlockIndex) + { + $doc = new DocBlock($tokens[$docBlockIndex]->getContent()); + if (!empty($this->filterDocBlock($doc))) { + return; + } + $doc = $this->makeDocBlockMultiLineIfNeeded($doc, $tokens, $docBlockIndex); + $lines = $this->addSizeAnnotation($doc, $tokens, $docBlockIndex); + $lines = implode('', $lines); + + $tokens[$docBlockIndex] = new Token([T_DOC_COMMENT, $lines]); + } + + /** + * @param int $docBlockIndex + * + * @return Line[] + */ + private function addSizeAnnotation(DocBlock $docBlock, Tokens $tokens, $docBlockIndex) + { + $lines = $docBlock->getLines(); + $originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $docBlockIndex); + $lineEnd = $this->whitespacesConfig->getLineEnding(); + $group = $this->configuration['group']; + array_splice($lines, -1, 0, $originalIndent.' *'.$lineEnd.$originalIndent.' * @'.$group.$lineEnd); + + return $lines; + } + + /** + * @param int $docBlockIndex + * + * @return DocBlock + */ + private function makeDocBlockMultiLineIfNeeded(DocBlock $doc, Tokens $tokens, $docBlockIndex) + { + $lines = $doc->getLines(); + if (1 === \count($lines) && empty($this->filterDocBlock($doc))) { + $lines = $this->splitUpDocBlock($lines, $tokens, $docBlockIndex); + + return new DocBlock(implode('', $lines)); + } + + return $doc; + } + + /** + * Take a one line doc block, and turn it into a multi line doc block. + * + * @param Line[] $lines + * @param int $docBlockIndex + * + * @return Line[] + */ + private function splitUpDocBlock($lines, Tokens $tokens, $docBlockIndex) + { + $lineContent = $this->getSingleLineDocBlockEntry($lines[0]); + $lineEnd = $this->whitespacesConfig->getLineEnding(); + $originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $tokens->getNextNonWhitespace($docBlockIndex)); + + return [ + new Line('/**'.$lineEnd), + new Line($originalIndent.' * '.$lineContent.$lineEnd), + new Line($originalIndent.' */'), + ]; + } + + /** + * @return string + */ + private function getSingleLineDocBlockEntry(Line $line) + { + $line = $line->getContent(); + $line = str_replace('*/', '', $line); + $line = trim($line); + $line = str_split($line); + $i = \count($line); + do { + --$i; + } while ('*' !== $line[$i] && '*' !== $line[$i - 1] && '/' !== $line[$i - 2]); + if (' ' === $line[$i]) { + ++$i; + } + $line = \array_slice($line, $i); + + return implode('', $line); + } + + /** + * @return Annotation[][] + */ + private function filterDocBlock(DocBlock $doc) + { + return array_filter([ + $doc->getAnnotationsOfType('small'), + $doc->getAnnotationsOfType('large'), + $doc->getAnnotationsOfType('medium'), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitStrictFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitStrictFixer.php new file mode 100644 index 0000000..0d85725 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitStrictFixer.php @@ -0,0 +1,146 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpUnitStrictFixer extends AbstractPhpUnitFixer implements ConfigurationDefinitionFixerInterface +{ + private static $assertionMap = [ + 'assertAttributeEquals' => 'assertAttributeSame', + 'assertAttributeNotEquals' => 'assertAttributeNotSame', + 'assertEquals' => 'assertSame', + 'assertNotEquals' => 'assertNotSame', + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHPUnit methods like `assertSame` should be used instead of `assertEquals`.', + [ + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testSomeTest() + { + $this->assertAttributeEquals(a(), b()); + $this->assertAttributeNotEquals(a(), b()); + $this->assertEquals(a(), b()); + $this->assertNotEquals(a(), b()); + } +} +' + ), + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testSomeTest() + { + $this->assertAttributeEquals(a(), b()); + $this->assertAttributeNotEquals(a(), b()); + $this->assertEquals(a(), b()); + $this->assertNotEquals(a(), b()); + } +} +', + ['assertions' => ['assertEquals']] + ), + ], + null, + 'Risky when any of the functions are overridden or when testing object equality.' + ); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $argumentsAnalyzer = new ArgumentsAnalyzer(); + $functionsAnalyzer = new FunctionsAnalyzer(); + + foreach ($this->configuration['assertions'] as $methodBefore) { + $methodAfter = self::$assertionMap[$methodBefore]; + + for ($index = $startIndex; $index < $endIndex; ++$index) { + $methodIndex = $tokens->getNextTokenOfKind($index, [[T_STRING, $methodBefore]]); + + if (null === $methodIndex) { + break; + } + + if (!$functionsAnalyzer->isTheSameClassCall($tokens, $methodIndex)) { + continue; + } + + $openingParenthesisIndex = $tokens->getNextMeaningfulToken($methodIndex); + $argumentsCount = $argumentsAnalyzer->countArguments( + $tokens, + $openingParenthesisIndex, + $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openingParenthesisIndex) + ); + + if (2 === $argumentsCount || 3 === $argumentsCount) { + $tokens[$methodIndex] = new Token([T_STRING, $methodAfter]); + } + + $index = $methodIndex; + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolverRootless('assertions', [ + (new FixerOptionBuilder('assertions', 'List of assertion methods to fix.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset(array_keys(self::$assertionMap))]) + ->setDefault([ + 'assertAttributeEquals', + 'assertAttributeNotEquals', + 'assertEquals', + 'assertNotEquals', + ]) + ->getOption(), + ], $this->getName()); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTargetVersion.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTargetVersion.php new file mode 100644 index 0000000..054158c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTargetVersion.php @@ -0,0 +1,62 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use Composer\Semver\Comparator; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class PhpUnitTargetVersion +{ + const VERSION_3_0 = '3.0'; + const VERSION_3_2 = '3.2'; + const VERSION_3_5 = '3.5'; + const VERSION_4_3 = '4.3'; + const VERSION_4_8 = '4.8'; + const VERSION_5_0 = '5.0'; + const VERSION_5_2 = '5.2'; + const VERSION_5_4 = '5.4'; + const VERSION_5_5 = '5.5'; + const VERSION_5_6 = '5.6'; + const VERSION_5_7 = '5.7'; + const VERSION_6_0 = '6.0'; + const VERSION_7_5 = '7.5'; + const VERSION_8_4 = '8.4'; + const VERSION_NEWEST = 'newest'; + + private function __construct() + { + } + + /** + * @param string $candidate + * @param string $target + * + * @return bool + */ + public static function fulfills($candidate, $target) + { + if (self::VERSION_NEWEST === $target) { + throw new \LogicException(sprintf('Parameter `target` shall not be provided as "%s", determine proper target for tested PHPUnit feature instead.', self::VERSION_NEWEST)); + } + + if (self::VERSION_NEWEST === $candidate) { + return true; + } + + return Comparator::greaterThanOrEqualTo($candidate, $target); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php new file mode 100644 index 0000000..9efaea7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php @@ -0,0 +1,477 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\Line; +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Gert de Pagter + */ +final class PhpUnitTestAnnotationFixer extends AbstractPhpUnitFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Adds or removes @test annotations from tests, following configuration.', + [ + new CodeSample('<?php +class Test extends \\PhpUnit\\FrameWork\\TestCase +{ + /** + * @test + */ + public function itDoesSomething() {} }'.$this->whitespacesConfig->getLineEnding()), + new CodeSample('<?php +class Test extends \\PhpUnit\\FrameWork\\TestCase +{ +public function testItDoesSomething() {}}'.$this->whitespacesConfig->getLineEnding(), ['style' => 'annotation']), + ], + null, + 'This fixer may change the name of your tests, and could cause incompatibility with'. + ' abstract classes or interfaces.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoEmptyPhpdocFixer, PhpUnitMethodCasingFixer, PhpdocTrimFixer. + */ + public function getPriority() + { + return 10; + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + if ('annotation' === $this->configuration['style']) { + $this->applyTestAnnotation($tokens, $startIndex, $endIndex); + } else { + $this->applyTestPrefix($tokens, $startIndex, $endIndex); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('style', 'Whether to use the @test annotation or not.')) + ->setAllowedValues(['prefix', 'annotation']) + ->setDefault('prefix') + ->getOption(), + (new FixerOptionBuilder('case', 'Whether to camel or snake case when adding the test prefix')) + ->setAllowedValues(['camel', 'snake']) + ->setDefault('camel') + ->setDeprecationMessage('Use `php_unit_method_casing` fixer instead.') + ->getOption(), + ]); + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function applyTestAnnotation(Tokens $tokens, $startIndex, $endIndex) + { + for ($i = $endIndex - 1; $i > $startIndex; --$i) { + if (!$this->isTestMethod($tokens, $i)) { + continue; + } + + $functionNameIndex = $tokens->getNextMeaningfulToken($i); + $functionName = $tokens[$functionNameIndex]->getContent(); + + if ($this->hasTestPrefix($functionName) && !$this->hasProperTestAnnotation($tokens, $i)) { + $newFunctionName = $this->removeTestPrefix($functionName); + $tokens[$functionNameIndex] = new Token([T_STRING, $newFunctionName]); + } + + $docBlockIndex = $this->getDocBlockIndex($tokens, $i); + + if ($this->isPHPDoc($tokens, $docBlockIndex)) { + $lines = $this->updateDocBlock($tokens, $docBlockIndex); + $lines = $this->addTestAnnotation($lines, $tokens, $docBlockIndex); + $lines = implode('', $lines); + + $tokens[$docBlockIndex] = new Token([T_DOC_COMMENT, $lines]); + } else { + // Create a new docblock if it didn't have one before; + $this->createDocBlock($tokens, $docBlockIndex); + } + } + } + + /** + * @param int $startIndex + * @param int $endIndex + */ + private function applyTestPrefix(Tokens $tokens, $startIndex, $endIndex) + { + for ($i = $endIndex - 1; $i > $startIndex; --$i) { + // We explicitly check again if the function has a doc block to save some time. + if (!$this->isTestMethod($tokens, $i)) { + continue; + } + + $docBlockIndex = $this->getDocBlockIndex($tokens, $i); + + if (!$this->isPHPDoc($tokens, $docBlockIndex)) { + continue; + } + + $lines = $this->updateDocBlock($tokens, $docBlockIndex); + $lines = implode('', $lines); + $tokens[$docBlockIndex] = new Token([T_DOC_COMMENT, $lines]); + + $functionNameIndex = $tokens->getNextMeaningfulToken($i); + $functionName = $tokens[$functionNameIndex]->getContent(); + + if ($this->hasTestPrefix($functionName)) { + continue; + } + + $newFunctionName = $this->addTestPrefix($functionName); + $tokens[$functionNameIndex] = new Token([T_STRING, $newFunctionName]); + } + } + + /** + * @param int$index + * + * @return bool + */ + private function isTestMethod(Tokens $tokens, $index) + { + // Check if we are dealing with a (non abstract, non lambda) function + if (!$this->isMethod($tokens, $index)) { + return false; + } + + // if the function name starts with test its a test + $functionNameIndex = $tokens->getNextMeaningfulToken($index); + $functionName = $tokens[$functionNameIndex]->getContent(); + + if ($this->hasTestPrefix($functionName)) { + return true; + } + + $docBlockIndex = $this->getDocBlockIndex($tokens, $index); + + // If the function doesn't have test in its name, and no doc block, its not a test + return + $this->isPHPDoc($tokens, $docBlockIndex) + && false !== strpos($tokens[$docBlockIndex]->getContent(), '@test') + ; + } + + /** + * @param int $index + * + * @return bool + */ + private function isMethod(Tokens $tokens, $index) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + + return $tokens[$index]->isGivenKind(T_FUNCTION) && !$tokensAnalyzer->isLambda($index); + } + + /** + * @param string $functionName + * + * @return bool + */ + private function hasTestPrefix($functionName) + { + return 0 === strpos($functionName, 'test'); + } + + /** + * @param int $index + * + * @return bool + */ + private function hasProperTestAnnotation(Tokens $tokens, $index) + { + $docBlockIndex = $this->getDocBlockIndex($tokens, $index); + $doc = $tokens[$docBlockIndex]->getContent(); + + return 1 === Preg::match('/\*\s+@test\b/', $doc); + } + + /** + * @param string $functionName + * + * @return string + */ + private function removeTestPrefix($functionName) + { + $remainder = Preg::replace('/^test(?=[A-Z_])_?/', '', $functionName); + + if ('' === $remainder) { + return $functionName; + } + + return lcfirst($remainder); + } + + /** + * @param string $functionName + * + * @return string + */ + private function addTestPrefix($functionName) + { + if ('camel' !== $this->configuration['case']) { + return 'test_'.$functionName; + } + + return 'test'.ucfirst($functionName); + } + + /** + * @param int $docBlockIndex + */ + private function createDocBlock(Tokens $tokens, $docBlockIndex) + { + $lineEnd = $this->whitespacesConfig->getLineEnding(); + $originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $tokens->getNextNonWhitespace($docBlockIndex)); + $toInsert = [ + new Token([T_DOC_COMMENT, '/**'.$lineEnd."{$originalIndent} * @test".$lineEnd."{$originalIndent} */"]), + new Token([T_WHITESPACE, $lineEnd.$originalIndent]), + ]; + $index = $tokens->getNextMeaningfulToken($docBlockIndex); + $tokens->insertAt($index, $toInsert); + } + + /** + * @param int $docBlockIndex + * + * @return Line[] + */ + private function updateDocBlock(Tokens $tokens, $docBlockIndex) + { + $doc = new DocBlock($tokens[$docBlockIndex]->getContent()); + $lines = $doc->getLines(); + + return $this->updateLines($lines, $tokens, $docBlockIndex); + } + + /** + * @param Line[] $lines + * @param int $docBlockIndex + * + * @return Line[] + */ + private function updateLines($lines, Tokens $tokens, $docBlockIndex) + { + $needsAnnotation = 'annotation' === $this->configuration['style']; + + $doc = new DocBlock($tokens[$docBlockIndex]->getContent()); + for ($i = 0; $i < \count($lines); ++$i) { + // If we need to add test annotation and it is a single line comment we need to deal with that separately + if ($needsAnnotation && ($lines[$i]->isTheStart() && $lines[$i]->isTheEnd())) { + if (!$this->doesDocBlockContainTest($doc)) { + $lines = $this->splitUpDocBlock($lines, $tokens, $docBlockIndex); + + return $this->updateLines($lines, $tokens, $docBlockIndex); + } + // One we split it up, we run the function again, so we deal with other things in a proper way + } + + if (!$needsAnnotation + && false !== strpos($lines[$i]->getContent(), ' @test') + && false === strpos($lines[$i]->getContent(), '@testWith') + && false === strpos($lines[$i]->getContent(), '@testdox') + ) { + // We remove @test from the doc block + $lines[$i] = new Line(str_replace(' @test', '', $lines[$i]->getContent())); + } + // ignore the line if it isn't @depends + if (false === strpos($lines[$i]->getContent(), '@depends')) { + continue; + } + + $lines[$i] = $this->updateDependsAnnotation($lines[$i]); + } + + return $lines; + } + + /** + * Take a one line doc block, and turn it into a multi line doc block. + * + * @param Line[] $lines + * @param int $docBlockIndex + * + * @return Line[] + */ + private function splitUpDocBlock($lines, Tokens $tokens, $docBlockIndex) + { + $lineContent = $this->getSingleLineDocBlockEntry($lines); + $lineEnd = $this->whitespacesConfig->getLineEnding(); + $originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $tokens->getNextNonWhitespace($docBlockIndex)); + + return [ + new Line('/**'.$lineEnd), + new Line($originalIndent.' * '.$lineContent.$lineEnd), + new Line($originalIndent.' */'), + ]; + } + + /** + * @param Line[] $lines + * + * @return string + */ + private function getSingleLineDocBlockEntry(array $lines) + { + $line = $lines[0]; + $line = str_replace('*/', '', $line->getContent()); + $line = trim($line); + $line = str_split($line); + $i = \count($line); + do { + --$i; + } while ('*' !== $line[$i] && '*' !== $line[$i - 1] && '/' !== $line[$i - 2]); + if (' ' === $line[$i]) { + ++$i; + } + $line = \array_slice($line, $i); + + return implode('', $line); + } + + /** + * Updates the depends tag on the current doc block. + * + * @return Line + */ + private function updateDependsAnnotation(Line $line) + { + if ('annotation' === $this->configuration['style']) { + return $this->removeTestPrefixFromDependsAnnotation($line); + } + + return $this->addTestPrefixToDependsAnnotation($line); + } + + /** + * @return Line + */ + private function removeTestPrefixFromDependsAnnotation(Line $line) + { + $line = str_split($line->getContent()); + + $dependsIndex = $this->findWhereDependsFunctionNameStarts($line); + $dependsFunctionName = implode('', \array_slice($line, $dependsIndex)); + + if ($this->hasTestPrefix($dependsFunctionName)) { + $dependsFunctionName = $this->removeTestPrefix($dependsFunctionName); + } + array_splice($line, $dependsIndex); + + return new Line(implode('', $line).$dependsFunctionName); + } + + /** + * @return Line + */ + private function addTestPrefixToDependsAnnotation(Line $line) + { + $line = str_split($line->getContent()); + $dependsIndex = $this->findWhereDependsFunctionNameStarts($line); + $dependsFunctionName = implode('', \array_slice($line, $dependsIndex)); + + if (!$this->hasTestPrefix($dependsFunctionName)) { + $dependsFunctionName = $this->addTestPrefix($dependsFunctionName); + } + + array_splice($line, $dependsIndex); + + return new Line(implode('', $line).$dependsFunctionName); + } + + /** + * Helps to find where the function name in the doc block starts. + * + * @return int + */ + private function findWhereDependsFunctionNameStarts(array $line) + { + $counter = \count($line); + + do { + --$counter; + } while (' ' !== $line[$counter]); + + return $counter + 1; + } + + /** + * @param Line[] $lines + * @param int $docBlockIndex + * + * @return Line[] + */ + private function addTestAnnotation($lines, Tokens $tokens, $docBlockIndex) + { + $doc = new DocBlock($tokens[$docBlockIndex]->getContent()); + + if (!$this->doesDocBlockContainTest($doc)) { + $originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $docBlockIndex); + $lineEnd = $this->whitespacesConfig->getLineEnding(); + + array_splice($lines, -1, 0, $originalIndent.' *'.$lineEnd.$originalIndent.' * @test'.$lineEnd); + } + + return $lines; + } + + /** + * @return bool + */ + private function doesDocBlockContainTest(DocBlock $doc) + { + return !empty($doc->getAnnotationsOfType('test')); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixer.php new file mode 100644 index 0000000..605dcee --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestCaseStaticMethodCallsFixer.php @@ -0,0 +1,482 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class PhpUnitTestCaseStaticMethodCallsFixer extends AbstractPhpUnitFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @internal + */ + const CALL_TYPE_THIS = 'this'; + + /** + * @internal + */ + const CALL_TYPE_SELF = 'self'; + + /** + * @internal + */ + const CALL_TYPE_STATIC = 'static'; + + private $allowedValues = [ + self::CALL_TYPE_THIS => true, + self::CALL_TYPE_SELF => true, + self::CALL_TYPE_STATIC => true, + ]; + + private $staticMethods = [ + // Assert methods + 'anything' => true, + 'arrayHasKey' => true, + 'assertArrayHasKey' => true, + 'assertArrayNotHasKey' => true, + 'assertArraySubset' => true, + 'assertAttributeContains' => true, + 'assertAttributeContainsOnly' => true, + 'assertAttributeCount' => true, + 'assertAttributeEmpty' => true, + 'assertAttributeEquals' => true, + 'assertAttributeGreaterThan' => true, + 'assertAttributeGreaterThanOrEqual' => true, + 'assertAttributeInstanceOf' => true, + 'assertAttributeInternalType' => true, + 'assertAttributeLessThan' => true, + 'assertAttributeLessThanOrEqual' => true, + 'assertAttributeNotContains' => true, + 'assertAttributeNotContainsOnly' => true, + 'assertAttributeNotCount' => true, + 'assertAttributeNotEmpty' => true, + 'assertAttributeNotEquals' => true, + 'assertAttributeNotInstanceOf' => true, + 'assertAttributeNotInternalType' => true, + 'assertAttributeNotSame' => true, + 'assertAttributeSame' => true, + 'assertClassHasAttribute' => true, + 'assertClassHasStaticAttribute' => true, + 'assertClassNotHasAttribute' => true, + 'assertClassNotHasStaticAttribute' => true, + 'assertContains' => true, + 'assertContainsEquals' => true, + 'assertContainsOnly' => true, + 'assertContainsOnlyInstancesOf' => true, + 'assertCount' => true, + 'assertDirectoryDoesNotExist' => true, + 'assertDirectoryExists' => true, + 'assertDirectoryIsNotReadable' => true, + 'assertDirectoryIsNotWritable' => true, + 'assertDirectoryIsReadable' => true, + 'assertDirectoryIsWritable' => true, + 'assertDirectoryNotExists' => true, + 'assertDirectoryNotIsReadable' => true, + 'assertDirectoryNotIsWritable' => true, + 'assertDoesNotMatchRegularExpression' => true, + 'assertEmpty' => true, + 'assertEqualXMLStructure' => true, + 'assertEquals' => true, + 'assertEqualsCanonicalizing' => true, + 'assertEqualsIgnoringCase' => true, + 'assertEqualsWithDelta' => true, + 'assertFalse' => true, + 'assertFileDoesNotExist' => true, + 'assertFileEquals' => true, + 'assertFileEqualsCanonicalizing' => true, + 'assertFileEqualsIgnoringCase' => true, + 'assertFileExists' => true, + 'assertFileIsNotReadable' => true, + 'assertFileIsNotWritable' => true, + 'assertFileIsReadable' => true, + 'assertFileIsWritable' => true, + 'assertFileNotEquals' => true, + 'assertFileNotEqualsCanonicalizing' => true, + 'assertFileNotEqualsIgnoringCase' => true, + 'assertFileNotExists' => true, + 'assertFileNotIsReadable' => true, + 'assertFileNotIsWritable' => true, + 'assertFinite' => true, + 'assertGreaterThan' => true, + 'assertGreaterThanOrEqual' => true, + 'assertInfinite' => true, + 'assertInstanceOf' => true, + 'assertInternalType' => true, + 'assertIsArray' => true, + 'assertIsBool' => true, + 'assertIsCallable' => true, + 'assertIsClosedResource' => true, + 'assertIsFloat' => true, + 'assertIsInt' => true, + 'assertIsIterable' => true, + 'assertIsNotArray' => true, + 'assertIsNotBool' => true, + 'assertIsNotCallable' => true, + 'assertIsNotClosedResource' => true, + 'assertIsNotFloat' => true, + 'assertIsNotInt' => true, + 'assertIsNotIterable' => true, + 'assertIsNotNumeric' => true, + 'assertIsNotObject' => true, + 'assertIsNotReadable' => true, + 'assertIsNotResource' => true, + 'assertIsNotScalar' => true, + 'assertIsNotString' => true, + 'assertIsNotWritable' => true, + 'assertIsNumeric' => true, + 'assertIsObject' => true, + 'assertIsReadable' => true, + 'assertIsResource' => true, + 'assertIsScalar' => true, + 'assertIsString' => true, + 'assertIsWritable' => true, + 'assertJson' => true, + 'assertJsonFileEqualsJsonFile' => true, + 'assertJsonFileNotEqualsJsonFile' => true, + 'assertJsonStringEqualsJsonFile' => true, + 'assertJsonStringEqualsJsonString' => true, + 'assertJsonStringNotEqualsJsonFile' => true, + 'assertJsonStringNotEqualsJsonString' => true, + 'assertLessThan' => true, + 'assertLessThanOrEqual' => true, + 'assertMatchesRegularExpression' => true, + 'assertNan' => true, + 'assertNotContains' => true, + 'assertNotContainsEquals' => true, + 'assertNotContainsOnly' => true, + 'assertNotCount' => true, + 'assertNotEmpty' => true, + 'assertNotEquals' => true, + 'assertNotEqualsCanonicalizing' => true, + 'assertNotEqualsIgnoringCase' => true, + 'assertNotEqualsWithDelta' => true, + 'assertNotFalse' => true, + 'assertNotInstanceOf' => true, + 'assertNotInternalType' => true, + 'assertNotIsReadable' => true, + 'assertNotIsWritable' => true, + 'assertNotNull' => true, + 'assertNotRegExp' => true, + 'assertNotSame' => true, + 'assertNotSameSize' => true, + 'assertNotTrue' => true, + 'assertNull' => true, + 'assertObjectEquals' => true, + 'assertObjectHasAttribute' => true, + 'assertObjectNotHasAttribute' => true, + 'assertRegExp' => true, + 'assertSame' => true, + 'assertSameSize' => true, + 'assertStringContainsString' => true, + 'assertStringContainsStringIgnoringCase' => true, + 'assertStringEndsNotWith' => true, + 'assertStringEndsWith' => true, + 'assertStringEqualsFile' => true, + 'assertStringEqualsFileCanonicalizing' => true, + 'assertStringEqualsFileIgnoringCase' => true, + 'assertStringMatchesFormat' => true, + 'assertStringMatchesFormatFile' => true, + 'assertStringNotContainsString' => true, + 'assertStringNotContainsStringIgnoringCase' => true, + 'assertStringNotEqualsFile' => true, + 'assertStringNotEqualsFileCanonicalizing' => true, + 'assertStringNotEqualsFileIgnoringCase' => true, + 'assertStringNotMatchesFormat' => true, + 'assertStringNotMatchesFormatFile' => true, + 'assertStringStartsNotWith' => true, + 'assertStringStartsWith' => true, + 'assertThat' => true, + 'assertTrue' => true, + 'assertXmlFileEqualsXmlFile' => true, + 'assertXmlFileNotEqualsXmlFile' => true, + 'assertXmlStringEqualsXmlFile' => true, + 'assertXmlStringEqualsXmlString' => true, + 'assertXmlStringNotEqualsXmlFile' => true, + 'assertXmlStringNotEqualsXmlString' => true, + 'attribute' => true, + 'attributeEqualTo' => true, + 'callback' => true, + 'classHasAttribute' => true, + 'classHasStaticAttribute' => true, + 'contains' => true, + 'containsEqual' => true, + 'containsIdentical' => true, + 'containsOnly' => true, + 'containsOnlyInstancesOf' => true, + 'countOf' => true, + 'directoryExists' => true, + 'equalTo' => true, + 'equalToCanonicalizing' => true, + 'equalToIgnoringCase' => true, + 'equalToWithDelta' => true, + 'fail' => true, + 'fileExists' => true, + 'getCount' => true, + 'getObjectAttribute' => true, + 'getStaticAttribute' => true, + 'greaterThan' => true, + 'greaterThanOrEqual' => true, + 'identicalTo' => true, + 'isEmpty' => true, + 'isFalse' => true, + 'isFinite' => true, + 'isInfinite' => true, + 'isInstanceOf' => true, + 'isJson' => true, + 'isNan' => true, + 'isNull' => true, + 'isReadable' => true, + 'isTrue' => true, + 'isType' => true, + 'isWritable' => true, + 'lessThan' => true, + 'lessThanOrEqual' => true, + 'logicalAnd' => true, + 'logicalNot' => true, + 'logicalOr' => true, + 'logicalXor' => true, + 'markTestIncomplete' => true, + 'markTestSkipped' => true, + 'matches' => true, + 'matchesRegularExpression' => true, + 'objectEquals' => true, + 'objectHasAttribute' => true, + 'readAttribute' => true, + 'resetCount' => true, + 'stringContains' => true, + 'stringEndsWith' => true, + 'stringStartsWith' => true, + + // TestCase methods + 'any' => true, + 'at' => true, + 'atLeast' => true, + 'atLeastOnce' => true, + 'atMost' => true, + 'exactly' => true, + 'never' => true, + 'once' => true, + 'onConsecutiveCalls' => true, + 'returnArgument' => true, + 'returnCallback' => true, + 'returnSelf' => true, + 'returnValue' => true, + 'returnValueMap' => true, + 'setUpBeforeClass' => true, + 'tearDownAfterClass' => true, + 'throwException' => true, + ]; + + private $conversionMap = [ + self::CALL_TYPE_THIS => [[T_OBJECT_OPERATOR, '->'], [T_VARIABLE, '$this']], + self::CALL_TYPE_SELF => [[T_DOUBLE_COLON, '::'], [T_STRING, 'self']], + self::CALL_TYPE_STATIC => [[T_DOUBLE_COLON, '::'], [T_STATIC, 'static']], + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + $codeSample = '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testMe() + { + $this->assertSame(1, 2); + self::assertSame(1, 2); + static::assertSame(1, 2); + } +} +'; + + return new FixerDefinition( + 'Calls to `PHPUnit\Framework\TestCase` static methods must all be of the same type, either `$this->`, `self::` or `static::`.', + [ + new CodeSample($codeSample), + new CodeSample($codeSample, ['call_type' => self::CALL_TYPE_THIS]), + ], + null, + 'Risky when PHPUnit methods are overridden or not accessible, or when project has PHPUnit incompatibilities.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before FinalStaticAccessFixer, SelfStaticAccessorFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $thisFixer = $this; + + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('call_type', 'The call type to use for referring to PHPUnit methods.')) + ->setAllowedTypes(['string']) + ->setAllowedValues(array_keys($this->allowedValues)) + ->setDefault('static') + ->getOption(), + (new FixerOptionBuilder('methods', 'Dictionary of `method` => `call_type` values that differ from the default strategy.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([static function ($option) use ($thisFixer) { + foreach ($option as $method => $value) { + if (!isset($thisFixer->staticMethods[$method])) { + throw new InvalidOptionsException( + sprintf( + 'Unexpected "methods" key, expected any of "%s", got "%s".', + implode('", "', array_keys($thisFixer->staticMethods)), + \is_object($method) ? \get_class($method) : \gettype($method).'#'.$method + ) + ); + } + + if (!isset($thisFixer->allowedValues[$value])) { + throw new InvalidOptionsException( + sprintf( + 'Unexpected value for method "%s", expected any of "%s", got "%s".', + $method, + implode('", "', array_keys($thisFixer->allowedValues)), + \is_object($value) ? \get_class($value) : (null === $value ? 'null' : \gettype($value).'#'.$value) + ) + ); + } + } + + return true; + }]) + ->setDefault([]) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $analyzer = new TokensAnalyzer($tokens); + + for ($index = $startIndex; $index < $endIndex; ++$index) { + // skip anonymous classes + if ($tokens[$index]->isGivenKind(T_CLASS)) { + $index = $this->findEndOfNextBlock($tokens, $index); + + continue; + } + + $callType = $this->configuration['call_type']; + + if ($tokens[$index]->isGivenKind(T_FUNCTION)) { + // skip lambda + if ($analyzer->isLambda($index)) { + $index = $this->findEndOfNextBlock($tokens, $index); + + continue; + } + + // do not change `self` to `this` in static methods + if ('this' === $callType) { + $attributes = $analyzer->getMethodAttributes($index); + if (false !== $attributes['static']) { + $index = $this->findEndOfNextBlock($tokens, $index); + + continue; + } + } + } + + if (!$tokens[$index]->isGivenKind(T_STRING) || !isset($this->staticMethods[$tokens[$index]->getContent()])) { + continue; + } + + $nextIndex = $tokens->getNextMeaningfulToken($index); + if (!$tokens[$nextIndex]->equals('(')) { + $index = $nextIndex; + + continue; + } + + $methodName = $tokens[$index]->getContent(); + + if (isset($this->configuration['methods'][$methodName])) { + $callType = $this->configuration['methods'][$methodName]; + } + + $operatorIndex = $tokens->getPrevMeaningfulToken($index); + $referenceIndex = $tokens->getPrevMeaningfulToken($operatorIndex); + if (!$this->needsConversion($tokens, $index, $referenceIndex, $callType)) { + continue; + } + + $tokens[$operatorIndex] = new Token($this->conversionMap[$callType][0]); + $tokens[$referenceIndex] = new Token($this->conversionMap[$callType][1]); + } + } + + /** + * @param int $index + * @param int $referenceIndex + * @param string $callType + * + * @return bool + */ + private function needsConversion(Tokens $tokens, $index, $referenceIndex, $callType) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + + return $functionsAnalyzer->isTheSameClassCall($tokens, $index) + && !$tokens[$referenceIndex]->equals($this->conversionMap[$callType][1], false); + } + + /** + * @param int $index + * + * @return int + */ + private function findEndOfNextBlock(Tokens $tokens, $index) + { + $nextIndex = $tokens->getNextTokenOfKind($index, [';', '{']); + + return $tokens[$nextIndex]->equals('{') + ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $nextIndex) + : $nextIndex; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestClassRequiresCoversFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestClassRequiresCoversFixer.php new file mode 100644 index 0000000..8c28d2e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitTestClassRequiresCoversFixer.php @@ -0,0 +1,132 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\PhpUnit; + +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\Line; +use PhpCsFixer\Fixer\AbstractPhpUnitFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpUnitTestClassRequiresCoversFixer extends AbstractPhpUnitFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Adds a default `@coversNothing` annotation to PHPUnit test classes that have no `@covers*` annotation.', + [ + new CodeSample( + '<?php +final class MyTest extends \PHPUnit_Framework_TestCase +{ + public function testSomeTest() + { + $this->assertSame(a(), b()); + } +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + protected function applyPhpUnitClassFix(Tokens $tokens, $startIndex, $endIndex) + { + $classIndex = $tokens->getPrevTokenOfKind($startIndex, [[T_CLASS]]); + $prevIndex = $tokens->getPrevMeaningfulToken($classIndex); + + // don't add `@covers` annotation for abstract base classes + if ($tokens[$prevIndex]->isGivenKind(T_ABSTRACT)) { + return; + } + + $index = $tokens[$prevIndex]->isGivenKind(T_FINAL) ? $prevIndex : $classIndex; + + $indent = $tokens[$index - 1]->isGivenKind(T_WHITESPACE) + ? Preg::replace('/^.*\R*/', '', $tokens[$index - 1]->getContent()) + : ''; + + $prevIndex = $tokens->getPrevNonWhitespace($index); + + if ($tokens[$prevIndex]->isGivenKind(T_DOC_COMMENT)) { + $docIndex = $prevIndex; + $docContent = $tokens[$docIndex]->getContent(); + + // ignore one-line phpdocs like `/** foo */`, as there is no place to put new annotations + if (false === strpos($docContent, "\n")) { + return; + } + + $doc = new DocBlock($docContent); + + // skip if already has annotation + if (!empty($doc->getAnnotationsOfType([ + 'covers', + 'coversDefaultClass', + 'coversNothing', + ]))) { + return; + } + } else { + $docIndex = $index; + $tokens->insertAt($docIndex, [ + new Token([T_DOC_COMMENT, sprintf('/**%s%s */', $this->whitespacesConfig->getLineEnding(), $indent)]), + new Token([T_WHITESPACE, sprintf('%s%s', $this->whitespacesConfig->getLineEnding(), $indent)]), + ]); + + if (!$tokens[$docIndex - 1]->isGivenKind(T_WHITESPACE)) { + $extraNewLines = $this->whitespacesConfig->getLineEnding(); + + if (!$tokens[$docIndex - 1]->isGivenKind(T_OPEN_TAG)) { + $extraNewLines .= $this->whitespacesConfig->getLineEnding(); + } + + $tokens->insertAt($docIndex, [ + new Token([T_WHITESPACE, $extraNewLines.$indent]), + ]); + ++$docIndex; + } + + $doc = new DocBlock($tokens[$docIndex]->getContent()); + } + + $lines = $doc->getLines(); + array_splice( + $lines, + \count($lines) - 1, + 0, + [ + new Line(sprintf( + '%s * @coversNothing%s', + $indent, + $this->whitespacesConfig->getLineEnding() + )), + ] + ); + + $tokens[$docIndex] = new Token([T_DOC_COMMENT, implode('', $lines)]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/AlignMultilineCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/AlignMultilineCommentFixer.php new file mode 100644 index 0000000..572c133 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/AlignMultilineCommentFixer.php @@ -0,0 +1,175 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + * @author Julien Falque <julien.falque@gmail.com> + */ +final class AlignMultilineCommentFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @var null|int[] + */ + private $tokenKinds; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->tokenKinds = [T_DOC_COMMENT]; + if ('phpdocs_only' !== $this->configuration['comment_type']) { + $this->tokenKinds[] = T_COMMENT; + } + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Each line of multi-line DocComments must have an asterisk [PSR-5] and must be aligned with the first one.', + [ + new CodeSample( + '<?php + /** + * This is a DOC Comment +with a line not prefixed with asterisk + + */ +' + ), + new CodeSample( + '<?php + /* + * This is a doc-like multiline comment +*/ +', + ['comment_type' => 'phpdocs_like'] + ), + new CodeSample( + '<?php + /* + * This is a doc-like multiline comment +with a line not prefixed with asterisk + + */ +', + ['comment_type' => 'all_multiline'] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before CommentToPhpdocFixer, GeneralPhpdocAnnotationRemoveFixer, GeneralPhpdocTagRenameFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocInlineTagFixer, PhpdocInlineTagNormalizerFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocTagCasingFixer, PhpdocTagTypeFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run after ArrayIndentationFixer. + */ + public function getPriority() + { + return 27; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound($this->tokenKinds); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind($this->tokenKinds)) { + continue; + } + + $whitespace = ''; + $previousIndex = $index - 1; + if ($tokens[$previousIndex]->isWhitespace()) { + $whitespace = $tokens[$previousIndex]->getContent(); + --$previousIndex; + } + if ($tokens[$previousIndex]->isGivenKind(T_OPEN_TAG)) { + $whitespace = Preg::replace('/\S/', '', $tokens[$previousIndex]->getContent()).$whitespace; + } + + if (1 !== Preg::match('/\R(\h*)$/', $whitespace, $matches)) { + continue; + } + + if ($token->isGivenKind(T_COMMENT) && 'all_multiline' !== $this->configuration['comment_type'] && 1 === Preg::match('/\R(?:\R|\s*[^\s\*])/', $token->getContent())) { + continue; + } + + $indentation = $matches[1]; + $lines = Preg::split('/\R/u', $token->getContent()); + + foreach ($lines as $lineNumber => $line) { + if (0 === $lineNumber) { + continue; + } + + $line = ltrim($line); + if ($token->isGivenKind(T_COMMENT) && (!isset($line[0]) || '*' !== $line[0])) { + continue; + } + + if (!isset($line[0])) { + $line = '*'; + } elseif ('*' !== $line[0]) { + $line = '* '.$line; + } + + $lines[$lineNumber] = $indentation.' '.$line; + } + + $tokens[$index] = new Token([$token->getId(), implode($lineEnding, $lines)]); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('comment_type', 'Whether to fix PHPDoc comments only (`phpdocs_only`), any multi-line comment whose lines all start with an asterisk (`phpdocs_like`) or any multi-line comment (`all_multiline`).')) + ->setAllowedValues(['phpdocs_only', 'phpdocs_like', 'all_multiline']) + ->setDefault('phpdocs_only') + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/GeneralPhpdocAnnotationRemoveFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/GeneralPhpdocAnnotationRemoveFixer.php new file mode 100644 index 0000000..f86027c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/GeneralPhpdocAnnotationRemoveFixer.php @@ -0,0 +1,130 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class GeneralPhpdocAnnotationRemoveFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Configured annotations should be omitted from PHPDoc.', + [ + new CodeSample( + '<?php +/** + * @internal + * @author John Doe + */ +function foo() {} +', + ['annotations' => ['author']] + ), + new CodeSample( + '<?php +/** + * @author John Doe + * @package ACME API + * @subpackage Authorization + * @version 1.0 + */ +function foo() {} +', + ['annotations' => ['package', 'subpackage']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoEmptyPhpdocFixer, PhpdocAlignFixer, PhpdocLineSpanFixer, PhpdocSeparationFixer, PhpdocTrimFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if (!\count($this->configuration['annotations'])) { + return; + } + + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $doc = new DocBlock($token->getContent()); + $annotations = $doc->getAnnotationsOfType($this->configuration['annotations']); + + // nothing to do if there are no annotations + if (empty($annotations)) { + continue; + } + + foreach ($annotations as $annotation) { + $annotation->remove(); + } + + if ('' === $doc->getContent()) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } else { + $tokens[$index] = new Token([T_DOC_COMMENT, $doc->getContent()]); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolverRootless('annotations', [ + (new FixerOptionBuilder('annotations', 'List of annotations to remove, e.g. `["author"]`.')) + ->setAllowedTypes(['array']) + ->setDefault([]) + ->getOption(), + ], $this->getName()); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/GeneralPhpdocTagRenameFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/GeneralPhpdocTagRenameFixer.php new file mode 100644 index 0000000..f668042 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/GeneralPhpdocTagRenameFixer.php @@ -0,0 +1,209 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; +use Symfony\Component\OptionsResolver\Options; + +final class GeneralPhpdocTagRenameFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Renames PHPDoc tags.', + [ + new CodeSample("<?php\n/**\n * @inheritDocs\n * {@inheritdocs}\n */\n", [ + 'replacements' => [ + 'inheritDocs' => 'inheritDoc', + ], + ]), + new CodeSample("<?php\n/**\n * @inheritDocs\n * {@inheritdocs}\n */\n", [ + 'replacements' => [ + 'inheritDocs' => 'inheritDoc', + ], + 'fix_annotation' => false, + ]), + new CodeSample("<?php\n/**\n * @inheritDocs\n * {@inheritdocs}\n */\n", [ + 'replacements' => [ + 'inheritDocs' => 'inheritDoc', + ], + 'fix_inline' => false, + ]), + new CodeSample("<?php\n/**\n * @inheritDocs\n * {@inheritdocs}\n */\n", [ + 'replacements' => [ + 'inheritDocs' => 'inheritDoc', + ], + 'case_sensitive' => true, + ]), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + // must be run before PhpdocAddMissingParamAnnotationFixer + return 11; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('fix_annotation', 'Whether annotation tags should be fixed.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('fix_inline', 'Whether inline tags should be fixed.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('replacements', 'A map of tags to replace.')) + ->setAllowedTypes(['array']) + ->setNormalizer(function (Options $options, $value) { + $normalizedValue = []; + + foreach ($value as $from => $to) { + if (!\is_string($from)) { + throw new InvalidOptionsException('Tag to replace must be a string.'); + } + + if (!\is_string($to)) { + throw new InvalidOptionsException(sprintf( + 'Tag to replace to from "%s" must be a string.', + $from + )); + } + + if (1 !== Preg::match('#^\S+$#', $to) || false !== strpos($to, '*/')) { + throw new InvalidOptionsException(sprintf( + 'Tag "%s" cannot be replaced by invalid tag "%s".', + $from, + $to + )); + } + + $from = trim($from); + $to = trim($to); + + if (!$options['case_sensitive']) { + $lowercaseFrom = strtolower($from); + + if (isset($normalizedValue[$lowercaseFrom]) && $normalizedValue[$lowercaseFrom] !== $to) { + throw new InvalidOptionsException(sprintf( + 'Tag "%s" cannot be configured to be replaced with several different tags when case sensitivity is off.', + $from + )); + } + + $from = $lowercaseFrom; + } + + $normalizedValue[$from] = $to; + } + + foreach ($normalizedValue as $from => $to) { + if (isset($normalizedValue[$to]) && $normalizedValue[$to] !== $to) { + throw new InvalidOptionsException(sprintf( + 'Cannot change tag "%1$s" to tag "%2$s", as the tag "%2$s" is configured to be replaced to "%3$s".', + $from, + $to, + $normalizedValue[$to] + )); + } + } + + return $normalizedValue; + }) + ->setDefault([]) + ->getOption(), + (new FixerOptionBuilder('case_sensitive', 'Whether tags should be replaced only if they have exact same casing.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if (!$this->configuration['replacements']) { + return; + } + + if ($this->configuration['fix_annotation']) { + if ($this->configuration['fix_inline']) { + $regex = '/"[^"]*"(*SKIP)(*FAIL)|\b(?<=@)(%s)\b/'; + } else { + $regex = '/"[^"]*"(*SKIP)(*FAIL)|(?<!\{@)(?<=@)(%s)(?!\})/'; + } + } else { + $regex = '/(?<={@)(%s)(?=[ \t}])/'; + } + + $caseInsensitive = !$this->configuration['case_sensitive']; + $replacements = $this->configuration['replacements']; + $regex = sprintf($regex, implode('|', array_keys($replacements))); + + if ($caseInsensitive) { + $regex .= 'i'; + } + + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $tokens[$index] = new Token([T_DOC_COMMENT, Preg::replaceCallback( + $regex, + function (array $matches) use ($caseInsensitive, $replacements) { + if ($caseInsensitive) { + $matches[1] = strtolower($matches[1]); + } + + return $replacements[$matches[1]]; + }, + $token->getContent() + )]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php new file mode 100644 index 0000000..ddb146f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php @@ -0,0 +1,114 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + */ +final class NoBlankLinesAfterPhpdocFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There should not be blank lines between docblock and the documented element.', + [ + new CodeSample( + '<?php + +/** + * This is the bar class. + */ + + +class Bar {} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before HeaderCommentFixer, PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return -20; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + static $forbiddenSuccessors = [ + T_BREAK, + T_COMMENT, + T_CONTINUE, + T_DECLARE, + T_DOC_COMMENT, + T_GOTO, + T_NAMESPACE, + T_RETURN, + T_THROW, + T_USE, + T_WHITESPACE, + ]; + + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + // get the next non-whitespace token inc comments, provided + // that there is whitespace between it and the current token + $next = $tokens->getNextNonWhitespace($index); + if ($index + 2 === $next && false === $tokens[$next]->isGivenKind($forbiddenSuccessors)) { + $this->fixWhitespace($tokens, $index + 1); + } + } + } + + /** + * Cleanup a whitespace token. + * + * @param int $index + */ + private function fixWhitespace(Tokens $tokens, $index) + { + $content = $tokens[$index]->getContent(); + // if there is more than one new line in the whitespace, then we need to fix it + if (substr_count($content, "\n") > 1) { + // the final bit of the whitespace must be the next statement's indentation + $tokens[$index] = new Token([T_WHITESPACE, substr($content, strrpos($content, "\n"))]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoEmptyPhpdocFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoEmptyPhpdocFixer.php new file mode 100644 index 0000000..eb84612 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoEmptyPhpdocFixer.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class NoEmptyPhpdocFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There should not be empty PHPDoc blocks.', + [new CodeSample("<?php /** */\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoExtraBlankLinesFixer, NoTrailingWhitespaceFixer, NoWhitespaceInBlankLineFixer, PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, GeneralPhpdocAnnotationRemoveFixer, NoSuperfluousPhpdocTagsFixer, PhpUnitNoExpectationAnnotationFixer, PhpUnitTestAnnotationFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocIndentFixer, PhpdocNoAccessFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 3; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + if (Preg::match('#^/\*\*[\s\*]*\*/$#', $token->getContent())) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixer.php new file mode 100644 index 0000000..0524619 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixer.php @@ -0,0 +1,510 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +final class NoSuperfluousPhpdocTagsFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Removes `@param`, `@return` and `@var` tags that don\'t provide any useful information.', + [ + new CodeSample('<?php +class Foo { + /** + * @param Bar $bar + * @param mixed $baz + */ + public function doFoo(Bar $bar, $baz) {} +} +'), + new CodeSample('<?php +class Foo { + /** + * @param Bar $bar + * @param mixed $baz + */ + public function doFoo(Bar $bar, $baz) {} +} +', ['allow_mixed' => true]), + new VersionSpecificCodeSample('<?php +class Foo { + /** + * @param Bar $bar + * @param mixed $baz + * + * @return Baz + */ + public function doFoo(Bar $bar, $baz): Baz {} +} +', new VersionSpecification(70000)), + new CodeSample('<?php +class Foo { + /** + * @inheritDoc + */ + public function doFoo(Bar $bar, $baz) {} +} +', ['remove_inheritdoc' => true]), + new CodeSample('<?php +class Foo { + /** + * @param Bar $bar + * @param mixed $baz + * @param string|int|null $qux + */ + public function doFoo(Bar $bar, $baz /*, $qux = null */) {} +} +', ['allow_unused_params' => true]), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoEmptyPhpdocFixer, PhpdocAlignFixer, VoidReturnFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, FullyQualifiedStrictTypesFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocIndentFixer, PhpdocReturnSelfReferenceFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 6; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $namespaceUseAnalyzer = new NamespaceUsesAnalyzer(); + + $shortNames = []; + foreach ($namespaceUseAnalyzer->getDeclarationsFromTokens($tokens) as $namespaceUseAnalysis) { + $shortNames[strtolower($namespaceUseAnalysis->getShortName())] = '\\'.strtolower($namespaceUseAnalysis->getFullName()); + } + + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $content = $initialContent = $token->getContent(); + + $documentedElementIndex = $this->findDocumentedElement($tokens, $index); + + if (null === $documentedElementIndex) { + continue; + } + + $token = $tokens[$documentedElementIndex]; + + if ($this->configuration['remove_inheritdoc']) { + $content = $this->removeSuperfluousInheritDoc($content); + } + + if ($token->isGivenKind(T_FUNCTION)) { + $content = $this->fixFunctionDocComment($content, $tokens, $index, $shortNames); + } elseif ($token->isGivenKind(T_VARIABLE)) { + $content = $this->fixPropertyDocComment($content, $tokens, $index, $shortNames); + } + + if ('' === $content) { + $content = '/** */'; + } + + if ($content !== $initialContent) { + $tokens[$index] = new Token([T_DOC_COMMENT, $content]); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('allow_mixed', 'Whether type `mixed` without description is allowed (`true`) or considered superfluous (`false`)')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + (new FixerOptionBuilder('remove_inheritdoc', 'Remove `@inheritDoc` tags')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + (new FixerOptionBuilder('allow_unused_params', 'Whether `param` annotation without actual signature is allowed (`true`) or considered superfluous (`false`)')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + ]); + } + + /** + * @param int $docCommentIndex + * + * @return null|int + */ + private function findDocumentedElement(Tokens $tokens, $docCommentIndex) + { + $index = $docCommentIndex; + + do { + $index = $tokens->getNextMeaningfulToken($index); + + if (null === $index || $tokens[$index]->isGivenKind([T_FUNCTION, T_CLASS, T_INTERFACE])) { + return $index; + } + } while ($tokens[$index]->isGivenKind([T_ABSTRACT, T_FINAL, T_STATIC, T_PRIVATE, T_PROTECTED, T_PUBLIC])); + + $index = $tokens->getNextMeaningfulToken($docCommentIndex); + + $kindsBeforeProperty = [T_STATIC, T_PRIVATE, T_PROTECTED, T_PUBLIC, CT::T_NULLABLE_TYPE, CT::T_ARRAY_TYPEHINT, T_STRING, T_NS_SEPARATOR]; + + if (!$tokens[$index]->isGivenKind($kindsBeforeProperty)) { + return null; + } + + do { + $index = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$index]->isGivenKind(T_VARIABLE)) { + return $index; + } + } while ($tokens[$index]->isGivenKind($kindsBeforeProperty)); + + return null; + } + + /** + * @param string $content + * @param int $functionIndex + * + * @return string + */ + private function fixFunctionDocComment($content, Tokens $tokens, $functionIndex, array $shortNames) + { + $docBlock = new DocBlock($content); + + $openingParenthesisIndex = $tokens->getNextTokenOfKind($functionIndex, ['(']); + $closingParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openingParenthesisIndex); + + $argumentsInfo = $this->getArgumentsInfo( + $tokens, + $openingParenthesisIndex + 1, + $closingParenthesisIndex - 1 + ); + + foreach ($docBlock->getAnnotationsOfType('param') as $annotation) { + $argumentName = $annotation->getVariableName(); + + if (null === $argumentName) { + continue; + } + + if (!isset($argumentsInfo[$argumentName]) && $this->configuration['allow_unused_params']) { + continue; + } + + if (!isset($argumentsInfo[$argumentName]) || $this->annotationIsSuperfluous($annotation, $argumentsInfo[$argumentName], $shortNames)) { + $annotation->remove(); + } + } + + $returnTypeInfo = $this->getReturnTypeInfo($tokens, $closingParenthesisIndex); + + foreach ($docBlock->getAnnotationsOfType('return') as $annotation) { + if ($this->annotationIsSuperfluous($annotation, $returnTypeInfo, $shortNames)) { + $annotation->remove(); + } + } + + return $docBlock->getContent(); + } + + /** + * @param string $content + * @param int $index Index of the DocComment token + * + * @return string + */ + private function fixPropertyDocComment($content, Tokens $tokens, $index, array $shortNames) + { + $docBlock = new DocBlock($content); + + do { + $index = $tokens->getNextMeaningfulToken($index); + } while ($tokens[$index]->isGivenKind([T_STATIC, T_PRIVATE, T_PROTECTED, T_PUBLIC])); + + $propertyTypeInfo = $this->getPropertyTypeInfo($tokens, $index); + + foreach ($docBlock->getAnnotationsOfType('var') as $annotation) { + if ($this->annotationIsSuperfluous($annotation, $propertyTypeInfo, $shortNames)) { + $annotation->remove(); + } + } + + return $docBlock->getContent(); + } + + /** + * @param int $start + * @param int $end + * + * @return array<string, array> + */ + private function getArgumentsInfo(Tokens $tokens, $start, $end) + { + $argumentsInfo = []; + + for ($index = $start; $index <= $end; ++$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_VARIABLE)) { + continue; + } + + $beforeArgumentIndex = $tokens->getPrevTokenOfKind($index, ['(', ',']); + $typeIndex = $tokens->getNextMeaningfulToken($beforeArgumentIndex); + + if ($typeIndex !== $index) { + $info = $this->parseTypeHint($tokens, $typeIndex); + } else { + $info = [ + 'type' => null, + 'allows_null' => true, + ]; + } + + if (!$info['allows_null']) { + $nextIndex = $tokens->getNextMeaningfulToken($index); + if ( + $tokens[$nextIndex]->equals('=') + && $tokens[$tokens->getNextMeaningfulToken($nextIndex)]->equals([T_STRING, 'null']) + ) { + $info['allows_null'] = true; + } + } + + $argumentsInfo[$token->getContent()] = $info; + } + + return $argumentsInfo; + } + + private function getReturnTypeInfo(Tokens $tokens, $closingParenthesisIndex) + { + $colonIndex = $tokens->getNextMeaningfulToken($closingParenthesisIndex); + if ($tokens[$colonIndex]->isGivenKind(CT::T_TYPE_COLON)) { + return $this->parseTypeHint($tokens, $tokens->getNextMeaningfulToken($colonIndex)); + } + + return [ + 'type' => null, + 'allows_null' => true, + ]; + } + + /** + * @param int $index The index of the first token of the type hint + * + * @return array + */ + private function getPropertyTypeInfo(Tokens $tokens, $index) + { + if ($tokens[$index]->isGivenKind(T_VARIABLE)) { + return [ + 'type' => null, + 'allows_null' => true, + ]; + } + + return $this->parseTypeHint($tokens, $index); + } + + /** + * @param int $index The index of the first token of the type hint + * + * @return array + */ + private function parseTypeHint(Tokens $tokens, $index) + { + $allowsNull = false; + if ($tokens[$index]->isGivenKind(CT::T_NULLABLE_TYPE)) { + $allowsNull = true; + $index = $tokens->getNextMeaningfulToken($index); + } + + $type = ''; + while ($tokens[$index]->isGivenKind([T_NS_SEPARATOR, T_STATIC, T_STRING, CT::T_ARRAY_TYPEHINT, T_CALLABLE])) { + $type .= $tokens[$index]->getContent(); + + $index = $tokens->getNextMeaningfulToken($index); + } + + return [ + 'type' => '' === $type ? null : $type, + 'allows_null' => $allowsNull, + ]; + } + + /** + * @param array<string, string> $symbolShortNames + * + * @return bool + */ + private function annotationIsSuperfluous(Annotation $annotation, array $info, array $symbolShortNames) + { + if ('param' === $annotation->getTag()->getName()) { + $regex = '/@param\s+(?:\S|\s(?!\$))++\s\$\S+\s+\S/'; + } elseif ('var' === $annotation->getTag()->getName()) { + $regex = '/@var\s+\S+(\s+\$\S+)?(\s+)(?!\*+\/)([^$\s]+)/'; + } else { + $regex = '/@return\s+\S+\s+\S/'; + } + + if (Preg::match($regex, $annotation->getContent())) { + return false; + } + + $annotationTypes = $this->toComparableNames($annotation->getTypes(), $symbolShortNames); + + if (['null'] === $annotationTypes) { + return false; + } + + if (['mixed'] === $annotationTypes && null === $info['type']) { + return !$this->configuration['allow_mixed']; + } + + $actualTypes = null === $info['type'] ? [] : [$info['type']]; + if ($info['allows_null']) { + $actualTypes[] = 'null'; + } + + return $annotationTypes === $this->toComparableNames($actualTypes, $symbolShortNames); + } + + /** + * Normalizes types to make them comparable. + * + * Converts given types to lowercase, replaces imports aliases with + * their matching FQCN, and finally sorts the result. + * + * @param string[] $types The types to normalize + * @param array<string, string> $symbolShortNames The imports aliases + * + * @return array The normalized types + */ + private function toComparableNames(array $types, array $symbolShortNames) + { + $normalized = array_map( + static function ($type) use ($symbolShortNames) { + $type = strtolower($type); + + if (isset($symbolShortNames[$type])) { + return $symbolShortNames[$type]; + } + + return $type; + }, + $types + ); + + sort($normalized); + + return $normalized; + } + + /** + * @param string $docComment + * + * @return string + */ + private function removeSuperfluousInheritDoc($docComment) + { + return Preg::replace('~ + # $1: before @inheritDoc tag + ( + # beginning of comment or a PHPDoc tag + (?: + ^/\*\* + (?: + \R + [ \t]*(?:\*[ \t]*)? + )*? + | + @\N+ + ) + + # empty comment lines + (?: + \R + [ \t]*(?:\*[ \t]*?)? + )* + ) + + # spaces before @inheritDoc tag + [ \t]* + + # @inheritDoc tag + (?:@inheritDocs?|\{@inheritDocs?\}) + + # $2: after @inheritDoc tag + ( + # empty comment lines + (?: + \R + [ \t]*(?:\*[ \t]*)? + )* + + # a PHPDoc tag or end of comment + (?: + @\N+ + | + (?: + \R + [ \t]*(?:\*[ \t]*)? + )* + [ \t]*\*/$ + ) + ) + ~ix', '$1$2', $docComment); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAddMissingParamAnnotationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAddMissingParamAnnotationFixer.php new file mode 100644 index 0000000..50a5e43 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAddMissingParamAnnotationFixer.php @@ -0,0 +1,278 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\Line; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpdocAddMissingParamAnnotationFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHPDoc should contain `@param` for all params.', + [ + new CodeSample( + '<?php +/** + * @param int $bar + * + * @return void + */ +function f9(string $foo, $bar, $baz) {} +' + ), + new CodeSample( + '<?php +/** + * @param int $bar + * + * @return void + */ +function f9(string $foo, $bar, $baz) {} +', + ['only_untyped' => true] + ), + new CodeSample( + '<?php +/** + * @param int $bar + * + * @return void + */ +function f9(string $foo, $bar, $baz) {} +', + ['only_untyped' => false] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocOrderFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, GeneralPhpdocTagRenameFixer, PhpdocIndentFixer, PhpdocNoAliasTagFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $argumentsAnalyzer = new ArgumentsAnalyzer(); + + for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $tokenContent = $token->getContent(); + + if (false !== stripos($tokenContent, 'inheritdoc')) { + continue; + } + + // ignore one-line phpdocs like `/** foo */`, as there is no place to put new annotations + if (false === strpos($tokenContent, "\n")) { + continue; + } + + $mainIndex = $index; + $index = $tokens->getNextMeaningfulToken($index); + + if (null === $index) { + return; + } + + while ($tokens[$index]->isGivenKind([ + T_ABSTRACT, + T_FINAL, + T_PRIVATE, + T_PROTECTED, + T_PUBLIC, + T_STATIC, + T_VAR, + ])) { + $index = $tokens->getNextMeaningfulToken($index); + } + + if (!$tokens[$index]->isGivenKind(T_FUNCTION)) { + continue; + } + + $openIndex = $tokens->getNextTokenOfKind($index, ['(']); + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); + + $arguments = []; + + foreach ($argumentsAnalyzer->getArguments($tokens, $openIndex, $index) as $start => $end) { + $argumentInfo = $this->prepareArgumentInformation($tokens, $start, $end); + + if (!$this->configuration['only_untyped'] || '' === $argumentInfo['type']) { + $arguments[$argumentInfo['name']] = $argumentInfo; + } + } + + if (!\count($arguments)) { + continue; + } + + $doc = new DocBlock($tokenContent); + $lastParamLine = null; + + foreach ($doc->getAnnotationsOfType('param') as $annotation) { + $pregMatched = Preg::match('/^[^$]+(\$\w+).*$/s', $annotation->getContent(), $matches); + + if (1 === $pregMatched) { + unset($arguments[$matches[1]]); + } + + $lastParamLine = max($lastParamLine, $annotation->getEnd()); + } + + if (!\count($arguments)) { + continue; + } + + $lines = $doc->getLines(); + $linesCount = \count($lines); + + Preg::match('/^(\s*).*$/', $lines[$linesCount - 1]->getContent(), $matches); + $indent = $matches[1]; + + $newLines = []; + + foreach ($arguments as $argument) { + $type = $argument['type'] ?: 'mixed'; + + if ('?' !== $type[0] && 'null' === strtolower($argument['default'])) { + $type = 'null|'.$type; + } + + $newLines[] = new Line(sprintf( + '%s* @param %s %s%s', + $indent, + $type, + $argument['name'], + $this->whitespacesConfig->getLineEnding() + )); + } + + array_splice( + $lines, + $lastParamLine ? $lastParamLine + 1 : $linesCount - 1, + 0, + $newLines + ); + + $tokens[$mainIndex] = new Token([T_DOC_COMMENT, implode('', $lines)]); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('only_untyped', 'Whether to add missing `@param` annotations for untyped parameters only.')) + ->setDefault(true) + ->setAllowedTypes(['bool']) + ->getOption(), + ]); + } + + /** + * @param int $start + * @param int $end + * + * @return array + */ + private function prepareArgumentInformation(Tokens $tokens, $start, $end) + { + $info = [ + 'default' => '', + 'name' => '', + 'type' => '', + ]; + + $sawName = false; + + for ($index = $start; $index <= $end; ++$index) { + $token = $tokens[$index]; + + if ($token->isComment() || $token->isWhitespace()) { + continue; + } + + if ($token->isGivenKind(T_VARIABLE)) { + $sawName = true; + $info['name'] = $token->getContent(); + + continue; + } + + if ($token->equals('=')) { + continue; + } + + if ($sawName) { + $info['default'] .= $token->getContent(); + } elseif ('&' !== $token->getContent()) { + if ($token->isGivenKind(T_ELLIPSIS)) { + if ('' === $info['type']) { + $info['type'] = 'array'; + } else { + $info['type'] .= '[]'; + } + } else { + $info['type'] .= $token->getContent(); + } + } + } + + return $info; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAlignFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAlignFixer.php new file mode 100644 index 0000000..71f4a81 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAlignFixer.php @@ -0,0 +1,434 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * @author Jordi Boggiano <j.boggiano@seld.be> + * @author Sebastiaan Stok <s.stok@rollerscapes.net> + * @author Graham Campbell <graham@alt-three.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpdocAlignFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @internal + */ + const ALIGN_LEFT = 'left'; + + /** + * @internal + */ + const ALIGN_VERTICAL = 'vertical'; + + /** + * @var string + */ + private $regex; + + /** + * @var string + */ + private $regexCommentLine; + + /** + * @var string + */ + private $align; + + private static $alignableTags = [ + 'param', + 'property', + 'property-read', + 'property-write', + 'return', + 'throws', + 'type', + 'var', + 'method', + ]; + + private static $tagsWithName = [ + 'param', + 'property', + ]; + + private static $tagsWithMethodSignature = [ + 'method', + ]; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $tagsWithNameToAlign = array_intersect($this->configuration['tags'], self::$tagsWithName); + $tagsWithMethodSignatureToAlign = array_intersect($this->configuration['tags'], self::$tagsWithMethodSignature); + $tagsWithoutNameToAlign = array_diff($this->configuration['tags'], $tagsWithNameToAlign, $tagsWithMethodSignatureToAlign); + $types = []; + + $indent = '(?P<indent>(?: {2}|\t)*)'; + // e.g. @param <hint> <$var> + if (!empty($tagsWithNameToAlign)) { + $types[] = '(?P<tag>'.implode('|', $tagsWithNameToAlign).')\s+(?P<hint>[^$]+?)\s+(?P<var>(?:&|\.{3})?\$[^\s]+)'; + } + + // e.g. @return <hint> + if (!empty($tagsWithoutNameToAlign)) { + $types[] = '(?P<tag2>'.implode('|', $tagsWithoutNameToAlign).')\s+(?P<hint2>[^\s]+?)'; + } + + // e.g. @method <hint> <signature> + if (!empty($tagsWithMethodSignatureToAlign)) { + $types[] = '(?P<tag3>'.implode('|', $tagsWithMethodSignatureToAlign).')(\s+(?P<hint3>[^\s(]+)|)\s+(?P<signature>.+\))'; + } + + // optional <desc> + $desc = '(?:\s+(?P<desc>\V*))'; + + $this->regex = '/^'.$indent.' \* @(?:'.implode('|', $types).')'.$desc.'\s*$/u'; + $this->regexCommentLine = '/^'.$indent.' \*(?! @)(?:\s+(?P<desc>\V+))(?<!\*\/)\r?$/u'; + $this->align = $this->configuration['align']; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + $code = <<<'EOF' +<?php +/** + * @param EngineInterface $templating + * @param string $format + * @param int $code an HTTP response status code + * @param bool $debug + * @param mixed &$reference a parameter passed by reference + */ + +EOF; + + return new FixerDefinition( + 'All items of the given phpdoc tags must be either left-aligned or (by default) aligned vertically.', + [ + new CodeSample($code), + new CodeSample($code, ['align' => self::ALIGN_VERTICAL]), + new CodeSample($code, ['align' => self::ALIGN_LEFT]), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, CommentToPhpdocFixer, GeneralPhpdocAnnotationRemoveFixer, GeneralPhpdocTagRenameFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAnnotationWithoutDotFixer, PhpdocIndentFixer, PhpdocIndentFixer, PhpdocInlineTagFixer, PhpdocInlineTagNormalizerFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocScalarFixer, PhpdocScalarFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocTagCasingFixer, PhpdocTagTypeFixer, PhpdocToCommentFixer, PhpdocToCommentFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesFixer, PhpdocTypesFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + */ + public function getPriority() + { + /* + * Should be run after all other docblock fixers. This because they + * modify other annotations to change their type and or separation + * which totally change the behavior of this fixer. It's important that + * annotations are of the correct type, and are grouped correctly + * before running this fixer. + */ + return -42; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $content = $token->getContent(); + $docBlock = new DocBlock($content); + $this->fixDocBlock($docBlock); + $newContent = $docBlock->getContent(); + if ($newContent !== $content) { + $tokens[$index] = new Token([T_DOC_COMMENT, $newContent]); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $tags = new FixerOptionBuilder('tags', 'The tags that should be aligned.'); + $tags + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset(self::$alignableTags)]) + /* + * By default, all tags apart from @property and @method will be aligned for backwards compatibility + * @TODO 3.0 Align all available tags by default + */ + ->setDefault([ + 'param', + 'return', + 'throws', + 'type', + 'var', + ]) + ; + + $align = new FixerOptionBuilder('align', 'Align comments'); + $align + ->setAllowedTypes(['string']) + ->setAllowedValues([self::ALIGN_LEFT, self::ALIGN_VERTICAL]) + ->setDefault(self::ALIGN_VERTICAL) + ; + + return new FixerConfigurationResolver([$tags->getOption(), $align->getOption()]); + } + + private function fixDocBlock(DocBlock $docBlock) + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + for ($i = 0, $l = \count($docBlock->getLines()); $i < $l; ++$i) { + $items = []; + $matches = $this->getMatches($docBlock->getLine($i)->getContent()); + + if (null === $matches) { + continue; + } + + $current = $i; + $items[] = $matches; + + while (true) { + if (null === $docBlock->getLine(++$i)) { + break 2; + } + + $matches = $this->getMatches($docBlock->getLine($i)->getContent(), true); + if (null === $matches) { + break; + } + + $items[] = $matches; + } + + // compute the max length of the tag, hint and variables + $tagMax = 0; + $hintMax = 0; + $varMax = 0; + + foreach ($items as $item) { + if (null === $item['tag']) { + continue; + } + + $tagMax = max($tagMax, \strlen($item['tag'])); + $hintMax = max($hintMax, \strlen($item['hint'])); + $varMax = max($varMax, \strlen($item['var'])); + } + + $currTag = null; + + // update + foreach ($items as $j => $item) { + if (null === $item['tag']) { + if ('@' === $item['desc'][0]) { + $docBlock->getLine($current + $j)->setContent($item['indent'].' * '.$item['desc'].$lineEnding); + + continue; + } + + $extraIndent = 2; + + if (\in_array($currTag, self::$tagsWithName, true) || \in_array($currTag, self::$tagsWithMethodSignature, true)) { + $extraIndent = 3; + } + + $line = + $item['indent'] + .' * ' + .$this->getIndent( + $tagMax + $hintMax + $varMax + $extraIndent, + $this->getLeftAlignedDescriptionIndent($items, $j) + ) + .$item['desc'] + .$lineEnding; + + $docBlock->getLine($current + $j)->setContent($line); + + continue; + } + + $currTag = $item['tag']; + + $line = + $item['indent'] + .' * @' + .$item['tag'] + .$this->getIndent( + $tagMax - \strlen($item['tag']) + 1, + $item['hint'] ? 1 : 0 + ) + .$item['hint'] + ; + + if (!empty($item['var'])) { + $line .= + $this->getIndent(($hintMax ?: -1) - \strlen($item['hint']) + 1) + .$item['var'] + .( + !empty($item['desc']) + ? $this->getIndent($varMax - \strlen($item['var']) + 1).$item['desc'].$lineEnding + : $lineEnding + ) + ; + } elseif (!empty($item['desc'])) { + $line .= $this->getIndent($hintMax - \strlen($item['hint']) + 1).$item['desc'].$lineEnding; + } else { + $line .= $lineEnding; + } + + $docBlock->getLine($current + $j)->setContent($line); + } + } + } + + /** + * @param string $line + * @param bool $matchCommentOnly + * + * @return null|array<string, null|string> + */ + private function getMatches($line, $matchCommentOnly = false) + { + if (Preg::match($this->regex, $line, $matches)) { + if (!empty($matches['tag2'])) { + $matches['tag'] = $matches['tag2']; + $matches['hint'] = $matches['hint2']; + $matches['var'] = ''; + } + + if (!empty($matches['tag3'])) { + $matches['tag'] = $matches['tag3']; + $matches['hint'] = $matches['hint3']; + $matches['var'] = $matches['signature']; + } + + if (isset($matches['hint'])) { + $matches['hint'] = trim($matches['hint']); + } + + return $matches; + } + + if ($matchCommentOnly && Preg::match($this->regexCommentLine, $line, $matches)) { + $matches['tag'] = null; + $matches['var'] = ''; + $matches['hint'] = ''; + + return $matches; + } + + return null; + } + + /** + * @param int $verticalAlignIndent + * @param int $leftAlignIndent + * + * @return string + */ + private function getIndent($verticalAlignIndent, $leftAlignIndent = 1) + { + $indent = self::ALIGN_VERTICAL === $this->align ? $verticalAlignIndent : $leftAlignIndent; + + return str_repeat(' ', $indent); + } + + /** + * @param array[] $items + * @param int $index + * + * @return int + */ + private function getLeftAlignedDescriptionIndent(array $items, $index) + { + if (self::ALIGN_LEFT !== $this->align) { + return 0; + } + + // Find last tagged line: + $item = null; + for (; $index >= 0; --$index) { + $item = $items[$index]; + if (null !== $item['tag']) { + break; + } + } + + // No last tag found — no indent: + if (null === $item) { + return 0; + } + + // Indent according to existing values: + return + $this->getSentenceIndent($item['tag']) + + $this->getSentenceIndent($item['hint']) + + $this->getSentenceIndent($item['var']); + } + + /** + * Get indent for sentence. + * + * @param null|string $sentence + * + * @return int + */ + private function getSentenceIndent($sentence) + { + if (null === $sentence) { + return 0; + } + + $length = \strlen($sentence); + + return 0 === $length ? 0 : $length + 1; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixer.php new file mode 100644 index 0000000..67b2278 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocAnnotationWithoutDotFixer.php @@ -0,0 +1,135 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpdocAnnotationWithoutDotFixer extends AbstractFixer +{ + /** + * @var string[] + */ + private $tags = ['throws', 'return', 'param', 'internal', 'deprecated', 'var', 'type']; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHPDoc annotation descriptions should not be a sentence.', + [new CodeSample('<?php +/** + * @param string $bar Some string. + */ +function foo ($bar) {} +')] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer, PhpdocTypesFixer, PhpdocTypesOrderFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocToCommentFixer. + */ + public function getPriority() + { + return 17; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $doc = new DocBlock($token->getContent()); + $annotations = $doc->getAnnotations(); + + if (empty($annotations)) { + continue; + } + + foreach ($annotations as $annotation) { + if ( + !$annotation->getTag()->valid() || !\in_array($annotation->getTag()->getName(), $this->tags, true) + ) { + continue; + } + + $lineAfterAnnotation = $doc->getLine($annotation->getEnd() + 1); + if (null !== $lineAfterAnnotation) { + $lineAfterAnnotationTrimmed = ltrim($lineAfterAnnotation->getContent()); + if ('' === $lineAfterAnnotationTrimmed || '*' !== $lineAfterAnnotationTrimmed[0]) { + // malformed PHPDoc, missing asterisk ! + continue; + } + } + + $content = $annotation->getContent(); + + if ( + 1 !== Preg::match('/[.。]\h*$/u', $content) + || 0 !== Preg::match('/[.。](?!\h*$)/u', $content, $matches) + ) { + continue; + } + + $endLine = $doc->getLine($annotation->getEnd()); + $endLine->setContent(Preg::replace('/(?<![.。])[.。]\h*(\H+)$/u', '\1', $endLine->getContent())); + + $startLine = $doc->getLine($annotation->getStart()); + $optionalTypeRegEx = $annotation->supportTypes() + ? sprintf('(?:%s\s+(?:\$\w+\s+)?)?', preg_quote(implode('|', $annotation->getTypes()), '/')) + : ''; + $content = Preg::replaceCallback( + '/^(\s*\*\s*@\w+\s+'.$optionalTypeRegEx.')(\p{Lu}?(?=\p{Ll}|\p{Zs}))(.*)$/', + static function (array $matches) { + if (\function_exists('mb_strtolower')) { + return $matches[1].mb_strtolower($matches[2]).$matches[3]; + } + + return $matches[1].strtolower($matches[2]).$matches[3]; + }, + $startLine->getContent(), + 1 + ); + $startLine->setContent($content); + } + + $tokens[$index] = new Token([T_DOC_COMMENT, $doc->getContent()]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocIndentFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocIndentFixer.php new file mode 100644 index 0000000..d5db616 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocIndentFixer.php @@ -0,0 +1,139 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Utils; + +/** + * @author Ceeram <ceeram@cakephp.org> + * @author Graham Campbell <graham@alt-three.com> + */ +final class PhpdocIndentFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Docblocks should have the same indentation as the documented subject.', + [new CodeSample('<?php +class DocBlocks +{ +/** + * Test constants + */ + const INDENT = 1; +} +')] + ); + } + + /** + * {@inheritdoc} + * + * Must run before GeneralPhpdocAnnotationRemoveFixer, GeneralPhpdocTagRenameFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocInlineTagFixer, PhpdocInlineTagNormalizerFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocTagCasingFixer, PhpdocTagTypeFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run after IndentationTypeFixer, PhpdocToCommentFixer. + */ + public function getPriority() + { + return 20; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $nextIndex = $tokens->getNextMeaningfulToken($index); + + // skip if there is no next token or if next token is block end `}` + if (null === $nextIndex || $tokens[$nextIndex]->equals('}')) { + continue; + } + + $prevIndex = $index - 1; + $prevToken = $tokens[$prevIndex]; + + // ignore inline docblocks + if ( + $prevToken->isGivenKind(T_OPEN_TAG) + || ($prevToken->isWhitespace(" \t") && !$tokens[$index - 2]->isGivenKind(T_OPEN_TAG)) + || $prevToken->equalsAny([';', ',', '{', '(']) + ) { + continue; + } + + $indent = ''; + if ($tokens[$nextIndex - 1]->isWhitespace()) { + $indent = Utils::calculateTrailingWhitespaceIndent($tokens[$nextIndex - 1]); + } + + $newPrevContent = $this->fixWhitespaceBeforeDocblock($prevToken->getContent(), $indent); + if ($newPrevContent) { + if ($prevToken->isArray()) { + $tokens[$prevIndex] = new Token([$prevToken->getId(), $newPrevContent]); + } else { + $tokens[$prevIndex] = new Token($newPrevContent); + } + } else { + $tokens->clearAt($prevIndex); + } + + $tokens[$index] = new Token([T_DOC_COMMENT, $this->fixDocBlock($token->getContent(), $indent)]); + } + } + + /** + * Fix indentation of Docblock. + * + * @param string $content Docblock contents + * @param string $indent Indentation to apply + * + * @return string Dockblock contents including correct indentation + */ + private function fixDocBlock($content, $indent) + { + return ltrim(Preg::replace('/^\h*\*/m', $indent.' *', $content)); + } + + /** + * @param string $content Whitespace before Docblock + * @param string $indent Indentation of the documented subject + * + * @return string Whitespace including correct indentation for Dockblock after this whitespace + */ + private function fixWhitespaceBeforeDocblock($content, $indent) + { + return rtrim($content, " \t").$indent; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocInlineTagFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocInlineTagFixer.php new file mode 100644 index 0000000..22380e5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocInlineTagFixer.php @@ -0,0 +1,93 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * Fix inline tags and make inheritdoc tag always inline. + * + * @deprecated since 2.9, replaced by PhpdocInlineTagNormalizerFixer GeneralPhpdocTagRenameFixer + * + * @TODO To be removed at 3.0 + */ +final class PhpdocInlineTagFixer extends AbstractProxyFixer implements DeprecatedFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Fix PHPDoc inline tags, make `@inheritdoc` always inline.', + [new CodeSample( + '<?php +/** + * @{TUTORIAL} + * {{ @link }} + * {@examples} + * @inheritdocs + */ +' + )] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + $inlineNormalizerFixer = new PhpdocInlineTagNormalizerFixer(); + + $renameFixer = new GeneralPhpdocTagRenameFixer(); + $renameFixer->configure([ + 'fix_annotation' => true, + 'fix_inline' => true, + 'replacements' => [ + 'inheritdoc' => 'inheritdoc', + 'inheritdocs' => 'inheritdoc', + ], + 'case_sensitive' => false, + ]); + + $tagTypeFixer = new PhpdocTagTypeFixer(); + $tagTypeFixer->configure([ + 'tags' => ['inheritdoc' => 'inline'], + ]); + + return [$inlineNormalizerFixer, $renameFixer, $tagTypeFixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixer.php new file mode 100644 index 0000000..2c0e5a9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocInlineTagNormalizerFixer.php @@ -0,0 +1,120 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class PhpdocInlineTagNormalizerFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Fixes PHPDoc inline tags.', + [ + new CodeSample( + "<?php\n/**\n * @{TUTORIAL}\n * {{ @link }}\n * @inheritDoc\n */\n" + ), + new CodeSample( + "<?php\n/**\n * @{TUTORIAL}\n * {{ @link }}\n * @inheritDoc\n */\n", + ['tags' => ['TUTORIAL']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if (!$this->configuration['tags']) { + return; + } + + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + // Move `@` inside tag, for example @{tag} -> {@tag}, replace multiple curly brackets, + // remove spaces between '{' and '@', remove white space between end + // of text and closing bracket and between the tag and inline comment. + $content = Preg::replaceCallback( + sprintf( + '#(?:@{+|{+\h*@)\h*(%s)s?([^}]*)(?:}+)#i', + implode('|', array_map(function ($tag) { + return preg_quote($tag, '/'); + }, $this->configuration['tags'])) + ), + function (array $matches) { + $doc = trim($matches[2]); + + if ('' === $doc) { + return '{@'.$matches[1].'}'; + } + + return '{@'.$matches[1].' '.$doc.'}'; + }, + $token->getContent() + ); + + $tokens[$index] = new Token([T_DOC_COMMENT, $content]); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('tags', 'The list of tags to normalize')) + ->setAllowedTypes(['array']) + ->setDefault(['example', 'id', 'internal', 'inheritdoc', 'inheritdocs', 'link', 'source', 'toc', 'tutorial']) + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocLineSpanFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocLineSpanFixer.php new file mode 100644 index 0000000..fb8633d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocLineSpanFixer.php @@ -0,0 +1,154 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author Gert de Pagter <BackEndTea@gmail.com> + */ +final class PhpdocLineSpanFixer extends AbstractFixer implements WhitespacesAwareFixerInterface, ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Changes doc blocks from single to multi line, or reversed. Works for class constants, properties and methods only.', + [ + new CodeSample("<?php\n\nclass Foo{\n /** @var bool */\n public \$var;\n}\n"), + new CodeSample( + "<?php\n\nclass Foo{\n /**\n * @var bool\n */\n public \$var;\n}\n", + ['property' => 'single'] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, GeneralPhpdocAnnotationRemoveFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('const', 'Whether const blocks should be single or multi line')) + ->setAllowedValues(['single', 'multi']) + ->setDefault('multi') + ->getOption(), + (new FixerOptionBuilder('property', 'Whether property doc blocks should be single or multi line')) + ->setAllowedValues(['single', 'multi']) + ->setDefault('multi') + ->getOption(), + (new FixerOptionBuilder('method', 'Whether method doc blocks should be single or multi line')) + ->setAllowedValues(['single', 'multi']) + ->setDefault('multi') + ->getOption(), + ]); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $analyzer = new TokensAnalyzer($tokens); + + $elements = $analyzer->getClassyElements(); + + foreach ($elements as $index => $element) { + if (!$this->hasDocBlock($tokens, $index)) { + continue; + } + + $type = $element['type']; + $docIndex = $this->getDocBlockIndex($tokens, $index); + $doc = new DocBlock($tokens[$docIndex]->getContent()); + + if ('multi' === $this->configuration[$type]) { + $doc->makeMultiLine($originalIndent = WhitespacesAnalyzer::detectIndent($tokens, $docIndex), $this->whitespacesConfig->getLineEnding()); + } else { + $doc->makeSingleLine(); + } + + $tokens->offsetSet($docIndex, new Token([T_DOC_COMMENT, $doc->getContent()])); + } + } + + /** + * @param int $index + * + * @return bool + */ + private function hasDocBlock(Tokens $tokens, $index) + { + $docBlockIndex = $this->getDocBlockIndex($tokens, $index); + + return $tokens[$docBlockIndex]->isGivenKind(T_DOC_COMMENT); + } + + /** + * @param int $index + * + * @return int + */ + private function getDocBlockIndex(Tokens $tokens, $index) + { + do { + $index = $tokens->getPrevNonWhitespace($index); + } while ($tokens[$index]->isGivenKind([ + T_PUBLIC, + T_PROTECTED, + T_PRIVATE, + T_FINAL, + T_ABSTRACT, + T_COMMENT, + T_VAR, + T_STATIC, + T_STRING, + T_NS_SEPARATOR, + CT::T_ARRAY_TYPEHINT, + CT::T_NULLABLE_TYPE, + ])); + + return $index; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoAccessFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoAccessFixer.php new file mode 100644 index 0000000..a100460 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoAccessFixer.php @@ -0,0 +1,70 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author Graham Campbell <graham@alt-three.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpdocNoAccessFixer extends AbstractProxyFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + '`@access` annotations should be omitted from PHPDoc.', + [ + new CodeSample( + '<?php +class Foo +{ + /** + * @internal + * @access private + */ + private $bar; +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoEmptyPhpdocFixer, PhpdocAlignFixer, PhpdocSeparationFixer, PhpdocTrimFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return parent::getPriority(); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + $fixer = new GeneralPhpdocAnnotationRemoveFixer(); + $fixer->configure(['annotations' => ['access']]); + + return [$fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoAliasTagFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoAliasTagFixer.php new file mode 100644 index 0000000..8c774eb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoAliasTagFixer.php @@ -0,0 +1,132 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\ConfigurationException\InvalidConfigurationException; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; + +/** + * Case sensitive tag replace fixer (does not process inline tags like {@inheritdoc}). + * + * @author Graham Campbell <graham@alt-three.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +final class PhpdocNoAliasTagFixer extends AbstractProxyFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'No alias PHPDoc tags should be used.', + [ + new CodeSample( + '<?php +/** + * @property string $foo + * @property-read string $bar + * + * @link baz + */ +final class Example +{ +} +' + ), + new CodeSample( + '<?php +/** + * @property string $foo + * @property-read string $bar + * + * @link baz + */ +final class Example +{ +} +', + ['replacements' => ['link' => 'website']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocSingleLineVarSpacingFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return parent::getPriority(); + } + + public function configure(array $configuration = null) + { + parent::configure($configuration); + + /** @var GeneralPhpdocTagRenameFixer $generalPhpdocTagRenameFixer */ + $generalPhpdocTagRenameFixer = $this->proxyFixers['general_phpdoc_tag_rename']; + + try { + $generalPhpdocTagRenameFixer->configure([ + 'fix_annotation' => true, + 'fix_inline' => false, + 'replacements' => $this->configuration['replacements'], + 'case_sensitive' => true, + ]); + } catch (InvalidConfigurationException $exception) { + throw new InvalidFixerConfigurationException( + $this->getName(), + Preg::replace('/^\[.+?\] /', '', $exception->getMessage()), + $exception + ); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolverRootless('replacements', [ + (new FixerOptionBuilder('replacements', 'Mapping between replaced annotations with new ones.')) + ->setAllowedTypes(['array']) + ->setDefault([ + 'property-read' => 'property', + 'property-write' => 'property', + 'type' => 'var', + 'link' => 'see', + ]) + ->getOption(), + ], $this->getName()); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + return [new GeneralPhpdocTagRenameFixer()]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoEmptyReturnFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoEmptyReturnFixer.php new file mode 100644 index 0000000..a721da2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoEmptyReturnFixer.php @@ -0,0 +1,123 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + */ +final class PhpdocNoEmptyReturnFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + '`@return void` and `@return null` annotations should be omitted from PHPDoc.', + [ + new CodeSample( + '<?php +/** + * @return null +*/ +function foo() {} +' + ), + new CodeSample( + '<?php +/** + * @return void +*/ +function foo() {} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoEmptyPhpdocFixer, PhpdocAlignFixer, PhpdocOrderFixer, PhpdocSeparationFixer, PhpdocTrimFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer, VoidReturnFixer. + */ + public function getPriority() + { + return 4; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $doc = new DocBlock($token->getContent()); + $annotations = $doc->getAnnotationsOfType('return'); + + if (empty($annotations)) { + continue; + } + + foreach ($annotations as $annotation) { + $this->fixAnnotation($doc, $annotation); + } + + $newContent = $doc->getContent(); + + if ($newContent === $token->getContent()) { + continue; + } + + if ('' === $newContent) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + + continue; + } + + $tokens[$index] = new Token([T_DOC_COMMENT, $doc->getContent()]); + } + } + + /** + * Remove return void or return null annotations.. + */ + private function fixAnnotation(DocBlock $doc, Annotation $annotation) + { + $types = $annotation->getNormalizedTypes(); + + if (1 === \count($types) && ('null' === $types[0] || 'void' === $types[0])) { + $annotation->remove(); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoPackageFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoPackageFixer.php new file mode 100644 index 0000000..f74cd0e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoPackageFixer.php @@ -0,0 +1,70 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author Graham Campbell <graham@alt-three.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpdocNoPackageFixer extends AbstractProxyFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + '`@package` and `@subpackage` annotations should be omitted from PHPDoc.', + [ + new CodeSample( + '<?php +/** + * @internal + * @package Foo + * subpackage Bar + */ +class Baz +{ +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoEmptyPhpdocFixer, PhpdocAlignFixer, PhpdocSeparationFixer, PhpdocTrimFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return parent::getPriority(); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + $fixer = new GeneralPhpdocAnnotationRemoveFixer(); + $fixer->configure(['annotations' => ['package', 'subpackage']]); + + return [$fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixer.php new file mode 100644 index 0000000..6b0e6ae --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocNoUselessInheritdocFixer.php @@ -0,0 +1,190 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Remove inheritdoc tags from classy that does not inherit. + * + * @author SpacePossum + */ +final class PhpdocNoUselessInheritdocFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Classy that does not inherit must not have `@inheritdoc` tags.', + [ + new CodeSample("<?php\n/** {@inheritdoc} */\nclass Sample\n{\n}\n"), + new CodeSample("<?php\nclass Sample\n{\n /**\n * @inheritdoc\n */\n public function Test()\n {\n }\n}\n"), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoEmptyPhpdocFixer, NoTrailingWhitespaceInCommentFixer, PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 6; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT) && $tokens->isAnyTokenKindsFound([T_CLASS, T_INTERFACE]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // min. offset 4 as minimal candidate is @: <?php\n/** @inheritdoc */class min{} + for ($index = 1, $count = \count($tokens) - 4; $index < $count; ++$index) { + if ($tokens[$index]->isGivenKind([T_CLASS, T_INTERFACE])) { + $index = $this->fixClassy($tokens, $index); + } + } + } + + /** + * @param int $index + * + * @return int + */ + private function fixClassy(Tokens $tokens, $index) + { + // figure out where the classy starts + $classOpenIndex = $tokens->getNextTokenOfKind($index, ['{']); + + // figure out where the classy ends + $classEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $classOpenIndex); + + // is classy extending or implementing some interface + $extendingOrImplementing = $this->isExtendingOrImplementing($tokens, $index, $classOpenIndex); + + if (!$extendingOrImplementing) { + // PHPDoc of classy should not have inherit tag even when using traits as Traits cannot provide this information + $this->fixClassyOutside($tokens, $index); + } + + // figure out if the classy uses a trait + if (!$extendingOrImplementing && $this->isUsingTrait($tokens, $index, $classOpenIndex, $classEndIndex)) { + $extendingOrImplementing = true; + } + + $this->fixClassyInside($tokens, $classOpenIndex, $classEndIndex, !$extendingOrImplementing); + + return $classEndIndex; + } + + /** + * @param int $classOpenIndex + * @param int $classEndIndex + * @param bool $fixThisLevel + */ + private function fixClassyInside(Tokens $tokens, $classOpenIndex, $classEndIndex, $fixThisLevel) + { + for ($i = $classOpenIndex; $i < $classEndIndex; ++$i) { + if ($tokens[$i]->isGivenKind(T_CLASS)) { + $i = $this->fixClassy($tokens, $i); + } elseif ($fixThisLevel && $tokens[$i]->isGivenKind(T_DOC_COMMENT)) { + $this->fixToken($tokens, $i); + } + } + } + + /** + * @param int $classIndex + */ + private function fixClassyOutside(Tokens $tokens, $classIndex) + { + $previousIndex = $tokens->getPrevNonWhitespace($classIndex); + if ($tokens[$previousIndex]->isGivenKind(T_DOC_COMMENT)) { + $this->fixToken($tokens, $previousIndex); + } + } + + /** + * @param int $tokenIndex + */ + private function fixToken(Tokens $tokens, $tokenIndex) + { + $count = 0; + $content = Preg::replaceCallback( + '#(\h*(?:@{*|{*\h*@)\h*inheritdoc\h*)([^}]*)((?:}*)\h*)#i', + static function ($matches) { + return ' '.$matches[2]; + }, + $tokens[$tokenIndex]->getContent(), + -1, + $count + ); + + if ($count) { + $tokens[$tokenIndex] = new Token([T_DOC_COMMENT, $content]); + } + } + + /** + * @param int $classIndex + * @param int $classOpenIndex + * + * @return bool + */ + private function isExtendingOrImplementing(Tokens $tokens, $classIndex, $classOpenIndex) + { + for ($index = $classIndex; $index < $classOpenIndex; ++$index) { + if ($tokens[$index]->isGivenKind([T_EXTENDS, T_IMPLEMENTS])) { + return true; + } + } + + return false; + } + + /** + * @param int $classIndex + * @param int $classOpenIndex + * @param int $classCloseIndex + * + * @return bool + */ + private function isUsingTrait(Tokens $tokens, $classIndex, $classOpenIndex, $classCloseIndex) + { + if ($tokens[$classIndex]->isGivenKind(T_INTERFACE)) { + // cannot use Trait inside an interface + return false; + } + + $useIndex = $tokens->getNextTokenOfKind($classOpenIndex, [[CT::T_USE_TRAIT]]); + + return null !== $useIndex && $useIndex < $classCloseIndex; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocOrderByValueFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocOrderByValueFixer.php new file mode 100644 index 0000000..c783914 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocOrderByValueFixer.php @@ -0,0 +1,218 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Options; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + * @author Andreas Möller <am@localheinz.com> + */ +final class PhpdocOrderByValueFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Order phpdoc tags by value.', + [ + new CodeSample( + '<?php +/** + * @covers Foo + * @covers Bar + */ +final class MyTest extends \PHPUnit_Framework_TestCase +{} +' + ), + new CodeSample( + '<?php +/** + * @author Bob + * @author Alice + */ +final class MyTest extends \PHPUnit_Framework_TestCase +{} +', + [ + 'annotations' => [ + 'author', + ], + ] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpUnitFqcnAnnotationFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_CLASS, T_DOC_COMMENT]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if ([] === $this->configuration['annotations']) { + return; + } + + for ($index = $tokens->count() - 1; $index > 0; --$index) { + foreach ($this->configuration['annotations'] as $type => $typeLowerCase) { + $findPattern = sprintf( + '/@%s\s.+@%s\s/s', + $type, + $type + ); + + if ( + !$tokens[$index]->isGivenKind(T_DOC_COMMENT) + || 0 === Preg::match($findPattern, $tokens[$index]->getContent()) + ) { + continue; + } + + $docBlock = new DocBlock($tokens[$index]->getContent()); + + $annotations = $docBlock->getAnnotationsOfType($type); + $annotationMap = []; + + if (\in_array($type, ['property', 'property-read', 'property-write'], true)) { + $replacePattern = sprintf( + '/(?s)\*\s*@%s\s+(?P<optionalTypes>.+\s+)?\$(?P<comparableContent>[^\s]+).*/', + $type + ); + + $replacement = '\2'; + } elseif ('method' === $type) { + $replacePattern = '/(?s)\*\s*@method\s+(?P<optionalReturnTypes>.+\s+)?(?P<comparableContent>.+)\(.*/'; + $replacement = '\2'; + } else { + $replacePattern = sprintf( + '/\*\s*@%s\s+(?P<comparableContent>.+)/', + $typeLowerCase + ); + + $replacement = '\1'; + } + + foreach ($annotations as $annotation) { + $rawContent = $annotation->getContent(); + + $comparableContent = Preg::replace( + $replacePattern, + $replacement, + strtolower(trim($rawContent)) + ); + + $annotationMap[$comparableContent] = $rawContent; + } + + $orderedAnnotationMap = $annotationMap; + + ksort($orderedAnnotationMap, SORT_STRING); + + if ($orderedAnnotationMap === $annotationMap) { + continue; + } + + $lines = $docBlock->getLines(); + + foreach (array_reverse($annotations) as $annotation) { + array_splice( + $lines, + $annotation->getStart(), + $annotation->getEnd() - $annotation->getStart() + 1, + array_pop($orderedAnnotationMap) + ); + } + + $tokens[$index] = new Token([T_DOC_COMMENT, implode('', $lines)]); + } + } + } + + protected function createConfigurationDefinition() + { + $allowedValues = [ + 'author', + 'covers', + 'coversNothing', + 'dataProvider', + 'depends', + 'group', + 'internal', + 'method', + 'property', + 'property-read', + 'property-write', + 'requires', + 'throws', + 'uses', + ]; + + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('annotations', 'List of annotations to order, e.g. `["covers"]`.')) + ->setAllowedTypes([ + 'array', + ]) + ->setAllowedValues([ + new AllowedValueSubset($allowedValues), + ]) + ->setNormalizer(function (Options $options, $value) { + $normalized = []; + + foreach ($value as $index => $annotation) { + // since we will be using strtolower on the input annotations when building the sorting + // map we must match the type in lower case as well + $normalized[$annotation] = strtolower($annotation); + } + + return $normalized; + }) + ->setDefault([ + 'covers', + ]) + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpdocOrderFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocOrderFixer.php similarity index 64% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpdocOrderFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocOrderFixer.php index 54ef551..fc91375 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/PhpdocOrderFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocOrderFixer.php @@ -10,59 +10,83 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Contrib; +namespace PhpCsFixer\Fixer\Phpdoc; -use Symfony\CS\AbstractFixer; -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; /** * @author Graham Campbell <graham@alt-three.com> */ -class PhpdocOrderFixer extends AbstractFixer +final class PhpdocOrderFixer extends AbstractFixer { /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function isCandidate(Tokens $tokens) { - $tokens = Tokens::fromCode($content); - - foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $token) { - $content = $token->getContent(); - // move param to start, return to end, leave throws in the middle - $content = $this->moveParamAnnotations($content); - // we're parsing the content again to make sure the internal - // state of the dockblock is correct after the modifications - $content = $this->moveReturnAnnotations($content); - // persist the content at the end - $token->setContent($content); - } - - return $tokens->generateCode(); + return $tokens->isTokenKindFound(T_DOC_COMMENT); } /** * {@inheritdoc} */ - public function getDescription() + public function getDefinition() { - return 'Annotations in phpdocs should be ordered so that param annotations come first, then throws annotations, then return annotations.'; + return new FixerDefinition( + 'Annotations in PHPDoc should be ordered so that `@param` annotations come first, then `@throws` annotations, then `@return` annotations.', + [ + new CodeSample( + '<?php +/** + * Hello there! + * + * @throws Exception|RuntimeException foo + * @custom Test! + * @return int Return the number of changes. + * @param string $foo + * @param bool $bar Bar + */ +' + ), + ] + ); } /** * {@inheritdoc} + * + * Must run before PhpdocAlignFixer, PhpdocSeparationFixer, PhpdocTrimFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocIndentFixer, PhpdocNoEmptyReturnFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. */ public function getPriority() { - // must be run before the PhpdocSeparationFixer - - /* - * Should be run before the php_doc_separation fixer so that if we - * create incorrect annotation grouping while moving the annotations - * about, we're still ok. - */ - return 5; + return -2; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $content = $token->getContent(); + // move param to start, return to end, leave throws in the middle + $content = $this->moveParamAnnotations($content); + // we're parsing the content again to make sure the internal + // state of the dockblock is correct after the modifications + $content = $this->moveReturnAnnotations($content); + // persist the content at the end + $tokens[$index] = new Token([T_DOC_COMMENT, $content]); + } } /** @@ -82,7 +106,7 @@ private function moveParamAnnotations($content) return $content; } - $others = $doc->getAnnotationsOfType(array('throws', 'return')); + $others = $doc->getAnnotationsOfType(['throws', 'return']); if (empty($others)) { return $content; @@ -122,7 +146,7 @@ private function moveReturnAnnotations($content) return $content; } - $others = $doc->getAnnotationsOfType(array('param', 'throws')); + $others = $doc->getAnnotationsOfType(['param', 'throws']); // nothing to do if there are no other annotations if (empty($others)) { diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixer.php new file mode 100644 index 0000000..86c9734 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocReturnSelfReferenceFixer.php @@ -0,0 +1,231 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; +use Symfony\Component\OptionsResolver\Options; + +/** + * @author SpacePossum + */ +final class PhpdocReturnSelfReferenceFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @var string[] + */ + private static $toTypes = [ + '$this', + 'static', + 'self', + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'The type of `@return` annotations of methods returning a reference to itself must the configured one.', + [ + new CodeSample( + '<?php +class Sample +{ + /** + * @return this + */ + public function test1() + { + return $this; + } + + /** + * @return $self + */ + public function test2() + { + return $this; + } +} +' + ), + new CodeSample( + '<?php +class Sample +{ + /** + * @return this + */ + public function test1() + { + return $this; + } + + /** + * @return $self + */ + public function test2() + { + return $this; + } +} +', + ['replacements' => ['this' => 'self']] + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \count($tokens) > 10 && $tokens->isTokenKindFound(T_DOC_COMMENT) && $tokens->isAnyTokenKindsFound([T_CLASS, T_INTERFACE]); + } + + /** + * {@inheritdoc} + * + * Must run before NoSuperfluousPhpdocTagsFixer, PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 10; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + foreach ($tokensAnalyzer->getClassyElements() as $index => $element) { + if ('method' === $element['type']) { + $this->fixMethod($tokens, $index); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $default = [ + 'this' => '$this', + '@this' => '$this', + '$self' => 'self', + '@self' => 'self', + '$static' => 'static', + '@static' => 'static', + ]; + + return new FixerConfigurationResolverRootless('replacements', [ + (new FixerOptionBuilder('replacements', 'Mapping between replaced return types with new ones.')) + ->setAllowedTypes(['array']) + ->setNormalizer(static function (Options $options, $value) use ($default) { + $normalizedValue = []; + foreach ($value as $from => $to) { + if (\is_string($from)) { + $from = strtolower($from); + } + + if (!isset($default[$from])) { + throw new InvalidOptionsException(sprintf( + 'Unknown key "%s", expected any of "%s".', + \is_object($from) ? \get_class($from) : \gettype($from).(\is_resource($from) ? '' : '#'.$from), + implode('", "', array_keys($default)) + )); + } + + if (!\in_array($to, self::$toTypes, true)) { + throw new InvalidOptionsException(sprintf( + 'Unknown value "%s", expected any of "%s".', + \is_object($to) ? \get_class($to) : \gettype($to).(\is_resource($to) ? '' : '#'.$to), + implode('", "', self::$toTypes) + )); + } + + $normalizedValue[$from] = $to; + } + + return $normalizedValue; + }) + ->setDefault($default) + ->getOption(), + ], $this->getName()); + } + + /** + * @param int $index + */ + private function fixMethod(Tokens $tokens, $index) + { + static $methodModifiers = [T_STATIC, T_FINAL, T_ABSTRACT, T_PRIVATE, T_PROTECTED, T_PUBLIC]; + + // find PHPDoc of method (if any) + do { + $tokenIndex = $tokens->getPrevMeaningfulToken($index); + if (!$tokens[$tokenIndex]->isGivenKind($methodModifiers)) { + break; + } + + $index = $tokenIndex; + } while (true); + + $docIndex = $tokens->getPrevNonWhitespace($index); + if (!$tokens[$docIndex]->isGivenKind(T_DOC_COMMENT)) { + return; + } + + // find @return + $docBlock = new DocBlock($tokens[$docIndex]->getContent()); + $returnsBlock = $docBlock->getAnnotationsOfType('return'); + + if (!\count($returnsBlock)) { + return; // no return annotation found + } + + $returnsBlock = $returnsBlock[0]; + $types = $returnsBlock->getTypes(); + + if (!\count($types)) { + return; // no return type(s) found + } + + $newTypes = []; + foreach ($types as $type) { + $lower = strtolower($type); + $newTypes[] = isset($this->configuration['replacements'][$lower]) ? $this->configuration['replacements'][$lower] : $type; + } + + if ($types === $newTypes) { + return; + } + + $returnsBlock->setTypes($newTypes); + $tokens[$docIndex] = new Token([T_DOC_COMMENT, $docBlock->getContent()]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocScalarFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocScalarFixer.php new file mode 100644 index 0000000..2e68381 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocScalarFixer.php @@ -0,0 +1,125 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractPhpdocTypesFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author Graham Campbell <graham@alt-three.com> + */ +final class PhpdocScalarFixer extends AbstractPhpdocTypesFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * The types to fix. + * + * @var array + */ + private static $types = [ + 'boolean' => 'bool', + 'callback' => 'callable', + 'double' => 'float', + 'integer' => 'int', + 'real' => 'float', + 'str' => 'string', + ]; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Scalar types should always be written in the same form. `int` not `integer`, `bool` not `boolean`, `float` not `real` or `double`.', + [ + new CodeSample('<?php +/** + * @param integer $a + * @param boolean $b + * @param real $c + * + * @return double + */ +function sample($a, $b, $c) +{ + return sample2($a, $b, $c); +} +'), + new CodeSample( + '<?php +/** + * @param integer $a + * @param boolean $b + * @param real $c + */ +function sample($a, $b, $c) +{ + return sample2($a, $b, $c); +} +', + ['types' => ['boolean']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before GeneralPhpdocAnnotationRemoveFixer, GeneralPhpdocTagRenameFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocInlineTagFixer, PhpdocInlineTagNormalizerFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocTagCasingFixer, PhpdocTagTypeFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run after PhpdocTypesFixer. + */ + public function getPriority() + { + /* + * Should be run before all other docblock fixers apart from the + * phpdoc_to_comment and phpdoc_indent fixer to make sure all fixers + * apply correct indentation to new code they add. This should run + * before alignment of params is done since this fixer might change + * the type and thereby un-aligning the params. We also must run after + * the phpdoc_types_fixer because it can convert types to things that + * we can fix. + */ + return 15; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('types', 'A list of types to fix.')) + ->setAllowedValues([new AllowedValueSubset(array_keys(self::$types))]) + ->setDefault(['boolean', 'double', 'integer', 'real', 'str']) // TODO 3.0 add "callback" + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function normalize($type) + { + if (\in_array($type, $this->configuration['types'], true)) { + return self::$types[$type]; + } + + return $type; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocSeparationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSeparationFixer.php similarity index 59% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocSeparationFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSeparationFixer.php index 5c6a49a..7da0762 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Symfony/PhpdocSeparationFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSeparationFixer.php @@ -10,48 +10,87 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Symfony; +namespace PhpCsFixer\Fixer\Phpdoc; -use Symfony\CS\AbstractFixer; -use Symfony\CS\DocBlock\Annotation; -use Symfony\CS\DocBlock\DocBlock; -use Symfony\CS\DocBlock\TagComparator; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\TagComparator; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; /** * @author Graham Campbell <graham@alt-three.com> */ -class PhpdocSeparationFixer extends AbstractFixer +final class PhpdocSeparationFixer extends AbstractFixer { /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function getDefinition() { - $tokens = Tokens::fromCode($content); + return new FixerDefinition( + 'Annotations in PHPDoc should be grouped together so that annotations of the same type immediately follow each other, and annotations of a different type are separated by a single blank line.', + [ + new CodeSample( + '<?php +/** + * Description. + * @param string $foo + * + * + * @param bool $bar Bar + * @throws Exception|RuntimeException + * @return bool + */ +function fnc($foo, $bar) {} +' + ), + ] + ); + } - foreach ($tokens->findGivenKind(T_DOC_COMMENT) as $index => $token) { - $doc = new DocBlock($token->getContent()); - $this->fixDescription($doc); - $this->fixAnnotations($doc); - $token->setContent($doc->getContent()); - } + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, GeneralPhpdocAnnotationRemoveFixer, PhpdocIndentFixer, PhpdocNoAccessFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocOrderFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return -3; + } - return $tokens->generateCode(); + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); } /** * {@inheritdoc} */ - public function getDescription() + protected function applyFix(\SplFileInfo $file, Tokens $tokens) { - return 'Annotations in phpdocs should be grouped together so that annotations of the same type immediately follow each other, and annotations of a different type are separated by a single blank line.'; + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $doc = new DocBlock($token->getContent()); + $this->fixDescription($doc); + $this->fixAnnotations($doc); + + $tokens[$index] = new Token([T_DOC_COMMENT, $doc->getContent()]); + } } /** * Make sure the description is separated from the annotations. - * - * @param DocBlock $doc */ private function fixDescription(DocBlock $doc) { @@ -63,8 +102,9 @@ private function fixDescription(DocBlock $doc) if ($line->containsUsefulContent()) { $next = $doc->getLine($index + 1); - if ($next->containsATag()) { + if (null !== $next && $next->containsATag()) { $line->addBlank(); + break; } } @@ -74,8 +114,6 @@ private function fixDescription(DocBlock $doc) /** * Make sure the annotations are correctly separated. * - * @param DocBlock $doc - * * @return string */ private function fixAnnotations(DocBlock $doc) @@ -101,10 +139,6 @@ private function fixAnnotations(DocBlock $doc) /** * Force the given annotations to immediately follow each other. - * - * @param DocBlock $doc - * @param Annotation $first - * @param Annotation $second */ private function ensureAreTogether(DocBlock $doc, Annotation $first, Annotation $second) { @@ -118,10 +152,6 @@ private function ensureAreTogether(DocBlock $doc, Annotation $first, Annotation /** * Force the given annotations to have one empty line between each other. - * - * @param DocBlock $doc - * @param Annotation $first - * @param Annotation $second */ private function ensureAreSeparate(DocBlock $doc, Annotation $first, Annotation $second) { diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixer.php new file mode 100644 index 0000000..5196bd7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSingleLineVarSpacingFixer.php @@ -0,0 +1,102 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for part of rule defined in PSR5 ¶7.22. + * + * @author SpacePossum + */ +final class PhpdocSingleLineVarSpacingFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Single line `@var` PHPDoc should have proper spacing.', + [new CodeSample("<?php /**@var MyClass \$a */\n\$a = test();\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocNoAliasTagFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_COMMENT, T_DOC_COMMENT]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + /** @var Token $token */ + foreach ($tokens as $index => $token) { + if (!$token->isComment()) { + continue; + } + + $content = $token->getContent(); + $fixedContent = $this->fixTokenContent($content); + + if ($content !== $fixedContent) { + $tokens[$index] = new Token([T_DOC_COMMENT, $fixedContent]); + } + } + } + + /** + * @param string $content + * + * @return string + */ + private function fixTokenContent($content) + { + return Preg::replaceCallback( + '#^/\*\*\h*@var\h+(\S+)\h*(\$\S+)?\h*([^\n]*)\*/$#', + static function (array $matches) { + $content = '/** @var'; + + for ($i = 1, $m = \count($matches); $i < $m; ++$i) { + if ('' !== $matches[$i]) { + $content .= ' '.$matches[$i]; + } + } + + return rtrim($content).' */'; + }, + $content + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSummaryFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSummaryFixer.php new file mode 100644 index 0000000..23e9bf2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocSummaryFixer.php @@ -0,0 +1,104 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\ShortDescription; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + */ +final class PhpdocSummaryFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHPDoc summary should end in either a full stop, exclamation mark, or question mark.', + [new CodeSample('<?php +/** + * Foo function is great + */ +function foo () {} +')] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $doc = new DocBlock($token->getContent()); + $end = (new ShortDescription($doc))->getEnd(); + + if (null !== $end) { + $line = $doc->getLine($end); + $content = rtrim($line->getContent()); + + if (!$this->isCorrectlyFormatted($content)) { + $line->setContent($content.'.'.$this->whitespacesConfig->getLineEnding()); + $tokens[$index] = new Token([T_DOC_COMMENT, $doc->getContent()]); + } + } + } + } + + /** + * Is the last line of the short description correctly formatted? + * + * @param string $content + * + * @return bool + */ + private function isCorrectlyFormatted($content) + { + if (false !== stripos($content, '{@inheritdoc}')) { + return true; + } + + return $content !== rtrim($content, '.。!?¡¿!?'); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTagCasingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTagCasingFixer.php new file mode 100644 index 0000000..51b362c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTagCasingFixer.php @@ -0,0 +1,102 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\ConfigurationException\InvalidConfigurationException; +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; + +final class PhpdocTagCasingFixer extends AbstractProxyFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Fixes casing of PHPDoc tags.', + [ + new CodeSample("<?php\n/**\n * @inheritdoc\n */\n"), + new CodeSample("<?php\n/**\n * @inheritdoc\n * @Foo\n */\n", [ + 'tags' => ['foo'], + ]), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return parent::getPriority(); + } + + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $replacements = []; + foreach ($this->configuration['tags'] as $tag) { + $replacements[$tag] = $tag; + } + + /** @var GeneralPhpdocTagRenameFixer $generalPhpdocTagRenameFixer */ + $generalPhpdocTagRenameFixer = $this->proxyFixers['general_phpdoc_tag_rename']; + + try { + $generalPhpdocTagRenameFixer->configure([ + 'fix_annotation' => true, + 'fix_inline' => true, + 'replacements' => $replacements, + 'case_sensitive' => false, + ]); + } catch (InvalidConfigurationException $exception) { + throw new InvalidFixerConfigurationException( + $this->getName(), + Preg::replace('/^\[.+?\] /', '', $exception->getMessage()), + $exception + ); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('tags', 'List of tags to fix with their expected casing.')) + ->setAllowedTypes(['array']) + ->setDefault(['inheritDoc']) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + return [new GeneralPhpdocTagRenameFixer()]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTagTypeFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTagTypeFixer.php new file mode 100644 index 0000000..d2aa635 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTagTypeFixer.php @@ -0,0 +1,211 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; +use Symfony\Component\OptionsResolver\Options; + +/** + * @author SpacePossum + */ +final class PhpdocTagTypeFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * @internal + */ + const TAG_REGEX = '/^(?: + (?<tag> + (?:@(?<tag_name>.+?)(?:\s.+)?) + ) + | + {(?<inlined_tag> + (?:@(?<inlined_tag_name>.+?)(?:\s.+)?) + )} + )$/x'; + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Forces PHPDoc tags to be either regular annotations or inline.', + [ + new CodeSample( + "<?php\n/**\n * {@api}\n */\n" + ), + new CodeSample( + "<?php\n/**\n * @inheritdoc\n */\n", + ['tags' => ['inheritdoc' => 'inline']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if (!$this->configuration['tags']) { + return; + } + + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $parts = Preg::split( + sprintf( + '/({?@(?:%s)(?:}|\h.*?(?:}|(?=\R)|(?=\h+\*\/)))?)/i', + implode('|', array_map( + function ($tag) { + return preg_quote($tag, '/'); + }, + array_keys($this->configuration['tags']) + )) + ), + $token->getContent(), + -1, + PREG_SPLIT_DELIM_CAPTURE + ); + + for ($i = 1, $max = \count($parts) - 1; $i < $max; $i += 2) { + if (!Preg::match(self::TAG_REGEX, $parts[$i], $matches)) { + continue; + } + + if ('' !== $matches['tag']) { + $tag = $matches['tag']; + $tagName = $matches['tag_name']; + } else { + $tag = $matches['inlined_tag']; + $tagName = $matches['inlined_tag_name']; + } + + $tagName = strtolower($tagName); + if (!isset($this->configuration['tags'][$tagName])) { + continue; + } + + if ('inline' === $this->configuration['tags'][$tagName]) { + $parts[$i] = '{'.$tag.'}'; + + continue; + } + + if (!$this->tagIsSurroundedByText($parts, $i)) { + $parts[$i] = $tag; + } + } + + $tokens[$index] = new Token([T_DOC_COMMENT, implode('', $parts)]); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('tags', 'The list of tags to fix')) + ->setAllowedTypes(['array']) + ->setAllowedValues([function ($value) { + foreach ($value as $type) { + if (!\in_array($type, ['annotation', 'inline'], true)) { + throw new InvalidOptionsException("Unknown tag type \"{$type}\"."); + } + } + + return true; + }]) + ->setDefault([ + 'api' => 'annotation', + 'author' => 'annotation', + 'copyright' => 'annotation', + 'deprecated' => 'annotation', + 'example' => 'annotation', + 'global' => 'annotation', + 'inheritDoc' => 'annotation', + 'internal' => 'annotation', + 'license' => 'annotation', + 'method' => 'annotation', + 'package' => 'annotation', + 'param' => 'annotation', + 'property' => 'annotation', + 'return' => 'annotation', + 'see' => 'annotation', + 'since' => 'annotation', + 'throws' => 'annotation', + 'todo' => 'annotation', + 'uses' => 'annotation', + 'var' => 'annotation', + 'version' => 'annotation', + ]) + ->setNormalizer(function (Options $options, $value) { + $normalized = []; + foreach ($value as $tag => $type) { + $normalized[strtolower($tag)] = $type; + } + + return $normalized; + }) + ->getOption(), + ]); + } + + private function tagIsSurroundedByText(array $parts, $index) + { + return + Preg::match('/(^|\R)\h*[^@\s]\N*/', $this->cleanComment($parts[$index - 1])) + || Preg::match('/^.*?\R\s*[^@\s]/', $this->cleanComment($parts[$index + 1])) + ; + } + + private function cleanComment($comment) + { + $comment = Preg::replace('/^\/\*\*|\*\/$/', '', $comment); + + return Preg::replace('/(\R)(\h*\*)?\h*/', '$1', $comment); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocToCommentFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocToCommentFixer.php new file mode 100644 index 0000000..dcb2236 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocToCommentFixer.php @@ -0,0 +1,97 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\CommentsAnalyzer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Ceeram <ceeram@cakephp.org> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpdocToCommentFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + * + * Must run before GeneralPhpdocAnnotationRemoveFixer, GeneralPhpdocTagRenameFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyCommentFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocIndentFixer, PhpdocInlineTagFixer, PhpdocInlineTagNormalizerFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocTagCasingFixer, PhpdocTagTypeFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run after CommentToPhpdocFixer. + */ + public function getPriority() + { + /* + * Should be run before all other docblock fixers so that these fixers + * don't touch doc comments which are meant to be converted to regular + * comments. + */ + return 25; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Docblocks should only be used on structural elements.', + [ + new CodeSample( + '<?php +$first = true;// needed because by default first docblock is never fixed. + +/** This should not be a docblock */ +foreach($connections as $key => $sqlite) { + $sqlite->open($path); +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $commentsAnalyzer = new CommentsAnalyzer(); + + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + if ($commentsAnalyzer->isHeaderComment($tokens, $index)) { + continue; + } + + if ($commentsAnalyzer->isBeforeStructuralElement($tokens, $index)) { + continue; + } + + $tokens[$index] = new Token([T_COMMENT, '/*'.ltrim($token->getContent(), '/*')]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTrimConsecutiveBlankLineSeparationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTrimConsecutiveBlankLineSeparationFixer.php new file mode 100644 index 0000000..f37a55f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTrimConsecutiveBlankLineSeparationFixer.php @@ -0,0 +1,217 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\Line; +use PhpCsFixer\DocBlock\ShortDescription; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Nobu Funaki <nobu.funaki@gmail.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpdocTrimConsecutiveBlankLineSeparationFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Removes extra blank lines after summary and after description in PHPDoc.', + [ + new CodeSample( + '<?php +/** + * Summary. + * + * + * Description that contain 4 lines, + * + * + * while 2 of them are blank! + * + * + * @param string $foo + * + * + * @dataProvider provideFixCases + */ +function fnc($foo) {} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return -41; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $doc = new DocBlock($token->getContent()); + $summaryEnd = (new ShortDescription($doc))->getEnd(); + + if (null !== $summaryEnd) { + $this->fixSummary($doc, $summaryEnd); + $this->fixDescription($doc, $summaryEnd); + } + + $this->fixAllTheRest($doc); + + $tokens[$index] = new Token([T_DOC_COMMENT, $doc->getContent()]); + } + } + + /** + * @param int $summaryEnd + */ + private function fixSummary(DocBlock $doc, $summaryEnd) + { + $nonBlankLineAfterSummary = $this->findNonBlankLine($doc, $summaryEnd); + + $this->removeExtraBlankLinesBetween($doc, $summaryEnd, $nonBlankLineAfterSummary); + } + + /** + * @param int $summaryEnd + */ + private function fixDescription(DocBlock $doc, $summaryEnd) + { + $annotationStart = $this->findFirstAnnotationOrEnd($doc); + + // assuming the end of the Description appears before the first Annotation + $descriptionEnd = $this->reverseFindLastUsefulContent($doc, $annotationStart); + + if (null === $descriptionEnd || $summaryEnd === $descriptionEnd) { + return; // no Description + } + + if ($annotationStart === \count($doc->getLines()) - 1) { + return; // no content after Description + } + + $this->removeExtraBlankLinesBetween($doc, $descriptionEnd, $annotationStart); + } + + private function fixAllTheRest(DocBlock $doc) + { + $annotationStart = $this->findFirstAnnotationOrEnd($doc); + $lastLine = $this->reverseFindLastUsefulContent($doc, \count($doc->getLines()) - 1); + + if (null !== $lastLine && $annotationStart !== $lastLine) { + $this->removeExtraBlankLinesBetween($doc, $annotationStart, $lastLine); + } + } + + /** + * @param int $from + * @param int $to + */ + private function removeExtraBlankLinesBetween(DocBlock $doc, $from, $to) + { + for ($index = $from + 1; $index < $to; ++$index) { + $line = $doc->getLine($index); + $next = $doc->getLine($index + 1); + $this->removeExtraBlankLine($line, $next); + } + } + + private function removeExtraBlankLine(Line $current, Line $next) + { + if (!$current->isTheEnd() && !$current->containsUsefulContent() + && !$next->isTheEnd() && !$next->containsUsefulContent()) { + $current->remove(); + } + } + + /** + * @param int $after + * + * @return null|int + */ + private function findNonBlankLine(DocBlock $doc, $after) + { + foreach ($doc->getLines() as $index => $line) { + if ($index <= $after) { + continue; + } + + if ($line->containsATag() || $line->containsUsefulContent() || $line->isTheEnd()) { + return $index; + } + } + + return null; + } + + /** + * @return int + */ + private function findFirstAnnotationOrEnd(DocBlock $doc) + { + $index = null; + foreach ($doc->getLines() as $index => $line) { + if ($line->containsATag()) { + return $index; + } + } + + return $index; // no Annotation, return the last line + } + + /** + * @param int $from + * + * @return null|int + */ + private function reverseFindLastUsefulContent(DocBlock $doc, $from) + { + for ($index = $from - 1; $index >= 0; --$index) { + if ($doc->getLine($index)->containsUsefulContent()) { + return $index; + } + } + + return null; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTrimFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTrimFixer.php new file mode 100644 index 0000000..7bd8e15 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTrimFixer.php @@ -0,0 +1,129 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + */ +final class PhpdocTrimFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'PHPDoc should start and end with content, excluding the very first and last line of the docblocks.', + [new CodeSample('<?php +/** + * + * Foo must be final class. + * + * + */ +final class Foo {} +')] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, GeneralPhpdocAnnotationRemoveFixer, PhpUnitTestAnnotationFixer, PhpdocIndentFixer, PhpdocNoAccessFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocOrderFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return -5; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $content = $token->getContent(); + $content = $this->fixStart($content); + // we need re-parse the docblock after fixing the start before + // fixing the end in order for the lines to be correctly indexed + $content = $this->fixEnd($content); + $tokens[$index] = new Token([T_DOC_COMMENT, $content]); + } + } + + /** + * Make sure the first useful line starts immediately after the first line. + * + * @param string $content + * + * @return string + */ + private function fixStart($content) + { + return Preg::replace( + '~ + (^/\*\*) # DocComment begin + (?: + \R\h*(?:\*\h*)? # lines without useful content + (?!\R\h*\*/) # not followed by a DocComment end + )+ + (\R\h*(?:\*\h*)?\S) # first line with useful content + ~x', + '$1$2', + $content + ); + } + + /** + * Make sure the last useful line is immediately before the final line. + * + * @param string $content + * + * @return string + */ + private function fixEnd($content) + { + return Preg::replace( + '~ + (\R\h*(?:\*\h*)?\S.*?) # last line with useful content + (?: + (?<!/\*\*) # not preceded by a DocComment start + \R\h*(?:\*\h*)? # lines without useful content + )+ + (\R\h*\*/$) # DocComment end + ~xu', + '$1$2', + $content + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTypesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTypesFixer.php new file mode 100644 index 0000000..9bb1fa7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTypesFixer.php @@ -0,0 +1,159 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractPhpdocTypesFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @author Graham Campbell <graham@alt-three.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class PhpdocTypesFixer extends AbstractPhpdocTypesFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * Available types, grouped. + * + * @var array<string,string[]> + */ + private static $possibleTypes = [ + 'simple' => [ + 'array', + 'bool', + 'callable', + 'float', + 'int', + 'iterable', + 'null', + 'object', + 'string', + ], + 'alias' => [ + 'boolean', + 'callback', + 'double', + 'integer', + 'real', + ], + 'meta' => [ + '$this', + 'false', + 'mixed', + 'parent', + 'resource', + 'scalar', + 'self', + 'static', + 'true', + 'void', + ], + ]; + + /** + * @var array string[] + */ + private $typesToFix = []; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->typesToFix = array_merge(...array_map(static function ($group) { + return self::$possibleTypes[$group]; + }, $this->configuration['groups'])); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'The correct case must be used for standard PHP types in PHPDoc.', + [ + new CodeSample( + '<?php +/** + * @param STRING|String[] $bar + * + * @return inT[] + */ +' + ), + new CodeSample( + '<?php +/** + * @param BOOL $foo + * + * @return MIXED + */ +', + ['groups' => ['simple', 'alias']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before GeneralPhpdocAnnotationRemoveFixer, GeneralPhpdocTagRenameFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocInlineTagFixer, PhpdocInlineTagNormalizerFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocScalarFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocTagCasingFixer, PhpdocTagTypeFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run after PhpdocAnnotationWithoutDotFixer, PhpdocIndentFixer. + */ + public function getPriority() + { + /* + * Should be run before all other docblock fixers apart from the + * phpdoc_to_comment and phpdoc_indent fixer to make sure all fixers + * apply correct indentation to new code they add. This should run + * before alignment of params is done since this fixer might change + * the type and thereby un-aligning the params. We also must run before + * the phpdoc_scalar_fixer so that it can make changes after us. + */ + return 16; + } + + /** + * {@inheritdoc} + */ + protected function normalize($type) + { + $lower = strtolower($type); + + return \in_array($lower, $this->typesToFix, true) ? $lower : $type; + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $possibleGroups = array_keys(self::$possibleTypes); + + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('groups', 'Type groups to fix.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset($possibleGroups)]) + ->setDefault($possibleGroups) + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTypesOrderFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTypesOrderFixer.php new file mode 100644 index 0000000..660c523 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocTypesOrderFixer.php @@ -0,0 +1,223 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Utils; + +final class PhpdocTypesOrderFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Sorts PHPDoc types.', + [ + new CodeSample( + '<?php +/** + * @param string|null $bar + */ +' + ), + new CodeSample( + '<?php +/** + * @param null|string $bar + */ +', + ['null_adjustment' => 'always_last'] + ), + new CodeSample( + '<?php +/** + * @param null|string|int|\Foo $bar + */ +', + ['sort_algorithm' => 'alpha'] + ), + new CodeSample( + '<?php +/** + * @param null|string|int|\Foo $bar + */ +', + [ + 'sort_algorithm' => 'alpha', + 'null_adjustment' => 'always_last', + ] + ), + new CodeSample( + '<?php +/** + * @param null|string|int|\Foo $bar + */ +', + [ + 'sort_algorithm' => 'alpha', + 'null_adjustment' => 'none', + ] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocAnnotationWithoutDotFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('sort_algorithm', 'The sorting algorithm to apply.')) + ->setAllowedValues(['alpha', 'none']) + ->setDefault('alpha') + ->getOption(), + (new FixerOptionBuilder('null_adjustment', 'Forces the position of `null` (overrides `sort_algorithm`).')) + ->setAllowedValues(['always_first', 'always_last', 'none']) + ->setDefault('always_first') + ->getOption(), + ]); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $doc = new DocBlock($token->getContent()); + $annotations = $doc->getAnnotationsOfType(Annotation::getTagsWithTypes()); + + if (!\count($annotations)) { + continue; + } + + foreach ($annotations as $annotation) { + $types = $annotation->getTypes(); + + // fix main types + $annotation->setTypes($this->sortTypes($types)); + + // fix @method parameters types + $line = $doc->getLine($annotation->getStart()); + $line->setContent(Preg::replaceCallback('/(@method\s+.+?\s+\w+\()(.*)\)/', function (array $matches) { + $sorted = Preg::replaceCallback('/([^\s,]+)([\s]+\$[^\s,]+)/', function (array $matches) { + return $this->sortJoinedTypes($matches[1]).$matches[2]; + }, $matches[2]); + + return $matches[1].$sorted.')'; + }, $line->getContent())); + } + + $tokens[$index] = new Token([T_DOC_COMMENT, $doc->getContent()]); + } + } + + /** + * @param string[] $types + * + * @return string[] + */ + private function sortTypes(array $types) + { + foreach ($types as $index => $type) { + $types[$index] = Preg::replaceCallback('/^([^<]+)<(?:([\w\|]+?|<?.*>)(,\s*))?(.*)>$/', function (array $matches) { + return $matches[1].'<'.$this->sortJoinedTypes($matches[2]).$matches[3].$this->sortJoinedTypes($matches[4]).'>'; + }, $type); + } + + if ('alpha' === $this->configuration['sort_algorithm']) { + $types = Utils::stableSort( + $types, + static function ($type) { return $type; }, + static function ($typeA, $typeB) { + $regexp = '/^\\??\\\?/'; + + return strcasecmp( + Preg::replace($regexp, '', $typeA), + Preg::replace($regexp, '', $typeB) + ); + } + ); + } + + if ('none' !== $this->configuration['null_adjustment']) { + $nulls = []; + foreach ($types as $index => $type) { + if (Preg::match('/^\\\?null$/i', $type)) { + $nulls[$index] = $type; + unset($types[$index]); + } + } + + if (\count($nulls)) { + if ('always_last' === $this->configuration['null_adjustment']) { + array_push($types, ...$nulls); + } else { + array_unshift($types, ...$nulls); + } + } + } + + return $types; + } + + /** + * @param string $types + * + * @return string + */ + private function sortJoinedTypes($types) + { + $types = array_filter( + Preg::split('/([^|<]+(?:<.*>)?)/', $types, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY), + static function ($value) { + return '|' !== $value; + } + ); + + return implode('|', $this->sortTypes($types)); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocVarAnnotationCorrectOrderFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocVarAnnotationCorrectOrderFixer.php new file mode 100644 index 0000000..269f411 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocVarAnnotationCorrectOrderFixer.php @@ -0,0 +1,78 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Kuba Werłos <werlos@gmail.com> + */ +final class PhpdocVarAnnotationCorrectOrderFixer extends AbstractFixer +{ + public function getDefinition() + { + return new FixerDefinition( + '`@var` and `@type` annotations must have type and name in the correct order.', + [new CodeSample('<?php +/** @var $foo int */ +$foo = 2 + 2; +')] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 0; + } + + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + if (false === stripos($token->getContent(), '@var') && false === stripos($token->getContent(), '@type')) { + continue; + } + + $newContent = Preg::replace( + '/(@(?:type|var)\s*)(\$\S+)(\h+)([^\$](?:[^<\s]|<[^>]*>)*)(\s|\*)/i', + '$1$4$3$2$5', + $token->getContent() + ); + + if ($newContent === $token->getContent()) { + continue; + } + + $tokens[$index] = new Token([$token->getId(), $newContent]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocVarWithoutNameFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocVarWithoutNameFixer.php new file mode 100644 index 0000000..58f407c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Phpdoc/PhpdocVarWithoutNameFixer.php @@ -0,0 +1,151 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Phpdoc; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\DocBlock\DocBlock; +use PhpCsFixer\DocBlock\Line; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + * @author Dave van der Brugge <dmvdbrugge@gmail.com> + */ +final class PhpdocVarWithoutNameFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + '`@var` and `@type` annotations of classy properties should not contain the name.', + [new CodeSample('<?php +final class Foo +{ + /** + * @var int $bar + */ + public $bar; + + /** + * @type $baz float + */ + public $baz; +} +')] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOC_COMMENT) && $tokens->isAnyTokenKindsFound(Token::getClassyTokenKinds()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $nextIndex = $tokens->getNextMeaningfulToken($index); + + if (null === $nextIndex) { + continue; + } + + // For people writing static public $foo instead of public static $foo + if ($tokens[$nextIndex]->isGivenKind(T_STATIC)) { + $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); + } + + // We want only doc blocks that are for properties and thus have specified access modifiers next + if (!$tokens[$nextIndex]->isGivenKind([T_PRIVATE, T_PROTECTED, T_PUBLIC, T_VAR])) { + continue; + } + + $doc = new DocBlock($token->getContent()); + + $firstLevelLines = $this->getFirstLevelLines($doc); + $annotations = $doc->getAnnotationsOfType(['type', 'var']); + + foreach ($annotations as $annotation) { + if (isset($firstLevelLines[$annotation->getStart()])) { + $this->fixLine($firstLevelLines[$annotation->getStart()]); + } + } + + $tokens[$index] = new Token([T_DOC_COMMENT, $doc->getContent()]); + } + } + + private function fixLine(Line $line) + { + $content = $line->getContent(); + + Preg::matchAll('/ \$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $content, $matches); + + if (isset($matches[0][0])) { + $line->setContent(str_replace($matches[0][0], '', $content)); + } + } + + /** + * @return Line[] + */ + private function getFirstLevelLines(DocBlock $docBlock) + { + $nested = 0; + $lines = $docBlock->getLines(); + + foreach ($lines as $index => $line) { + $content = $line->getContent(); + + if (Preg::match('/\s*\*\s*}$/', $content)) { + --$nested; + } + + if ($nested > 0) { + unset($lines[$index]); + } + + if (Preg::match('/\s\{$/', $content)) { + ++$nested; + } + } + + return $lines; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/BlankLineBeforeReturnFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/BlankLineBeforeReturnFixer.php new file mode 100644 index 0000000..ce8eec3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/BlankLineBeforeReturnFixer.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ReturnNotation; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\Fixer\Whitespace\BlankLineBeforeStatementFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @deprecated since 2.4, replaced by BlankLineBeforeStatementFixer + * + * @todo To be removed at 3.0 + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Andreas Möller <am@localheinz.com> + */ +final class BlankLineBeforeReturnFixer extends AbstractProxyFixer implements DeprecatedFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'An empty line feed should precede a return statement.', + [new CodeSample("<?php\nfunction A()\n{\n echo 1;\n return 1;\n}\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run after NoUselessReturnFixer. + */ + public function getPriority() + { + return parent::getPriority(); + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + $fixer = new BlankLineBeforeStatementFixer(); + $fixer->configure(['statements' => ['return']]); + + return [$fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoUselessReturnFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/NoUselessReturnFixer.php similarity index 54% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoUselessReturnFixer.php rename to vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/NoUselessReturnFixer.php index ebe2d9f..740a18d 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Fixer/Contrib/NoUselessReturnFixer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/NoUselessReturnFixer.php @@ -10,10 +10,12 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Fixer\Contrib; +namespace PhpCsFixer\Fixer\ReturnNotation; -use Symfony\CS\AbstractFixer; -use Symfony\CS\Tokenizer\Tokens; +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; /** * @author SpacePossum @@ -23,45 +25,64 @@ final class NoUselessReturnFixer extends AbstractFixer /** * {@inheritdoc} */ - public function fix(\SplFileInfo $file, $content) + public function isCandidate(Tokens $tokens) { - $tokens = Tokens::fromCode($content); - - foreach ($tokens as $index => $token) { - if (!$token->isGivenKind(T_FUNCTION)) { - continue; - } - - $index = $tokens->getNextTokenOfKind($index, array(';', '{')); - if ($tokens[$index]->equals('{')) { - $this->fixFunction($tokens, $index, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index)); - } - } - - return $tokens->generateCode(); + return $tokens->isAllTokenKindsFound([T_FUNCTION, T_RETURN]); } /** * {@inheritdoc} */ - public function getDescription() + public function getDefinition() { - return 'There should not be an empty return statement at the end of a function.'; + return new FixerDefinition( + 'There should not be an empty `return` statement at the end of a function.', + [ + new CodeSample( + '<?php +function example($b) { + if ($b) { + return; + } + return; +} +' + ), + ] + ); } /** * {@inheritdoc} + * + * Must run before BlankLineBeforeReturnFixer, BlankLineBeforeStatementFixer, NoExtraBlankLinesFixer, NoWhitespaceInBlankLineFixer, SingleLineCommentStyleFixer. + * Must run after NoEmptyStatementFixer, NoUnneededCurlyBracesFixer, NoUselessElseFixer, SimplifiedNullReturnFixer. */ public function getPriority() { - // should be run before ReturnFixer, ExtraEmptyLinesFixer, WhitespacyLinesFixer and after EmptyReturnFixer and DuplicateSemicolonFixer. return -18; } /** - * @param Tokens $tokens - * @param int $start Token index of the opening brace token of the function - * @param int $end Token index of the closing brace token of the function + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_FUNCTION)) { + continue; + } + + $index = $tokens->getNextTokenOfKind($index, [';', '{']); + if ($tokens[$index]->equals('{')) { + $this->fixFunction($tokens, $index, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index)); + } + } + } + + /** + * @param int $start Token index of the opening brace token of the function + * @param int $end Token index of the closing brace token of the function */ private function fixFunction(Tokens $tokens, $start, $end) { @@ -80,7 +101,7 @@ private function fixFunction(Tokens $tokens, $start, $end) } $previous = $tokens->getPrevMeaningfulToken($index); - if ($tokens[$previous]->equalsAny(array(array(T_ELSE), ')'))) { + if ($tokens[$previous]->equalsAny([[T_ELSE], ')'])) { continue; } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/ReturnAssignmentFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/ReturnAssignmentFixer.php new file mode 100644 index 0000000..ac8c8f2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/ReturnAssignmentFixer.php @@ -0,0 +1,357 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ReturnNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author SpacePossum + */ +final class ReturnAssignmentFixer extends AbstractFixer +{ + /** + * @var TokensAnalyzer + */ + private $tokensAnalyzer; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Local, dynamic and directly referenced variables should not be assigned and directly returned by a function or method.', + [new CodeSample("<?php\nfunction a() {\n \$a = 1;\n return \$a;\n}\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BlankLineBeforeStatementFixer. + * Must run after NoEmptyStatementFixer, NoUnneededCurlyBracesFixer. + */ + public function getPriority() + { + return -15; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAllTokenKindsFound([T_FUNCTION, T_RETURN, T_VARIABLE]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $tokenCount = \count($tokens); + $this->tokensAnalyzer = new TokensAnalyzer($tokens); + + for ($index = 1; $index < $tokenCount; ++$index) { + if (!$tokens[$index]->isGivenKind(T_FUNCTION)) { + continue; + } + + $functionOpenIndex = $tokens->getNextTokenOfKind($index, ['{', ';']); + if ($tokens[$functionOpenIndex]->equals(';')) { // abstract function + $index = $functionOpenIndex - 1; + + continue; + } + + $functionCloseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $functionOpenIndex); + $totalTokensAdded = 0; + + do { + $tokensAdded = $this->fixFunction( + $tokens, + $index, + $functionOpenIndex, + $functionCloseIndex + ); + + $totalTokensAdded += $tokensAdded; + } while ($tokensAdded > 0); + + $index = $functionCloseIndex + $totalTokensAdded; + $tokenCount += $totalTokensAdded; + } + } + + /** + * @param int $functionIndex token index of T_FUNCTION + * @param int $functionOpenIndex token index of the opening brace token of the function + * @param int $functionCloseIndex token index of the closing brace token of the function + * + * @return int >= 0 number of tokens inserted into the Tokens collection + */ + private function fixFunction(Tokens $tokens, $functionIndex, $functionOpenIndex, $functionCloseIndex) + { + static $riskyKinds = [ + CT::T_DYNAMIC_VAR_BRACE_OPEN, // "$h = ${$g};" case + T_EVAL, // "$c = eval('return $this;');" case + T_GLOBAL, + T_INCLUDE, // loading additional symbols we cannot analyze here + T_INCLUDE_ONCE, // " + T_REQUIRE, // " + T_REQUIRE_ONCE, // " + T_STATIC, + ]; + + $inserted = 0; + $candidates = []; + $isRisky = false; + + // go through the function declaration and check if references are passed + // - check if it will be risky to fix return statements of this function + for ($index = $functionIndex + 1; $index < $functionOpenIndex; ++$index) { + if ($tokens[$index]->equals('&')) { + $isRisky = true; + + break; + } + } + + // go through all the tokens of the body of the function: + // - check if it will be risky to fix return statements of this function + // - check nested functions; fix when found and update the upper limit + number of inserted token + // - check for return statements that might be fixed (based on if fixing will be risky, which is only know after analyzing the whole function) + + for ($index = $functionOpenIndex + 1; $index < $functionCloseIndex; ++$index) { + if ($tokens[$index]->isGivenKind(T_FUNCTION)) { + $nestedFunctionOpenIndex = $tokens->getNextTokenOfKind($index, ['{', ';']); + if ($tokens[$nestedFunctionOpenIndex]->equals(';')) { // abstract function + $index = $nestedFunctionOpenIndex - 1; + + continue; + } + + $nestedFunctionCloseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $nestedFunctionOpenIndex); + + $tokensAdded = $this->fixFunction( + $tokens, + $index, + $nestedFunctionOpenIndex, + $nestedFunctionCloseIndex + ); + + $index = $nestedFunctionCloseIndex + $tokensAdded; + $functionCloseIndex += $tokensAdded; + $inserted += $tokensAdded; + } + + if ($isRisky) { + continue; // don't bother to look into anything else than nested functions as the current is risky already + } + + if ($tokens[$index]->equals('&')) { + $isRisky = true; + + continue; + } + + if ($tokens[$index]->isGivenKind(T_RETURN)) { + $candidates[] = $index; + + continue; + } + + // test if there this is anything in the function body that might + // change global state or indirect changes (like through references, eval, etc.) + + if ($tokens[$index]->isGivenKind($riskyKinds)) { + $isRisky = true; + + continue; + } + + if ($tokens[$index]->equals('$')) { + $nextIndex = $tokens->getNextMeaningfulToken($index); + if ($tokens[$nextIndex]->isGivenKind(T_VARIABLE)) { + $isRisky = true; // "$$a" case + + continue; + } + } + + if ($this->tokensAnalyzer->isSuperGlobal($index)) { + $isRisky = true; + + continue; + } + } + + if ($isRisky) { + return $inserted; + } + + // fix the candidates in reverse order when applicable + for ($i = \count($candidates) - 1; $i >= 0; --$i) { + $index = $candidates[$i]; + + // Check if returning only a variable (i.e. not the result of an expression, function call etc.) + $returnVarIndex = $tokens->getNextMeaningfulToken($index); + if (!$tokens[$returnVarIndex]->isGivenKind(T_VARIABLE)) { + continue; // example: "return 1;" + } + + $endReturnVarIndex = $tokens->getNextMeaningfulToken($returnVarIndex); + if (!$tokens[$endReturnVarIndex]->equalsAny([';', [T_CLOSE_TAG]])) { + continue; // example: "return $a + 1;" + } + + // Check that the variable is assigned just before it is returned + $assignVarEndIndex = $tokens->getPrevMeaningfulToken($index); + if (!$tokens[$assignVarEndIndex]->equals(';')) { + continue; // example: "? return $a;" + } + + // Note: here we are @ "; return $a;" (or "; return $a ? >") + do { + $prevMeaningFul = $tokens->getPrevMeaningfulToken($assignVarEndIndex); + + if (!$tokens[$prevMeaningFul]->equals(')')) { + break; + } + + $assignVarEndIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $prevMeaningFul); + } while (true); + + $assignVarOperatorIndex = $tokens->getPrevTokenOfKind( + $assignVarEndIndex, + ['=', ';', '{', [T_OPEN_TAG], [T_OPEN_TAG_WITH_ECHO]] + ); + + if (null === $assignVarOperatorIndex || !$tokens[$assignVarOperatorIndex]->equals('=')) { + continue; + } + + // Note: here we are @ "= [^;{<? ? >] ; return $a;" + $assignVarIndex = $tokens->getPrevMeaningfulToken($assignVarOperatorIndex); + if (!$tokens[$assignVarIndex]->equals($tokens[$returnVarIndex], false)) { + continue; + } + + // Note: here we are @ "$a = [^;{<? ? >] ; return $a;" + $beforeAssignVarIndex = $tokens->getPrevMeaningfulToken($assignVarIndex); + if (!$tokens[$beforeAssignVarIndex]->equalsAny([';', '{', '}'])) { + continue; + } + + // Note: here we are @ "[;{}] $a = [^;{<? ? >] ; return $a;" + $inserted += $this->simplifyReturnStatement( + $tokens, + $assignVarIndex, + $assignVarOperatorIndex, + $index, + $endReturnVarIndex + ); + } + + return $inserted; + } + + /** + * @param int $assignVarIndex + * @param int $assignVarOperatorIndex + * @param int $returnIndex + * @param int $returnVarEndIndex + * + * @return int >= 0 number of tokens inserted into the Tokens collection + */ + private function simplifyReturnStatement( + Tokens $tokens, + $assignVarIndex, + $assignVarOperatorIndex, + $returnIndex, + $returnVarEndIndex + ) { + $inserted = 0; + $originalIndent = $tokens[$assignVarIndex - 1]->isWhitespace() + ? $tokens[$assignVarIndex - 1]->getContent() + : null + ; + + // remove the return statement + if ($tokens[$returnVarEndIndex]->equals(';')) { // do not remove PHP close tags + $tokens->clearTokenAndMergeSurroundingWhitespace($returnVarEndIndex); + } + + for ($i = $returnIndex; $i <= $returnVarEndIndex - 1; ++$i) { + $this->clearIfSave($tokens, $i); + } + + // remove no longer needed indentation of the old/remove return statement + if ($tokens[$returnIndex - 1]->isWhitespace()) { + $content = $tokens[$returnIndex - 1]->getContent(); + $fistLinebreakPos = strrpos($content, "\n"); + $content = false === $fistLinebreakPos + ? ' ' + : substr($content, $fistLinebreakPos) + ; + + $tokens[$returnIndex - 1] = new Token([T_WHITESPACE, $content]); + } + + // remove the variable and the assignment + for ($i = $assignVarIndex; $i <= $assignVarOperatorIndex; ++$i) { + $this->clearIfSave($tokens, $i); + } + + // insert new return statement + $tokens->insertAt($assignVarIndex, new Token([T_RETURN, 'return'])); + ++$inserted; + + // use the original indent of the var assignment for the new return statement + if ( + null !== $originalIndent + && $tokens[$assignVarIndex - 1]->isWhitespace() + && $originalIndent !== $tokens[$assignVarIndex - 1]->getContent() + ) { + $tokens[$assignVarIndex - 1] = new Token([T_WHITESPACE, $originalIndent]); + } + + // remove trailing space after the new return statement which might be added during the clean up process + $nextIndex = $tokens->getNonEmptySibling($assignVarIndex, 1); + if (!$tokens[$nextIndex]->isWhitespace()) { + $tokens->insertAt($nextIndex, new Token([T_WHITESPACE, ' '])); + ++$inserted; + } + + return $inserted; + } + + private function clearIfSave(Tokens $tokens, $index) + { + if ($tokens[$index]->isComment()) { + return; + } + + if ($tokens[$index]->isWhitespace() && $tokens[$tokens->getPrevNonWhitespace($index)]->isComment()) { + return; + } + + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/SimplifiedNullReturnFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/SimplifiedNullReturnFixer.php new file mode 100644 index 0000000..6b324ea --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/ReturnNotation/SimplifiedNullReturnFixer.php @@ -0,0 +1,170 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\ReturnNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + */ +final class SimplifiedNullReturnFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'A return statement wishing to return `void` should not return `null`.', + [ + new CodeSample("<?php return null;\n"), + new VersionSpecificCodeSample( + <<<'EOT' +<?php +function foo() { return null; } +function bar(): int { return null; } +function baz(): ?int { return null; } +function xyz(): void { return null; } + +EOT + , + new VersionSpecification(70100) + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before NoUselessReturnFixer, VoidReturnFixer. + */ + public function getPriority() + { + return 16; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_RETURN); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_RETURN)) { + continue; + } + + if ($this->needFixing($tokens, $index)) { + $this->clear($tokens, $index); + } + } + } + + /** + * Clear the return statement located at a given index. + * + * @param int $index + */ + private function clear(Tokens $tokens, $index) + { + while (!$tokens[++$index]->equals(';')) { + if ($this->shouldClearToken($tokens, $index)) { + $tokens->clearAt($index); + } + } + } + + /** + * Does the return statement located at a given index need fixing? + * + * @param int $index + * + * @return bool + */ + private function needFixing(Tokens $tokens, $index) + { + if ($this->isStrictOrNullableReturnTypeFunction($tokens, $index)) { + return false; + } + + $content = ''; + while (!$tokens[$index]->equals(';')) { + $index = $tokens->getNextMeaningfulToken($index); + $content .= $tokens[$index]->getContent(); + } + + $content = ltrim($content, '('); + $content = rtrim($content, ');'); + + return 'null' === strtolower($content); + } + + /** + * Is the return within a function with a non-void or nullable return type? + * + * @param int $returnIndex Current return token index + * + * @return bool + */ + private function isStrictOrNullableReturnTypeFunction(Tokens $tokens, $returnIndex) + { + $functionIndex = $returnIndex; + do { + $functionIndex = $tokens->getPrevTokenOfKind($functionIndex, [[T_FUNCTION]]); + if (null === $functionIndex) { + return false; + } + $openingCurlyBraceIndex = $tokens->getNextTokenOfKind($functionIndex, ['{']); + $closingCurlyBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $openingCurlyBraceIndex); + } while ($closingCurlyBraceIndex < $returnIndex); + + $possibleVoidIndex = $tokens->getPrevMeaningfulToken($openingCurlyBraceIndex); + $isStrictReturnType = $tokens[$possibleVoidIndex]->isGivenKind(T_STRING) && 'void' !== $tokens[$possibleVoidIndex]->getContent(); + + $nullableTypeIndex = $tokens->getNextTokenOfKind($functionIndex, [[CT::T_NULLABLE_TYPE]]); + $isNullableReturnType = null !== $nullableTypeIndex && $nullableTypeIndex < $openingCurlyBraceIndex; + + return $isStrictReturnType || $isNullableReturnType; + } + + /** + * Should we clear the specific token? + * + * If the token is a comment, or is whitespace that is immediately before a + * comment, then we'll leave it alone. + * + * @param int $index + * + * @return bool + */ + private function shouldClearToken(Tokens $tokens, $index) + { + $token = $tokens[$index]; + + return !$token->isComment() && !($token->isWhitespace() && $tokens[$index + 1]->isComment()); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/MultilineWhitespaceBeforeSemicolonsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/MultilineWhitespaceBeforeSemicolonsFixer.php new file mode 100644 index 0000000..35907bd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/MultilineWhitespaceBeforeSemicolonsFixer.php @@ -0,0 +1,304 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Semicolon; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + * @author Egidijus Girčys <e.gircys@gmail.com> + */ +final class MultilineWhitespaceBeforeSemicolonsFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @internal + */ + const STRATEGY_NO_MULTI_LINE = 'no_multi_line'; + + /** + * @internal + */ + const STRATEGY_NEW_LINE_FOR_CHAINED_CALLS = 'new_line_for_chained_calls'; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Forbid multi-line whitespace before the closing semicolon or move the semicolon to the new line for chained calls.', + [ + new CodeSample( + '<?php +function foo () { + return 1 + 2 + ; +} +' + ), + new CodeSample( + '<?php + $this->method1() + ->method2() + ->method(3); + ?> +', + ['strategy' => self::STRATEGY_NEW_LINE_FOR_CHAINED_CALLS] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before SpaceAfterSemicolonFixer. + * Must run after CombineConsecutiveIssetsFixer, NoEmptyStatementFixer, SingleImportPerStatementFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(';'); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder( + 'strategy', + 'Forbid multi-line whitespace or move the semicolon to the new line for chained calls.' + )) + ->setAllowedValues([self::STRATEGY_NO_MULTI_LINE, self::STRATEGY_NEW_LINE_FOR_CHAINED_CALLS]) + ->setDefault(self::STRATEGY_NO_MULTI_LINE) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + if (self::STRATEGY_NEW_LINE_FOR_CHAINED_CALLS === $this->configuration['strategy']) { + $this->applyChainedCallsFix($tokens); + + return; + } + + if (self::STRATEGY_NO_MULTI_LINE === $this->configuration['strategy']) { + $this->applyNoMultiLineFix($tokens); + } + } + + private function applyNoMultiLineFix(Tokens $tokens) + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + foreach ($tokens as $index => $token) { + if (!$token->equals(';')) { + continue; + } + + $previousIndex = $index - 1; + $previous = $tokens[$previousIndex]; + if (!$previous->isWhitespace() || false === strpos($previous->getContent(), "\n")) { + continue; + } + + $content = $previous->getContent(); + if (0 === strpos($content, $lineEnding) && $tokens[$index - 2]->isComment()) { + $tokens->ensureWhitespaceAtIndex($previousIndex, 0, $lineEnding); + } else { + $tokens->clearAt($previousIndex); + } + } + } + + private function applyChainedCallsFix(Tokens $tokens) + { + for ($index = \count($tokens) - 1; $index >= 0; --$index) { + // continue if token is not a semicolon + if (!$tokens[$index]->equals(';')) { + continue; + } + + // get the indent of the chained call, null in case it's not a chained call + $indent = $this->findWhitespaceBeforeFirstCall($index - 1, $tokens); + + if (null === $indent) { + continue; + } + + // unset semicolon + $tokens->clearAt($index); + + // find the line ending token index after the semicolon + $index = $this->getNewLineIndex($index, $tokens); + + // line ending string of the last method call + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + // appended new line to the last method call + $newline = new Token([T_WHITESPACE, $lineEnding.$indent]); + + // insert the new line with indented semicolon + $tokens->insertAt($index, [$newline, new Token(';')]); + } + } + + /** + * Find the index for the new line. Return the given index when there's no new line. + * + * @param int $index + * + * @return int + */ + private function getNewLineIndex($index, Tokens $tokens) + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + for ($index, $count = \count($tokens); $index < $count; ++$index) { + if (false !== strstr($tokens[$index]->getContent(), $lineEnding)) { + return $index; + } + } + + return $index; + } + + /** + * Checks if the semicolon closes a chained call and returns the whitespace of the first call at $index. + * i.e. it will return the whitespace marked with '____' in the example underneath. + * + * .. + * ____$this->methodCall() + * ->anotherCall(); + * .. + * + * @param int $index + * + * @return null|string + */ + private function findWhitespaceBeforeFirstCall($index, Tokens $tokens) + { + // semicolon followed by a closing bracket? + if (!$tokens[$index]->equals(')')) { + return null; + } + + // find opening bracket + $openingBrackets = 1; + for (--$index; $index > 0; --$index) { + if ($tokens[$index]->equals(')')) { + ++$openingBrackets; + + continue; + } + + if ($tokens[$index]->equals('(')) { + if (1 === $openingBrackets) { + break; + } + --$openingBrackets; + } + } + + // method name + if (!$tokens[--$index]->isGivenKind(T_STRING)) { + return null; + } + + // ->, ?-> or :: + if (!$tokens[--$index]->isObjectOperator() && !$tokens[$index]->isGivenKind(T_DOUBLE_COLON)) { + return null; + } + + // white space + if (!$tokens[--$index]->isGivenKind(T_WHITESPACE)) { + return null; + } + + $closingBrackets = 0; + for ($index; $index >= 0; --$index) { + if ($tokens[$index]->equals(')')) { + ++$closingBrackets; + } + + if ($tokens[$index]->equals('(')) { + --$closingBrackets; + } + + // must be the variable of the first call in the chain + if ($tokens[$index]->isGivenKind([T_VARIABLE, T_RETURN, T_STRING]) && 0 === $closingBrackets) { + if ($tokens[--$index]->isGivenKind(T_WHITESPACE) + || $tokens[$index]->isGivenKind(T_OPEN_TAG)) { + return $this->getIndentAt($tokens, $index); + } + } + } + + return null; + } + + /** + * @param int $index + * + * @return null|string + */ + private function getIndentAt(Tokens $tokens, $index) + { + $content = ''; + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + // find line ending token + for ($index; $index > 0; --$index) { + if (false !== strstr($tokens[$index]->getContent(), $lineEnding)) { + break; + } + } + + if ($tokens[$index]->isWhitespace()) { + $content = $tokens[$index]->getContent(); + --$index; + } + + if ($tokens[$index]->isGivenKind(T_OPEN_TAG)) { + $content = $tokens[$index]->getContent().$content; + } + + if (1 === Preg::match('/\R{1}(\h*)$/', $content, $matches)) { + return $matches[1]; + } + + return null; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoEmptyStatementFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoEmptyStatementFixer.php new file mode 100644 index 0000000..a51de8d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoEmptyStatementFixer.php @@ -0,0 +1,194 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Semicolon; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @author SpacePossum + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NoEmptyStatementFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Remove useless (semicolon) statements.', + [ + new CodeSample("<?php \$a = 1;;\n"), + new CodeSample("<?php echo 1;2;\n"), + new CodeSample("<?php while(foo()){\n continue 1;\n}\n"), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer, CombineConsecutiveUnsetsFixer, MultilineWhitespaceBeforeSemicolonsFixer, NoExtraBlankLinesFixer, NoSinglelineWhitespaceBeforeSemicolonsFixer, NoTrailingWhitespaceFixer, NoUselessElseFixer, NoUselessReturnFixer, NoWhitespaceInBlankLineFixer, ReturnAssignmentFixer, SpaceAfterSemicolonFixer, SwitchCaseSemicolonToColonFixer. + * Must run after NoUselessSprintfFixer. + */ + public function getPriority() + { + return 40; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(';'); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) { + if ($tokens[$index]->isGivenKind([T_BREAK, T_CONTINUE])) { + $index = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$index]->equals([T_LNUMBER, '1'])) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } + + continue; + } + + // skip T_FOR parenthesis to ignore double `;` like `for ($i = 1; ; ++$i) {...}` + if ($tokens[$index]->isGivenKind(T_FOR)) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $tokens->getNextMeaningfulToken($index)) + 1; + + continue; + } + + if (!$tokens[$index]->equals(';')) { + continue; + } + + $previousMeaningfulIndex = $tokens->getPrevMeaningfulToken($index); + + // A semicolon can always be removed if it follows a semicolon, '{' or opening tag. + if ($tokens[$previousMeaningfulIndex]->equalsAny(['{', ';', [T_OPEN_TAG]])) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + + continue; + } + + // A semicolon might be removed if it follows a '}' but only if the brace is part of certain structures. + if ($tokens[$previousMeaningfulIndex]->equals('}')) { + $this->fixSemicolonAfterCurlyBraceClose($tokens, $index, $previousMeaningfulIndex); + + continue; + } + + // A semicolon might be removed together with its noop statement, for example "<?php 1;" + $prePreviousMeaningfulIndex = $tokens->getPrevMeaningfulToken($previousMeaningfulIndex); + + if ( + $tokens[$prePreviousMeaningfulIndex]->equalsAny([';', '{', '}', [T_OPEN_TAG]]) + && $tokens[$previousMeaningfulIndex]->isGivenKind([T_CONSTANT_ENCAPSED_STRING, T_DNUMBER, T_LNUMBER, T_STRING, T_VARIABLE]) + ) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + $tokens->clearTokenAndMergeSurroundingWhitespace($previousMeaningfulIndex); + } + } + } + + /** + * Fix semicolon after closing curly brace if needed. + * + * Test for the following cases + * - just '{' '}' block (following open tag or ';') + * - if, else, elseif + * - interface, trait, class (but not anonymous) + * - catch, finally (but not try) + * - for, foreach, while (but not 'do - while') + * - switch + * - function (declaration, but not lambda) + * - declare (with '{' '}') + * - namespace (with '{' '}') + * + * @param int $index Semicolon index + * @param int $curlyCloseIndex + */ + private function fixSemicolonAfterCurlyBraceClose(Tokens $tokens, $index, $curlyCloseIndex) + { + static $beforeCurlyOpeningKinds = null; + + if (null === $beforeCurlyOpeningKinds) { + $beforeCurlyOpeningKinds = [T_ELSE, T_FINALLY, T_NAMESPACE, T_OPEN_TAG]; + } + + $curlyOpeningIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $curlyCloseIndex); + $beforeCurlyOpeningIndex = $tokens->getPrevMeaningfulToken($curlyOpeningIndex); + + if ($tokens[$beforeCurlyOpeningIndex]->isGivenKind($beforeCurlyOpeningKinds) || $tokens[$beforeCurlyOpeningIndex]->equalsAny([';', '{', '}'])) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + + return; + } + + // check for namespaces and class, interface and trait definitions + if ($tokens[$beforeCurlyOpeningIndex]->isGivenKind(T_STRING)) { + $classyTestIndex = $tokens->getPrevMeaningfulToken($beforeCurlyOpeningIndex); + + while ($tokens[$classyTestIndex]->equals(',') || $tokens[$classyTestIndex]->isGivenKind([T_STRING, T_NS_SEPARATOR, T_EXTENDS, T_IMPLEMENTS])) { + $classyTestIndex = $tokens->getPrevMeaningfulToken($classyTestIndex); + } + + $tokensAnalyzer = new TokensAnalyzer($tokens); + + if ( + $tokens[$classyTestIndex]->isGivenKind(T_NAMESPACE) + || ($tokens[$classyTestIndex]->isClassy() && !$tokensAnalyzer->isAnonymousClass($classyTestIndex)) + ) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + } + + return; + } + + // early return check, below only control structures with conditions are fixed + if (!$tokens[$beforeCurlyOpeningIndex]->equals(')')) { + return; + } + + $openingBraceIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $beforeCurlyOpeningIndex); + $beforeOpeningBraceIndex = $tokens->getPrevMeaningfulToken($openingBraceIndex); + + if ($tokens[$beforeOpeningBraceIndex]->isGivenKind([T_IF, T_ELSEIF, T_FOR, T_FOREACH, T_WHILE, T_SWITCH, T_CATCH, T_DECLARE])) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); + + return; + } + + // check for function definition + if ($tokens[$beforeOpeningBraceIndex]->isGivenKind(T_STRING)) { + $beforeStringIndex = $tokens->getPrevMeaningfulToken($beforeOpeningBraceIndex); + + if ($tokens[$beforeStringIndex]->isGivenKind(T_FUNCTION)) { + $tokens->clearTokenAndMergeSurroundingWhitespace($index); // implicit return + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoMultilineWhitespaceBeforeSemicolonsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoMultilineWhitespaceBeforeSemicolonsFixer.php new file mode 100644 index 0000000..2756b9f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoMultilineWhitespaceBeforeSemicolonsFixer.php @@ -0,0 +1,78 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Semicolon; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; + +/** + * @deprecated since 2.9.1, replaced by MultilineWhitespaceBeforeSemicolonsFixer + * + * @todo To be removed at 3.0 + * + * @author Graham Campbell <graham@alt-three.com> + */ +final class NoMultilineWhitespaceBeforeSemicolonsFixer extends AbstractProxyFixer implements DeprecatedFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Multi-line whitespace before closing semicolon are prohibited.', + [ + new CodeSample( + '<?php +function foo () { + return 1 + 2 + ; +} +' + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after SimplifiedIfReturnFixer. + */ + public function getPriority() + { + return parent::getPriority(); + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + $fixer = new MultilineWhitespaceBeforeSemicolonsFixer(); + $fixer->configure(['strategy' => MultilineWhitespaceBeforeSemicolonsFixer::STRATEGY_NO_MULTI_LINE]); + + return [$fixer]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixer.php new file mode 100644 index 0000000..f8e4faa --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/NoSinglelineWhitespaceBeforeSemicolonsFixer.php @@ -0,0 +1,75 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Semicolon; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Graham Campbell <graham@alt-three.com> + */ +final class NoSinglelineWhitespaceBeforeSemicolonsFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Single-line whitespace before closing semicolon are prohibited.', + [new CodeSample("<?php \$this->foo() ;\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run after CombineConsecutiveIssetsFixer, FunctionToConstantFixer, NoEmptyStatementFixer, SimplifiedIfReturnFixer, SingleImportPerStatementFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(';'); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->equals(';') || !$tokens[$index - 1]->isWhitespace(" \t")) { + continue; + } + + if ($tokens[$index - 2]->equals(';')) { + // do not remove all whitespace before the semicolon because it is also whitespace after another semicolon + if (!$tokens[$index - 1]->equals(' ')) { + $tokens[$index - 1] = new Token([T_WHITESPACE, ' ']); + } + } elseif (!$tokens[$index - 2]->isComment()) { + $tokens->clearAt($index - 1); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/SemicolonAfterInstructionFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/SemicolonAfterInstructionFixer.php new file mode 100644 index 0000000..64205ff --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/SemicolonAfterInstructionFixer.php @@ -0,0 +1,73 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Semicolon; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class SemicolonAfterInstructionFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Instructions must be terminated with a semicolon.', + [new CodeSample("<?php echo 1 ?>\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before SimplifiedIfReturnFixer. + */ + public function getPriority() + { + return 2; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_CLOSE_TAG); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = \count($tokens) - 1; $index > 1; --$index) { + if (!$tokens[$index]->isGivenKind(T_CLOSE_TAG)) { + continue; + } + + $prev = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$prev]->equalsAny([';', '{', '}', ':', [T_OPEN_TAG]])) { + continue; + } + + $tokens->insertAt($prev + 1, new Token(';')); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/SpaceAfterSemicolonFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/SpaceAfterSemicolonFixer.php new file mode 100644 index 0000000..e11c1f1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Semicolon/SpaceAfterSemicolonFixer.php @@ -0,0 +1,145 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Semicolon; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author SpacePossum + */ +final class SpaceAfterSemicolonFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Fix whitespace after a semicolon.', + [ + new CodeSample( + "<?php + sample(); \$test = 1; + sample();\$test = 2; + for ( ;;++\$sample) { + }\n" + ), + new CodeSample("<?php\nfor (\$i = 0; ; ++\$i) {\n}\n", [ + 'remove_in_empty_for_expressions' => true, + ]), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after CombineConsecutiveUnsetsFixer, MultilineWhitespaceBeforeSemicolonsFixer, NoEmptyStatementFixer, OrderedClassElementsFixer, SingleImportPerStatementFixer, SingleTraitInsertPerStatementFixer. + */ + public function getPriority() + { + return -1; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(';'); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('remove_in_empty_for_expressions', 'Whether spaces should be removed for empty `for` expressions.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + ]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $insideForParenthesesUntil = null; + + for ($index = 0, $max = \count($tokens) - 1; $index < $max; ++$index) { + if ($this->configuration['remove_in_empty_for_expressions']) { + if ($tokens[$index]->isGivenKind(T_FOR)) { + $index = $tokens->getNextMeaningfulToken($index); + $insideForParenthesesUntil = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + + continue; + } + + if ($index === $insideForParenthesesUntil) { + $insideForParenthesesUntil = null; + + continue; + } + } + + if (!$tokens[$index]->equals(';')) { + continue; + } + + if (!$tokens[$index + 1]->isWhitespace()) { + if ( + !$tokens[$index + 1]->equalsAny([')', [T_INLINE_HTML]]) && ( + !$this->configuration['remove_in_empty_for_expressions'] + || !$tokens[$index + 1]->equals(';') + ) + ) { + $tokens->insertAt($index + 1, new Token([T_WHITESPACE, ' '])); + ++$max; + } + + continue; + } + + if ( + null !== $insideForParenthesesUntil + && ($tokens[$index + 2]->equals(';') || $index + 2 === $insideForParenthesesUntil) + && !Preg::match('/\R/', $tokens[$index + 1]->getContent()) + ) { + $tokens->clearAt($index + 1); + + continue; + } + + if ( + isset($tokens[$index + 2]) + && !$tokens[$index + 1]->equals([T_WHITESPACE, ' ']) + && $tokens[$index + 1]->isWhitespace(" \t") + && !$tokens[$index + 2]->isComment() + && !$tokens[$index + 2]->equals(')') + ) { + $tokens[$index + 1] = new Token([T_WHITESPACE, ' ']); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/DeclareStrictTypesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/DeclareStrictTypesFixer.php new file mode 100644 index 0000000..ef11e6c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/DeclareStrictTypesFixer.php @@ -0,0 +1,152 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Strict; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Jordi Boggiano <j.boggiano@seld.be> + * @author SpacePossum + */ +final class DeclareStrictTypesFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Force strict types declaration in all files. Requires PHP >= 7.0.', + [ + new VersionSpecificCodeSample( + "<?php\n", + new VersionSpecification(70000) + ), + ], + null, + 'Forcing strict types will stop non strict code from working.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before BlankLineAfterOpeningTagFixer, DeclareEqualNormalizeFixer, HeaderCommentFixer. + */ + public function getPriority() + { + return 2; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70000 && isset($tokens[0]) && $tokens[0]->isGivenKind(T_OPEN_TAG); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // check if the declaration is already done + $searchIndex = $tokens->getNextMeaningfulToken(0); + if (null === $searchIndex) { + $this->insertSequence($tokens); // declaration not found, insert one + + return; + } + + $sequenceLocation = $tokens->findSequence([[T_DECLARE, 'declare'], '(', [T_STRING, 'strict_types'], '=', [T_LNUMBER], ')'], $searchIndex, null, false); + if (null === $sequenceLocation) { + $this->insertSequence($tokens); // declaration not found, insert one + + return; + } + + $this->fixStrictTypesCasingAndValue($tokens, $sequenceLocation); + } + + /** + * @param array<int, Token> $sequence + */ + private function fixStrictTypesCasingAndValue(Tokens $tokens, array $sequence) + { + /** @var int $index */ + /** @var Token $token */ + foreach ($sequence as $index => $token) { + if ($token->isGivenKind(T_STRING)) { + $tokens[$index] = new Token([T_STRING, strtolower($token->getContent())]); + + continue; + } + if ($token->isGivenKind(T_LNUMBER)) { + $tokens[$index] = new Token([T_LNUMBER, '1']); + + break; + } + } + } + + private function insertSequence(Tokens $tokens) + { + $sequence = [ + new Token([T_DECLARE, 'declare']), + new Token('('), + new Token([T_STRING, 'strict_types']), + new Token('='), + new Token([T_LNUMBER, '1']), + new Token(')'), + new Token(';'), + ]; + $endIndex = \count($sequence); + + $tokens->insertAt(1, $sequence); + + // start index of the sequence is always 1 here, 0 is always open tag + // transform "<?php\n" to "<?php " if needed + if (false !== strpos($tokens[0]->getContent(), "\n")) { + $tokens[0] = new Token([$tokens[0]->getId(), trim($tokens[0]->getContent()).' ']); + } + + if ($endIndex === \count($tokens) - 1) { + return; // no more tokens afters sequence, single_blank_line_at_eof might add a line + } + + $lineEnding = $this->whitespacesConfig->getLineEnding(); + if (!$tokens[1 + $endIndex]->isWhitespace()) { + $tokens->insertAt(1 + $endIndex, new Token([T_WHITESPACE, $lineEnding])); + + return; + } + + $content = $tokens[1 + $endIndex]->getContent(); + $tokens[1 + $endIndex] = new Token([T_WHITESPACE, $lineEnding.ltrim($content, " \t")]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/StrictComparisonFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/StrictComparisonFixer.php new file mode 100644 index 0000000..7a706a6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/StrictComparisonFixer.php @@ -0,0 +1,86 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Strict; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class StrictComparisonFixer extends AbstractFixer +{ + public function getDefinition() + { + return new FixerDefinition( + 'Comparisons should be strict.', + [new CodeSample("<?php\n\$a = 1== \$b;\n")], + null, + 'Changing comparisons to strict might change code behavior.' + ); + } + + /** + * {@inheritdoc} + * + * Must run before BinaryOperatorSpacesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_IS_EQUAL, T_IS_NOT_EQUAL]); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + static $map = [ + T_IS_EQUAL => [ + 'id' => T_IS_IDENTICAL, + 'content' => '===', + ], + T_IS_NOT_EQUAL => [ + 'id' => T_IS_NOT_IDENTICAL, + 'content' => '!==', + ], + ]; + + foreach ($tokens as $index => $token) { + $tokenId = $token->getId(); + + if (isset($map[$tokenId])) { + $tokens[$index] = new Token([$map[$tokenId]['id'], $map[$tokenId]['content']]); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/StrictParamFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/StrictParamFixer.php new file mode 100644 index 0000000..dba06a9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Strict/StrictParamFixer.php @@ -0,0 +1,174 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Strict; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class StrictParamFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Functions should be used with `$strict` param set to `true`.', + [new CodeSample("<?php\n\$a = array_keys(\$b);\n\$a = array_search(\$b, \$c);\n\$a = base64_decode(\$b);\n\$a = in_array(\$b, \$c);\n\$a = mb_detect_encoding(\$b, \$c);\n")], + 'The functions "array_keys", "array_search", "base64_decode", "in_array" and "mb_detect_encoding" should be used with $strict param.', + 'Risky when the fixed function is overridden or if the code relies on non-strict usage.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_STRING); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + * + * Must run before NativeFunctionInvocationFixer. + */ + public function getPriority() + { + return 11; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $functionsAnalyzer = new FunctionsAnalyzer(); + + static $map = null; + + if (null === $map) { + $trueToken = new Token([T_STRING, 'true']); + + $map = [ + 'array_keys' => [null, null, $trueToken], + 'array_search' => [null, null, $trueToken], + 'base64_decode' => [null, $trueToken], + 'in_array' => [null, null, $trueToken], + 'mb_detect_encoding' => [null, [new Token([T_STRING, 'mb_detect_order']), new Token('('), new Token(')')], $trueToken], + ]; + } + + for ($index = $tokens->count() - 1; 0 <= $index; --$index) { + $token = $tokens[$index]; + + $nextIndex = $tokens->getNextMeaningfulToken($index); + if (null !== $nextIndex && !$tokens[$nextIndex]->equals('(')) { + continue; + } + + $lowercaseContent = strtolower($token->getContent()); + if (isset($map[$lowercaseContent]) && $functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) { + $this->fixFunction($tokens, $index, $map[$lowercaseContent]); + } + } + } + + private function fixFunction(Tokens $tokens, $functionIndex, array $functionParams) + { + $startBraceIndex = $tokens->getNextTokenOfKind($functionIndex, ['(']); + $endBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startBraceIndex); + $paramsQuantity = 0; + $expectParam = true; + + for ($index = $startBraceIndex + 1; $index < $endBraceIndex; ++$index) { + $token = $tokens[$index]; + + if ($expectParam && !$token->isWhitespace() && !$token->isComment()) { + ++$paramsQuantity; + $expectParam = false; + } + + if ($token->equals('(')) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + + continue; + } + + if ($token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $index); + + continue; + } + + if ($token->equals(',')) { + $expectParam = true; + + continue; + } + } + + $functionParamsQuantity = \count($functionParams); + + if ($paramsQuantity === $functionParamsQuantity) { + return; + } + + $tokensToInsert = []; + + for ($i = $paramsQuantity; $i < $functionParamsQuantity; ++$i) { + // function call do not have all params that are required to set useStrict flag, exit from method! + if (!$functionParams[$i]) { + return; + } + + $tokensToInsert[] = new Token(','); + $tokensToInsert[] = new Token([T_WHITESPACE, ' ']); + + if (!\is_array($functionParams[$i])) { + $tokensToInsert[] = clone $functionParams[$i]; + + continue; + } + + foreach ($functionParams[$i] as $param) { + $tokensToInsert[] = clone $param; + } + } + + $beforeEndBraceIndex = $tokens->getPrevMeaningfulToken($endBraceIndex); + + if ($tokens[$beforeEndBraceIndex]->equals(',')) { + array_shift($tokensToInsert); + $tokensToInsert[] = new Token(','); + } + + $tokens->insertAt($beforeEndBraceIndex + 1, $tokensToInsert); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php new file mode 100644 index 0000000..8cd23bd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php @@ -0,0 +1,167 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\StringNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class EscapeImplicitBackslashesFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + $codeSample = <<<'EOF' +<?php + +$singleQuoted = 'String with \" and My\Prefix\\'; + +$doubleQuoted = "Interpret my \n but not my \a"; + +$hereDoc = <<<HEREDOC +Interpret my \100 but not my \999 +HEREDOC; + +EOF; + + return new FixerDefinition( + 'Escape implicit backslashes in strings and heredocs to ease the understanding of which are special chars interpreted by PHP and which not.', + [ + new CodeSample($codeSample), + new CodeSample( + $codeSample, + ['single_quoted' => true] + ), + new CodeSample( + $codeSample, + ['double_quoted' => false] + ), + new CodeSample( + $codeSample, + ['heredoc_syntax' => false] + ), + ], + 'In PHP double-quoted strings and heredocs some chars like `n`, `$` or `u` have special meanings if preceded by a backslash ' + .'(and some are special only if followed by other special chars), while a backslash preceding other chars are interpreted like a plain ' + .'backslash. The precise list of those special chars is hard to remember and to identify quickly: this fixer escapes backslashes ' + ."that do not start a special interpretation with the char after them.\n" + .'It is possible to fix also single-quoted strings: in this case there is no special chars apart from single-quote and backslash ' + .'itself, so the fixer simply ensure that all backslashes are escaped. Both single and double backslashes are allowed in single-quoted ' + .'strings, so the purpose in this context is mainly to have a uniformed way to have them written all over the codebase.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_ENCAPSED_AND_WHITESPACE, T_CONSTANT_ENCAPSED_STRING]); + } + + /** + * {@inheritdoc} + * + * Must run before HeredocToNowdocFixer, SingleQuoteFixer. + * Must run after BacktickToShellExecFixer. + */ + public function getPriority() + { + return 1; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + static $singleQuotedRegex = '/(?<!\\\\)\\\\((?:\\\\\\\\)*)(?![\\\'\\\\])/'; + static $doubleQuotedRegex = '/(?<!\\\\)\\\\((?:\\\\\\\\)*)(?![efnrtv$"\\\\0-7]|x[0-9A-Fa-f]|u{)/'; + static $heredocSyntaxRegex = '/(?<!\\\\)\\\\((?:\\\\\\\\)*)(?![efnrtv$\\\\0-7]|x[0-9A-Fa-f]|u{)/'; + + $doubleQuoteOpened = false; + foreach ($tokens as $index => $token) { + $content = $token->getContent(); + if ($token->equalsAny(['"', 'b"', 'B"'])) { + $doubleQuoteOpened = !$doubleQuoteOpened; + } + if (!$token->isGivenKind([T_ENCAPSED_AND_WHITESPACE, T_CONSTANT_ENCAPSED_STRING]) || false === strpos($content, '\\')) { + continue; + } + + // Nowdoc syntax + if ($token->isGivenKind(T_ENCAPSED_AND_WHITESPACE) && '\'' === substr(rtrim($tokens[$index - 1]->getContent()), -1)) { + continue; + } + + $firstTwoCharacters = strtolower(substr($content, 0, 2)); + $isSingleQuotedString = $token->isGivenKind(T_CONSTANT_ENCAPSED_STRING) && ('\'' === $content[0] || 'b\'' === $firstTwoCharacters); + $isDoubleQuotedString = + ($token->isGivenKind(T_CONSTANT_ENCAPSED_STRING) && ('"' === $content[0] || 'b"' === $firstTwoCharacters)) + || ($token->isGivenKind(T_ENCAPSED_AND_WHITESPACE) && $doubleQuoteOpened) + ; + $isHeredocSyntax = !$isSingleQuotedString && !$isDoubleQuotedString; + if ( + (false === $this->configuration['single_quoted'] && $isSingleQuotedString) + || (false === $this->configuration['double_quoted'] && $isDoubleQuotedString) + || (false === $this->configuration['heredoc_syntax'] && $isHeredocSyntax) + ) { + continue; + } + + $regex = $heredocSyntaxRegex; + if ($isSingleQuotedString) { + $regex = $singleQuotedRegex; + } elseif ($isDoubleQuotedString) { + $regex = $doubleQuotedRegex; + } + + $newContent = Preg::replace($regex, '\\\\\\\\$1', $content); + if ($newContent !== $content) { + $tokens[$index] = new Token([$token->getId(), $newContent]); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('single_quoted', 'Whether to fix single-quoted strings.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + (new FixerOptionBuilder('double_quoted', 'Whether to fix double-quoted strings.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + (new FixerOptionBuilder('heredoc_syntax', 'Whether to fix heredoc syntax.')) + ->setAllowedTypes(['bool']) + ->setDefault(true) + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/ExplicitStringVariableFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/ExplicitStringVariableFixer.php new file mode 100644 index 0000000..8c48584 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/ExplicitStringVariableFixer.php @@ -0,0 +1,172 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\StringNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Filippo Tessarotto <zoeslam@gmail.com> + */ +final class ExplicitStringVariableFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Converts implicit variables into explicit ones in double-quoted strings or heredoc syntax.', + [new CodeSample( + <<<'EOT' +<?php +$a = "My name is $name !"; +$b = "I live in $state->country !"; +$c = "I have $farm[0] chickens !"; + +EOT + )], + 'The reasoning behind this rule is the following:' + ."\n".'- When there are two valid ways of doing the same thing, using both is confusing, there should be a coding standard to follow' + ."\n".'- PHP manual marks `"$var"` syntax as implicit and `"${var}"` syntax as explicit: explicit code should always be preferred' + ."\n".'- Explicit syntax allows word concatenation inside strings, e.g. `"${var}IsAVar"`, implicit doesn\'t' + ."\n".'- Explicit syntax is easier to detect for IDE/editors and therefore has colors/highlight with higher contrast, which is easier to read' + ."\n".'Backtick operator is skipped because it is harder to handle; you can use `backtick_to_shell_exec` fixer to normalize backticks to strings' + ); + } + + /** + * {@inheritdoc} + * + * Must run before SimpleToComplexStringVariableFixer. + * Must run after BacktickToShellExecFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_VARIABLE); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $backtickStarted = false; + for ($index = \count($tokens) - 1; $index > 0; --$index) { + $token = $tokens[$index]; + if ($token->equals('`')) { + $backtickStarted = !$backtickStarted; + + continue; + } + + if ($backtickStarted || !$token->isGivenKind(T_VARIABLE)) { + continue; + } + + $prevToken = $tokens[$index - 1]; + if (!$this->isStringPartToken($prevToken)) { + continue; + } + + $distinctVariableIndex = $index; + $variableTokens = [ + $distinctVariableIndex => [ + 'tokens' => [$index => $token], + 'firstVariableTokenIndex' => $index, + 'lastVariableTokenIndex' => $index, + ], + ]; + + $nextIndex = $index + 1; + $squareBracketCount = 0; + while (!$this->isStringPartToken($tokens[$nextIndex])) { + if ($tokens[$nextIndex]->isGivenKind(T_CURLY_OPEN)) { + $nextIndex = $tokens->getNextTokenOfKind($nextIndex, [[CT::T_CURLY_CLOSE]]); + } elseif ($tokens[$nextIndex]->isGivenKind(T_VARIABLE) && 1 !== $squareBracketCount) { + $distinctVariableIndex = $nextIndex; + $variableTokens[$distinctVariableIndex] = [ + 'tokens' => [$nextIndex => $tokens[$nextIndex]], + 'firstVariableTokenIndex' => $nextIndex, + 'lastVariableTokenIndex' => $nextIndex, + ]; + } else { + $variableTokens[$distinctVariableIndex]['tokens'][$nextIndex] = $tokens[$nextIndex]; + $variableTokens[$distinctVariableIndex]['lastVariableTokenIndex'] = $nextIndex; + + if ($tokens[$nextIndex]->equalsAny(['[', ']'])) { + ++$squareBracketCount; + } + } + + ++$nextIndex; + } + krsort($variableTokens, SORT_NUMERIC); + + foreach ($variableTokens as $distinctVariableSet) { + if (1 === \count($distinctVariableSet['tokens'])) { + $singleVariableIndex = key($distinctVariableSet['tokens']); + $singleVariableToken = current($distinctVariableSet['tokens']); + $tokens->overrideRange($singleVariableIndex, $singleVariableIndex, [ + new Token([T_DOLLAR_OPEN_CURLY_BRACES, '${']), + new Token([T_STRING_VARNAME, substr($singleVariableToken->getContent(), 1)]), + new Token([CT::T_DOLLAR_CLOSE_CURLY_BRACES, '}']), + ]); + } else { + foreach ($distinctVariableSet['tokens'] as $variablePartIndex => $variablePartToken) { + if ($variablePartToken->isGivenKind(T_NUM_STRING)) { + $tokens[$variablePartIndex] = new Token([T_LNUMBER, $variablePartToken->getContent()]); + + continue; + } + + if ($variablePartToken->isGivenKind(T_STRING) && $tokens[$variablePartIndex + 1]->equals(']')) { + $tokens[$variablePartIndex] = new Token([T_CONSTANT_ENCAPSED_STRING, "'".$variablePartToken->getContent()."'"]); + } + } + + $tokens->insertAt($distinctVariableSet['lastVariableTokenIndex'] + 1, new Token([CT::T_CURLY_CLOSE, '}'])); + $tokens->insertAt($distinctVariableSet['firstVariableTokenIndex'], new Token([T_CURLY_OPEN, '{'])); + } + } + } + } + + /** + * Check if token is a part of a string. + * + * @param Token $token The token to check + * + * @return bool + */ + private function isStringPartToken(Token $token) + { + return $token->isGivenKind(T_ENCAPSED_AND_WHITESPACE) + || $token->isGivenKind(T_START_HEREDOC) + || '"' === $token->getContent() + || 'b"' === strtolower($token->getContent()) + ; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/HeredocToNowdocFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/HeredocToNowdocFixer.php new file mode 100644 index 0000000..a517b45 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/HeredocToNowdocFixer.php @@ -0,0 +1,115 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\StringNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Gregor Harlan <gharlan@web.de> + */ +final class HeredocToNowdocFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Convert `heredoc` to `nowdoc` where possible.', + [ + new CodeSample( + <<<'EOF' +<?php $a = <<<"TEST" +Foo +TEST; + +EOF + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after EscapeImplicitBackslashesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_START_HEREDOC); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_START_HEREDOC) || false !== strpos($token->getContent(), "'")) { + continue; + } + + if ($tokens[$index + 1]->isGivenKind(T_END_HEREDOC)) { + $tokens[$index] = $this->convertToNowdoc($token); + + continue; + } + + if ( + !$tokens[$index + 1]->isGivenKind(T_ENCAPSED_AND_WHITESPACE) + || !$tokens[$index + 2]->isGivenKind(T_END_HEREDOC) + ) { + continue; + } + + $content = $tokens[$index + 1]->getContent(); + // regex: odd number of backslashes, not followed by dollar + if (Preg::match('/(?<!\\\\)(?:\\\\{2})*\\\\(?![$\\\\])/', $content)) { + continue; + } + + $tokens[$index] = $this->convertToNowdoc($token); + $content = str_replace(['\\\\', '\\$'], ['\\', '$'], $content); + $tokens[$index + 1] = new Token([ + $tokens[$index + 1]->getId(), + $content, + ]); + } + } + + /** + * Transforms the heredoc start token to nowdoc notation. + * + * @return Token + */ + private function convertToNowdoc(Token $token) + { + return new Token([ + $token->getId(), + Preg::replace('/^([Bb]?<<<)(\h*)"?([^\s"]+)"?/', '$1$2\'$3\'', $token->getContent()), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/NoBinaryStringFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/NoBinaryStringFixer.php new file mode 100644 index 0000000..08a2561 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/NoBinaryStringFixer.php @@ -0,0 +1,65 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\StringNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author ntzm + */ +final class NoBinaryStringFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_CONSTANT_ENCAPSED_STRING, T_START_HEREDOC]); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There should not be a binary flag before strings.', + [ + new CodeSample("<?php \$a = b'foo';\n"), + new CodeSample("<?php \$a = b<<<EOT\nfoo\nEOT;\n"), + ] + ); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind([T_CONSTANT_ENCAPSED_STRING, T_START_HEREDOC])) { + continue; + } + + $content = $token->getContent(); + + if ('b' === strtolower($content[0])) { + $tokens[$index] = new Token([$token->getId(), substr($content, 1)]); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/NoTrailingWhitespaceInStringFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/NoTrailingWhitespaceInStringFixer.php new file mode 100644 index 0000000..da7c231 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/NoTrailingWhitespaceInStringFixer.php @@ -0,0 +1,113 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\StringNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Gregor Harlan + */ +final class NoTrailingWhitespaceInStringFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_INLINE_HTML]); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There must be no trailing whitespace in strings.', + [ + new CodeSample( + "<?php \$a = ' \n foo \n';\n" + ), + ], + null, + 'Changing the whitespaces in strings might affect string comparisons and outputs.' + ); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1, $last = true; $index >= 0; --$index, $last = false) { + /** @var Token $token */ + $token = $tokens[$index]; + + if (!$token->isGivenKind([T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_INLINE_HTML])) { + continue; + } + + $isInlineHtml = $token->isGivenKind(T_INLINE_HTML); + $regex = $isInlineHtml && $last ? '/\h+(?=\R|$)/' : '/\h+(?=\R)/'; + $content = Preg::replace($regex, '', $token->getContent()); + + if ($token->getContent() === $content) { + continue; + } + + if (!$isInlineHtml || 0 === $index) { + $this->updateContent($tokens, $index, $content); + + continue; + } + + $prev = $index - 1; + + if ($tokens[$prev]->equals([T_CLOSE_TAG, '?>']) && Preg::match('/^\R/', $content, $match)) { + $tokens[$prev] = new Token([T_CLOSE_TAG, $tokens[$prev]->getContent().$match[0]]); + $content = substr($content, \strlen($match[0])); + $content = false === $content ? '' : $content; // @phpstan-ignore-line due to https://github.com/phpstan/phpstan/issues/1215 , awaiting PHP8 as min requirement of Fixer + } + + $this->updateContent($tokens, $index, $content); + } + } + + /** + * @param int $index + * @param string $content + */ + private function updateContent(Tokens $tokens, $index, $content) + { + if ('' === $content) { + $tokens->clearAt($index); + + return; + } + + $tokens[$index] = new Token([$tokens[$index]->getId(), $content]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/SimpleToComplexStringVariableFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/SimpleToComplexStringVariableFixer.php new file mode 100644 index 0000000..14cb635 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/SimpleToComplexStringVariableFixer.php @@ -0,0 +1,113 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\StringNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dave van der Brugge <dmvdbrugge@gmail.com> + */ +final class SimpleToComplexStringVariableFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Converts explicit variables in double-quoted strings and heredoc syntax from simple to complex format (`${` to `{$`).', + [ + new CodeSample( + <<<'EOT' +<?php +$name = 'World'; +echo "Hello ${name}!"; + +EOT + ), + new CodeSample( + <<<'EOT' +<?php +$name = 'World'; +echo <<<TEST +Hello ${name}! +TEST; + +EOT + ), + ], + "Doesn't touch implicit variables. Works together nicely with `explicit_string_variable`." + ); + } + + /** + * {@inheritdoc} + * + * Must run after ExplicitStringVariableFixer. + */ + public function getPriority() + { + return -10; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_DOLLAR_OPEN_CURLY_BRACES); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = \count($tokens) - 3; $index > 0; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_DOLLAR_OPEN_CURLY_BRACES)) { + continue; + } + + $varnameToken = $tokens[$index + 1]; + + if (!$varnameToken->isGivenKind(T_STRING_VARNAME)) { + continue; + } + + $dollarCloseToken = $tokens[$index + 2]; + + if (!$dollarCloseToken->isGivenKind(CT::T_DOLLAR_CLOSE_CURLY_BRACES)) { + continue; + } + + $tokenOfStringBeforeToken = $tokens[$index - 1]; + $stringContent = $tokenOfStringBeforeToken->getContent(); + + if ('$' === substr($stringContent, -1) && '\\$' !== substr($stringContent, -2)) { + $newContent = substr($stringContent, 0, -1).'\\$'; + $tokenOfStringBeforeToken = new Token([T_ENCAPSED_AND_WHITESPACE, $newContent]); + } + + $tokens->overrideRange($index - 1, $index + 2, [ + $tokenOfStringBeforeToken, + new Token([T_CURLY_OPEN, '{']), + new Token([T_VARIABLE, '$'.$varnameToken->getContent()]), + new Token([CT::T_CURLY_CLOSE, '}']), + ]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/SingleQuoteFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/SingleQuoteFixer.php new file mode 100644 index 0000000..0d29a73 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/SingleQuoteFixer.php @@ -0,0 +1,116 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\StringNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Gregor Harlan <gharlan@web.de> + */ +final class SingleQuoteFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + $codeSample = <<<'EOF' +<?php + +$a = "sample"; +$b = "sample with 'single-quotes'"; + +EOF; + + return new FixerDefinition( + 'Convert double quotes to single quotes for simple strings.', + [ + new CodeSample($codeSample), + new CodeSample( + $codeSample, + ['strings_containing_single_quote_chars' => true] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after BacktickToShellExecFixer, EscapeImplicitBackslashesFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound(T_CONSTANT_ENCAPSED_STRING); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) { + continue; + } + + $content = $token->getContent(); + $prefix = ''; + + if ('b' === strtolower($content[0])) { + $prefix = $content[0]; + $content = substr($content, 1); + } + + if ( + '"' === $content[0] + && (true === $this->configuration['strings_containing_single_quote_chars'] || false === strpos($content, "'")) + // regex: odd number of backslashes, not followed by double quote or dollar + && !Preg::match('/(?<!\\\\)(?:\\\\{2})*\\\\(?!["$\\\\])/', $content) + ) { + $content = substr($content, 1, -1); + $content = str_replace(['\\"', '\\$', '\''], ['"', '$', '\\\''], $content); + $tokens[$index] = new Token([T_CONSTANT_ENCAPSED_STRING, $prefix.'\''.$content.'\'']); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('strings_containing_single_quote_chars', 'Whether to fix double-quoted strings that contains single-quotes.')) + ->setAllowedTypes(['bool']) + ->setDefault(false) + ->getOption(), + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/StringLineEndingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/StringLineEndingFixer.php new file mode 100644 index 0000000..33a50f7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/StringLineEndingFixer.php @@ -0,0 +1,85 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\StringNotation; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixes the line endings in multi-line strings. + * + * @author Ilija Tovilo <ilija.tovilo@me.com> + */ +final class StringLineEndingFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_INLINE_HTML]); + } + + /** + * {@inheritdoc} + */ + public function isRisky() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'All multi-line strings must use correct line ending.', + [ + new CodeSample( + "<?php \$a = 'my\r\nmulti\nline\r\nstring';\r\n" + ), + ], + null, + 'Changing the line endings of multi-line strings might affect string comparisons and outputs.' + ); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $ending = $this->whitespacesConfig->getLineEnding(); + + foreach ($tokens as $tokenIndex => $token) { + if (!$token->isGivenKind([T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_INLINE_HTML])) { + continue; + } + + $tokens[$tokenIndex] = new Token([ + $token->getId(), + Preg::replace( + '#\R#u', + $ending, + $token->getContent() + ), + ]); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/ArrayIndentationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/ArrayIndentationFixer.php new file mode 100644 index 0000000..075119a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/ArrayIndentationFixer.php @@ -0,0 +1,277 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +final class ArrayIndentationFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** @var int */ + private $newlineTokenIndexCache; + + /** @var int */ + private $newlineTokenPositionCache; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Each element of an array must be indented exactly once.', + [ + new CodeSample("<?php\n\$foo = [\n 'bar' => [\n 'baz' => true,\n ],\n];\n"), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN]); + } + + /** + * {@inheritdoc} + * + * Must run before AlignMultilineCommentFixer, BinaryOperatorSpacesFixer. + * Must run after BracesFixer, MethodArgumentSpaceFixer, MethodChainingIndentationFixer. + */ + public function getPriority() + { + return 29; + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $this->returnWithUpdateCache(0, null); + + $scopes = []; + $previousLineInitialIndent = ''; + $previousLineNewIndent = ''; + + foreach ($tokens as $index => $token) { + $currentScope = [] !== $scopes ? \count($scopes) - 1 : null; + + if ($token->isComment()) { + continue; + } + + if ( + $token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN) + || ($token->equals('(') && $tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_ARRAY)) + ) { + $endIndex = $tokens->findBlockEnd( + $token->equals('(') ? Tokens::BLOCK_TYPE_PARENTHESIS_BRACE : Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, + $index + ); + + $scopes[] = [ + 'type' => 'array', + 'end_index' => $endIndex, + 'initial_indent' => $this->getLineIndentation($tokens, $index), + ]; + + continue; + } + + if (null === $currentScope) { + continue; + } + + if ($token->isWhitespace()) { + if (!Preg::match('/\R/', $token->getContent())) { + continue; + } + + if ('array' === $scopes[$currentScope]['type']) { + $indent = false; + + for ($searchEndIndex = $index + 1; $searchEndIndex < $scopes[$currentScope]['end_index']; ++$searchEndIndex) { + $searchEndToken = $tokens[$searchEndIndex]; + + if ( + (!$searchEndToken->isWhitespace() && !$searchEndToken->isComment()) + || ($searchEndToken->isWhitespace() && Preg::match('/\R/', $searchEndToken->getContent())) + ) { + $indent = true; + + break; + } + } + + $content = Preg::replace( + '/(\R+)\h*$/', + '$1'.$scopes[$currentScope]['initial_indent'].($indent ? $this->whitespacesConfig->getIndent() : ''), + $token->getContent() + ); + + $previousLineInitialIndent = $this->extractIndent($token->getContent()); + $previousLineNewIndent = $this->extractIndent($content); + } else { + $content = Preg::replace( + '/(\R)'.preg_quote($scopes[$currentScope]['initial_indent'], '/').'(\h*)$/', + '$1'.$scopes[$currentScope]['new_indent'].'$2', + $token->getContent() + ); + } + + $tokens[$index] = new Token([T_WHITESPACE, $content]); + + continue; + } + + if ($index === $scopes[$currentScope]['end_index']) { + while ([] !== $scopes && $index === $scopes[$currentScope]['end_index']) { + array_pop($scopes); + --$currentScope; + } + + continue; + } + + if ($token->equals(',')) { + continue; + } + + if ('expression' !== $scopes[$currentScope]['type']) { + $endIndex = $this->findExpressionEndIndex($tokens, $index, $scopes[$currentScope]['end_index']); + + if ($endIndex === $index) { + continue; + } + + $scopes[] = [ + 'type' => 'expression', + 'end_index' => $endIndex, + 'initial_indent' => $previousLineInitialIndent, + 'new_indent' => $previousLineNewIndent, + ]; + } + } + } + + private function findExpressionEndIndex(Tokens $tokens, $index, $parentScopeEndIndex) + { + $endIndex = null; + + for ($searchEndIndex = $index + 1; $searchEndIndex < $parentScopeEndIndex; ++$searchEndIndex) { + $searchEndToken = $tokens[$searchEndIndex]; + + if ($searchEndToken->equalsAny(['(', '{']) || $searchEndToken->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN)) { + $type = Tokens::detectBlockType($searchEndToken); + $searchEndIndex = $tokens->findBlockEnd( + $type['type'], + $searchEndIndex + ); + + continue; + } + + if ($searchEndToken->equals(',')) { + $endIndex = $tokens->getPrevMeaningfulToken($searchEndIndex); + + break; + } + } + + if (null !== $endIndex) { + return $endIndex; + } + + return $tokens->getPrevMeaningfulToken($parentScopeEndIndex); + } + + private function getLineIndentation(Tokens $tokens, $index) + { + $newlineTokenIndex = $this->getPreviousNewlineTokenIndex($tokens, $index); + + if (null === $newlineTokenIndex) { + return ''; + } + + return $this->extractIndent($this->computeNewLineContent($tokens, $newlineTokenIndex)); + } + + private function extractIndent($content) + { + if (Preg::match('/\R(\h*)[^\r\n]*$/D', $content, $matches)) { + return $matches[1]; + } + + return ''; + } + + private function getPreviousNewlineTokenIndex(Tokens $tokens, $startIndex) + { + $index = $startIndex; + while ($index > 0) { + $index = $tokens->getPrevTokenOfKind($index, [[T_WHITESPACE], [T_INLINE_HTML]]); + + if ($this->newlineTokenIndexCache > $index) { + return $this->returnWithUpdateCache($startIndex, $this->newlineTokenPositionCache); + } + + if (null === $index) { + break; + } + + if ($this->isNewLineToken($tokens, $index)) { + return $this->returnWithUpdateCache($startIndex, $index); + } + } + + return $this->returnWithUpdateCache($startIndex, null); + } + + private function isNewLineToken(Tokens $tokens, $index) + { + if (!$tokens[$index]->isGivenKind([T_WHITESPACE, T_INLINE_HTML])) { + return false; + } + + return (bool) Preg::match('/\R/', $this->computeNewLineContent($tokens, $index)); + } + + private function computeNewLineContent(Tokens $tokens, $index) + { + $content = $tokens[$index]->getContent(); + + if (0 !== $index && $tokens[$index - 1]->equalsAny([[T_OPEN_TAG], [T_CLOSE_TAG]])) { + $content = Preg::replace('/\S/', '', $tokens[$index - 1]->getContent()).$content; + } + + return $content; + } + + /** + * @param int $index + * @param null|int $position + */ + private function returnWithUpdateCache($index, $position) + { + $this->newlineTokenIndexCache = $index; + $this->newlineTokenPositionCache = $position; + + return $position; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/BlankLineBeforeStatementFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/BlankLineBeforeStatementFixer.php new file mode 100644 index 0000000..abde159 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/BlankLineBeforeStatementFixer.php @@ -0,0 +1,378 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use PhpCsFixer\Utils; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Andreas Möller <am@localheinz.com> + * @author SpacePossum + */ +final class BlankLineBeforeStatementFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @var array + */ + private static $tokenMap = [ + 'break' => T_BREAK, + 'case' => T_CASE, + 'continue' => T_CONTINUE, + 'declare' => T_DECLARE, + 'default' => T_DEFAULT, + 'die' => T_EXIT, // TODO remove this alias 3.0, use `exit` + 'do' => T_DO, + 'exit' => T_EXIT, + 'for' => T_FOR, + 'foreach' => T_FOREACH, + 'goto' => T_GOTO, + 'if' => T_IF, + 'include' => T_INCLUDE, + 'include_once' => T_INCLUDE_ONCE, + 'require' => T_REQUIRE, + 'require_once' => T_REQUIRE_ONCE, + 'return' => T_RETURN, + 'switch' => T_SWITCH, + 'throw' => T_THROW, + 'try' => T_TRY, + 'while' => T_WHILE, + 'yield' => T_YIELD, + ]; + + /** + * @var array + */ + private $fixTokenMap = []; + + /** + * Dynamic yield from option set on constructor. + */ + public function __construct() + { + parent::__construct(); + + // @TODO: To be moved back to compile time property declaration when PHP support of PHP CS Fixer will be 7.0+ + if (\defined('T_YIELD_FROM')) { + self::$tokenMap['yield_from'] = T_YIELD_FROM; + } + } + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + $this->fixTokenMap = []; + + foreach ($this->configuration['statements'] as $key) { + if ('die' === $key) { + Utils::triggerDeprecation(new \RuntimeException('Option "die" is deprecated, use "exit" instead.')); + } + + $this->fixTokenMap[$key] = self::$tokenMap[$key]; + } + + $this->fixTokenMap = array_values($this->fixTokenMap); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'An empty line feed must precede any configured statement.', + [ + new CodeSample( + '<?php +function A() { + echo 1; + return 1; +} +' + ), + new CodeSample( + '<?php +switch ($foo) { + case 42: + $bar->process(); + break; + case 44: + break; +} +', + [ + 'statements' => ['break'], + ] + ), + new CodeSample( + '<?php +foreach ($foo as $bar) { + if ($bar->isTired()) { + $bar->sleep(); + continue; + } +} +', + [ + 'statements' => ['continue'], + ] + ), + new CodeSample( + '<?php +$i = 0; +do { + echo $i; +} while ($i > 0); +', + [ + 'statements' => ['do'], + ] + ), + new CodeSample( + '<?php +if ($foo === false) { + exit(0); +} else { + $bar = 9000; + exit(1); +} +', + [ + 'statements' => ['exit'], + ] + ), + new CodeSample( + '<?php +a: + +if ($foo === false) { + goto a; +} else { + $bar = 9000; + goto b; +} +', + [ + 'statements' => ['goto'], + ] + ), + new CodeSample( + '<?php +$a = 9000; +if (true) { + $foo = $bar; +} +', + [ + 'statements' => ['if'], + ] + ), + new CodeSample( + '<?php + +if (true) { + $foo = $bar; + return; +} +', + [ + 'statements' => ['return'], + ] + ), + new CodeSample( + '<?php +$a = 9000; +switch ($a) { + case 42: + break; +} +', + [ + 'statements' => ['switch'], + ] + ), + new CodeSample( + '<?php +if (null === $a) { + $foo->bar(); + throw new \UnexpectedValueException("A cannot be null."); +} +', + [ + 'statements' => ['throw'], + ] + ), + new CodeSample( + '<?php +$a = 9000; +try { + $foo->bar(); +} catch (\Exception $exception) { + $a = -1; +} +', + [ + 'statements' => ['try'], + ] + ), + new CodeSample( + '<?php + +if (true) { + $foo = $bar; + yield $foo; +} +', + [ + 'statements' => ['yield'], + ] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run after NoExtraBlankLinesFixer, NoUselessReturnFixer, ReturnAssignmentFixer. + */ + public function getPriority() + { + return -21; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound($this->fixTokenMap); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $analyzer = new TokensAnalyzer($tokens); + + for ($index = $tokens->count() - 1; $index > 0; --$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind($this->fixTokenMap)) { + continue; + } + + if ($token->isGivenKind(T_WHILE) && $analyzer->isWhilePartOfDoWhile($index)) { + continue; + } + + $prevNonWhitespace = $tokens->getPrevNonWhitespace($index); + + if ($this->shouldAddBlankLine($tokens, $prevNonWhitespace)) { + $this->insertBlankLine($tokens, $index); + } + + $index = $prevNonWhitespace; + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $allowed = self::$tokenMap; + $allowed['yield_from'] = true; // TODO remove this when update to PHP7.0 + ksort($allowed); + + $allowed = array_keys($allowed); + + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('statements', 'List of statements which must be preceded by an empty line.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset($allowed)]) + ->setDefault([ + 'break', + 'continue', + 'declare', + 'return', + 'throw', + 'try', + ]) + ->getOption(), + ]); + } + + /** + * @param int $prevNonWhitespace + * + * @return bool + */ + private function shouldAddBlankLine(Tokens $tokens, $prevNonWhitespace) + { + $prevNonWhitespaceToken = $tokens[$prevNonWhitespace]; + + if ($prevNonWhitespaceToken->isComment()) { + for ($j = $prevNonWhitespace - 1; $j >= 0; --$j) { + if (false !== strpos($tokens[$j]->getContent(), "\n")) { + return false; + } + + if ($tokens[$j]->isWhitespace() || $tokens[$j]->isComment()) { + continue; + } + + return $tokens[$j]->equalsAny([';', '}']); + } + } + + return $prevNonWhitespaceToken->equalsAny([';', '}']); + } + + /** + * @param int $index + */ + private function insertBlankLine(Tokens $tokens, $index) + { + $prevIndex = $index - 1; + $prevToken = $tokens[$prevIndex]; + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + if ($prevToken->isWhitespace()) { + $newlinesCount = substr_count($prevToken->getContent(), "\n"); + + if (0 === $newlinesCount) { + $tokens[$prevIndex] = new Token([T_WHITESPACE, rtrim($prevToken->getContent(), " \t").$lineEnding.$lineEnding]); + } elseif (1 === $newlinesCount) { + $tokens[$prevIndex] = new Token([T_WHITESPACE, $lineEnding.$prevToken->getContent()]); + } + } else { + $tokens->insertAt($index, new Token([T_WHITESPACE, $lineEnding.$lineEnding])); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/CompactNullableTypehintFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/CompactNullableTypehintFixer.php new file mode 100644 index 0000000..34f6aef --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/CompactNullableTypehintFixer.php @@ -0,0 +1,79 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Jack Cherng <jfcherng@gmail.com> + */ +final class CompactNullableTypehintFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Remove extra spaces in a nullable typehint.', + [ + new VersionSpecificCodeSample( + "<?php\nfunction sample(? string \$str): ? string\n{}\n", + new VersionSpecification(70100) + ), + ], + 'Rule is applied only in a PHP 7.1+ environment.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70100 && $tokens->isTokenKindFound(CT::T_NULLABLE_TYPE); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + static $typehintKinds = [ + CT::T_ARRAY_TYPEHINT, + T_CALLABLE, + T_NS_SEPARATOR, + T_STRING, + ]; + + for ($index = $tokens->count() - 1; $index >= 0; --$index) { + if (!$tokens[$index]->isGivenKind(CT::T_NULLABLE_TYPE)) { + continue; + } + + // remove whitespaces only if there are only whitespaces + // between '?' and the variable type + if ( + $tokens[$index + 1]->isWhitespace() + && $tokens[$index + 2]->isGivenKind($typehintKinds) + ) { + $tokens->removeTrailingWhitespace($index); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/HeredocIndentationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/HeredocIndentationFixer.php new file mode 100644 index 0000000..a23280f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/HeredocIndentationFixer.php @@ -0,0 +1,200 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Gregor Harlan + */ +final class HeredocIndentationFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Heredoc/nowdoc content must be properly indented. Requires PHP >= 7.3.', + [ + new VersionSpecificCodeSample( + <<<'SAMPLE' +<?php + $a = <<<EOD +abc + def +EOD; + +SAMPLE + , + new VersionSpecification(70300) + ), + new VersionSpecificCodeSample( + <<<'SAMPLE' +<?php + $a = <<<'EOD' +abc + def +EOD; + +SAMPLE + , + new VersionSpecification(70300) + ), + new VersionSpecificCodeSample( + <<<'SAMPLE' +<?php + $a = <<<'EOD' +abc + def +EOD; + +SAMPLE + , + new VersionSpecification(70300), + ['indentation' => 'same_as_start'] + ), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70300 && $tokens->isTokenKindFound(T_START_HEREDOC); + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + return new FixerConfigurationResolver([ + (new FixerOptionBuilder('indentation', 'Whether the indentation should be the same as in the start token line or one level more.')) + ->setAllowedValues(['start_plus_one', 'same_as_start']) + ->setDefault('start_plus_one') + ->getOption(), + ]); + } + + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = \count($tokens) - 1; 0 <= $index; --$index) { + if (!$tokens[$index]->isGivenKind(T_END_HEREDOC)) { + continue; + } + + $end = $index; + $index = $tokens->getPrevTokenOfKind($index, [[T_START_HEREDOC]]); + + $this->fixIndentation($tokens, $index, $end); + } + } + + /** + * @param int $start + * @param int $end + */ + private function fixIndentation(Tokens $tokens, $start, $end) + { + $indent = $this->getIndentAt($tokens, $start); + + if ('start_plus_one' === $this->configuration['indentation']) { + $indent .= $this->whitespacesConfig->getIndent(); + } + + Preg::match('/^\h*/', $tokens[$end]->getContent(), $matches); + $currentIndent = $matches[0]; + $currentIndentLength = \strlen($currentIndent); + + $content = $indent.substr($tokens[$end]->getContent(), $currentIndentLength); + $tokens[$end] = new Token([T_END_HEREDOC, $content]); + + if ($end === $start + 1) { + return; + } + + for ($index = $end - 1, $last = true; $index > $start; --$index, $last = false) { + if (!$tokens[$index]->isGivenKind([T_ENCAPSED_AND_WHITESPACE, T_WHITESPACE])) { + continue; + } + + $content = $tokens[$index]->getContent(); + + if ('' !== $currentIndent) { + $content = Preg::replace('/(?<=\v)(?!'.$currentIndent.')\h+/', '', $content); + } + + $regexEnd = $last && !$currentIndent ? '(?!\v|$)' : '(?!\v)'; + $content = Preg::replace('/(?<=\v)'.$currentIndent.$regexEnd.'/', $indent, $content); + + $tokens[$index] = new Token([$tokens[$index]->getId(), $content]); + } + + ++$index; + + if (!$tokens[$index]->isGivenKind(T_ENCAPSED_AND_WHITESPACE)) { + $tokens->insertAt($index, new Token([T_ENCAPSED_AND_WHITESPACE, $indent])); + + return; + } + + $content = $tokens[$index]->getContent(); + + if (!\in_array($content[0], ["\r", "\n"], true) && (!$currentIndent || $currentIndent === substr($content, 0, $currentIndentLength))) { + $content = $indent.substr($content, $currentIndentLength); + } elseif ($currentIndent) { + $content = Preg::replace('/^(?!'.$currentIndent.')\h+/', '', $content); + } + + $tokens[$index] = new Token([T_ENCAPSED_AND_WHITESPACE, $content]); + } + + /** + * @param int $index + * + * @return string + */ + private function getIndentAt(Tokens $tokens, $index) + { + for (; $index >= 0; --$index) { + if (!$tokens[$index]->isGivenKind([T_WHITESPACE, T_INLINE_HTML, T_OPEN_TAG])) { + continue; + } + + $content = $tokens[$index]->getContent(); + + if ($tokens[$index]->isWhitespace() && $tokens[$index - 1]->isGivenKind(T_OPEN_TAG)) { + $content = $tokens[$index - 1]->getContent().$content; + } + + if (1 === Preg::match('/\R(\h*)$/', $content, $matches)) { + return $matches[1]; + } + } + + return ''; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/IndentationTypeFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/IndentationTypeFixer.php new file mode 100644 index 0000000..90b627f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/IndentationTypeFixer.php @@ -0,0 +1,163 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR2 ¶2.4. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class IndentationTypeFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * @var string + */ + private $indent; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Code MUST use configured indentation type.', + [ + new CodeSample("<?php\n\nif (true) {\n\techo 'Hello!';\n}\n"), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before PhpdocIndentFixer. + * Must run after ClassAttributesSeparationFixer, MethodSeparationFixer. + */ + public function getPriority() + { + return 50; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound([T_COMMENT, T_DOC_COMMENT, T_WHITESPACE]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $this->indent = $this->whitespacesConfig->getIndent(); + + foreach ($tokens as $index => $token) { + if ($token->isComment()) { + $tokens[$index] = $this->fixIndentInComment($tokens, $index); + + continue; + } + + if ($token->isWhitespace()) { + $tokens[$index] = $this->fixIndentToken($tokens, $index); + + continue; + } + } + } + + /** + * @param int $index + * + * @return Token + */ + private function fixIndentInComment(Tokens $tokens, $index) + { + $content = Preg::replace('/^(?:(?<! ) {1,3})?\t/m', '\1 ', $tokens[$index]->getContent(), -1, $count); + + // Also check for more tabs. + while (0 !== $count) { + $content = Preg::replace('/^(\ +)?\t/m', '\1 ', $content, -1, $count); + } + + $indent = $this->indent; + + // change indent to expected one + $content = Preg::replaceCallback('/^(?: )+/m', function ($matches) use ($indent) { + return $this->getExpectedIndent($matches[0], $indent); + }, $content); + + return new Token([$tokens[$index]->getId(), $content]); + } + + /** + * @param int $index + * + * @return Token + */ + private function fixIndentToken(Tokens $tokens, $index) + { + $content = $tokens[$index]->getContent(); + $previousTokenHasTrailingLinebreak = false; + + // @TODO this can be removed when we have a transformer for "T_OPEN_TAG" to "T_OPEN_TAG + T_WHITESPACE" + if (false !== strpos($tokens[$index - 1]->getContent(), "\n")) { + $content = "\n".$content; + $previousTokenHasTrailingLinebreak = true; + } + + $indent = $this->indent; + $newContent = Preg::replaceCallback( + '/(\R)(\h+)/', // find indent + function (array $matches) use ($indent) { + // normalize mixed indent + $content = Preg::replace('/(?:(?<! ) {1,3})?\t/', ' ', $matches[2]); + + // change indent to expected one + return $matches[1].$this->getExpectedIndent($content, $indent); + }, + $content + ); + + if ($previousTokenHasTrailingLinebreak) { + $newContent = substr($newContent, 1); + } + + return new Token([T_WHITESPACE, $newContent]); + } + + /** + * @param string $content + * @param string $indent + * + * @return string mixed + */ + private function getExpectedIndent($content, $indent) + { + if ("\t" === $indent) { + $content = str_replace(' ', $indent, $content); + } + + return $content; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/LineEndingFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/LineEndingFixer.php new file mode 100644 index 0000000..27e69fd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/LineEndingFixer.php @@ -0,0 +1,102 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR2 ¶2.2. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author SpacePossum + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class LineEndingFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'All PHP files must use same line ending.', + [ + new CodeSample( + "<?php \$b = \" \$a \r\n 123\"; \$a = <<<TEST\r\nAAAAA \r\n |\r\nTEST;\n" + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BracesFixer. + */ + public function getPriority() + { + return 40; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $ending = $this->whitespacesConfig->getLineEnding(); + + for ($index = 0, $count = \count($tokens); $index < $count; ++$index) { + $token = $tokens[$index]; + + if ($token->isGivenKind(T_ENCAPSED_AND_WHITESPACE)) { + if ($tokens[$tokens->getNextMeaningfulToken($index)]->isGivenKind(T_END_HEREDOC)) { + $tokens[$index] = new Token([ + $token->getId(), + Preg::replace( + '#\R#', + $ending, + $token->getContent() + ), + ]); + } + + continue; + } + + if ($token->isGivenKind([T_CLOSE_TAG, T_COMMENT, T_DOC_COMMENT, T_OPEN_TAG, T_START_HEREDOC, T_WHITESPACE])) { + $tokens[$index] = new Token([ + $token->getId(), + Preg::replace( + '#\R#', + $ending, + $token->getContent() + ), + ]); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/MethodChainingIndentationFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/MethodChainingIndentationFixer.php new file mode 100644 index 0000000..31b3e0b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/MethodChainingIndentationFixer.php @@ -0,0 +1,202 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Vladimir Boliev <voff.web@gmail.com> + */ +final class MethodChainingIndentationFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Method chaining MUST be properly indented. Method chaining with different levels of indentation is not supported.', + [new CodeSample("<?php\n\$user->setEmail('voff.web@gmail.com')\n ->setPassword('233434');\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run before ArrayIndentationFixer, MethodArgumentSpaceFixer. + * Must run after BracesFixer. + */ + public function getPriority() + { + return 34; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(Token::getObjectOperatorKinds()); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $lineEnding = $this->whitespacesConfig->getLineEnding(); + + for ($index = 1, $count = \count($tokens); $index < $count; ++$index) { + if (!$tokens[$index]->isObjectOperator()) { + continue; + } + + if ($this->canBeMovedToNextLine($index, $tokens)) { + $newline = new Token([T_WHITESPACE, $lineEnding]); + if ($tokens[$index - 1]->isWhitespace()) { + $tokens[$index - 1] = $newline; + } else { + $tokens->insertAt($index, $newline); + ++$index; + } + } + + $currentIndent = $this->getIndentAt($tokens, $index - 1); + if (null === $currentIndent) { + continue; + } + + $expectedIndent = $this->getExpectedIndentAt($tokens, $index); + if ($currentIndent !== $expectedIndent) { + $tokens[$index - 1] = new Token([T_WHITESPACE, $lineEnding.$expectedIndent]); + } + } + } + + /** + * @param int $index index of the first token on the line to indent + * + * @return string + */ + private function getExpectedIndentAt(Tokens $tokens, $index) + { + $index = $tokens->getPrevMeaningfulToken($index); + $indent = $this->whitespacesConfig->getIndent(); + + for ($i = $index; $i >= 0; --$i) { + if ($tokens[$i]->equals(')')) { + $i = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $i); + } + + $currentIndent = $this->getIndentAt($tokens, $i); + if (null === $currentIndent) { + continue; + } + + if ($this->currentLineRequiresExtraIndentLevel($tokens, $i, $index)) { + return $currentIndent.$indent; + } + + return $currentIndent; + } + + return $indent; + } + + /** + * @param int $index position of the object operator token ("->" or "?->") + * + * @return bool + */ + private function canBeMovedToNextLine($index, Tokens $tokens) + { + $prevMeaningful = $tokens->getPrevMeaningfulToken($index); + $hasCommentBefore = false; + + for ($i = $index - 1; $i > $prevMeaningful; --$i) { + if ($tokens[$i]->isComment()) { + $hasCommentBefore = true; + + continue; + } + + if ($tokens[$i]->isWhitespace() && 1 === Preg::match('/\R/', $tokens[$i]->getContent())) { + return $hasCommentBefore; + } + } + + return false; + } + + /** + * @param int $index index of the indentation token + * + * @return null|string + */ + private function getIndentAt(Tokens $tokens, $index) + { + if (1 === Preg::match('/\R{1}(\h*)$/', $this->getIndentContentAt($tokens, $index), $matches)) { + return $matches[1]; + } + + return null; + } + + private function getIndentContentAt(Tokens $tokens, $index) + { + if (!$tokens[$index]->isGivenKind([T_WHITESPACE, T_INLINE_HTML])) { + return ''; + } + + $content = $tokens[$index]->getContent(); + + if ($tokens[$index]->isWhitespace() && $tokens[$index - 1]->isGivenKind(T_OPEN_TAG)) { + $content = $tokens[$index - 1]->getContent().$content; + } + + if (Preg::match('/\R/', $content)) { + return $content; + } + + return ''; + } + + /** + * @param int $start index of first meaningful token on previous line + * @param int $end index of last token on previous line + * + * @return bool + */ + private function currentLineRequiresExtraIndentLevel(Tokens $tokens, $start, $end) + { + if ($tokens[$start + 1]->isObjectOperator()) { + return false; + } + + if ($tokens[$end]->isGivenKind(CT::T_BRACE_CLASS_INSTANTIATION_CLOSE)) { + return true; + } + + return + !$tokens[$end]->equals(')') + || $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $end) >= $start + ; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoExtraBlankLinesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoExtraBlankLinesFixer.php new file mode 100644 index 0000000..64bed16 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoExtraBlankLinesFixer.php @@ -0,0 +1,488 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\ConfigurationException\InvalidConfigurationException; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; +use PhpCsFixer\Utils; +use Symfony\Component\OptionsResolver\Options; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + */ +final class NoExtraBlankLinesFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface, WhitespacesAwareFixerInterface +{ + /** + * @var string[] + */ + private static $availableTokens = [ + 'break', + 'case', + 'continue', + 'curly_brace_block', + 'default', + 'extra', + 'parenthesis_brace_block', + 'return', + 'square_brace_block', + 'switch', + 'throw', + 'use', + 'useTrait', + 'use_trait', + ]; + + /** + * @var array<int, string> key is token id, value is name of callback + */ + private $tokenKindCallbackMap; + + /** + * @var array<string, string> token prototype, value is name of callback + */ + private $tokenEqualsMap; + + /** + * @var Tokens + */ + private $tokens; + + /** + * @var TokensAnalyzer + */ + private $tokensAnalyzer; + + /** + * {@inheritdoc} + */ + public function configure(array $configuration = null) + { + parent::configure($configuration); + + static $reprToTokenMap = [ + 'break' => T_BREAK, + 'case' => T_CASE, + 'continue' => T_CONTINUE, + 'curly_brace_block' => '{', + 'default' => T_DEFAULT, + 'extra' => T_WHITESPACE, + 'parenthesis_brace_block' => '(', + 'return' => T_RETURN, + 'square_brace_block' => CT::T_ARRAY_SQUARE_BRACE_OPEN, + 'switch' => T_SWITCH, + 'throw' => T_THROW, + 'use' => T_USE, + 'use_trait' => CT::T_USE_TRAIT, + ]; + + static $tokenKindCallbackMap = [ + T_BREAK => 'fixAfterToken', + T_CASE => 'fixAfterToken', + T_CONTINUE => 'fixAfterToken', + T_DEFAULT => 'fixAfterToken', + T_RETURN => 'fixAfterToken', + T_SWITCH => 'fixAfterToken', + T_THROW => 'fixAfterThrowToken', + T_USE => 'removeBetweenUse', + T_WHITESPACE => 'removeMultipleBlankLines', + CT::T_USE_TRAIT => 'removeBetweenUse', + CT::T_ARRAY_SQUARE_BRACE_OPEN => 'fixStructureOpenCloseIfMultiLine', // typeless '[' tokens should not be fixed (too rare) + ]; + + static $tokenEqualsMap = [ + '{' => 'fixStructureOpenCloseIfMultiLine', // i.e. not: CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN + '(' => 'fixStructureOpenCloseIfMultiLine', // i.e. not: CT::T_BRACE_CLASS_INSTANTIATION_OPEN + ]; + + $tokensAssoc = array_flip(array_intersect_key($reprToTokenMap, array_flip($this->configuration['tokens']))); + + $this->tokenKindCallbackMap = array_intersect_key($tokenKindCallbackMap, $tokensAssoc); + $this->tokenEqualsMap = array_intersect_key($tokenEqualsMap, $tokensAssoc); + } + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Removes extra blank lines and/or blank lines following configuration.', + [ + new CodeSample( + '<?php + +$foo = array("foo"); + + +$bar = "bar"; +' + ), + new CodeSample( + '<?php + +switch ($foo) { + case 41: + echo "foo"; + break; + + case 42: + break; +} +', + ['tokens' => ['break']] + ), + new CodeSample( + '<?php + +for ($i = 0; $i < 9000; ++$i) { + if (true) { + continue; + + } +} +', + ['tokens' => ['continue']] + ), + new CodeSample( + '<?php + +for ($i = 0; $i < 9000; ++$i) { + + echo $i; + +} +', + ['tokens' => ['curly_brace_block']] + ), + new CodeSample( + '<?php + +$foo = array("foo"); + + +$bar = "bar"; +', + ['tokens' => ['extra']] + ), + new CodeSample( + '<?php + +$foo = array( + + "foo" + +); +', + ['tokens' => ['parenthesis_brace_block']] + ), + new CodeSample( + '<?php + +function foo($bar) +{ + return $bar; + +} +', + ['tokens' => ['return']] + ), + new CodeSample( + '<?php + +$foo = [ + + "foo" + +]; +', + ['tokens' => ['square_brace_block']] + ), + new CodeSample( + '<?php + +function foo($bar) +{ + throw new \Exception("Hello!"); + +} +', + ['tokens' => ['throw']] + ), + new CodeSample( + '<?php + +namespace Foo; + +use Bar\Baz; + +use Baz\Bar; + +class Bar +{ +} +', + ['tokens' => ['use']] + ), + new CodeSample( + '<?php + +class Foo +{ + use Bar; + + use Baz; +} +', + ['tokens' => ['use_trait']] + ), + new CodeSample( + '<?php +switch($a) { + + case 1: + + default: + + echo 3; +} +', + ['tokens' => ['switch', 'case', 'default']] + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before BlankLineBeforeStatementFixer. + * Must run after CombineConsecutiveUnsetsFixer, FunctionToConstantFixer, NoEmptyCommentFixer, NoEmptyPhpdocFixer, NoEmptyStatementFixer, NoUnusedImportsFixer, NoUselessElseFixer, NoUselessReturnFixer, NoUselessSprintfFixer. + */ + public function getPriority() + { + return -20; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $this->tokens = $tokens; + $this->tokensAnalyzer = new TokensAnalyzer($this->tokens); + for ($index = $tokens->getSize() - 1; $index > 0; --$index) { + $this->fixByToken($tokens[$index], $index); + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $that = $this; + + return new FixerConfigurationResolverRootless('tokens', [ + (new FixerOptionBuilder('tokens', 'List of tokens to fix.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset(self::$availableTokens)]) + ->setNormalizer(static function (Options $options, $tokens) use ($that) { + foreach ($tokens as &$token) { + if ('useTrait' === $token) { + Utils::triggerDeprecation(new InvalidConfigurationException( + "Token \"useTrait\" in option \"tokens\" for rule \"{$that->getName()}\" is deprecated and will be removed in 3.0, use \"use_trait\" instead." + )); + $token = 'use_trait'; + + break; + } + } + + return $tokens; + }) + ->setDefault(['extra']) + ->getOption(), + ], $this->getName()); + } + + private function fixByToken(Token $token, $index) + { + foreach ($this->tokenKindCallbackMap as $kind => $callback) { + if (!$token->isGivenKind($kind)) { + continue; + } + + $this->{$callback}($index); + + return; + } + + foreach ($this->tokenEqualsMap as $equals => $callback) { + if (!$token->equals($equals)) { + continue; + } + + $this->{$callback}($index); + + return; + } + } + + private function removeBetweenUse($index) + { + $next = $this->tokens->getNextTokenOfKind($index, [';', [T_CLOSE_TAG]]); + if (null === $next || $this->tokens[$next]->isGivenKind(T_CLOSE_TAG)) { + return; + } + + $nextUseCandidate = $this->tokens->getNextMeaningfulToken($next); + if (null === $nextUseCandidate || !$this->tokens[$nextUseCandidate]->isGivenKind($this->tokens[$index]->getId()) || !$this->containsLinebreak($index, $nextUseCandidate)) { + return; + } + + $this->removeEmptyLinesAfterLineWithTokenAt($next); + } + + private function removeMultipleBlankLines($index) + { + $expected = $this->tokens[$index - 1]->isGivenKind(T_OPEN_TAG) && 1 === Preg::match('/\R$/', $this->tokens[$index - 1]->getContent()) ? 1 : 2; + + $parts = Preg::split('/(.*\R)/', $this->tokens[$index]->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + $count = \count($parts); + + if ($count > $expected) { + $this->tokens[$index] = new Token([T_WHITESPACE, implode('', \array_slice($parts, 0, $expected)).rtrim($parts[$count - 1], "\r\n")]); + } + } + + private function fixAfterToken($index) + { + for ($i = $index - 1; $i > 0; --$i) { + if ($this->tokens[$i]->isGivenKind(T_FUNCTION) && $this->tokensAnalyzer->isLambda($i)) { + return; + } + + if ($this->tokens[$i]->isGivenKind(T_CLASS) && $this->tokensAnalyzer->isAnonymousClass($i)) { + return; + } + + if ($this->tokens[$i]->isWhitespace() && false !== strpos($this->tokens[$i]->getContent(), "\n")) { + break; + } + } + + $this->removeEmptyLinesAfterLineWithTokenAt($index); + } + + private function fixAfterThrowToken($index) + { + if ($this->tokens[$this->tokens->getPrevMeaningfulToken($index)]->equalsAny([';', '{', '}', ':', [T_OPEN_TAG]])) { + $this->fixAfterToken($index); + } + } + + /** + * Remove white line(s) after the index of a block type, + * but only if the block is not on one line. + * + * @param int $index body start + */ + private function fixStructureOpenCloseIfMultiLine($index) + { + $blockTypeInfo = Tokens::detectBlockType($this->tokens[$index]); + $bodyEnd = $this->tokens->findBlockEnd($blockTypeInfo['type'], $index); + + for ($i = $bodyEnd - 1; $i >= $index; --$i) { + if (false !== strpos($this->tokens[$i]->getContent(), "\n")) { + $this->removeEmptyLinesAfterLineWithTokenAt($i); + $this->removeEmptyLinesAfterLineWithTokenAt($index); + + break; + } + } + } + + private function removeEmptyLinesAfterLineWithTokenAt($index) + { + // find the line break + $tokenCount = \count($this->tokens); + for ($end = $index; $end < $tokenCount; ++$end) { + if ( + $this->tokens[$end]->equals('}') + || false !== strpos($this->tokens[$end]->getContent(), "\n") + ) { + break; + } + } + + if ($end === $tokenCount) { + return; // not found, early return + } + + $ending = $this->whitespacesConfig->getLineEnding(); + + for ($i = $end; $i < $tokenCount && $this->tokens[$i]->isWhitespace(); ++$i) { + $content = $this->tokens[$i]->getContent(); + if (substr_count($content, "\n") < 1) { + continue; + } + + $pos = strrpos($content, "\n"); + if ($pos + 2 <= \strlen($content)) { // preserve indenting where possible + $newContent = $ending.substr($content, $pos + 1); + } else { + $newContent = $ending; + } + + $this->tokens[$i] = new Token([T_WHITESPACE, $newContent]); + } + } + + /** + * @param int $startIndex + * @param int $endIndex + * + * @return bool + */ + private function containsLinebreak($startIndex, $endIndex) + { + for ($i = $endIndex; $i > $startIndex; --$i) { + if (Preg::match('/\R/', $this->tokens[$i]->getContent())) { + return true; + } + } + + return false; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoExtraConsecutiveBlankLinesFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoExtraConsecutiveBlankLinesFixer.php new file mode 100644 index 0000000..5845747 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoExtraConsecutiveBlankLinesFixer.php @@ -0,0 +1,73 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + * + * @deprecated in 2.10, proxy to NoExtraBlankLinesFixer + */ +final class NoExtraConsecutiveBlankLinesFixer extends AbstractProxyFixer implements ConfigurationDefinitionFixerInterface, DeprecatedFixerInterface, WhitespacesAwareFixerInterface +{ + private $fixer; + + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return $this->getFixer()->getDefinition(); + } + + public function configure(array $configuration = null) + { + $this->getFixer()->configure($configuration); + $this->configuration = $configuration; + } + + /** + * {@inheritdoc} + */ + public function getSuccessorsNames() + { + return array_keys($this->proxyFixers); + } + + protected function createConfigurationDefinition() + { + return $this->getFixer()->createConfigurationDefinition(); + } + + /** + * {@inheritdoc} + */ + protected function createProxyFixers() + { + return [$this->getFixer()]; + } + + private function getFixer() + { + if (null === $this->fixer) { + $this->fixer = new NoExtraBlankLinesFixer(); + } + + return $this->fixer; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoSpacesAroundOffsetFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoSpacesAroundOffsetFixer.php new file mode 100644 index 0000000..1ffc2ed --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoSpacesAroundOffsetFixer.php @@ -0,0 +1,107 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\FixerConfiguration\AllowedValueSubset; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverRootless; +use PhpCsFixer\FixerConfiguration\FixerOptionBuilder; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Javier Spagnoletti <phansys@gmail.com> + */ +final class NoSpacesAroundOffsetFixer extends AbstractFixer implements ConfigurationDefinitionFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There MUST NOT be spaces around offset braces.', + [ + new CodeSample("<?php\n\$sample = \$b [ 'a' ] [ 'b' ];\n"), + new CodeSample("<?php\n\$sample = \$b [ 'a' ] [ 'b' ];\n", ['positions' => ['inside']]), + new CodeSample("<?php\n\$sample = \$b [ 'a' ] [ 'b' ];\n", ['positions' => ['outside']]), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isAnyTokenKindsFound(['[', CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN]); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->equalsAny(['[', [CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN]])) { + continue; + } + + if (\in_array('inside', $this->configuration['positions'], true)) { + if ($token->equals('[')) { + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE, $index); + } else { + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_INDEX_CURLY_BRACE, $index); + } + + // remove space after opening `[` or `{` + if ($tokens[$index + 1]->isWhitespace(" \t")) { + $tokens->clearAt($index + 1); + } + + // remove space before closing `]` or `}` + if ($tokens[$endIndex - 1]->isWhitespace(" \t")) { + $tokens->clearAt($endIndex - 1); + } + } + + if (\in_array('outside', $this->configuration['positions'], true)) { + $prevNonWhitespaceIndex = $tokens->getPrevNonWhitespace($index); + if ($tokens[$prevNonWhitespaceIndex]->isComment()) { + continue; + } + + $tokens->removeLeadingWhitespace($index); + } + } + } + + /** + * {@inheritdoc} + */ + protected function createConfigurationDefinition() + { + $values = ['inside', 'outside']; + + return new FixerConfigurationResolverRootless('positions', [ + (new FixerOptionBuilder('positions', 'Whether spacing should be fixed inside and/or outside the offset braces.')) + ->setAllowedTypes(['array']) + ->setAllowedValues([new AllowedValueSubset($values)]) + ->setDefault($values) + ->getOption(), + ], $this->getName()); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoSpacesInsideParenthesisFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoSpacesInsideParenthesisFixer.php new file mode 100644 index 0000000..767aba2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoSpacesInsideParenthesisFixer.php @@ -0,0 +1,110 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR2 ¶4.3, ¶4.6, ¶5. + * + * @author Marc Aubé + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NoSpacesInsideParenthesisFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'There MUST NOT be a space after the opening parenthesis. There MUST NOT be a space before the closing parenthesis.', + [ + new CodeSample("<?php\nif ( \$a ) {\n foo( );\n}\n"), + new CodeSample( + "<?php +function foo( \$bar, \$baz ) +{ +}\n" + ), + ] + ); + } + + /** + * {@inheritdoc} + * + * Must run before FunctionToConstantFixer. + * Must run after CombineConsecutiveIssetsFixer, CombineNestedDirnameFixer, LambdaNotUsedImportFixer, NoUselessSprintfFixer, PowToExponentiationFixer. + */ + public function getPriority() + { + return 2; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return $tokens->isTokenKindFound('('); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + foreach ($tokens as $index => $token) { + if (!$token->equals('(')) { + continue; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + + // ignore parenthesis for T_ARRAY + if (null !== $prevIndex && $tokens[$prevIndex]->isGivenKind(T_ARRAY)) { + continue; + } + + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + + // remove space after opening `(` + if (!$tokens[$tokens->getNextNonWhitespace($index)]->isComment()) { + $this->removeSpaceAroundToken($tokens, $index + 1); + } + + // remove space before closing `)` if it is not `list($a, $b, )` case + if (!$tokens[$tokens->getPrevMeaningfulToken($endIndex)]->equals(',')) { + $this->removeSpaceAroundToken($tokens, $endIndex - 1); + } + } + } + + /** + * Remove spaces from token at a given index. + * + * @param int $index + */ + private function removeSpaceAroundToken(Tokens $tokens, $index) + { + $token = $tokens[$index]; + + if ($token->isWhitespace() && false === strpos($token->getContent(), "\n")) { + $tokens->clearAt($index); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoTrailingWhitespaceFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoTrailingWhitespaceFixer.php new file mode 100644 index 0000000..4d89193 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoTrailingWhitespaceFixer.php @@ -0,0 +1,114 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Fixer for rules defined in PSR2 ¶2.3. + * + * Don't add trailing spaces at the end of non-blank lines. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NoTrailingWhitespaceFixer extends AbstractFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Remove trailing whitespace at the end of non-blank lines.', + [new CodeSample("<?php\n\$a = 1; \n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run after CombineConsecutiveIssetsFixer, CombineConsecutiveUnsetsFixer, FunctionToConstantFixer, NoEmptyCommentFixer, NoEmptyPhpdocFixer, NoEmptyStatementFixer, NoUnneededControlParenthesesFixer, NoUselessElseFixer, TernaryToElvisOperatorFixer. + */ + public function getPriority() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = \count($tokens) - 1; $index >= 0; --$index) { + $token = $tokens[$index]; + if ( + $token->isGivenKind(T_OPEN_TAG) + && $tokens->offsetExists($index + 1) + && $tokens[$index + 1]->isWhitespace() + && 1 === Preg::match('/(.*)\h$/', $token->getContent(), $openTagMatches) + && 1 === Preg::match('/^(\R)(.*)$/s', $tokens[$index + 1]->getContent(), $whitespaceMatches) + ) { + $tokens[$index] = new Token([T_OPEN_TAG, $openTagMatches[1].$whitespaceMatches[1]]); + if ('' === $whitespaceMatches[2]) { + $tokens->clearAt($index + 1); + } else { + $tokens[$index + 1] = new Token([T_WHITESPACE, $whitespaceMatches[2]]); + } + + continue; + } + + if (!$token->isWhitespace()) { + continue; + } + + $lines = Preg::split('/(\\R+)/', $token->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + $linesSize = \count($lines); + + // fix only multiline whitespaces or singleline whitespaces at the end of file + if ($linesSize > 1 || !isset($tokens[$index + 1])) { + if (!$tokens[$index - 1]->isGivenKind(T_OPEN_TAG) || 1 !== Preg::match('/(.*)\R$/', $tokens[$index - 1]->getContent())) { + $lines[0] = rtrim($lines[0], " \t"); + } + + for ($i = 1; $i < $linesSize; ++$i) { + $trimmedLine = rtrim($lines[$i], " \t"); + if ('' !== $trimmedLine) { + $lines[$i] = $trimmedLine; + } + } + + $content = implode('', $lines); + if ('' !== $content) { + $tokens[$index] = new Token([$token->getId(), $content]); + } else { + $tokens->clearAt($index); + } + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoWhitespaceInBlankLineFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoWhitespaceInBlankLineFixer.php new file mode 100644 index 0000000..139afa2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/NoWhitespaceInBlankLineFixer.php @@ -0,0 +1,103 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class NoWhitespaceInBlankLineFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'Remove trailing whitespace at the end of blank lines.', + [new CodeSample("<?php\n \n\$a = 1;\n")] + ); + } + + /** + * {@inheritdoc} + * + * Must run after CombineConsecutiveIssetsFixer, CombineConsecutiveUnsetsFixer, FunctionToConstantFixer, NoEmptyCommentFixer, NoEmptyPhpdocFixer, NoEmptyStatementFixer, NoUselessElseFixer, NoUselessReturnFixer. + */ + public function getPriority() + { + return -19; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + // skip first as it cannot be a white space token + for ($i = 1, $count = \count($tokens); $i < $count; ++$i) { + if ($tokens[$i]->isWhitespace()) { + $this->fixWhitespaceToken($tokens, $i); + } + } + } + + /** + * @param int $index + */ + private function fixWhitespaceToken(Tokens $tokens, $index) + { + $content = $tokens[$index]->getContent(); + $lines = Preg::split("/(\r\n|\n)/", $content); + $lineCount = \count($lines); + + if ( + // fix T_WHITESPACES with at least 3 lines (eg `\n \n`) + $lineCount > 2 + // and T_WHITESPACES with at least 2 lines at the end of file or after open tag with linebreak + || ($lineCount > 0 && (!isset($tokens[$index + 1]) || $tokens[$index - 1]->isGivenKind(T_OPEN_TAG))) + ) { + $lMax = isset($tokens[$index + 1]) ? $lineCount - 1 : $lineCount; + + $lStart = 1; + if ($tokens[$index - 1]->isGivenKind(T_OPEN_TAG) && "\n" === substr($tokens[$index - 1]->getContent(), -1)) { + $lStart = 0; + } + + for ($l = $lStart; $l < $lMax; ++$l) { + $lines[$l] = Preg::replace('/^\h+$/', '', $lines[$l]); + } + $content = implode($this->whitespacesConfig->getLineEnding(), $lines); + if ('' !== $content) { + $tokens[$index] = new Token([T_WHITESPACE, $content]); + } else { + $tokens->clearAt($index); + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/SingleBlankLineAtEofFixer.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/SingleBlankLineAtEofFixer.php new file mode 100644 index 0000000..a8a59dd --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/Whitespace/SingleBlankLineAtEofFixer.php @@ -0,0 +1,73 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\Whitespace; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\FixerDefinition\CodeSample; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * A file must always end with a line endings character. + * + * Fixer for rules defined in PSR2 ¶2.2. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class SingleBlankLineAtEofFixer extends AbstractFixer implements WhitespacesAwareFixerInterface +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'A PHP file without end tag must always end with a single empty line feed.', + [ + new CodeSample("<?php\n\$a = 1;"), + new CodeSample("<?php\n\$a = 1;\n\n"), + ] + ); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + // must run last to be sure the file is properly formatted before it runs + return -50; + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + $count = $tokens->count(); + + if ($count && !$tokens[$count - 1]->isGivenKind([T_INLINE_HTML, T_CLOSE_TAG, T_OPEN_TAG])) { + $tokens->ensureWhitespaceAtIndex($count - 1, 1, $this->whitespacesConfig->getLineEnding()); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Fixer/WhitespacesAwareFixerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Fixer/WhitespacesAwareFixerInterface.php new file mode 100644 index 0000000..7f1c22c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Fixer/WhitespacesAwareFixerInterface.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer; + +use PhpCsFixer\WhitespacesFixerConfig; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +interface WhitespacesAwareFixerInterface extends FixerInterface +{ + public function setWhitespacesConfig(WhitespacesFixerConfig $config); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AliasedFixerOption.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AliasedFixerOption.php new file mode 100644 index 0000000..7bb1517 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AliasedFixerOption.php @@ -0,0 +1,101 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +/** + * @author ntzm + * + * @internal + */ +final class AliasedFixerOption implements FixerOptionInterface +{ + /** + * @var FixerOptionInterface + */ + private $fixerOption; + + /** + * @var string + */ + private $alias; + + public function __construct(FixerOptionInterface $fixerOption, $alias) + { + $this->fixerOption = $fixerOption; + $this->alias = $alias; + } + + /** + * @return string + */ + public function getAlias() + { + return $this->alias; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->fixerOption->getName(); + } + + /** + * {@inheritdoc} + */ + public function getDescription() + { + return $this->fixerOption->getDescription(); + } + + /** + * {@inheritdoc} + */ + public function hasDefault() + { + return $this->fixerOption->hasDefault(); + } + + /** + * {@inheritdoc} + */ + public function getDefault() + { + return $this->fixerOption->getDefault(); + } + + /** + * {@inheritdoc} + */ + public function getAllowedTypes() + { + return $this->fixerOption->getAllowedTypes(); + } + + /** + * {@inheritdoc} + */ + public function getAllowedValues() + { + return $this->fixerOption->getAllowedValues(); + } + + /** + * {@inheritdoc} + */ + public function getNormalizer() + { + return $this->fixerOption->getNormalizer(); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AliasedFixerOptionBuilder.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AliasedFixerOptionBuilder.php new file mode 100644 index 0000000..3f9cbac --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AliasedFixerOptionBuilder.php @@ -0,0 +1,92 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +/** + * @author ntzm + * + * @internal + */ +final class AliasedFixerOptionBuilder +{ + /** + * @var FixerOptionBuilder + */ + private $optionBuilder; + + /** + * @var string + */ + private $alias; + + public function __construct(FixerOptionBuilder $optionBuilder, $alias) + { + $this->optionBuilder = $optionBuilder; + $this->alias = $alias; + } + + /** + * @param mixed $default + * + * @return $this + */ + public function setDefault($default) + { + $this->optionBuilder->setDefault($default); + + return $this; + } + + /** + * @param string[] $allowedTypes + * + * @return $this + */ + public function setAllowedTypes(array $allowedTypes) + { + $this->optionBuilder->setAllowedTypes($allowedTypes); + + return $this; + } + + /** + * @return $this + */ + public function setAllowedValues(array $allowedValues) + { + $this->optionBuilder->setAllowedValues($allowedValues); + + return $this; + } + + /** + * @return $this + */ + public function setNormalizer(\Closure $normalizer) + { + $this->optionBuilder->setNormalizer($normalizer); + + return $this; + } + + /** + * @return AliasedFixerOption + */ + public function getOption() + { + return new AliasedFixerOption( + $this->optionBuilder->getOption(), + $this->alias + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AllowedValueSubset.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AllowedValueSubset.php new file mode 100644 index 0000000..8a2e2c1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/AllowedValueSubset.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +/** + * @internal + */ +final class AllowedValueSubset +{ + /** + * @var array + */ + private $allowedValues; + + public function __construct(array $allowedValues) + { + $this->allowedValues = $allowedValues; + } + + /** + * Checks whether the given values are a subset of the allowed ones. + * + * @param mixed $values the value to validate + * + * @return bool + */ + public function __invoke($values) + { + if (!\is_array($values)) { + return false; + } + + foreach ($values as $value) { + if (!\in_array($value, $this->allowedValues, true)) { + return false; + } + } + + return true; + } + + public function getAllowedValues() + { + return $this->allowedValues; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/DeprecatedFixerOption.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/DeprecatedFixerOption.php new file mode 100644 index 0000000..f498ea3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/DeprecatedFixerOption.php @@ -0,0 +1,99 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +final class DeprecatedFixerOption implements DeprecatedFixerOptionInterface +{ + /** + * @var FixerOptionInterface + */ + private $option; + + /** + * @var string + */ + private $deprecationMessage; + + /** + * @param string $deprecationMessage + */ + public function __construct(FixerOptionInterface $option, $deprecationMessage) + { + $this->option = $option; + $this->deprecationMessage = $deprecationMessage; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->option->getName(); + } + + /** + * {@inheritdoc} + */ + public function getDescription() + { + return $this->option->getDescription(); + } + + /** + * {@inheritdoc} + */ + public function hasDefault() + { + return $this->option->hasDefault(); + } + + /** + * {@inheritdoc} + */ + public function getDefault() + { + return $this->option->getDefault(); + } + + /** + * {@inheritdoc} + */ + public function getAllowedTypes() + { + return $this->option->getAllowedTypes(); + } + + /** + * {@inheritdoc} + */ + public function getAllowedValues() + { + return $this->option->getAllowedValues(); + } + + /** + * {@inheritdoc} + */ + public function getNormalizer() + { + return $this->option->getNormalizer(); + } + + /** + * @return string + */ + public function getDeprecationMessage() + { + return $this->deprecationMessage; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/DeprecatedFixerOptionInterface.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/DeprecatedFixerOptionInterface.php new file mode 100644 index 0000000..fc84798 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/DeprecatedFixerOptionInterface.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +interface DeprecatedFixerOptionInterface extends FixerOptionInterface +{ + /** + * @return string + */ + public function getDeprecationMessage(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolver.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolver.php new file mode 100644 index 0000000..7d07b2d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolver.php @@ -0,0 +1,133 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +use PhpCsFixer\Utils; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; +use Symfony\Component\OptionsResolver\OptionsResolver; + +final class FixerConfigurationResolver implements FixerConfigurationResolverInterface +{ + /** + * @var FixerOptionInterface[] + */ + private $options = []; + + /** + * @var string[] + */ + private $registeredNames = []; + + /** + * @param iterable<FixerOptionInterface> $options + */ + public function __construct($options) + { + foreach ($options as $option) { + $this->addOption($option); + } + + if (empty($this->registeredNames)) { + throw new \LogicException('Options cannot be empty.'); + } + } + + /** + * {@inheritdoc} + */ + public function getOptions() + { + return $this->options; + } + + /** + * {@inheritdoc} + */ + public function resolve(array $options) + { + $resolver = new OptionsResolver(); + + foreach ($this->options as $option) { + $name = $option->getName(); + + if ($option instanceof AliasedFixerOption) { + $alias = $option->getAlias(); + + if (\array_key_exists($alias, $options)) { + if (\array_key_exists($name, $options)) { + throw new InvalidOptionsException(sprintf('Aliased option "%s"/"%s" is passed multiple times.', $name, $alias)); + } + + Utils::triggerDeprecation(new \RuntimeException(sprintf( + 'Option "%s" is deprecated, use "%s" instead.', + $alias, + $name + ))); + + $options[$name] = $options[$alias]; + unset($options[$alias]); + } + } + + if ($option->hasDefault()) { + $resolver->setDefault($name, $option->getDefault()); + } else { + $resolver->setRequired($name); + } + + $allowedValues = $option->getAllowedValues(); + if (null !== $allowedValues) { + foreach ($allowedValues as &$allowedValue) { + if (\is_object($allowedValue) && \is_callable($allowedValue)) { + $allowedValue = static function ($values) use ($allowedValue) { + return $allowedValue($values); + }; + } + } + + $resolver->setAllowedValues($name, $allowedValues); + } + + $allowedTypes = $option->getAllowedTypes(); + if (null !== $allowedTypes) { + $resolver->setAllowedTypes($name, $allowedTypes); + } + + $normalizer = $option->getNormalizer(); + if (null !== $normalizer) { + $resolver->setNormalizer($name, $normalizer); + } + } + + return $resolver->resolve($options); + } + + /** + * @throws \LogicException when the option is already defined + * + * @return $this + */ + private function addOption(FixerOptionInterface $option) + { + $name = $option->getName(); + + if (\in_array($name, $this->registeredNames, true)) { + throw new \LogicException(sprintf('The "%s" option is defined multiple times.', $name)); + } + + $this->options[] = $option; + $this->registeredNames[] = $name; + + return $this; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolverInterface.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolverInterface.php new file mode 100644 index 0000000..099f5f1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolverInterface.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +interface FixerConfigurationResolverInterface +{ + /** + * @return FixerOptionInterface[] + */ + public function getOptions(); + + /** + * @param array<string, mixed> $configuration + * + * @return array<string, mixed> + */ + public function resolve(array $configuration); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolverRootless.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolverRootless.php new file mode 100644 index 0000000..46437d2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerConfigurationResolverRootless.php @@ -0,0 +1,97 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +use PhpCsFixer\Utils; + +/** + * @internal + * + * @deprecated will be removed in 3.0 + */ +final class FixerConfigurationResolverRootless implements FixerConfigurationResolverInterface +{ + /** + * @var FixerConfigurationResolverInterface + */ + private $resolver; + + /** + * @var string + */ + private $root; + + /** + * @var string + */ + private $fixerName; + + /** + * @param string $root + * @param iterable<FixerOptionInterface> $options + * @param string $fixerName + */ + public function __construct($root, $options, $fixerName) + { + $this->resolver = new FixerConfigurationResolver($options); + $this->fixerName = $fixerName; + + $names = array_map( + static function (FixerOptionInterface $option) { + return $option->getName(); + }, + $this->resolver->getOptions() + ); + + if (!\in_array($root, $names, true)) { + throw new \LogicException(sprintf('The "%s" option is not defined.', $root)); + } + + $this->root = $root; + } + + /** + * {@inheritdoc} + */ + public function getOptions() + { + return $this->resolver->getOptions(); + } + + /** + * {@inheritdoc} + */ + public function resolve(array $options) + { + if (!empty($options) && !\array_key_exists($this->root, $options)) { + $names = array_map( + static function (FixerOptionInterface $option) { + return $option->getName(); + }, + $this->resolver->getOptions() + ); + + $passedNames = array_keys($options); + + if (!empty(array_diff($passedNames, $names))) { + Utils::triggerDeprecation(new \RuntimeException( + "Passing \"{$this->root}\" at the root of the configuration for rule \"{$this->fixerName}\" is deprecated and will not be supported in 3.0, use \"{$this->root}\" => array(...) option instead." + )); + + $options = [$this->root => $options]; + } + } + + return $this->resolver->resolve($options); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOption.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOption.php new file mode 100644 index 0000000..55ada57 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOption.php @@ -0,0 +1,172 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +final class FixerOption implements FixerOptionInterface +{ + /** + * @var string + */ + private $name; + + /** + * @var string + */ + private $description; + + /** + * @var mixed + */ + private $default; + + /** + * @var bool + */ + private $isRequired; + + /** + * @var null|string[] + */ + private $allowedTypes; + + /** + * @var null|array + */ + private $allowedValues; + + /** + * @var null|\Closure + */ + private $normalizer; + + /** + * @param string $name + * @param string $description + * @param bool $isRequired + * @param mixed $default + * @param null|string[] $allowedTypes + */ + public function __construct( + $name, + $description, + $isRequired = true, + $default = null, + array $allowedTypes = null, + array $allowedValues = null, + \Closure $normalizer = null + ) { + if ($isRequired && null !== $default) { + throw new \LogicException('Required options cannot have a default value.'); + } + + if (null !== $allowedValues) { + foreach ($allowedValues as &$allowedValue) { + if ($allowedValue instanceof \Closure) { + $allowedValue = $this->unbind($allowedValue); + } + } + } + + $this->name = $name; + $this->description = $description; + $this->isRequired = $isRequired; + $this->default = $default; + $this->allowedTypes = $allowedTypes; + $this->allowedValues = $allowedValues; + if (null !== $normalizer) { + $this->normalizer = $this->unbind($normalizer); + } + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function getDescription() + { + return $this->description; + } + + /** + * {@inheritdoc} + */ + public function hasDefault() + { + return !$this->isRequired; + } + + /** + * {@inheritdoc} + */ + public function getDefault() + { + if (!$this->hasDefault()) { + throw new \LogicException('No default value defined.'); + } + + return $this->default; + } + + /** + * {@inheritdoc} + */ + public function getAllowedTypes() + { + return $this->allowedTypes; + } + + /** + * {@inheritdoc} + */ + public function getAllowedValues() + { + return $this->allowedValues; + } + + /** + * {@inheritdoc} + */ + public function getNormalizer() + { + return $this->normalizer; + } + + /** + * Unbinds the given closure to avoid memory leaks. + * + * The closures provided to this class were probably defined in a fixer + * class and thus bound to it by default. The configuration will then be + * stored in {@see AbstractFixer::$configurationDefinition}, leading to the + * following cyclic reference: + * + * fixer -> configuration definition -> options -> closures -> fixer + * + * This cyclic reference prevent the garbage collector to free memory as + * all elements are still referenced. + * + * See {@see https://bugs.php.net/bug.php?id=69639 Bug #69639} for details. + * + * @return \Closure + */ + private function unbind(\Closure $closure) + { + return $closure->bindTo(null); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOptionBuilder.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOptionBuilder.php new file mode 100644 index 0000000..d839574 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOptionBuilder.php @@ -0,0 +1,145 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +final class FixerOptionBuilder +{ + /** + * @var string + */ + private $name; + + /** + * @var string + */ + private $description; + + /** + * @var mixed + */ + private $default; + + /** + * @var bool + */ + private $isRequired = true; + + /** + * @var null|string[] + */ + private $allowedTypes; + + /** + * @var null|array + */ + private $allowedValues; + + /** + * @var null|\Closure + */ + private $normalizer; + + /** + * @var null|string + */ + private $deprecationMessage; + + /** + * @param string $name + * @param string $description + */ + public function __construct($name, $description) + { + $this->name = $name; + $this->description = $description; + } + + /** + * @param mixed $default + * + * @return $this + */ + public function setDefault($default) + { + $this->default = $default; + $this->isRequired = false; + + return $this; + } + + /** + * @param string[] $allowedTypes + * + * @return $this + */ + public function setAllowedTypes(array $allowedTypes) + { + $this->allowedTypes = $allowedTypes; + + return $this; + } + + /** + * @return $this + */ + public function setAllowedValues(array $allowedValues) + { + $this->allowedValues = $allowedValues; + + return $this; + } + + /** + * @return $this + */ + public function setNormalizer(\Closure $normalizer) + { + $this->normalizer = $normalizer; + + return $this; + } + + /** + * @param null|string $deprecationMessage + * + * @return $this + */ + public function setDeprecationMessage($deprecationMessage) + { + $this->deprecationMessage = $deprecationMessage; + + return $this; + } + + /** + * @return FixerOptionInterface + */ + public function getOption() + { + $option = new FixerOption( + $this->name, + $this->description, + $this->isRequired, + $this->default, + $this->allowedTypes, + $this->allowedValues, + $this->normalizer + ); + + if (null !== $this->deprecationMessage) { + $option = new DeprecatedFixerOption($option, $this->deprecationMessage); + } + + return $option; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOptionInterface.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOptionInterface.php new file mode 100644 index 0000000..c682db6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/FixerOptionInterface.php @@ -0,0 +1,53 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +interface FixerOptionInterface +{ + /** + * @return string + */ + public function getName(); + + /** + * @return string + */ + public function getDescription(); + + /** + * @return bool + */ + public function hasDefault(); + + /** + * @throws \LogicException when no default value is defined + * + * @return mixed + */ + public function getDefault(); + + /** + * @return null|string[] + */ + public function getAllowedTypes(); + + /** + * @return null|array + */ + public function getAllowedValues(); + + /** + * @return null|\Closure + */ + public function getNormalizer(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/InvalidOptionsForEnvException.php b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/InvalidOptionsForEnvException.php new file mode 100644 index 0000000..755d0b0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerConfiguration/InvalidOptionsForEnvException.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerConfiguration; + +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class InvalidOptionsForEnvException extends InvalidOptionsException +{ +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/CodeSample.php b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/CodeSample.php new file mode 100644 index 0000000..4e7dab7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/CodeSample.php @@ -0,0 +1,54 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerDefinition; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class CodeSample implements CodeSampleInterface +{ + /** + * @var string + */ + private $code; + + /** + * @var null|array + */ + private $configuration; + + /** + * @param string $code + */ + public function __construct($code, array $configuration = null) + { + $this->code = $code; + $this->configuration = $configuration; + } + + /** + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * @return null|array + */ + public function getConfiguration() + { + return $this->configuration; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/CodeSampleInterface.php b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/CodeSampleInterface.php new file mode 100644 index 0000000..877214a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/CodeSampleInterface.php @@ -0,0 +1,29 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerDefinition; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +interface CodeSampleInterface +{ + /** + * @return string + */ + public function getCode(); + + /** + * @return null|array + */ + public function getConfiguration(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FileSpecificCodeSample.php b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FileSpecificCodeSample.php new file mode 100644 index 0000000..3f3c1e8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FileSpecificCodeSample.php @@ -0,0 +1,67 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerDefinition; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FileSpecificCodeSample implements FileSpecificCodeSampleInterface +{ + /** + * @var CodeSampleInterface + */ + private $codeSample; + + /** + * @var \SplFileInfo + */ + private $splFileInfo; + + /** + * @param string $code + */ + public function __construct( + $code, + \SplFileInfo $splFileInfo, + array $configuration = null + ) { + $this->codeSample = new CodeSample($code, $configuration); + $this->splFileInfo = $splFileInfo; + } + + /** + * {@inheritdoc} + */ + public function getCode() + { + return $this->codeSample->getCode(); + } + + /** + * {@inheritdoc} + */ + public function getConfiguration() + { + return $this->codeSample->getConfiguration(); + } + + /** + * {@inheritdoc} + */ + public function getSplFileInfo() + { + return $this->splFileInfo; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FileSpecificCodeSampleInterface.php b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FileSpecificCodeSampleInterface.php new file mode 100644 index 0000000..b069e30 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FileSpecificCodeSampleInterface.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerDefinition; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +interface FileSpecificCodeSampleInterface extends CodeSampleInterface +{ + /** + * @return \SplFileInfo + */ + public function getSplFileInfo(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FixerDefinition.php b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FixerDefinition.php new file mode 100644 index 0000000..bfb6a5b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FixerDefinition.php @@ -0,0 +1,118 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerDefinition; + +use PhpCsFixer\Utils; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class FixerDefinition implements FixerDefinitionInterface +{ + /** + * @var null|string + */ + private $riskyDescription; + + private $configurationDescription; + + private $defaultConfiguration; + + /** + * @var CodeSampleInterface[] + */ + private $codeSamples; + + /** + * @var string + */ + private $summary; + + /** + * @var null|string + */ + private $description; + + /** + * @param string $summary + * @param CodeSampleInterface[] $codeSamples array of samples, where single sample is [code, configuration] + * @param null|string $description + * @param null|string $configurationDescription null for non-configurable fixer + * @param null|array $defaultConfiguration null for non-configurable fixer + * @param null|string $riskyDescription null for non-risky fixer + */ + public function __construct( + $summary, + array $codeSamples, + $description = null, + $configurationDescription = null, + array $defaultConfiguration = null, + $riskyDescription = null + ) { + if (6 === \func_num_args()) { + Utils::triggerDeprecation(new \RuntimeException('Arguments #5 and #6 of FixerDefinition::__construct() are deprecated and will be removed in 3.0, use argument #4 instead.')); + } elseif (5 === \func_num_args()) { + Utils::triggerDeprecation(new \RuntimeException('Argument #5 of FixerDefinition::__construct() is deprecated and will be removed in 3.0.')); + } else { + $riskyDescription = $configurationDescription; + $configurationDescription = null; + } + + $this->summary = $summary; + $this->codeSamples = $codeSamples; + $this->description = $description; + $this->configurationDescription = $configurationDescription; + $this->defaultConfiguration = $defaultConfiguration; + $this->riskyDescription = $riskyDescription; + } + + public function getSummary() + { + return $this->summary; + } + + public function getDescription() + { + return $this->description; + } + + public function getConfigurationDescription() + { + Utils::triggerDeprecation(new \RuntimeException(sprintf( + '%s is deprecated and will be removed in 3.0.', + __METHOD__ + ))); + + return $this->configurationDescription; + } + + public function getDefaultConfiguration() + { + Utils::triggerDeprecation(new \RuntimeException(sprintf( + '%s is deprecated and will be removed in 3.0.', + __METHOD__ + ))); + + return $this->defaultConfiguration; + } + + public function getRiskyDescription() + { + return $this->riskyDescription; + } + + public function getCodeSamples() + { + return $this->codeSamples; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FixerDefinitionInterface.php b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FixerDefinitionInterface.php new file mode 100644 index 0000000..1b1e93e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/FixerDefinitionInterface.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerDefinition; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +interface FixerDefinitionInterface +{ + /** + * @return string + */ + public function getSummary(); + + /** + * @return null|string + */ + public function getDescription(); + + /** + * @return null|string null for non-configurable fixer + * + * @deprecated will be removed in 3.0 + */ + public function getConfigurationDescription(); + + /** + * @return null|array null for non-configurable fixer + * + * @deprecated will be removed in 3.0 + */ + public function getDefaultConfiguration(); + + /** + * @return null|string null for non-risky fixer + */ + public function getRiskyDescription(); + + /** + * Array of samples, where single sample is [code, configuration]. + * + * @return CodeSampleInterface[] + */ + public function getCodeSamples(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificCodeSample.php b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificCodeSample.php new file mode 100644 index 0000000..01080e7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificCodeSample.php @@ -0,0 +1,65 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerDefinition; + +/** + * @author Andreas Möller <am@localheinz.com> + */ +final class VersionSpecificCodeSample implements VersionSpecificCodeSampleInterface +{ + /** + * @var CodeSampleInterface + */ + private $codeSample; + + /** + * @var VersionSpecificationInterface + */ + private $versionSpecification; + + /** + * @param string $code + */ + public function __construct( + $code, + VersionSpecificationInterface $versionSpecification, + array $configuration = null + ) { + $this->codeSample = new CodeSample($code, $configuration); + $this->versionSpecification = $versionSpecification; + } + + /** + * {@inheritdoc} + */ + public function getCode() + { + return $this->codeSample->getCode(); + } + + /** + * {@inheritdoc} + */ + public function getConfiguration() + { + return $this->codeSample->getConfiguration(); + } + + /** + * {@inheritdoc} + */ + public function isSuitableFor($version) + { + return $this->versionSpecification->isSatisfiedBy($version); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificCodeSampleInterface.php b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificCodeSampleInterface.php new file mode 100644 index 0000000..9612770 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificCodeSampleInterface.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerDefinition; + +/** + * @author Andreas Moeller <am@localheinz.com> + */ +interface VersionSpecificCodeSampleInterface extends CodeSampleInterface +{ + /** + * @param int $version + * + * @return bool + */ + public function isSuitableFor($version); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecification.php b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecification.php new file mode 100644 index 0000000..d1459d1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecification.php @@ -0,0 +1,75 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerDefinition; + +/** + * @author Andreas Möller <am@localheinz.com> + */ +final class VersionSpecification implements VersionSpecificationInterface +{ + /** + * @var null|int + */ + private $minimum; + + /** + * @var null|int + */ + private $maximum; + + /** + * @param null|int $minimum + * @param null|int $maximum + * + * @throws \InvalidArgumentException + */ + public function __construct($minimum = null, $maximum = null) + { + if (null === $minimum && null === $maximum) { + throw new \InvalidArgumentException('Minimum or maximum need to be specified.'); + } + + if (null !== $minimum && (!\is_int($minimum) || 1 > $minimum)) { + throw new \InvalidArgumentException('Minimum needs to be either null or an integer greater than 0.'); + } + + if (null !== $maximum) { + if (!\is_int($maximum) || 1 > $maximum) { + throw new \InvalidArgumentException('Maximum needs to be either null or an integer greater than 0.'); + } + + if (null !== $minimum && $maximum < $minimum) { + throw new \InvalidArgumentException('Maximum should not be lower than the minimum.'); + } + } + + $this->minimum = $minimum; + $this->maximum = $maximum; + } + + /** + * {@inheritdoc} + */ + public function isSatisfiedBy($version) + { + if (null !== $this->minimum && $version < $this->minimum) { + return false; + } + + if (null !== $this->maximum && $version > $this->maximum) { + return false; + } + + return true; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificationInterface.php b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificationInterface.php new file mode 100644 index 0000000..36ae354 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerDefinition/VersionSpecificationInterface.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\FixerDefinition; + +/** + * @author Andreas Möller <am@localheinz.com> + */ +interface VersionSpecificationInterface +{ + /** + * @param int $version + * + * @return bool + */ + public function isSatisfiedBy($version); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerFactory.php b/vendor/friendsofphp/php-cs-fixer/src/FixerFactory.php new file mode 100644 index 0000000..6c50122 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerFactory.php @@ -0,0 +1,246 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\Fixer\ConfigurableFixerInterface; +use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface; +use PhpCsFixer\RuleSet\RuleSetInterface; +use Symfony\Component\Finder\Finder as SymfonyFinder; +use Symfony\Component\Finder\SplFileInfo; + +/** + * Class provides a way to create a group of fixers. + * + * Fixers may be registered (made the factory aware of them) by + * registering a custom fixer and default, built in fixers. + * Then, one can attach Config instance to fixer instances. + * + * Finally factory creates a ready to use group of fixers. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FixerFactory +{ + /** + * @var FixerNameValidator + */ + private $nameValidator; + + /** + * @var FixerInterface[] + */ + private $fixers = []; + + /** + * @var FixerInterface[] Associative array of fixers with names as keys + */ + private $fixersByName = []; + + public function __construct() + { + $this->nameValidator = new FixerNameValidator(); + } + + public function setWhitespacesConfig(WhitespacesFixerConfig $config) + { + foreach ($this->fixers as $fixer) { + if ($fixer instanceof WhitespacesAwareFixerInterface) { + $fixer->setWhitespacesConfig($config); + } + } + + return $this; + } + + /** + * @return FixerInterface[] + */ + public function getFixers() + { + $this->fixers = Utils::sortFixers($this->fixers); + + return $this->fixers; + } + + /** + * @return $this + */ + public function registerBuiltInFixers() + { + static $builtInFixers = null; + + if (null === $builtInFixers) { + $builtInFixers = []; + + /** @var SplFileInfo $file */ + foreach (SymfonyFinder::create()->files()->in(__DIR__.'/Fixer')->depth(1) as $file) { + $relativeNamespace = $file->getRelativePath(); + $fixerClass = 'PhpCsFixer\\Fixer\\'.($relativeNamespace ? $relativeNamespace.'\\' : '').$file->getBasename('.php'); + if ('Fixer' === substr($fixerClass, -5)) { + $builtInFixers[] = $fixerClass; + } + } + } + + foreach ($builtInFixers as $class) { + $this->registerFixer(new $class(), false); + } + + return $this; + } + + /** + * @param FixerInterface[] $fixers + * + * @return $this + */ + public function registerCustomFixers(array $fixers) + { + foreach ($fixers as $fixer) { + $this->registerFixer($fixer, true); + } + + return $this; + } + + /** + * @param bool $isCustom + * + * @return $this + */ + public function registerFixer(FixerInterface $fixer, $isCustom) + { + $name = $fixer->getName(); + + if (isset($this->fixersByName[$name])) { + throw new \UnexpectedValueException(sprintf('Fixer named "%s" is already registered.', $name)); + } + + if (!$this->nameValidator->isValid($name, $isCustom)) { + throw new \UnexpectedValueException(sprintf('Fixer named "%s" has invalid name.', $name)); + } + + $this->fixers[] = $fixer; + $this->fixersByName[$name] = $fixer; + + return $this; + } + + /** + * Apply RuleSet on fixers to filter out all unwanted fixers. + * + * @return $this + */ + public function useRuleSet(RuleSetInterface $ruleSet) + { + $fixers = []; + $fixersByName = []; + $fixerConflicts = []; + + $fixerNames = array_keys($ruleSet->getRules()); + foreach ($fixerNames as $name) { + if (!\array_key_exists($name, $this->fixersByName)) { + throw new \UnexpectedValueException(sprintf('Rule "%s" does not exist.', $name)); + } + + $fixer = $this->fixersByName[$name]; + + $config = $ruleSet->getRuleConfiguration($name); + if (null !== $config) { + if ($fixer instanceof ConfigurableFixerInterface) { + if (!\is_array($config) || !\count($config)) { + throw new InvalidFixerConfigurationException($fixer->getName(), 'Configuration must be an array and may not be empty.'); + } + + $fixer->configure($config); + } else { + throw new InvalidFixerConfigurationException($fixer->getName(), 'Is not configurable.'); + } + } + + $fixers[] = $fixer; + $fixersByName[$name] = $fixer; + + $conflicts = array_intersect($this->getFixersConflicts($fixer), $fixerNames); + if (\count($conflicts) > 0) { + $fixerConflicts[$name] = $conflicts; + } + } + + if (\count($fixerConflicts) > 0) { + throw new \UnexpectedValueException($this->generateConflictMessage($fixerConflicts)); + } + + $this->fixers = $fixers; + $this->fixersByName = $fixersByName; + + return $this; + } + + /** + * Check if fixer exists. + * + * @param string $name + * + * @return bool + */ + public function hasRule($name) + { + return isset($this->fixersByName[$name]); + } + + /** + * @return null|string[] + */ + private function getFixersConflicts(FixerInterface $fixer) + { + static $conflictMap = [ + 'no_blank_lines_before_namespace' => ['single_blank_line_before_namespace'], + 'single_import_per_statement' => ['group_import'], + ]; + + $fixerName = $fixer->getName(); + + return \array_key_exists($fixerName, $conflictMap) ? $conflictMap[$fixerName] : []; + } + + /** + * @param array<string, string[]> $fixerConflicts + * + * @return string + */ + private function generateConflictMessage(array $fixerConflicts) + { + $message = 'Rule contains conflicting fixers:'; + $report = []; + foreach ($fixerConflicts as $fixer => $fixers) { + // filter mutual conflicts + $report[$fixer] = array_filter( + $fixers, + static function ($candidate) use ($report, $fixer) { + return !\array_key_exists($candidate, $report) || !\in_array($fixer, $report[$candidate], true); + } + ); + + if (\count($report[$fixer]) > 0) { + $message .= sprintf("\n- \"%s\" with \"%s\"", $fixer, implode('", "', $report[$fixer])); + } + } + + return $message; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerFileProcessedEvent.php b/vendor/friendsofphp/php-cs-fixer/src/FixerFileProcessedEvent.php new file mode 100644 index 0000000..1fafb70 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerFileProcessedEvent.php @@ -0,0 +1,59 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Event\Event; + +/** + * Event that is fired when file was processed by Fixer. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FixerFileProcessedEvent extends Event +{ + /** + * Event name. + */ + const NAME = 'fixer.file_processed'; + + const STATUS_UNKNOWN = 0; + const STATUS_INVALID = 1; + const STATUS_SKIPPED = 2; + const STATUS_NO_CHANGES = 3; + const STATUS_FIXED = 4; + const STATUS_EXCEPTION = 5; + const STATUS_LINT = 6; + + /** + * @var int + */ + private $status; + + /** + * @param int $status + */ + public function __construct($status) + { + $this->status = $status; + } + + /** + * @return int + */ + public function getStatus() + { + return $this->status; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/FixerNameValidator.php b/vendor/friendsofphp/php-cs-fixer/src/FixerNameValidator.php new file mode 100644 index 0000000..bfa4477 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/FixerNameValidator.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FixerNameValidator +{ + /** + * @param string $name + * @param bool $isCustom + * + * @return bool + */ + public function isValid($name, $isCustom) + { + if (!$isCustom) { + return 1 === Preg::match('/^[a-z][a-z0-9_]*$/', $name); + } + + return 1 === Preg::match('/^[A-Z][a-zA-Z0-9]*\/[a-z][a-z0-9_]*$/', $name); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Indicator/PhpUnitTestCaseIndicator.php b/vendor/friendsofphp/php-cs-fixer/src/Indicator/PhpUnitTestCaseIndicator.php new file mode 100644 index 0000000..4589fce --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Indicator/PhpUnitTestCaseIndicator.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Indicator; + +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +final class PhpUnitTestCaseIndicator +{ + public function isPhpUnitClass(Tokens $tokens, $index) + { + if (!$tokens[$index]->isGivenKind(T_CLASS)) { + throw new \LogicException(sprintf('No "T_CLASS" at given index %d, got "%s".', $index, $tokens[$index]->getName())); + } + + $index = $tokens->getNextMeaningfulToken($index); + if (0 !== Preg::match('/(?:Test|TestCase)$/', $tokens[$index]->getContent())) { + return true; + } + + while (null !== $index = $tokens->getNextMeaningfulToken($index)) { + if ($tokens[$index]->equals('{')) { + break; // end of class signature + } + + if (!$tokens[$index]->isGivenKind(T_STRING)) { + continue; // not part of extends nor part of implements; so continue + } + + if (0 !== Preg::match('/(?:Test|TestCase)(?:Interface)?$/', $tokens[$index]->getContent())) { + return true; + } + } + + return false; + } + + /** + * @return \Generator array of [int start, int end] indexes from sooner to later classes + */ + public function findPhpUnitClasses(Tokens $tokens) + { + for ($index = $tokens->count() - 1; $tokens->offsetExists($index); --$index) { + if (!$tokens[$index]->isGivenKind(T_CLASS) || !$this->isPhpUnitClass($tokens, $index)) { + continue; + } + + $startIndex = $tokens->getNextTokenOfKind($index, ['{'], false); + + if (null === $startIndex) { + return; + } + + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $startIndex); + yield [$startIndex, $endIndex]; + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/CachingLinter.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/CachingLinter.php new file mode 100644 index 0000000..9367cf0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/CachingLinter.php @@ -0,0 +1,72 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class CachingLinter implements LinterInterface +{ + /** + * @var LinterInterface + */ + private $sublinter; + + /** + * @var array<int, LintingResultInterface> + */ + private $cache = []; + + public function __construct(LinterInterface $linter) + { + $this->sublinter = $linter; + } + + /** + * {@inheritdoc} + */ + public function isAsync() + { + return $this->sublinter->isAsync(); + } + + /** + * {@inheritdoc} + */ + public function lintFile($path) + { + $checksum = crc32(file_get_contents($path)); + + if (!isset($this->cache[$checksum])) { + $this->cache[$checksum] = $this->sublinter->lintFile($path); + } + + return $this->cache[$checksum]; + } + + /** + * {@inheritdoc} + */ + public function lintSource($source) + { + $checksum = crc32($source); + + if (!isset($this->cache[$checksum])) { + $this->cache[$checksum] = $this->sublinter->lintSource($source); + } + + return $this->cache[$checksum]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/Linter.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/Linter.php new file mode 100644 index 0000000..199eacc --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/Linter.php @@ -0,0 +1,64 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +/** + * Handle PHP code linting process. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class Linter implements LinterInterface +{ + /** + * @var LinterInterface + */ + private $sublinter; + + /** + * @param null|string $executable PHP executable, null for autodetection + */ + public function __construct($executable = null) + { + try { + $this->sublinter = new TokenizerLinter(); + } catch (UnavailableLinterException $e) { + $this->sublinter = new ProcessLinter($executable); + } + } + + /** + * {@inheritdoc} + */ + public function isAsync() + { + return $this->sublinter->isAsync(); + } + + /** + * {@inheritdoc} + */ + public function lintFile($path) + { + return $this->sublinter->lintFile($path); + } + + /** + * {@inheritdoc} + */ + public function lintSource($source) + { + return $this->sublinter->lintSource($source); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/LinterInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/LinterInterface.php new file mode 100644 index 0000000..efaa2a4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/LinterInterface.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +/** + * Interface for PHP code linting process manager. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +interface LinterInterface +{ + /** + * @return bool + */ + public function isAsync(); + + /** + * Lint PHP file. + * + * @param string $path + * + * @return LintingResultInterface + */ + public function lintFile($path); + + /** + * Lint PHP code. + * + * @param string $source + * + * @return LintingResultInterface + */ + public function lintSource($source); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/LintingException.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/LintingException.php new file mode 100644 index 0000000..7ce51fe --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/LintingException.php @@ -0,0 +1,20 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +class LintingException extends \RuntimeException +{ +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/LintingResultInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/LintingResultInterface.php new file mode 100644 index 0000000..75f56a1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/LintingResultInterface.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +interface LintingResultInterface +{ + /** + * Check if linting process was successful and raise LintingException if not. + */ + public function check(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLinter.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLinter.php new file mode 100644 index 0000000..1f0f3c4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLinter.php @@ -0,0 +1,171 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +use PhpCsFixer\FileReader; +use PhpCsFixer\FileRemoval; +use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Process\PhpExecutableFinder; +use Symfony\Component\Process\Process; + +/** + * Handle PHP code linting using separated process of `php -l _file_`. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ProcessLinter implements LinterInterface +{ + /** + * @var FileRemoval + */ + private $fileRemoval; + + /** + * @var ProcessLinterProcessBuilder + */ + private $processBuilder; + + /** + * Temporary file for code linting. + * + * @var null|string + */ + private $temporaryFile; + + /** + * @param null|string $executable PHP executable, null for autodetection + */ + public function __construct($executable = null) + { + if (null === $executable) { + $executableFinder = new PhpExecutableFinder(); + $executable = $executableFinder->find(false); + + if (false === $executable) { + throw new UnavailableLinterException('Cannot find PHP executable.'); + } + + if ('phpdbg' === \PHP_SAPI) { + if (false === strpos($executable, 'phpdbg')) { + throw new UnavailableLinterException('Automatically found PHP executable is non-standard phpdbg. Could not find proper PHP executable.'); + } + + // automatically found executable is `phpdbg`, let us try to fallback to regular `php` + $executable = str_replace('phpdbg', 'php', $executable); + + if (!is_executable($executable)) { + throw new UnavailableLinterException('Automatically found PHP executable is phpdbg. Could not find proper PHP executable.'); + } + } + } + + $this->processBuilder = new ProcessLinterProcessBuilder($executable); + + $this->fileRemoval = new FileRemoval(); + } + + public function __destruct() + { + if (null !== $this->temporaryFile) { + $this->fileRemoval->delete($this->temporaryFile); + } + } + + /** + * This class is not intended to be serialized, + * and cannot be deserialized (see __wakeup method). + * + * @return array + */ + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + /** + * Disable the deserialization of the class to prevent attacker executing + * code by leveraging the __destruct method. + * + * @see https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection + */ + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + /** + * {@inheritdoc} + */ + public function isAsync() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function lintFile($path) + { + return new ProcessLintingResult($this->createProcessForFile($path), $path); + } + + /** + * {@inheritdoc} + */ + public function lintSource($source) + { + return new ProcessLintingResult($this->createProcessForSource($source), $this->temporaryFile); + } + + /** + * @param string $path path to file + * + * @return Process + */ + private function createProcessForFile($path) + { + // in case php://stdin + if (!is_file($path)) { + return $this->createProcessForSource(FileReader::createSingleton()->read($path)); + } + + $process = $this->processBuilder->build($path); + $process->setTimeout(10); + $process->start(); + + return $process; + } + + /** + * Create process that lint PHP code. + * + * @param string $source code + * + * @return Process + */ + private function createProcessForSource($source) + { + if (null === $this->temporaryFile) { + $this->temporaryFile = tempnam(sys_get_temp_dir(), 'cs_fixer_tmp_'); + $this->fileRemoval->observe($this->temporaryFile); + } + + if (false === @file_put_contents($this->temporaryFile, $source)) { + throw new IOException(sprintf('Failed to write file "%s".', $this->temporaryFile), 0, null, $this->temporaryFile); + } + + return $this->createProcessForFile($this->temporaryFile); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLinterProcessBuilder.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLinterProcessBuilder.php new file mode 100644 index 0000000..5cce9e1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLinterProcessBuilder.php @@ -0,0 +1,50 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +use Symfony\Component\Process\Process; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ProcessLinterProcessBuilder +{ + /** + * @var string + */ + private $executable; + + /** + * @param string $executable PHP executable + */ + public function __construct($executable) + { + $this->executable = $executable; + } + + /** + * @param string $path + * + * @return Process + */ + public function build($path) + { + return new Process([ + $this->executable, + '-l', + $path, + ]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLintingResult.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLintingResult.php new file mode 100644 index 0000000..35573bb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/ProcessLintingResult.php @@ -0,0 +1,98 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +use Symfony\Component\Process\Process; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ProcessLintingResult implements LintingResultInterface +{ + /** + * @var bool + */ + private $isSuccessful; + + /** + * @var Process + */ + private $process; + + /** + * @var null|string + */ + private $path; + + /** + * @param null|string $path + */ + public function __construct(Process $process, $path = null) + { + $this->process = $process; + $this->path = $path; + } + + /** + * {@inheritdoc} + */ + public function check() + { + if (!$this->isSuccessful()) { + // on some systems stderr is used, but on others, it's not + throw new LintingException($this->getProcessErrorMessage(), $this->process->getExitCode()); + } + } + + private function getProcessErrorMessage() + { + $output = strtok(ltrim($this->process->getErrorOutput() ?: $this->process->getOutput()), "\n"); + + if (false === $output) { + return 'Fatal error: Unable to lint file.'; + } + + if (null !== $this->path) { + $needle = sprintf('in %s ', $this->path); + $pos = strrpos($output, $needle); + + if (false !== $pos) { + $output = sprintf('%s%s', substr($output, 0, $pos), substr($output, $pos + \strlen($needle))); + } + } + + $prefix = substr($output, 0, 18); + + if ('PHP Parse error: ' === $prefix) { + return sprintf('Parse error: %s.', substr($output, 18)); + } + + if ('PHP Fatal error: ' === $prefix) { + return sprintf('Fatal error: %s.', substr($output, 18)); + } + + return sprintf('%s.', $output); + } + + private function isSuccessful() + { + if (null === $this->isSuccessful) { + $this->process->wait(); + $this->isSuccessful = $this->process->isSuccessful(); + } + + return $this->isSuccessful; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/TokenizerLinter.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/TokenizerLinter.php new file mode 100644 index 0000000..28d2ff2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/TokenizerLinter.php @@ -0,0 +1,77 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +use PhpCsFixer\FileReader; +use PhpCsFixer\Tokenizer\CodeHasher; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Handle PHP code linting. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class TokenizerLinter implements LinterInterface +{ + public function __construct() + { + if ( + // @TODO: drop condition when PHP 7.0+ is required + false === \defined('TOKEN_PARSE') + // @TODO: drop condition when PHP 7.3+ is required + || false === class_exists(\CompileError::class) + ) { + throw new UnavailableLinterException('Cannot use tokenizer as linter.'); + } + } + + /** + * {@inheritdoc} + */ + public function isAsync() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function lintFile($path) + { + return $this->lintSource(FileReader::createSingleton()->read($path)); + } + + /** + * {@inheritdoc} + */ + public function lintSource($source) + { + try { + // To lint, we will parse the source into Tokens. + // During that process, it might throw a ParseError or CompileError. + // If it won't, cache of tokenized version of source will be kept, which is great for Runner. + // Yet, first we need to clear already existing cache to not hit it and lint the code indeed. + $codeHash = CodeHasher::calculateCodeHash($source); + Tokens::clearCache($codeHash); + Tokens::fromCode($source); + + return new TokenizerLintingResult(); + } catch (\ParseError $e) { + return new TokenizerLintingResult($e); + } catch (\CompileError $e) { + return new TokenizerLintingResult($e); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/TokenizerLintingResult.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/TokenizerLintingResult.php new file mode 100644 index 0000000..399f1ff --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/TokenizerLintingResult.php @@ -0,0 +1,50 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class TokenizerLintingResult implements LintingResultInterface +{ + /** + * @var null|\Error + */ + private $error; + + public function __construct(\Error $error = null) + { + $this->error = $error; + } + + /** + * {@inheritdoc} + */ + public function check() + { + if (null !== $this->error) { + throw new LintingException( + sprintf('%s: %s on line %d.', $this->getMessagePrefix(), $this->error->getMessage(), $this->error->getLine()), + $this->error->getCode(), + $this->error + ); + } + } + + private function getMessagePrefix() + { + return $this->error instanceof \ParseError ? 'Parse error' : 'Fatal error'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Linter/UnavailableLinterException.php b/vendor/friendsofphp/php-cs-fixer/src/Linter/UnavailableLinterException.php new file mode 100644 index 0000000..6e8cd63 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Linter/UnavailableLinterException.php @@ -0,0 +1,22 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Linter; + +/** + * Exception that is thrown when the chosen linter is not available on the environment. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +class UnavailableLinterException extends \RuntimeException +{ +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/PharChecker.php b/vendor/friendsofphp/php-cs-fixer/src/PharChecker.php new file mode 100644 index 0000000..81fae9f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/PharChecker.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * @internal + */ +final class PharChecker implements PharCheckerInterface +{ + /** + * {@inheritdoc} + */ + public function checkFileValidity($filename) + { + try { + $phar = new \Phar($filename); + // free the variable to unlock the file + unset($phar); + } catch (\Exception $e) { + if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) { + throw $e; + } + + return 'Failed to create Phar instance. '.$e->getMessage(); + } + + return null; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/PharCheckerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/PharCheckerInterface.php new file mode 100644 index 0000000..8de1395 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/PharCheckerInterface.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * @internal + */ +interface PharCheckerInterface +{ + /** + * @param string $filename + * + * @return null|string the invalidity reason if any, null otherwise + */ + public function checkFileValidity($filename); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Preg.php b/vendor/friendsofphp/php-cs-fixer/src/Preg.php new file mode 100644 index 0000000..d4161ad --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Preg.php @@ -0,0 +1,233 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * This class replaces preg_* functions to better handling UTF8 strings, + * ensuring no matter "u" modifier is present or absent subject will be handled correctly. + * + * @author Kuba Werłos <werlos@gmail.com> + * + * @internal + */ +final class Preg +{ + /** + * @param string $pattern + * @param string $subject + * @param null|string[] $matches + * @param int $flags + * @param int $offset + * + * @throws PregException + * + * @return int + */ + public static function match($pattern, $subject, &$matches = null, $flags = 0, $offset = 0) + { + $result = @preg_match(self::addUtf8Modifier($pattern), $subject, $matches, $flags, $offset); + if (false !== $result && PREG_NO_ERROR === preg_last_error()) { + return $result; + } + + $result = @preg_match(self::removeUtf8Modifier($pattern), $subject, $matches, $flags, $offset); + if (false !== $result && PREG_NO_ERROR === preg_last_error()) { + return $result; + } + + throw self::newPregException(preg_last_error(), __METHOD__, (array) $pattern); + } + + /** + * @param string $pattern + * @param string $subject + * @param null|string[] $matches + * @param int $flags + * @param int $offset + * + * @throws PregException + * + * @return int + */ + public static function matchAll($pattern, $subject, &$matches = null, $flags = PREG_PATTERN_ORDER, $offset = 0) + { + $result = @preg_match_all(self::addUtf8Modifier($pattern), $subject, $matches, $flags, $offset); + if (false !== $result && PREG_NO_ERROR === preg_last_error()) { + return $result; + } + + $result = @preg_match_all(self::removeUtf8Modifier($pattern), $subject, $matches, $flags, $offset); + if (false !== $result && PREG_NO_ERROR === preg_last_error()) { + return $result; + } + + throw self::newPregException(preg_last_error(), __METHOD__, (array) $pattern); + } + + /** + * @param string|string[] $pattern + * @param string|string[] $replacement + * @param string|string[] $subject + * @param int $limit + * @param null|int $count + * + * @throws PregException + * + * @return string|string[] + */ + public static function replace($pattern, $replacement, $subject, $limit = -1, &$count = null) + { + $result = @preg_replace(self::addUtf8Modifier($pattern), $replacement, $subject, $limit, $count); + if (null !== $result && PREG_NO_ERROR === preg_last_error()) { + return $result; + } + + $result = @preg_replace(self::removeUtf8Modifier($pattern), $replacement, $subject, $limit, $count); + if (null !== $result && PREG_NO_ERROR === preg_last_error()) { + return $result; + } + + throw self::newPregException(preg_last_error(), __METHOD__, (array) $pattern); + } + + /** + * @param string|string[] $pattern + * @param callable $callback + * @param string|string[] $subject + * @param int $limit + * @param null|int $count + * + * @throws PregException + * + * @return string|string[] + */ + public static function replaceCallback($pattern, $callback, $subject, $limit = -1, &$count = null) + { + $result = @preg_replace_callback(self::addUtf8Modifier($pattern), $callback, $subject, $limit, $count); + if (null !== $result && PREG_NO_ERROR === preg_last_error()) { + return $result; + } + + $result = @preg_replace_callback(self::removeUtf8Modifier($pattern), $callback, $subject, $limit, $count); + if (null !== $result && PREG_NO_ERROR === preg_last_error()) { + return $result; + } + + throw self::newPregException(preg_last_error(), __METHOD__, (array) $pattern); + } + + /** + * @param string $pattern + * @param string $subject + * @param int $limit + * @param int $flags + * + * @throws PregException + * + * @return string[] + */ + public static function split($pattern, $subject, $limit = -1, $flags = 0) + { + $result = @preg_split(self::addUtf8Modifier($pattern), $subject, $limit, $flags); + if (false !== $result && PREG_NO_ERROR === preg_last_error()) { + return $result; + } + + $result = @preg_split(self::removeUtf8Modifier($pattern), $subject, $limit, $flags); + if (false !== $result && PREG_NO_ERROR === preg_last_error()) { + return $result; + } + + throw self::newPregException(preg_last_error(), __METHOD__, (array) $pattern); + } + + /** + * @param string|string[] $pattern + * + * @return string|string[] + */ + private static function addUtf8Modifier($pattern) + { + if (\is_array($pattern)) { + return array_map(__METHOD__, $pattern); + } + + return $pattern.'u'; + } + + /** + * @param string|string[] $pattern + * + * @return string|string[] + */ + private static function removeUtf8Modifier($pattern) + { + if (\is_array($pattern)) { + return array_map(__METHOD__, $pattern); + } + + if ('' === $pattern) { + return ''; + } + + $delimiter = $pattern[0]; + + $endDelimiterPosition = strrpos($pattern, $delimiter); + + return substr($pattern, 0, $endDelimiterPosition).str_replace('u', '', substr($pattern, $endDelimiterPosition)); + } + + /** + * Create PregException. + * + * Create the generic PregException message and if possible due to finding + * an invalid pattern, tell more about such kind of error in the message. + * + * @param int $error + * @param string $method + * @param string[] $patterns + * + * @return PregException + */ + private static function newPregException($error, $method, array $patterns) + { + foreach ($patterns as $pattern) { + $last = error_get_last(); + $result = @preg_match($pattern, ''); + + if (false !== $result) { + continue; + } + + $code = preg_last_error(); + $next = error_get_last(); + + if ($last !== $next) { + $message = sprintf( + '(code: %d) %s', + $code, + preg_replace('~preg_[a-z_]+[()]{2}: ~', '', $next['message']) + ); + } else { + $message = sprintf('(code: %d)', $code); + } + + return new PregException( + sprintf('%s(): Invalid PCRE pattern "%s": %s (version: %s)', $method, $pattern, $message, PCRE_VERSION), + $code + ); + } + + return new PregException(sprintf('Error occurred when calling %s.', $method), $error); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/PregException.php b/vendor/friendsofphp/php-cs-fixer/src/PregException.php new file mode 100644 index 0000000..79ff1e0 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/PregException.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * Exception that is thrown when PCRE function encounters an error. + * + * @author Kuba Werłos <werlos@gmail.com> + * + * @internal + */ +final class PregException extends \RuntimeException +{ +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet.php new file mode 100644 index 0000000..8d86b33 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * Set of rules to be used by fixer. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + * + * @internal + * + * @deprecated will be removed in 3.0, use \PhpCsFixer\RuleSet\RuleSet + */ +final class RuleSet extends RuleSet\RuleSet +{ +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/AbstractRuleSetDescription.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/AbstractRuleSetDescription.php new file mode 100644 index 0000000..fe95e04 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/AbstractRuleSetDescription.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet; + +/** + * @internal + */ +abstract class AbstractRuleSetDescription implements RuleSetDescriptionInterface +{ + public function __construct() + { + } + + public function getName() + { + $name = substr(static::class, 1 + strrpos(static::class, '\\'), -3); + + return '@'.str_replace('Risky', ':risky', $name); + } + + public function isRisky() + { + return false !== strpos(static::class, 'Risky'); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSet.php new file mode 100644 index 0000000..25f82b9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSet.php @@ -0,0 +1,184 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet; + +use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; +use PhpCsFixer\Utils; + +/** + * Set of rules to be used by fixer. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + * + * @internal + * @final + * + * TODO on 3.0 make final after PhpCsFixer\RuleSet has been removed + */ +class RuleSet implements RuleSetInterface +{ + /** + * Group of rules generated from input set. + * + * The key is name of rule, value is bool if the rule/set should be used. + * The key must not point to any set. + * + * @var array + */ + private $rules; + + public function __construct(array $set = []) + { + foreach ($set as $name => $value) { + if ('' === $name) { + throw new \InvalidArgumentException('Rule/set name must not be empty.'); + } + + if (\is_int($name)) { + throw new \InvalidArgumentException(sprintf('Missing value for "%s" rule/set.', $value)); + } + + if (!\is_bool($value) && !\is_array($value)) { + // @TODO drop me on 3.0 + if (null === $value) { + Utils::triggerDeprecation(new InvalidFixerConfigurationException( + $name, + 'To disable the rule, use "FALSE" instead of "NULL".' + )); + + continue; + } + + $message = '@' === $name[0] ? 'Set must be enabled (true) or disabled (false). Other values are not allowed.' : 'Rule must be enabled (true), disabled (false) or configured (non-empty, assoc array). Other values are not allowed.'; + + throw new InvalidFixerConfigurationException($name, $message); + } + } + + $this->resolveSet($set); + } + + /** + * {@inheritdoc} + */ + public function hasRule($rule) + { + return \array_key_exists($rule, $this->rules); + } + + /** + * {@inheritdoc} + */ + public function getRuleConfiguration($rule) + { + if (!$this->hasRule($rule)) { + throw new \InvalidArgumentException(sprintf('Rule "%s" is not in the set.', $rule)); + } + + if (true === $this->rules[$rule]) { + return null; + } + + return $this->rules[$rule]; + } + + /** + * {@inheritdoc} + */ + public function getRules() + { + return $this->rules; + } + + /** + * @deprecated will be removed in 3.0 Use the constructor. + */ + public static function create(array $set = []) + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated and will be removed in 3.0, use the constructor.')); + + return new self($set); + } + + /** + * @deprecated will be removed in 3.0 Use PhpCsFixer\RuleSet\RuleSets::getSetDefinitionNames + */ + public function getSetDefinitionNames() + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated and will be removed in 3.0, use PhpCsFixer\RuleSet\RuleSets::getSetDefinitionNames.')); + + return RuleSets::getSetDefinitionNames(); + } + + /** + * Resolve input set into group of rules. + * + * @return $this + */ + private function resolveSet(array $rules) + { + $resolvedRules = []; + + // expand sets + foreach ($rules as $name => $value) { + if ('@' === $name[0]) { + if (!\is_bool($value)) { + throw new \UnexpectedValueException(sprintf('Nested rule set "%s" configuration must be a boolean.', $name)); + } + + $set = $this->resolveSubset($name, $value); + $resolvedRules = array_merge($resolvedRules, $set); + } else { + $resolvedRules[$name] = $value; + } + } + + // filter out all resolvedRules that are off + $resolvedRules = array_filter($resolvedRules); + + $this->rules = $resolvedRules; + + return $this; + } + + /** + * Resolve set rules as part of another set. + * + * If set value is false then disable all fixers in set, + * if not then get value from set item. + * + * @param string $setName + * @param bool $setValue + * + * @return array + */ + private function resolveSubset($setName, $setValue) + { + $rules = RuleSets::getSetDefinition($setName)->getRules(); + + foreach ($rules as $name => $value) { + if ('@' === $name[0]) { + $set = $this->resolveSubset($name, $setValue); + unset($rules[$name]); + $rules = array_merge($rules, $set); + } elseif (!$setValue) { + $rules[$name] = false; + } else { + $rules[$name] = $value; + } + } + + return $rules; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSetDescriptionInterface.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSetDescriptionInterface.php new file mode 100644 index 0000000..bb52ecb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSetDescriptionInterface.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet; + +/** + * @author SpacePossum + * + * @internal + */ +interface RuleSetDescriptionInterface +{ + public function __construct(); + + /** + * @return string + */ + public function getDescription(); + + /** + * @return string + */ + public function getName(); + + /** + * Get all rules from rules set. + * + * @return array + */ + public function getRules(); + + /** + * @return bool + */ + public function isRisky(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSetInterface.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSetInterface.php new file mode 100644 index 0000000..6d73ac5 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSetInterface.php @@ -0,0 +1,60 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet; + +/** + * Set of rules to be used by fixer. + * + * Example of set: ["@PSR2" => true, "@PSR1" => false, "strict" => true]. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +interface RuleSetInterface +{ + public function __construct(array $set = []); + + /** + * Get configuration for given rule. + * + * @param string $rule name of rule + * + * @return null|array + */ + public function getRuleConfiguration($rule); + + /** + * Get all rules from rules set. + * + * @return array + */ + public function getRules(); + + /** + * Check given rule is in rules set. + * + * @param string $rule name of rule + * + * @return bool + */ + public function hasRule($rule); + + /** + * @deprecated will be removed in 3.0 Use the constructor. + */ + public static function create(array $set = []); + + /** + * @deprecated will be removed in 3.0 Use PhpCsFixer\RuleSet\RuleSets::getSetDefinitionNames + */ + public function getSetDefinitionNames(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSets.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSets.php new file mode 100644 index 0000000..dbd5268 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/RuleSets.php @@ -0,0 +1,72 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet; + +use Symfony\Component\Finder\Finder; + +/** + * Set of rule sets to be used by fixer. + * + * @author SpacePossum + * + * @internal + */ +final class RuleSets +{ + private static $setDefinitions; + + /** + * @return array<string, RuleSetDescriptionInterface> + */ + public static function getSetDefinitions() + { + if (null === self::$setDefinitions) { + self::$setDefinitions = []; + + foreach (Finder::create()->files()->in(__DIR__.'/Sets') as $file) { + $class = 'PhpCsFixer\RuleSet\Sets\\'.$file->getBasename('.php'); + $set = new $class(); + + self::$setDefinitions[$set->getName()] = $set; + } + + ksort(self::$setDefinitions); + } + + return self::$setDefinitions; + } + + /** + * @return string[] + */ + public static function getSetDefinitionNames() + { + return array_keys(self::getSetDefinitions()); + } + + /** + * @param string $name + * + * @return RuleSetDescriptionInterface + */ + public static function getSetDefinition($name) + { + $definitions = self::getSetDefinitions(); + + if (!isset($definitions[$name])) { + throw new \InvalidArgumentException(sprintf('Set "%s" does not exist.', $name)); + } + + return $definitions[$name]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/DoctrineAnnotationSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/DoctrineAnnotationSet.php new file mode 100644 index 0000000..d3c6fdb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/DoctrineAnnotationSet.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class DoctrineAnnotationSet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + 'doctrine_annotation_array_assignment' => [ + 'operator' => ':', + ], + 'doctrine_annotation_braces' => true, + 'doctrine_annotation_indentation' => true, + 'doctrine_annotation_spaces' => [ + 'before_array_assignments_colon' => false, + ], + ]; + } + + public function getDescription() + { + return 'Rules covering Doctrine annotations with configuration based on examples found in `Doctrine Annotation documentation <http://docs.doctrine-project.org/projects/doctrine-common/en/latest/reference/annotations.html>`_ and `Symfony documentation <http://symfony.com/doc/master/bundles/SensioFrameworkExtraBundle/annotations/routing.html>`_.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP54MigrationSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP54MigrationSet.php new file mode 100644 index 0000000..c99de54 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP54MigrationSet.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP54MigrationSet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + 'array_syntax' => ['syntax' => 'short'], + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 5.4 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP56MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP56MigrationRiskySet.php new file mode 100644 index 0000000..d682e5c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP56MigrationRiskySet.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP56MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + 'pow_to_exponentiation' => true, + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 5.6 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP56MigrationSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP56MigrationSet.php new file mode 100644 index 0000000..3cc1ba9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP56MigrationSet.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP56MigrationSet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHP54Migration' => true, + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 5.6 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP70MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP70MigrationRiskySet.php new file mode 100644 index 0000000..5b0490b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP70MigrationRiskySet.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP70MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHP56Migration:risky' => true, + 'combine_nested_dirname' => true, + 'declare_strict_types' => true, + 'non_printable_character' => [ + 'use_escape_sequences_in_strings' => true, + ], + 'random_api_migration' => [ + 'replacements' => [ + 'mt_rand' => 'random_int', + 'rand' => 'random_int', + ], + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 7.0 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP70MigrationSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP70MigrationSet.php new file mode 100644 index 0000000..2bb3f8b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP70MigrationSet.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP70MigrationSet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHP56Migration' => true, + 'ternary_to_null_coalescing' => true, + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 7.0 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP71MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP71MigrationRiskySet.php new file mode 100644 index 0000000..36b0574 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP71MigrationRiskySet.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP71MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHP70Migration:risky' => true, + 'void_return' => true, + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 7.1 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP71MigrationSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP71MigrationSet.php new file mode 100644 index 0000000..7945b31 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP71MigrationSet.php @@ -0,0 +1,41 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP71MigrationSet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHP70Migration' => true, + 'list_syntax' => ['syntax' => 'short'], + 'visibility_required' => [ + 'elements' => [ + 'const', + 'method', + 'property', + ], + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 7.1 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP73MigrationSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP73MigrationSet.php new file mode 100644 index 0000000..05b2e9b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP73MigrationSet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP73MigrationSet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHP71Migration' => true, + 'heredoc_indentation' => true, + 'method_argument_space' => ['after_heredoc' => true], + 'no_whitespace_before_comma_in_array' => ['after_heredoc' => true], + 'trailing_comma_in_multiline' => ['after_heredoc' => true], + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 7.3 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP74MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP74MigrationRiskySet.php new file mode 100644 index 0000000..26b40cf --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP74MigrationRiskySet.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP74MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHP71Migration:risky' => true, + 'implode_call' => true, + 'no_alias_functions' => true, + 'use_arrow_functions' => true, + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 7.4 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP74MigrationSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP74MigrationSet.php new file mode 100644 index 0000000..d908aa9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP74MigrationSet.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP74MigrationSet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHP73Migration' => true, + 'normalize_index_brace' => true, + 'short_scalar_cast' => true, + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 7.4 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP80MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP80MigrationRiskySet.php new file mode 100644 index 0000000..5d35a3b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP80MigrationRiskySet.php @@ -0,0 +1,41 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP80MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHP74Migration:risky' => true, + 'no_alias_functions' => [ + 'sets' => [ + '@all', + ], + ], + 'no_php4_constructor' => true, + 'no_unneeded_final_method' => true, // final private method (not constructor) are no longer allowed >= PHP8.0 + 'no_unreachable_default_argument_value' => true, + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 8.0 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP80MigrationSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP80MigrationSet.php new file mode 100644 index 0000000..7e909ea --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHP80MigrationSet.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHP80MigrationSet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHP74Migration' => true, + 'clean_namespace' => true, + 'no_unset_cast' => true, + ]; + } + + public function getDescription() + { + return 'Rules to improve code for PHP 8.0 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit30MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit30MigrationRiskySet.php new file mode 100644 index 0000000..aa361be --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit30MigrationRiskySet.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit30MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + 'php_unit_dedicate_assert' => [ + 'target' => PhpUnitTargetVersion::VERSION_3_0, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 3.0 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit32MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit32MigrationRiskySet.php new file mode 100644 index 0000000..5a9d9f8 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit32MigrationRiskySet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit32MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit30Migration:risky' => true, + 'php_unit_no_expectation_annotation' => [ + 'target' => PhpUnitTargetVersion::VERSION_3_2, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 3.2 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit35MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit35MigrationRiskySet.php new file mode 100644 index 0000000..3e0e6fb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit35MigrationRiskySet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit35MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit32Migration:risky' => true, + 'php_unit_dedicate_assert' => [ + 'target' => PhpUnitTargetVersion::VERSION_3_5, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 3.5 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit43MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit43MigrationRiskySet.php new file mode 100644 index 0000000..2fa2556 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit43MigrationRiskySet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit43MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit35Migration:risky' => true, + 'php_unit_no_expectation_annotation' => [ + 'target' => PhpUnitTargetVersion::VERSION_4_3, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 4.3 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit48MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit48MigrationRiskySet.php new file mode 100644 index 0000000..959ed02 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit48MigrationRiskySet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit48MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit43Migration:risky' => true, + 'php_unit_namespaced' => [ + 'target' => PhpUnitTargetVersion::VERSION_4_8, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 4.8 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit50MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit50MigrationRiskySet.php new file mode 100644 index 0000000..906e282 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit50MigrationRiskySet.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit50MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit48Migration:risky' => true, + 'php_unit_dedicate_assert' => true, + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 5.0 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit52MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit52MigrationRiskySet.php new file mode 100644 index 0000000..390eb18 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit52MigrationRiskySet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit52MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit50Migration:risky' => true, + 'php_unit_expectation' => [ + 'target' => PhpUnitTargetVersion::VERSION_5_2, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 5.2 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit54MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit54MigrationRiskySet.php new file mode 100644 index 0000000..8f6efd2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit54MigrationRiskySet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit54MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit52Migration:risky' => true, + 'php_unit_mock' => [ + 'target' => PhpUnitTargetVersion::VERSION_5_4, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 5.4 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit55MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit55MigrationRiskySet.php new file mode 100644 index 0000000..4e9de44 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit55MigrationRiskySet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit55MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit54Migration:risky' => true, + 'php_unit_mock' => [ + 'target' => PhpUnitTargetVersion::VERSION_5_5, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 5.5 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit56MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit56MigrationRiskySet.php new file mode 100644 index 0000000..4df2082 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit56MigrationRiskySet.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit56MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit55Migration:risky' => true, + 'php_unit_dedicate_assert' => [ + 'target' => PhpUnitTargetVersion::VERSION_5_6, + ], + 'php_unit_expectation' => [ + 'target' => PhpUnitTargetVersion::VERSION_5_6, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 5.6 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit57MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit57MigrationRiskySet.php new file mode 100644 index 0000000..80076bb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit57MigrationRiskySet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit57MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit56Migration:risky' => true, + 'php_unit_namespaced' => [ + 'target' => PhpUnitTargetVersion::VERSION_5_7, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 5.7 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php new file mode 100644 index 0000000..f0b977f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit60MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit57Migration:risky' => true, + 'php_unit_namespaced' => [ + 'target' => PhpUnitTargetVersion::VERSION_6_0, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 6.0 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php new file mode 100644 index 0000000..e50c53d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit75MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit60Migration:risky' => true, + 'php_unit_dedicate_assert_internal_type' => [ + 'target' => PhpUnitTargetVersion::VERSION_7_5, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 7.5 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php new file mode 100644 index 0000000..00f5eac --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php @@ -0,0 +1,38 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion; +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PHPUnit84MigrationRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PHPUnit60Migration:risky' => true, + '@PHPUnit75Migration:risky' => true, + 'php_unit_expectation' => [ + 'target' => PhpUnitTargetVersion::VERSION_8_4, + ], + ]; + } + + public function getDescription() + { + return 'Rules to improve tests code for PHPUnit 8.4 compatibility.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12RiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12RiskySet.php new file mode 100644 index 0000000..f34537e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12RiskySet.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PSR12RiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + 'no_trailing_whitespace_in_string' => true, + 'no_unreachable_default_argument_value' => true, + ]; + } + + public function getDescription() + { + return 'Rules that follow `PSR-12 <https://www.php-fig.org/psr/psr-12/>`_ standard.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12Set.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12Set.php new file mode 100644 index 0000000..09d811e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12Set.php @@ -0,0 +1,70 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PSR12Set extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PSR2' => true, + 'blank_line_after_opening_tag' => true, + 'braces' => [ + 'allow_single_line_anonymous_class_with_empty_body' => true, + ], + 'compact_nullable_typehint' => true, + 'declare_equal_normalize' => true, + 'lowercase_cast' => true, + 'lowercase_static_reference' => true, + 'new_with_braces' => true, + 'no_blank_lines_after_class_opening' => true, + 'no_leading_import_slash' => true, + 'no_whitespace_in_blank_line' => true, + 'ordered_class_elements' => [ + 'order' => [ + 'use_trait', + ], + ], + 'ordered_imports' => [ + 'imports_order' => [ + 'class', + 'function', + 'const', + ], + 'sort_algorithm' => 'none', + ], + 'return_type_declaration' => true, + 'short_scalar_cast' => true, + 'single_blank_line_before_namespace' => true, + 'single_trait_insert_per_statement' => true, + 'ternary_operator_spaces' => true, + 'visibility_required' => [ + 'elements' => [ + 'const', + 'method', + 'property', + ], + ], + ]; + } + + public function getDescription() + { + return 'Rules that follow `PSR-12 <https://www.php-fig.org/psr/psr-12/>`_ standard.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR1Set.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR1Set.php new file mode 100644 index 0000000..de6760a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR1Set.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PSR1Set extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + 'encoding' => true, + 'full_opening_tag' => true, + ]; + } + + public function getDescription() + { + return 'Rules that follow `PSR-1 <https://www.php-fig.org/psr/psr-1/>`_ standard.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR2Set.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR2Set.php new file mode 100644 index 0000000..68ae8d2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR2Set.php @@ -0,0 +1,62 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PSR2Set extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PSR1' => true, + 'blank_line_after_namespace' => true, + 'braces' => true, + 'class_definition' => true, + 'constant_case' => true, + 'elseif' => true, + 'function_declaration' => true, + 'indentation_type' => true, + 'line_ending' => true, + 'lowercase_keywords' => true, + 'method_argument_space' => [ + 'on_multiline' => 'ensure_fully_multiline', + ], + 'no_break_comment' => true, + 'no_closing_tag' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'single_blank_line_at_eof' => true, + 'single_class_element_per_statement' => [ + 'elements' => [ + 'property', + ], + ], + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'switch_case_semicolon_to_colon' => true, + 'switch_case_space' => true, + 'visibility_required' => true, + ]; + } + + public function getDescription() + { + return 'Rules that follow `PSR-2 <https://www.php-fig.org/psr/psr-2/>`_ standard.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PhpCsFixerRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PhpCsFixerRiskySet.php new file mode 100644 index 0000000..e126229 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PhpCsFixerRiskySet.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PhpCsFixerRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@Symfony:risky' => true, + 'comment_to_phpdoc' => true, + 'final_internal_class' => true, + // @TODO: consider switching to `true`, like in @Symfony + 'native_constant_invocation' => [ + 'fix_built_in' => false, + 'include' => [ + 'DIRECTORY_SEPARATOR', + 'PHP_INT_SIZE', + 'PHP_SAPI', + 'PHP_VERSION_ID', + ], + 'scope' => 'namespaced', + 'strict' => true, + ], + 'no_alias_functions' => [ + 'sets' => [ + '@all', + ], + ], + 'no_unreachable_default_argument_value' => true, + 'no_unset_on_property' => true, + 'php_unit_strict' => true, + 'php_unit_test_case_static_method_calls' => true, + 'strict_comparison' => true, + 'strict_param' => true, + ]; + } + + public function getDescription() + { + return 'Rule set as used by the PHP-CS-Fixer development team, highly opinionated.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PhpCsFixerSet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PhpCsFixerSet.php new file mode 100644 index 0000000..30c1847 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PhpCsFixerSet.php @@ -0,0 +1,105 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class PhpCsFixerSet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@Symfony' => true, + 'align_multiline_comment' => true, + 'array_indentation' => true, + 'blank_line_before_statement' => [ + 'statements' => [ + 'break', + 'case', + 'continue', + 'declare', + 'default', + 'exit', + 'goto', + 'include', + 'include_once', + 'require', + 'require_once', + 'return', + 'switch', + 'throw', + 'try', + ], + ], + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'escape_implicit_backslashes' => true, + 'explicit_indirect_variable' => true, + 'explicit_string_variable' => true, + 'heredoc_to_nowdoc' => true, + 'method_argument_space' => [ + 'on_multiline' => 'ensure_fully_multiline', + ], + 'method_chaining_indentation' => true, + 'multiline_comment_opening_closing' => true, + 'multiline_whitespace_before_semicolons' => [ + 'strategy' => 'new_line_for_chained_calls', + ], + 'no_extra_blank_lines' => [ + 'tokens' => [ + 'break', + 'case', + 'continue', + 'curly_brace_block', + 'default', + 'extra', + 'parenthesis_brace_block', + 'return', + 'square_brace_block', + 'switch', + 'throw', + 'use', + 'use_trait', + ], + ], + 'no_null_property_initialization' => true, + 'no_superfluous_elseif' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'operator_linebreak' => [ + 'only_booleans' => true, + ], + 'ordered_class_elements' => true, + 'php_unit_internal_class' => true, + 'php_unit_test_class_requires_covers' => true, + 'phpdoc_add_missing_param_annotation' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_order' => true, + 'phpdoc_order_by_value' => true, + 'phpdoc_types_order' => true, + 'phpdoc_var_annotation_correct_order' => true, + 'return_assignment' => true, + 'simple_to_complex_string_variable' => true, + 'single_line_comment_style' => true, + 'single_line_throw' => false, + ]; + } + + public function getDescription() + { + return 'Rule set as used by the PHP-CS-Fixer development team, highly opinionated.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/SymfonyRiskySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/SymfonyRiskySet.php new file mode 100644 index 0000000..f69c1d4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/SymfonyRiskySet.php @@ -0,0 +1,91 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class SymfonyRiskySet extends AbstractRuleSetDescription +{ + public function getRules() + { + $rules = [ + '@PHP56Migration:risky' => true, + '@PSR12:risky' => true, + 'array_push' => true, + 'combine_nested_dirname' => true, + 'dir_constant' => true, + 'ereg_to_preg' => true, + 'error_suppression' => true, + 'fopen_flag_order' => true, + 'fopen_flags' => [ + 'b_mode' => false, + ], + 'function_to_constant' => [ + 'functions' => [ + 'get_called_class', + 'get_class', + 'get_class_this', + 'php_sapi_name', + 'phpversion', + 'pi', + ], + ], + 'implode_call' => true, + 'is_null' => true, + 'logical_operators' => true, + 'modernize_types_casting' => true, + 'native_constant_invocation' => true, + 'native_function_invocation' => [ + 'include' => [ + '@compiler_optimized', + ], + 'scope' => 'namespaced', + 'strict' => true, + ], + 'no_alias_functions' => true, + 'no_homoglyph_names' => true, + 'no_php4_constructor' => true, + 'no_unneeded_final_method' => true, + 'no_unreachable_default_argument_value' => false, + 'no_useless_sprintf' => true, + 'non_printable_character' => true, + 'ordered_traits' => true, + 'php_unit_construct' => true, + 'php_unit_mock_short_will_return' => true, + 'php_unit_set_up_tear_down_visibility' => true, + 'php_unit_test_annotation' => true, + 'psr_autoloading' => true, + 'self_accessor' => true, + 'set_type_to_cast' => true, + 'string_line_ending' => true, + 'ternary_to_elvis_operator' => true, + ]; + + $rules['non_printable_character'] = \PHP_VERSION_ID < 70000 + ? true + : ['use_escape_sequences_in_strings' => true] + ; + + ksort($rules); + + return $rules; + } + + public function getDescription() + { + return 'Rules that follow the official `Symfony Coding Standards <https://symfony.com/doc/current/contributing/code/standards.html>`_.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/SymfonySet.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/SymfonySet.php new file mode 100644 index 0000000..a9534da --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSet/Sets/SymfonySet.php @@ -0,0 +1,191 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\RuleSet\Sets; + +use PhpCsFixer\RuleSet\AbstractRuleSetDescription; + +/** + * @internal + */ +final class SymfonySet extends AbstractRuleSetDescription +{ + public function getRules() + { + return [ + '@PSR12' => true, + 'array_syntax' => [ + 'syntax' => 'short', + ], + 'backtick_to_shell_exec' => true, + 'binary_operator_spaces' => true, + 'blank_line_before_statement' => [ + 'statements' => [ + 'return', + ], + ], + 'braces' => [ + 'allow_single_line_anonymous_class_with_empty_body' => true, + 'allow_single_line_closure' => true, + ], + 'cast_spaces' => true, + 'class_attributes_separation' => [ + 'elements' => [ + 'method' => 'one', + ], + ], + 'class_definition' => [ + 'single_line' => true, + ], + 'clean_namespace' => true, + 'concat_space' => true, + 'echo_tag_syntax' => true, + 'fully_qualified_strict_types' => true, + 'function_typehint_space' => true, + 'general_phpdoc_tag_rename' => [ + 'replacements' => [ + 'inheritDocs' => 'inheritDoc', + ], + ], + 'include' => true, + 'increment_style' => true, + 'lambda_not_used_import' => true, + 'linebreak_after_opening_tag' => true, + 'magic_constant_casing' => true, + 'magic_method_casing' => true, + 'method_argument_space' => true, + 'native_function_casing' => true, + 'native_function_type_declaration_casing' => true, + 'no_alias_language_construct_call' => true, + 'no_alternative_syntax' => true, + 'no_binary_string' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => [ + 'tokens' => [ + 'case', + 'continue', + 'curly_brace_block', + 'default', + 'extra', + 'parenthesis_brace_block', + 'square_brace_block', + 'switch', + 'throw', + 'use', + 'use_trait', + ], + ], + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => true, + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_short_bool_cast' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_spaces_around_offset' => true, + 'no_superfluous_phpdoc_tags' => [ + 'allow_mixed' => true, + 'allow_unused_params' => true, + ], + 'no_trailing_comma_in_list_call' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_unneeded_control_parentheses' => [ + 'statements' => [ + 'break', + 'clone', + 'continue', + 'echo_print', + 'return', + 'switch_case', + 'yield', + 'yield_from', + ], + ], + 'no_unneeded_curly_braces' => ['namespaces' => true], + 'no_unset_cast' => true, + 'no_unused_imports' => true, + 'no_whitespace_before_comma_in_array' => true, + 'normalize_index_brace' => true, + 'object_operator_without_whitespace' => true, + 'ordered_imports' => true, + 'php_unit_fqcn_annotation' => true, + 'php_unit_method_casing' => true, + 'phpdoc_align' => [ + // @TODO: on 3.0 switch whole rule to `=> true`, currently we use custom config that will be default on 3.0 + 'tags' => [ + 'method', + 'param', + 'property', + 'return', + 'throws', + 'type', + 'var', + ], + ], + 'phpdoc_annotation_without_dot' => true, + 'phpdoc_indent' => true, + 'phpdoc_inline_tag_normalizer' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_alias_tag' => true, + 'phpdoc_no_package' => true, + 'phpdoc_no_useless_inheritdoc' => true, + 'phpdoc_return_self_reference' => true, + 'phpdoc_scalar' => true, + 'phpdoc_separation' => true, + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_summary' => true, + 'phpdoc_tag_type' => [ + 'tags' => [ + 'inheritDoc' => 'inline', + ], + ], + 'phpdoc_to_comment' => true, + 'phpdoc_trim' => true, + 'phpdoc_trim_consecutive_blank_line_separation' => true, + 'phpdoc_types' => true, + 'phpdoc_types_order' => [ + 'null_adjustment' => 'always_last', + 'sort_algorithm' => 'none', + ], + 'phpdoc_var_without_name' => true, + 'protected_to_private' => true, + 'semicolon_after_instruction' => true, + 'single_class_element_per_statement' => true, + 'single_line_comment_style' => [ + 'comment_types' => [ + 'hash', + ], + ], + 'single_line_throw' => true, + 'single_quote' => true, + 'single_space_after_construct' => true, + 'space_after_semicolon' => [ + 'remove_in_empty_for_expressions' => true, + ], + 'standardize_increment' => true, + 'standardize_not_equals' => true, + 'switch_continue_to_break' => true, + 'trailing_comma_in_multiline' => true, + 'trim_array_spaces' => true, + 'unary_operator_spaces' => true, + 'visibility_required' => true, + 'whitespace_after_comma_in_array' => true, + 'yoda_style' => true, + ]; + } + + public function getDescription() + { + return 'Rules that follow the official `Symfony Coding Standards <https://symfony.com/doc/current/contributing/code/standards.html>`_.'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/RuleSetInterface.php b/vendor/friendsofphp/php-cs-fixer/src/RuleSetInterface.php new file mode 100644 index 0000000..701a59f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/RuleSetInterface.php @@ -0,0 +1,20 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * @deprecated will be removed in 3.0 Use \PhpCsFixer\RuleSet\RuleSetInterface + */ +interface RuleSetInterface extends \PhpCsFixer\RuleSet\RuleSetInterface +{ +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Runner/FileCachingLintingIterator.php b/vendor/friendsofphp/php-cs-fixer/src/Runner/FileCachingLintingIterator.php new file mode 100644 index 0000000..cd6bcb6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Runner/FileCachingLintingIterator.php @@ -0,0 +1,80 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Runner; + +use PhpCsFixer\Linter\LinterInterface; +use PhpCsFixer\Linter\LintingResultInterface; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FileCachingLintingIterator extends \CachingIterator +{ + /** + * @var LintingResultInterface + */ + private $currentResult; + + /** + * @var LinterInterface + */ + private $linter; + + /** + * @var LintingResultInterface + */ + private $nextResult; + + public function __construct(\Iterator $iterator, LinterInterface $linter) + { + parent::__construct($iterator); + + $this->linter = $linter; + } + + public function currentLintingResult() + { + return $this->currentResult; + } + + public function next() + { + parent::next(); + + $this->currentResult = $this->nextResult; + + if ($this->hasNext()) { + $this->nextResult = $this->handleItem($this->getInnerIterator()->current()); + } + } + + public function rewind() + { + parent::rewind(); + + if ($this->valid()) { + $this->currentResult = $this->handleItem($this->current()); + } + + if ($this->hasNext()) { + $this->nextResult = $this->handleItem($this->getInnerIterator()->current()); + } + } + + private function handleItem(\SplFileInfo $file) + { + return $this->linter->lintFile($file->getRealPath()); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Runner/FileFilterIterator.php b/vendor/friendsofphp/php-cs-fixer/src/Runner/FileFilterIterator.php new file mode 100644 index 0000000..7a4ac22 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Runner/FileFilterIterator.php @@ -0,0 +1,122 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Runner; + +use PhpCsFixer\Cache\CacheManagerInterface; +use PhpCsFixer\Event\Event; +use PhpCsFixer\FileReader; +use PhpCsFixer\FixerFileProcessedEvent; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FileFilterIterator extends \FilterIterator +{ + /** + * @var null|EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * @var CacheManagerInterface + */ + private $cacheManager; + + /** + * @var array<string,bool> + */ + private $visitedElements = []; + + public function __construct( + \Traversable $iterator, + EventDispatcherInterface $eventDispatcher = null, + CacheManagerInterface $cacheManager + ) { + if (!$iterator instanceof \Iterator) { + $iterator = new \IteratorIterator($iterator); + } + + parent::__construct($iterator); + + $this->eventDispatcher = $eventDispatcher; + $this->cacheManager = $cacheManager; + } + + public function accept() + { + $file = $this->current(); + if (!$file instanceof \SplFileInfo) { + throw new \RuntimeException( + sprintf( + 'Expected instance of "\SplFileInfo", got "%s".', + \is_object($file) ? \get_class($file) : \gettype($file) + ) + ); + } + + $path = $file->isLink() ? $file->getPathname() : $file->getRealPath(); + + if (isset($this->visitedElements[$path])) { + return false; + } + + $this->visitedElements[$path] = true; + + if (!$file->isFile() || $file->isLink()) { + return false; + } + + $content = FileReader::createSingleton()->read($path); + + // mark as skipped: + if ( + // empty file + '' === $content + // file that does not need fixing due to cache + || !$this->cacheManager->needFixing($file->getPathname(), $content) + ) { + $this->dispatchEvent( + FixerFileProcessedEvent::NAME, + new FixerFileProcessedEvent(FixerFileProcessedEvent::STATUS_SKIPPED) + ); + + return false; + } + + return true; + } + + /** + * @param string $name + */ + private function dispatchEvent($name, Event $event) + { + if (null === $this->eventDispatcher) { + return; + } + + // BC compatibility < Sf 4.3 + if ( + !$this->eventDispatcher instanceof \Symfony\Contracts\EventDispatcher\EventDispatcherInterface + ) { + $this->eventDispatcher->dispatch($name, $event); + + return; + } + + $this->eventDispatcher->dispatch($event, $name); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Runner/FileLintingIterator.php b/vendor/friendsofphp/php-cs-fixer/src/Runner/FileLintingIterator.php new file mode 100644 index 0000000..fbd9b34 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Runner/FileLintingIterator.php @@ -0,0 +1,68 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Runner; + +use PhpCsFixer\Linter\LinterInterface; +use PhpCsFixer\Linter\LintingResultInterface; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class FileLintingIterator extends \IteratorIterator +{ + /** + * @var LintingResultInterface + */ + private $currentResult; + + /** + * @var null|LinterInterface + */ + private $linter; + + public function __construct(\Iterator $iterator, LinterInterface $linter) + { + parent::__construct($iterator); + + $this->linter = $linter; + } + + /** + * @return null|LintingResultInterface + */ + public function currentLintingResult() + { + return $this->currentResult; + } + + public function next() + { + parent::next(); + + $this->currentResult = $this->valid() ? $this->handleItem($this->current()) : null; + } + + public function rewind() + { + parent::rewind(); + + $this->currentResult = $this->valid() ? $this->handleItem($this->current()) : null; + } + + private function handleItem(\SplFileInfo $file) + { + return $this->linter->lintFile($file->getRealPath()); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Runner/Runner.php b/vendor/friendsofphp/php-cs-fixer/src/Runner/Runner.php new file mode 100644 index 0000000..3a0e79e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Runner/Runner.php @@ -0,0 +1,337 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Runner; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\Cache\CacheManagerInterface; +use PhpCsFixer\Cache\Directory; +use PhpCsFixer\Cache\DirectoryInterface; +use PhpCsFixer\Differ\DifferInterface; +use PhpCsFixer\Error\Error; +use PhpCsFixer\Error\ErrorsManager; +use PhpCsFixer\Event\Event; +use PhpCsFixer\FileReader; +use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\FixerFileProcessedEvent; +use PhpCsFixer\Linter\LinterInterface; +use PhpCsFixer\Linter\LintingException; +use PhpCsFixer\Linter\LintingResultInterface; +use PhpCsFixer\Tokenizer\Tokens; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Filesystem\Exception\IOException; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class Runner +{ + /** + * @var DifferInterface + */ + private $differ; + + /** + * @var DirectoryInterface + */ + private $directory; + + /** + * @var null|EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * @var ErrorsManager + */ + private $errorsManager; + + /** + * @var CacheManagerInterface + */ + private $cacheManager; + + /** + * @var bool + */ + private $isDryRun; + + /** + * @var LinterInterface + */ + private $linter; + + /** + * @var \Traversable + */ + private $finder; + + /** + * @var FixerInterface[] + */ + private $fixers; + + /** + * @var bool + */ + private $stopOnViolation; + + public function __construct( + $finder, + array $fixers, + DifferInterface $differ, + EventDispatcherInterface $eventDispatcher = null, + ErrorsManager $errorsManager, + LinterInterface $linter, + $isDryRun, + CacheManagerInterface $cacheManager, + DirectoryInterface $directory = null, + $stopOnViolation = false + ) { + $this->finder = $finder; + $this->fixers = $fixers; + $this->differ = $differ; + $this->eventDispatcher = $eventDispatcher; + $this->errorsManager = $errorsManager; + $this->linter = $linter; + $this->isDryRun = $isDryRun; + $this->cacheManager = $cacheManager; + $this->directory = $directory ?: new Directory(''); + $this->stopOnViolation = $stopOnViolation; + } + + /** + * @return array + */ + public function fix() + { + $changed = []; + + $finder = $this->finder; + $finderIterator = $finder instanceof \IteratorAggregate ? $finder->getIterator() : $finder; + $fileFilteredFileIterator = new FileFilterIterator( + $finderIterator, + $this->eventDispatcher, + $this->cacheManager + ); + + $collection = $this->linter->isAsync() + ? new FileCachingLintingIterator($fileFilteredFileIterator, $this->linter) + : new FileLintingIterator($fileFilteredFileIterator, $this->linter); + + /** @var \SplFileInfo $file */ + foreach ($collection as $file) { + $fixInfo = $this->fixFile($file, $collection->currentLintingResult()); + + // we do not need Tokens to still caching just fixed file - so clear the cache + Tokens::clearCache(); + + if ($fixInfo) { + $name = $this->directory->getRelativePathTo($file->__toString()); + $changed[$name] = $fixInfo; + + if ($this->stopOnViolation) { + break; + } + } + } + + return $changed; + } + + private function fixFile(\SplFileInfo $file, LintingResultInterface $lintingResult) + { + $name = $file->getPathname(); + + try { + $lintingResult->check(); + } catch (LintingException $e) { + $this->dispatchEvent( + FixerFileProcessedEvent::NAME, + new FixerFileProcessedEvent(FixerFileProcessedEvent::STATUS_INVALID) + ); + + $this->errorsManager->report(new Error(Error::TYPE_INVALID, $name, $e)); + + return; + } + + $old = FileReader::createSingleton()->read($file->getRealPath()); + + Tokens::setLegacyMode(false); + + $tokens = Tokens::fromCode($old); + $oldHash = $tokens->getCodeHash(); + + $newHash = $oldHash; + $new = $old; + + $appliedFixers = []; + + try { + foreach ($this->fixers as $fixer) { + // for custom fixers we don't know is it safe to run `->fix()` without checking `->supports()` and `->isCandidate()`, + // thus we need to check it and conditionally skip fixing + if ( + !$fixer instanceof AbstractFixer + && (!$fixer->supports($file) || !$fixer->isCandidate($tokens)) + ) { + continue; + } + + $fixer->fix($file, $tokens); + + if ($tokens->isChanged()) { + $tokens->clearEmptyTokens(); + $tokens->clearChanged(); + $appliedFixers[] = $fixer->getName(); + } + } + } catch (\Exception $e) { + $this->processException($name, $e); + + return; + } catch (\ParseError $e) { + $this->dispatchEvent( + FixerFileProcessedEvent::NAME, + new FixerFileProcessedEvent(FixerFileProcessedEvent::STATUS_LINT) + ); + + $this->errorsManager->report(new Error(Error::TYPE_LINT, $name, $e)); + + return; + } catch (\Throwable $e) { + $this->processException($name, $e); + + return; + } + + $fixInfo = null; + + if (!empty($appliedFixers)) { + $new = $tokens->generateCode(); + $newHash = $tokens->getCodeHash(); + } + + // We need to check if content was changed and then applied changes. + // But we can't simple check $appliedFixers, because one fixer may revert + // work of other and both of them will mark collection as changed. + // Therefore we need to check if code hashes changed. + if ($oldHash !== $newHash) { + $fixInfo = [ + 'appliedFixers' => $appliedFixers, + 'diff' => $this->differ->diff($old, $new), + ]; + + try { + $this->linter->lintSource($new)->check(); + } catch (LintingException $e) { + $this->dispatchEvent( + FixerFileProcessedEvent::NAME, + new FixerFileProcessedEvent(FixerFileProcessedEvent::STATUS_LINT) + ); + + $this->errorsManager->report(new Error(Error::TYPE_LINT, $name, $e, $fixInfo['appliedFixers'], $fixInfo['diff'])); + + return; + } + + if (!$this->isDryRun) { + $fileName = $file->getRealPath(); + + if (!file_exists($fileName)) { + throw new IOException( + sprintf('Failed to write file "%s" (no longer) exists.', $file->getPathname()), + 0, + null, + $file->getPathname() + ); + } + + if (is_dir($fileName)) { + throw new IOException( + sprintf('Cannot write file "%s" as the location exists as directory.', $fileName), + 0, + null, + $fileName + ); + } + + if (!is_writable($fileName)) { + throw new IOException( + sprintf('Cannot write to file "%s" as it is not writable.', $fileName), + 0, + null, + $fileName + ); + } + + if (false === @file_put_contents($fileName, $new)) { + $error = error_get_last(); + + throw new IOException( + sprintf('Failed to write file "%s", "%s".', $fileName, $error ? $error['message'] : 'no reason available'), + 0, + null, + $fileName + ); + } + } + } + + $this->cacheManager->setFile($name, $new); + + $this->dispatchEvent( + FixerFileProcessedEvent::NAME, + new FixerFileProcessedEvent($fixInfo ? FixerFileProcessedEvent::STATUS_FIXED : FixerFileProcessedEvent::STATUS_NO_CHANGES) + ); + + return $fixInfo; + } + + /** + * Process an exception that occurred. + * + * @param string $name + * @param \Throwable $e + */ + private function processException($name, $e) + { + $this->dispatchEvent( + FixerFileProcessedEvent::NAME, + new FixerFileProcessedEvent(FixerFileProcessedEvent::STATUS_EXCEPTION) + ); + + $this->errorsManager->report(new Error(Error::TYPE_EXCEPTION, $name, $e)); + } + + /** + * @param string $name + */ + private function dispatchEvent($name, Event $event) + { + if (null === $this->eventDispatcher) { + return; + } + + // BC compatibility < Sf 4.3 + if ( + !$this->eventDispatcher instanceof \Symfony\Contracts\EventDispatcher\EventDispatcherInterface + ) { + $this->eventDispatcher->dispatch($name, $event); + + return; + } + + $this->eventDispatcher->dispatch($event, $name); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/StdinFileInfo.php b/vendor/friendsofphp/php-cs-fixer/src/StdinFileInfo.php similarity index 72% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/StdinFileInfo.php rename to vendor/friendsofphp/php-cs-fixer/src/StdinFileInfo.php index fe34eae..2eedfa3 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/StdinFileInfo.php +++ b/vendor/friendsofphp/php-cs-fixer/src/StdinFileInfo.php @@ -10,12 +10,14 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS; +namespace PhpCsFixer; /** * @author Davi Koscianski Vidal <davividal@gmail.com> + * + * @internal */ -class StdinFileInfo extends \SplFileInfo +final class StdinFileInfo extends \SplFileInfo { public function __construct() { @@ -23,20 +25,16 @@ public function __construct() public function __toString() { - return $this->getContents(); + return $this->getRealPath(); } - public function getRealpath() + public function getRealPath() { // So file_get_contents & friends will work. + // Warning - this stream is not seekable, so `file_get_contents` will work only once! Consider using `FileReader`. return 'php://stdin'; } - public function getContents() - { - return file_get_contents($this->getRealpath()); - } - public function getATime() { return 0; @@ -57,9 +55,9 @@ public function getExtension() return '.php'; } - public function getFileInfo($class_name = null) + public function getFileInfo($className = null) { - throw new \RuntimeException('Not implemented'); + throw new \BadMethodCallException(sprintf('Method "%s" is not implemented.', __METHOD__)); } public function getFilename() @@ -104,9 +102,9 @@ public function getPath() return ''; } - public function getPathInfo($class_name = null) + public function getPathInfo($className = null) { - throw new \RuntimeException('Not implemented'); + throw new \BadMethodCallException(sprintf('Method "%s" is not implemented.', __METHOD__)); } public function getPathname() @@ -159,16 +157,16 @@ public function isWritable() return false; } - public function openFile($open_mode = 'r', $use_include_path = false, $context = null) + public function openFile($openMode = 'r', $useIncludePath = false, $context = null) { - throw new \RuntimeException('Not implemented'); + throw new \BadMethodCallException(sprintf('Method "%s" is not implemented.', __METHOD__)); } - public function setFileClass($class_name = null) + public function setFileClass($className = null) { } - public function setInfoClass($class_name = null) + public function setInfoClass($className = null) { } } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Test/AbstractFixerTestCase.php b/vendor/friendsofphp/php-cs-fixer/src/Test/AbstractFixerTestCase.php new file mode 100644 index 0000000..f947a93 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Test/AbstractFixerTestCase.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Test; + +use PhpCsFixer\Tests\Test\AbstractFixerTestCase as BaseAbstractFixerTestCase; +use PhpCsFixer\Utils; + +/** + * @TODO 3.0 While removing, remove loading `tests/Test` from `autoload` section of `composer.json`. + * + * @deprecated since v2.4 + */ +abstract class AbstractFixerTestCase extends BaseAbstractFixerTestCase +{ + public function __construct($name = null, array $data = [], $dataName = '') + { + Utils::triggerDeprecation(new \RuntimeException( + sprintf( + 'The "%s" class is deprecated. You should stop using it, as it will be removed in 3.0 version.', + __CLASS__ + ) + )); + + parent::__construct($name, $data, $dataName); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Test/AbstractIntegrationTestCase.php b/vendor/friendsofphp/php-cs-fixer/src/Test/AbstractIntegrationTestCase.php new file mode 100644 index 0000000..a2eeb8d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Test/AbstractIntegrationTestCase.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Test; + +use PhpCsFixer\Tests\Test\AbstractIntegrationTestCase as BaseAbstractIntegrationTestCase; +use PhpCsFixer\Utils; + +/** + * @TODO 3.0 While removing, remove loading `tests/Test` from `autoload` section of `composer.json`. + * + * @deprecated since v2.4 + */ +abstract class AbstractIntegrationTestCase extends BaseAbstractIntegrationTestCase +{ + public function __construct($name = null, array $data = [], $dataName = '') + { + Utils::triggerDeprecation(new \RuntimeException( + sprintf( + 'The "%s" class is deprecated. You should stop using it, as it will be removed in 3.0 version.', + __CLASS__ + ) + )); + + parent::__construct($name, $data, $dataName); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Test/AccessibleObject.php b/vendor/friendsofphp/php-cs-fixer/src/Test/AccessibleObject.php new file mode 100644 index 0000000..0d0df4f --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Test/AccessibleObject.php @@ -0,0 +1,94 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Test; + +use PhpCsFixer\Utils; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @deprecated since v2.5. Use "php-cs-fixer/accessible-object" package instead. + */ +final class AccessibleObject +{ + private $object; + private $reflection; + + /** + * @param object $object + */ + public function __construct($object) + { + Utils::triggerDeprecation(new \RuntimeException( + sprintf( + 'The "%s" class is deprecated and will be removed in 3.0 version. Use "php-cs-fixer/accessible-object" package instead.', + __CLASS__ + ) + )); + + $this->object = $object; + $this->reflection = new \ReflectionClass($object); + } + + public function __call($name, array $arguments) + { + if (!method_exists($this->object, $name)) { + throw new \LogicException(sprintf('Cannot call non existing method "%s"->%s.', \get_class($this->object), $name)); + } + + $method = $this->reflection->getMethod($name); + $method->setAccessible(true); + + return $method->invokeArgs($this->object, $arguments); + } + + public function __isset($name) + { + try { + $value = $this->{$name}; + } catch (\LogicException $e) { + return false; + } + + return isset($value); + } + + public function __get($name) + { + if (!property_exists($this->object, $name)) { + throw new \LogicException(sprintf('Cannot get non existing property "%s"->%s.', \get_class($this->object), $name)); + } + + $property = $this->reflection->getProperty($name); + $property->setAccessible(true); + + return $property->getValue($this->object); + } + + public function __set($name, $value) + { + if (!property_exists($this->object, $name)) { + throw new \LogicException(sprintf('Cannot set non existing property "%s"->%s = "%s".', \get_class($this->object), $name, var_export($value, true))); + } + + $property = $this->reflection->getProperty($name); + $property->setAccessible(true); + + $property->setValue($this->object, $value); + } + + public static function create($object) + { + return new self($object); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Test/IntegrationCase.php b/vendor/friendsofphp/php-cs-fixer/src/Test/IntegrationCase.php new file mode 100644 index 0000000..87bdb80 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Test/IntegrationCase.php @@ -0,0 +1,132 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Test; + +use PhpCsFixer\RuleSet\RuleSet; +use PhpCsFixer\Tests\Test\IntegrationCase as BaseIntegrationCase; +use PhpCsFixer\Utils; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @TODO 3.0 While removing, remove loading `tests/Test` from `autoload` section of `composer.json`. + * + * @deprecated since v2.4 + */ +final class IntegrationCase +{ + /** + * @var BaseIntegrationCase + */ + private $base; + + /** + * @param string $fileName + * @param string $title + * @param string $expectedCode + * @param null|string $inputCode + */ + public function __construct( + $fileName, + $title, + array $settings, + array $requirements, + array $config, + RuleSet $ruleset, + $expectedCode, + $inputCode + ) { + $this->base = new BaseIntegrationCase( + $fileName, + $title, + $settings, + $requirements, + $config, + $ruleset, + $expectedCode, + $inputCode + ); + + Utils::triggerDeprecation(new \RuntimeException(sprintf( + 'The "%s" class is deprecated. You should stop using it, as it will be removed in 3.0 version.', + __CLASS__ + ))); + } + + public function hasInputCode() + { + return $this->base->hasInputCode(); + } + + public function getConfig() + { + return $this->base->getConfig(); + } + + public function getExpectedCode() + { + return $this->base->getExpectedCode(); + } + + public function getFileName() + { + return $this->base->getFileName(); + } + + public function getInputCode() + { + return $this->base->getInputCode(); + } + + public function getRequirement($name) + { + return $this->base->getRequirement($name); + } + + public function getRequirements() + { + return $this->base->getRequirements(); + } + + public function getRuleset() + { + return $this->base->getRuleset(); + } + + public function getSettings() + { + return $this->base->getSettings(); + } + + public function getTitle() + { + return $this->base->getTitle(); + } + + /** + * @return bool + * + * @deprecated since v2.1, on ~2.1 line IntegrationTest check whether different priorities are required is done automatically, this method will be removed on v3.0 + */ + public function shouldCheckPriority() + { + Utils::triggerDeprecation(new \RuntimeException(sprintf( + 'The "%s" method is deprecated. You should stop using it, as it will be removed in 3.0 version.', + __METHOD__ + ))); + + $settings = $this->base->getSettings(); + + return isset($settings['checkPriority']) ? $settings['checkPriority'] : true; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/AbstractTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/AbstractTransformer.php similarity index 52% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/AbstractTransformer.php rename to vendor/friendsofphp/php-cs-fixer/src/Tokenizer/AbstractTransformer.php index 155673a..5294bcf 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/AbstractTransformer.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/AbstractTransformer.php @@ -10,33 +10,24 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Tokenizer; +namespace PhpCsFixer\Tokenizer; -use Symfony\CS\Utils; +use PhpCsFixer\Utils; /** - * Abstract base for Transformer class. - * - * It provides unified registerCustomTokens method. - * * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal */ abstract class AbstractTransformer implements TransformerInterface { - /** - * Last generated value for custom token. - * - * @var int - */ - private static $lastGeneratedCustomTokenValue = 10000; - /** * {@inheritdoc} */ public function getName() { - $nameParts = explode('\\', get_called_class()); - $name = end($nameParts); + $nameParts = explode('\\', static::class); + $name = substr(end($nameParts), 0, -\strlen('Transformer')); return Utils::camelCaseToUnderscore($name); } @@ -52,12 +43,5 @@ public function getPriority() /** * {@inheritdoc} */ - public function registerCustomTokens() - { - foreach ($this->getCustomTokenNames() as $name) { - if (!defined($name)) { - define($name, ++self::$lastGeneratedCustomTokenValue); - } - } - } + abstract public function getCustomTokens(); } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/ArgumentAnalysis.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/ArgumentAnalysis.php new file mode 100644 index 0000000..4b747fb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/ArgumentAnalysis.php @@ -0,0 +1,108 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer\Analysis; + +/** + * @internal + */ +final class ArgumentAnalysis +{ + /** + * The default value of the argument. + * + * @var null|string + */ + private $default; + + /** + * The name of the argument. + * + * @var string + */ + private $name; + + /** + * The index where the name is located in the supplied Tokens object. + * + * @var int + */ + private $nameIndex; + + /** + * The type analysis of the argument. + * + * @var null|TypeAnalysis + */ + private $typeAnalysis; + + /** + * @param string $name + * @param int $nameIndex + * @param null|string $default + */ + public function __construct($name, $nameIndex, $default, TypeAnalysis $typeAnalysis = null) + { + $this->name = $name; + $this->nameIndex = $nameIndex; + $this->default = $default ?: null; + $this->typeAnalysis = $typeAnalysis ?: null; + } + + /** + * @return null|string + */ + public function getDefault() + { + return $this->default; + } + + /** + * @return bool + */ + public function hasDefault() + { + return null !== $this->default; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return int + */ + public function getNameIndex() + { + return $this->nameIndex; + } + + /** + * @return null|TypeAnalysis + */ + public function getTypeAnalysis() + { + return $this->typeAnalysis; + } + + /** + * @return bool + */ + public function hasTypeAnalysis() + { + return null !== $this->typeAnalysis; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/CaseAnalysis.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/CaseAnalysis.php new file mode 100644 index 0000000..edf5421 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/CaseAnalysis.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer\Analysis; + +/** + * @author Kuba Werłos <werlos@gmail.com> + * + * @internal + */ +final class CaseAnalysis +{ + /** + * @var int + */ + private $colonIndex; + + /** + * @param int $colonIndex + */ + public function __construct($colonIndex) + { + $this->colonIndex = $colonIndex; + } + + /** + * @return int + */ + public function getColonIndex() + { + return $this->colonIndex; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/NamespaceAnalysis.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/NamespaceAnalysis.php new file mode 100644 index 0000000..4457db7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/NamespaceAnalysis.php @@ -0,0 +1,127 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer\Analysis; + +/** + * @internal + */ +final class NamespaceAnalysis implements StartEndTokenAwareAnalysis +{ + /** + * The fully qualified namespace name. + * + * @var string + */ + private $fullName; + + /** + * The short version of the namespace. + * + * @var string + */ + private $shortName; + + /** + * The start index of the namespace declaration in the analyzed Tokens. + * + * @var int + */ + private $startIndex; + + /** + * The end index of the namespace declaration in the analyzed Tokens. + * + * @var int + */ + private $endIndex; + + /** + * The start index of the scope of the namespace in the analyzed Tokens. + * + * @var int + */ + private $scopeStartIndex; + + /** + * The end index of the scope of the namespace in the analyzed Tokens. + * + * @var int + */ + private $scopeEndIndex; + + /** + * @param string $fullName + * @param string $shortName + * @param int $startIndex + * @param int $endIndex + * @param int $scopeStartIndex + * @param int $scopeEndIndex + */ + public function __construct($fullName, $shortName, $startIndex, $endIndex, $scopeStartIndex, $scopeEndIndex) + { + $this->fullName = $fullName; + $this->shortName = $shortName; + $this->startIndex = $startIndex; + $this->endIndex = $endIndex; + $this->scopeStartIndex = $scopeStartIndex; + $this->scopeEndIndex = $scopeEndIndex; + } + + /** + * @return string + */ + public function getFullName() + { + return $this->fullName; + } + + /** + * @return string + */ + public function getShortName() + { + return $this->shortName; + } + + /** + * @return int + */ + public function getStartIndex() + { + return $this->startIndex; + } + + /** + * @return int + */ + public function getEndIndex() + { + return $this->endIndex; + } + + /** + * @return int + */ + public function getScopeStartIndex() + { + return $this->scopeStartIndex; + } + + /** + * @return int + */ + public function getScopeEndIndex() + { + return $this->scopeEndIndex; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/NamespaceUseAnalysis.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/NamespaceUseAnalysis.php new file mode 100644 index 0000000..0621292 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/NamespaceUseAnalysis.php @@ -0,0 +1,155 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer\Analysis; + +/** + * @internal + */ +final class NamespaceUseAnalysis implements StartEndTokenAwareAnalysis +{ + const TYPE_CLASS = 1; + const TYPE_FUNCTION = 2; + const TYPE_CONSTANT = 3; + + /** + * The fully qualified use namespace. + * + * @var string + */ + private $fullName; + + /** + * The short version of use namespace or the alias name in case of aliased use statements. + * + * @var string + */ + private $shortName; + + /** + * Is the use statement being aliased? + * + * @var bool + */ + private $isAliased; + + /** + * The start index of the namespace declaration in the analyzed Tokens. + * + * @var int + */ + private $startIndex; + + /** + * The end index of the namespace declaration in the analyzed Tokens. + * + * @var int + */ + private $endIndex; + + /** + * The type of import: class, function or constant. + * + * @var int + */ + private $type; + + /** + * @param string $fullName + * @param string $shortName + * @param bool $isAliased + * @param int $startIndex + * @param int $endIndex + * @param int $type + */ + public function __construct($fullName, $shortName, $isAliased, $startIndex, $endIndex, $type) + { + $this->fullName = $fullName; + $this->shortName = $shortName; + $this->isAliased = $isAliased; + $this->startIndex = $startIndex; + $this->endIndex = $endIndex; + $this->type = $type; + } + + /** + * @return string + */ + public function getFullName() + { + return $this->fullName; + } + + /** + * @return string + */ + public function getShortName() + { + return $this->shortName; + } + + /** + * @return bool + */ + public function isAliased() + { + return $this->isAliased; + } + + /** + * @return int + */ + public function getStartIndex() + { + return $this->startIndex; + } + + /** + * @return int + */ + public function getEndIndex() + { + return $this->endIndex; + } + + /** + * @return int + */ + public function getType() + { + return $this->type; + } + + /** + * @return bool + */ + public function isClass() + { + return self::TYPE_CLASS === $this->type; + } + + /** + * @return bool + */ + public function isFunction() + { + return self::TYPE_FUNCTION === $this->type; + } + + /** + * @return bool + */ + public function isConstant() + { + return self::TYPE_CONSTANT === $this->type; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/StartEndTokenAwareAnalysis.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/StartEndTokenAwareAnalysis.php new file mode 100644 index 0000000..1cadfff --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/StartEndTokenAwareAnalysis.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer\Analysis; + +interface StartEndTokenAwareAnalysis +{ + /** + * The start index of the analyzed subject inside of the Tokens. + * + * @return int + */ + public function getStartIndex(); + + /** + * The end index of the analyzed subject inside of the Tokens. + * + * @return int + */ + public function getEndIndex(); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/SwitchAnalysis.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/SwitchAnalysis.php new file mode 100644 index 0000000..cb73c7b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/SwitchAnalysis.php @@ -0,0 +1,72 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer\Analysis; + +/** + * @author Kuba Werłos <werlos@gmail.com> + * + * @internal + */ +final class SwitchAnalysis +{ + /** + * @var int + */ + private $casesStart; + + /** + * @var int + */ + private $casesEnd; + + /** + * @var CaseAnalysis[] + */ + private $cases = []; + + /** + * @param int $casesStart + * @param int $casesEnd + * @param CaseAnalysis[] $cases + */ + public function __construct($casesStart, $casesEnd, array $cases) + { + $this->casesStart = $casesStart; + $this->casesEnd = $casesEnd; + $this->cases = $cases; + } + + /** + * @return int + */ + public function getCasesStart() + { + return $this->casesStart; + } + + /** + * @return int + */ + public function getCasesEnd() + { + return $this->casesEnd; + } + + /** + * @return CaseAnalysis[] + */ + public function getCases() + { + return $this->cases; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/TypeAnalysis.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/TypeAnalysis.php new file mode 100644 index 0000000..ed1b927 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/Analysis/TypeAnalysis.php @@ -0,0 +1,125 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer\Analysis; + +/** + * @internal + */ +final class TypeAnalysis implements StartEndTokenAwareAnalysis +{ + /** + * This list contains soft and hard reserved types that can be used or will be used by PHP at some point. + * + * More info: + * + * @see https://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration.types + * @see https://php.net/manual/en/reserved.other-reserved-words.php + * @see https://php.net/manual/en/language.pseudo-types.php + * + * @var array + */ + private static $reservedTypes = [ + 'array', + 'bool', + 'callable', + 'int', + 'iterable', + 'float', + 'mixed', + 'numeric', + 'object', + 'resource', + 'self', + 'string', + 'void', + ]; + + /** + * @var string + */ + private $name; + + /** + * @var int + */ + private $startIndex; + + /** + * @var int + */ + private $endIndex; + + /** + * @var bool + */ + private $nullable; + + /** + * @param string $name + * @param int $startIndex + * @param int $endIndex + */ + public function __construct($name, $startIndex, $endIndex) + { + $this->name = $name; + $this->nullable = false; + + if (0 === strpos($name, '?')) { + $this->name = substr($name, 1); + $this->nullable = true; + } + + $this->startIndex = $startIndex; + $this->endIndex = $endIndex; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return int + */ + public function getStartIndex() + { + return $this->startIndex; + } + + /** + * @return int + */ + public function getEndIndex() + { + return $this->endIndex; + } + + /** + * @return bool + */ + public function isReservedType() + { + return \in_array($this->name, self::$reservedTypes, true); + } + + /** + * @return bool + */ + public function isNullable() + { + return $this->nullable; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ArgumentsAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ArgumentsAnalyzer.php new file mode 100644 index 0000000..0eb87c1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ArgumentsAnalyzer.php @@ -0,0 +1,159 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\Analyzer\Analysis\ArgumentAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\TypeAnalysis; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Vladimir Reznichenko <kalessil@gmail.com> + * + * @internal + */ +final class ArgumentsAnalyzer +{ + /** + * Count amount of parameters in a function/method reference. + * + * @param int $openParenthesis + * @param int $closeParenthesis + * + * @return int + */ + public function countArguments(Tokens $tokens, $openParenthesis, $closeParenthesis) + { + return \count($this->getArguments($tokens, $openParenthesis, $closeParenthesis)); + } + + /** + * Returns start and end token indexes of arguments. + * + * Returns an array with each key being the first token of an + * argument and the value the last. Including non-function tokens + * such as comments and white space tokens, but without the separation + * tokens like '(', ',' and ')'. + * + * @param int $openParenthesis + * @param int $closeParenthesis + * + * @return array<int, int> + */ + public function getArguments(Tokens $tokens, $openParenthesis, $closeParenthesis) + { + $arguments = []; + $firstSensibleToken = $tokens->getNextMeaningfulToken($openParenthesis); + + if ($tokens[$firstSensibleToken]->equals(')')) { + return $arguments; + } + + $paramContentIndex = $openParenthesis + 1; + $argumentsStart = $paramContentIndex; + + for (; $paramContentIndex < $closeParenthesis; ++$paramContentIndex) { + $token = $tokens[$paramContentIndex]; + + // skip nested (), [], {} constructs + $blockDefinitionProbe = Tokens::detectBlockType($token); + + if (null !== $blockDefinitionProbe && true === $blockDefinitionProbe['isStart']) { + $paramContentIndex = $tokens->findBlockEnd($blockDefinitionProbe['type'], $paramContentIndex); + + continue; + } + + // if comma matched, increase arguments counter + if ($token->equals(',')) { + if ($tokens->getNextMeaningfulToken($paramContentIndex) === $closeParenthesis) { + break; // trailing ',' in function call (PHP 7.3) + } + + $arguments[$argumentsStart] = $paramContentIndex - 1; + $argumentsStart = $paramContentIndex + 1; + } + } + + $arguments[$argumentsStart] = $paramContentIndex - 1; + + return $arguments; + } + + /** + * @param int $argumentStart + * @param int $argumentEnd + * + * @return ArgumentAnalysis + */ + public function getArgumentInfo(Tokens $tokens, $argumentStart, $argumentEnd) + { + $info = [ + 'default' => null, + 'name' => null, + 'name_index' => null, + 'type' => null, + 'type_index_start' => null, + 'type_index_end' => null, + ]; + + $sawName = false; + + for ($index = $argumentStart; $index <= $argumentEnd; ++$index) { + $token = $tokens[$index]; + + if ( + $token->isComment() + || $token->isWhitespace() + || $token->isGivenKind([T_ELLIPSIS, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE]) + || $token->equals('&') + ) { + continue; + } + + if ($token->isGivenKind(T_VARIABLE)) { + $sawName = true; + $info['name_index'] = $index; + $info['name'] = $token->getContent(); + + continue; + } + + if ($token->equals('=')) { + continue; + } + + if (\defined('T_ATTRIBUTE') && $token->isGivenKind(T_ATTRIBUTE)) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ATTRIBUTE, $index); + + continue; + } + + if ($sawName) { + $info['default'] .= $token->getContent(); + } else { + $info['type_index_start'] = ($info['type_index_start'] > 0) ? $info['type_index_start'] : $index; + $info['type_index_end'] = $index; + $info['type'] .= $token->getContent(); + } + } + + return new ArgumentAnalysis( + $info['name'], + $info['name_index'], + $info['default'], + $info['type'] ? new TypeAnalysis($info['type'], $info['type_index_start'], $info['type_index_end']) : null + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/BlocksAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/BlocksAnalyzer.php new file mode 100644 index 0000000..8a1eb91 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/BlocksAnalyzer.php @@ -0,0 +1,67 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Kuba Werłos <werlos@gmail.com> + * + * @internal + */ +final class BlocksAnalyzer +{ + /** + * @param null|int $openIndex + * @param null|int $closeIndex + * + * @return bool + */ + public function isBlock(Tokens $tokens, $openIndex, $closeIndex) + { + if (null === $openIndex || null === $closeIndex) { + return false; + } + + if (!$tokens->offsetExists($openIndex)) { + return false; + } + + if (!$tokens->offsetExists($closeIndex)) { + return false; + } + + $blockType = $this->getBlockType($tokens[$openIndex]); + + if (null === $blockType) { + return false; + } + + return $closeIndex === $tokens->findBlockEnd($blockType, $openIndex); + } + + /** + * @return null|int + */ + private function getBlockType(Token $token) + { + foreach (Tokens::getBlockEdgeDefinitions() as $blockType => $definition) { + if ($token->equals($definition['start'])) { + return $blockType; + } + } + + return null; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ClassyAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ClassyAnalyzer.php new file mode 100644 index 0000000..8abb73e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ClassyAnalyzer.php @@ -0,0 +1,82 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +final class ClassyAnalyzer +{ + /** + * @param int $index + * + * @return bool + */ + public function isClassyInvocation(Tokens $tokens, $index) + { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_STRING)) { + throw new \LogicException(sprintf('No T_STRING at given index %d, got "%s".', $index, $tokens[$index]->getName())); + } + + if (\in_array(strtolower($token->getContent()), ['bool', 'float', 'int', 'iterable', 'object', 'parent', 'self', 'string', 'void', 'null', 'false'], true)) { + return false; + } + + $next = $tokens->getNextMeaningfulToken($index); + $nextToken = $tokens[$next]; + + if ($nextToken->isGivenKind(T_NS_SEPARATOR)) { + return false; + } + + if ($nextToken->isGivenKind([T_DOUBLE_COLON, T_ELLIPSIS, CT::T_TYPE_ALTERNATION, T_VARIABLE])) { + return true; + } + + $prev = $tokens->getPrevMeaningfulToken($index); + + while ($tokens[$prev]->isGivenKind([CT::T_NAMESPACE_OPERATOR, T_NS_SEPARATOR, T_STRING])) { + $prev = $tokens->getPrevMeaningfulToken($prev); + } + + $prevToken = $tokens[$prev]; + + if ($prevToken->isGivenKind([T_EXTENDS, T_INSTANCEOF, T_INSTEADOF, T_IMPLEMENTS, T_NEW, CT::T_NULLABLE_TYPE, CT::T_TYPE_ALTERNATION, CT::T_TYPE_COLON, CT::T_USE_TRAIT])) { + return true; + } + + // `Foo & $bar` could be: + // - function reference parameter: function baz(Foo & $bar) {} + // - bit operator: $x = Foo & $bar; + if ($nextToken->equals('&') && $tokens[$tokens->getNextMeaningfulToken($next)]->isGivenKind(T_VARIABLE)) { + $checkIndex = $tokens->getPrevTokenOfKind($prev + 1, [';', '{', '}', [T_FUNCTION], [T_OPEN_TAG], [T_OPEN_TAG_WITH_ECHO]]); + + return $tokens[$checkIndex]->isGivenKind(T_FUNCTION); + } + + if (!$prevToken->equals(',')) { + return false; + } + + do { + $prev = $tokens->getPrevMeaningfulToken($prev); + } while ($tokens[$prev]->equalsAny([',', [T_NS_SEPARATOR], [T_STRING], [CT::T_NAMESPACE_OPERATOR]])); + + return $tokens[$prev]->isGivenKind([T_IMPLEMENTS, CT::T_USE_TRAIT]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/CommentsAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/CommentsAnalyzer.php new file mode 100644 index 0000000..8bef550 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/CommentsAnalyzer.php @@ -0,0 +1,322 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Kuba Werłos <werlos@gmail.com> + * @author SpacePossum + * + * @internal + */ +final class CommentsAnalyzer +{ + const TYPE_HASH = 1; + const TYPE_DOUBLE_SLASH = 2; + const TYPE_SLASH_ASTERISK = 3; + + /** + * @param int $index + * + * @return bool + */ + public function isHeaderComment(Tokens $tokens, $index) + { + if (!$tokens[$index]->isGivenKind([T_COMMENT, T_DOC_COMMENT])) { + throw new \InvalidArgumentException('Given index must point to a comment.'); + } + + if (null === $tokens->getNextMeaningfulToken($index)) { + return false; + } + + $prevIndex = $tokens->getPrevNonWhitespace($index); + + if ($tokens[$prevIndex]->equals(';')) { + $braceCloseIndex = $tokens->getPrevMeaningfulToken($prevIndex); + if (!$tokens[$braceCloseIndex]->equals(')')) { + return false; + } + + $braceOpenIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $braceCloseIndex); + $declareIndex = $tokens->getPrevMeaningfulToken($braceOpenIndex); + if (!$tokens[$declareIndex]->isGivenKind(T_DECLARE)) { + return false; + } + + $prevIndex = $tokens->getPrevNonWhitespace($declareIndex); + } + + return $tokens[$prevIndex]->isGivenKind(T_OPEN_TAG); + } + + /** + * Check if comment at given index precedes structural element. + * + * @see https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md#3-definitions + * + * @param int $index + * + * @return bool + */ + public function isBeforeStructuralElement(Tokens $tokens, $index) + { + $token = $tokens[$index]; + + if (!$token->isGivenKind([T_COMMENT, T_DOC_COMMENT])) { + throw new \InvalidArgumentException('Given index must point to a comment.'); + } + + $nextIndex = $index; + do { + $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); + + // @TODO: drop condition when PHP 8.0+ is required + if (\defined('T_ATTRIBUTE')) { + while (null !== $nextIndex && $tokens[$nextIndex]->isGivenKind(T_ATTRIBUTE)) { + $nextIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ATTRIBUTE, $nextIndex); + $nextIndex = $tokens->getNextMeaningfulToken($nextIndex); + } + } + } while (null !== $nextIndex && $tokens[$nextIndex]->equals('(')); + + if (null === $nextIndex || $tokens[$nextIndex]->equals('}')) { + return false; + } + + $nextToken = $tokens[$nextIndex]; + + if ($this->isStructuralElement($nextToken)) { + return true; + } + + if ($this->isValidControl($tokens, $token, $nextIndex)) { + return true; + } + + if ($this->isValidVariable($tokens, $nextIndex)) { + return true; + } + + if ($this->isValidLanguageConstruct($tokens, $token, $nextIndex)) { + return true; + } + + return false; + } + + /** + * Return array of indices that are part of a comment started at given index. + * + * @param int $index T_COMMENT index + * + * @return null|array + */ + public function getCommentBlockIndices(Tokens $tokens, $index) + { + if (!$tokens[$index]->isGivenKind(T_COMMENT)) { + throw new \InvalidArgumentException('Given index must point to a comment.'); + } + + $commentType = $this->getCommentType($tokens[$index]->getContent()); + $indices = [$index]; + + if (self::TYPE_SLASH_ASTERISK === $commentType) { + return $indices; + } + + $count = \count($tokens); + ++$index; + + for (; $index < $count; ++$index) { + if ($tokens[$index]->isComment()) { + if ($commentType === $this->getCommentType($tokens[$index]->getContent())) { + $indices[] = $index; + + continue; + } + + break; + } + + if (!$tokens[$index]->isWhitespace() || $this->getLineBreakCount($tokens, $index, $index + 1) > 1) { + break; + } + } + + return $indices; + } + + /** + * @see https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md#3-definitions + * + * @return bool + */ + private function isStructuralElement(Token $token) + { + static $skip = [ + T_PRIVATE, + T_PROTECTED, + T_PUBLIC, + T_VAR, + T_FUNCTION, + T_ABSTRACT, + T_CONST, + T_NAMESPACE, + T_REQUIRE, + T_REQUIRE_ONCE, + T_INCLUDE, + T_INCLUDE_ONCE, + T_FINAL, + T_STATIC, + ]; + + return $token->isClassy() || $token->isGivenKind($skip); + } + + /** + * Checks control structures (for, foreach, if, switch, while) for correct docblock usage. + * + * @param Token $docsToken docs Token + * @param int $controlIndex index of control structure Token + * + * @return bool + */ + private function isValidControl(Tokens $tokens, Token $docsToken, $controlIndex) + { + static $controlStructures = [ + T_FOR, + T_FOREACH, + T_IF, + T_SWITCH, + T_WHILE, + ]; + + if (!$tokens[$controlIndex]->isGivenKind($controlStructures)) { + return false; + } + + $index = $tokens->getNextMeaningfulToken($controlIndex); + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + $docsContent = $docsToken->getContent(); + + for ($index = $index + 1; $index < $endIndex; ++$index) { + $token = $tokens[$index]; + + if ( + $token->isGivenKind(T_VARIABLE) + && false !== strpos($docsContent, $token->getContent()) + ) { + return true; + } + } + + return false; + } + + /** + * Checks variable assignments through `list()`, `print()` etc. calls for correct docblock usage. + * + * @param Token $docsToken docs Token + * @param int $languageConstructIndex index of variable Token + * + * @return bool + */ + private function isValidLanguageConstruct(Tokens $tokens, Token $docsToken, $languageConstructIndex) + { + static $languageStructures = [ + T_LIST, + T_PRINT, + T_ECHO, + CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN, + ]; + + if (!$tokens[$languageConstructIndex]->isGivenKind($languageStructures)) { + return false; + } + + $endKind = $tokens[$languageConstructIndex]->isGivenKind(CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN) + ? [CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE] + : ')'; + + $endIndex = $tokens->getNextTokenOfKind($languageConstructIndex, [$endKind]); + + $docsContent = $docsToken->getContent(); + + for ($index = $languageConstructIndex + 1; $index < $endIndex; ++$index) { + $token = $tokens[$index]; + + if ($token->isGivenKind(T_VARIABLE) && false !== strpos($docsContent, $token->getContent())) { + return true; + } + } + + return false; + } + + /** + * Checks variable assignments for correct docblock usage. + * + * @param int $index index of variable Token + * + * @return bool + */ + private function isValidVariable(Tokens $tokens, $index) + { + if (!$tokens[$index]->isGivenKind(T_VARIABLE)) { + return false; + } + + $nextIndex = $tokens->getNextMeaningfulToken($index); + + return $tokens[$nextIndex]->equals('='); + } + + /** + * @param string $content + * + * @return int + */ + private function getCommentType($content) + { + if ('#' === $content[0]) { + return self::TYPE_HASH; + } + + if ('*' === $content[1]) { + return self::TYPE_SLASH_ASTERISK; + } + + return self::TYPE_DOUBLE_SLASH; + } + + /** + * @param int $whiteStart + * @param int $whiteEnd + * + * @return int + */ + private function getLineBreakCount(Tokens $tokens, $whiteStart, $whiteEnd) + { + $lineCount = 0; + for ($i = $whiteStart; $i < $whiteEnd; ++$i) { + $lineCount += Preg::matchAll('/\R/u', $tokens[$i]->getContent()); + } + + return $lineCount; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/FunctionsAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/FunctionsAnalyzer.php new file mode 100644 index 0000000..feee3d4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/FunctionsAnalyzer.php @@ -0,0 +1,275 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\Analyzer\Analysis\ArgumentAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\TypeAnalysis; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +final class FunctionsAnalyzer +{ + /** + * @var array + */ + private $functionsAnalysis = ['tokens' => '', 'imports' => [], 'declarations' => []]; + + /** + * Important: risky because of the limited (file) scope of the tool. + * + * @param int $index + * + * @return bool + */ + public function isGlobalFunctionCall(Tokens $tokens, $index) + { + if (!$tokens[$index]->isGivenKind(T_STRING)) { + return false; + } + + $nextIndex = $tokens->getNextMeaningfulToken($index); + + if (!$tokens[$nextIndex]->equals('(')) { + return false; + } + + $previousIsNamespaceSeparator = false; + $prevIndex = $tokens->getPrevMeaningfulToken($index); + + if ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + $previousIsNamespaceSeparator = true; + $prevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + } + + $possibleKind = array_merge([T_DOUBLE_COLON, T_FUNCTION, CT::T_NAMESPACE_OPERATOR, T_NEW, CT::T_RETURN_REF, T_STRING], Token::getObjectOperatorKinds()); + + // @TODO: drop condition when PHP 8.0+ is required + if (\defined('T_ATTRIBUTE')) { + $possibleKind[] = T_ATTRIBUTE; + } + + if ($tokens[$prevIndex]->isGivenKind($possibleKind)) { + return false; + } + + if ($previousIsNamespaceSeparator) { + return true; + } + + if ($tokens->isChanged() || $tokens->getCodeHash() !== $this->functionsAnalysis['tokens']) { + $this->buildFunctionsAnalysis($tokens); + } + + // figure out in which namespace we are + $namespaceAnalyzer = new NamespacesAnalyzer(); + + $declarations = $namespaceAnalyzer->getDeclarations($tokens); + $scopeStartIndex = 0; + $scopeEndIndex = \count($tokens) - 1; + $inGlobalNamespace = false; + + foreach ($declarations as $declaration) { + $scopeStartIndex = $declaration->getScopeStartIndex(); + $scopeEndIndex = $declaration->getScopeEndIndex(); + + if ($index >= $scopeStartIndex && $index <= $scopeEndIndex) { + $inGlobalNamespace = '' === $declaration->getFullName(); + + break; + } + } + + $call = strtolower($tokens[$index]->getContent()); + + // check if the call is to a function declared in the same namespace as the call is done, + // if the call is already in the global namespace than declared functions are in the same + // global namespace and don't need checking + + if (!$inGlobalNamespace) { + /** @var int $functionNameIndex */ + foreach ($this->functionsAnalysis['declarations'] as $functionNameIndex) { + if ($functionNameIndex < $scopeStartIndex || $functionNameIndex > $scopeEndIndex) { + continue; + } + + if (strtolower($tokens[$functionNameIndex]->getContent()) === $call) { + return false; + } + } + } + + /** @var NamespaceUseAnalysis $functionUse */ + foreach ($this->functionsAnalysis['imports'] as $functionUse) { + if ($functionUse->getStartIndex() < $scopeStartIndex || $functionUse->getEndIndex() > $scopeEndIndex) { + continue; + } + + if ($call !== strtolower($functionUse->getShortName())) { + continue; + } + + // global import like `use function \str_repeat;` + return $functionUse->getShortName() === ltrim($functionUse->getFullName(), '\\'); + } + + return true; + } + + /** + * @param int $methodIndex + * + * @return ArgumentAnalysis[] + */ + public function getFunctionArguments(Tokens $tokens, $methodIndex) + { + $argumentsStart = $tokens->getNextTokenOfKind($methodIndex, ['(']); + $argumentsEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $argumentsStart); + $argumentAnalyzer = new ArgumentsAnalyzer(); + $arguments = []; + + foreach ($argumentAnalyzer->getArguments($tokens, $argumentsStart, $argumentsEnd) as $start => $end) { + $argumentInfo = $argumentAnalyzer->getArgumentInfo($tokens, $start, $end); + $arguments[$argumentInfo->getName()] = $argumentInfo; + } + + return $arguments; + } + + /** + * @param int $methodIndex + * + * @return null|TypeAnalysis + */ + public function getFunctionReturnType(Tokens $tokens, $methodIndex) + { + $argumentsStart = $tokens->getNextTokenOfKind($methodIndex, ['(']); + $argumentsEnd = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $argumentsStart); + $typeColonIndex = $tokens->getNextMeaningfulToken($argumentsEnd); + + if (!$tokens[$typeColonIndex]->isGivenKind(CT::T_TYPE_COLON)) { + return null; + } + + $type = ''; + $typeStartIndex = $tokens->getNextMeaningfulToken($typeColonIndex); + $typeEndIndex = $typeStartIndex; + $functionBodyStart = $tokens->getNextTokenOfKind($typeColonIndex, ['{', ';', [T_DOUBLE_ARROW]]); + + for ($i = $typeStartIndex; $i < $functionBodyStart; ++$i) { + if ($tokens[$i]->isWhitespace() || $tokens[$i]->isComment()) { + continue; + } + + $type .= $tokens[$i]->getContent(); + $typeEndIndex = $i; + } + + return new TypeAnalysis($type, $typeStartIndex, $typeEndIndex); + } + + /** + * @param int $index + * + * @return bool + */ + public function isTheSameClassCall(Tokens $tokens, $index) + { + if (!$tokens->offsetExists($index)) { + return false; + } + + $operatorIndex = $tokens->getPrevMeaningfulToken($index); + + if (null === $operatorIndex) { + return false; + } + + if (!$tokens[$operatorIndex]->isObjectOperator() && !$tokens[$operatorIndex]->isGivenKind(T_DOUBLE_COLON)) { + return false; + } + + $referenceIndex = $tokens->getPrevMeaningfulToken($operatorIndex); + + if (null === $referenceIndex) { + return false; + } + + return $tokens[$referenceIndex]->equalsAny([[T_VARIABLE, '$this'], [T_STRING, 'self'], [T_STATIC, 'static']], false); + } + + private function buildFunctionsAnalysis(Tokens $tokens) + { + $this->functionsAnalysis = [ + 'tokens' => $tokens->getCodeHash(), + 'imports' => [], + 'declarations' => [], + ]; + + // find declarations + + if ($tokens->isTokenKindFound(T_FUNCTION)) { + $end = \count($tokens); + + for ($i = 0; $i < $end; ++$i) { + // skip classy, we are looking for functions not methods + if ($tokens[$i]->isGivenKind(Token::getClassyTokenKinds())) { + $i = $tokens->getNextTokenOfKind($i, ['(', '{']); + + if ($tokens[$i]->equals('(')) { // anonymous class + $i = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $i); + $i = $tokens->getNextTokenOfKind($i, ['{']); + } + + $i = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $i); + + continue; + } + + if (!$tokens[$i]->isGivenKind(T_FUNCTION)) { + continue; + } + + $i = $tokens->getNextMeaningfulToken($i); + + if ($tokens[$i]->isGivenKind(CT::T_RETURN_REF)) { + $i = $tokens->getNextMeaningfulToken($i); + } + + if (!$tokens[$i]->isGivenKind(T_STRING)) { + continue; + } + + $this->functionsAnalysis['declarations'][] = $i; + } + } + + // find imported functions + + $namespaceUsesAnalyzer = new NamespaceUsesAnalyzer(); + + if ($tokens->isTokenKindFound(CT::T_FUNCTION_IMPORT)) { + $declarations = $namespaceUsesAnalyzer->getDeclarationsFromTokens($tokens); + + foreach ($declarations as $declaration) { + if ($declaration->isFunction()) { + $this->functionsAnalysis['imports'][] = $declaration; + } + } + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/GotoLabelAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/GotoLabelAnalyzer.php new file mode 100644 index 0000000..4028217 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/GotoLabelAnalyzer.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +final class GotoLabelAnalyzer +{ + /** + * @param int $index + * + * @return bool + */ + public function belongsToGoToLabel(Tokens $tokens, $index) + { + if (!$tokens[$index]->equals(':')) { + return false; + } + + $prevMeaningfulTokenIndex = $tokens->getPrevMeaningfulToken($index); + + if (!$tokens[$prevMeaningfulTokenIndex]->isGivenKind(T_STRING)) { + return false; + } + + $prevMeaningfulTokenIndex = $tokens->getPrevMeaningfulToken($prevMeaningfulTokenIndex); + + return $tokens[$prevMeaningfulTokenIndex]->equalsAny([';', '{', '}', [T_OPEN_TAG]]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/NamespaceUsesAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/NamespaceUsesAnalyzer.php new file mode 100644 index 0000000..63ffc64 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/NamespaceUsesAnalyzer.php @@ -0,0 +1,122 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\TokensAnalyzer; + +/** + * @internal + */ +final class NamespaceUsesAnalyzer +{ + /** + * @return NamespaceUseAnalysis[] + */ + public function getDeclarationsFromTokens(Tokens $tokens) + { + $tokenAnalyzer = new TokensAnalyzer($tokens); + $useIndexes = $tokenAnalyzer->getImportUseIndexes(); + + return $this->getDeclarations($tokens, $useIndexes); + } + + /** + * @return NamespaceUseAnalysis[] + */ + public function getDeclarationsInNamespace(Tokens $tokens, NamespaceAnalysis $namespace) + { + $namespaceUses = []; + + foreach ($this->getDeclarationsFromTokens($tokens) as $namespaceUse) { + if ($namespaceUse->getStartIndex() >= $namespace->getScopeStartIndex() && $namespaceUse->getStartIndex() <= $namespace->getScopeEndIndex()) { + $namespaceUses[] = $namespaceUse; + } + } + + return $namespaceUses; + } + + /** + * @return NamespaceUseAnalysis[] + */ + private function getDeclarations(Tokens $tokens, array $useIndexes) + { + $uses = []; + + foreach ($useIndexes as $index) { + $endIndex = $tokens->getNextTokenOfKind($index, [';', [T_CLOSE_TAG]]); + $analysis = $this->parseDeclaration($tokens, $index, $endIndex); + if ($analysis) { + $uses[] = $analysis; + } + } + + return $uses; + } + + /** + * @param int $startIndex + * @param int $endIndex + * + * @return null|NamespaceUseAnalysis + */ + private function parseDeclaration(Tokens $tokens, $startIndex, $endIndex) + { + $fullName = $shortName = ''; + $aliased = false; + + $type = NamespaceUseAnalysis::TYPE_CLASS; + for ($i = $startIndex; $i <= $endIndex; ++$i) { + $token = $tokens[$i]; + if ($token->equals(',') || $token->isGivenKind(CT::T_GROUP_IMPORT_BRACE_CLOSE)) { + // do not touch group use declarations until the logic of this is added (for example: `use some\a\{ClassD};`) + // ignore multiple use statements that should be split into few separate statements (for example: `use BarB, BarC as C;`) + return null; + } + + if ($token->isGivenKind(CT::T_FUNCTION_IMPORT)) { + $type = NamespaceUseAnalysis::TYPE_FUNCTION; + } elseif ($token->isGivenKind(CT::T_CONST_IMPORT)) { + $type = NamespaceUseAnalysis::TYPE_CONSTANT; + } + + if ($token->isWhitespace() || $token->isComment() || $token->isGivenKind(T_USE)) { + continue; + } + + if ($token->isGivenKind(T_STRING)) { + $shortName = $token->getContent(); + if (!$aliased) { + $fullName .= $shortName; + } + } elseif ($token->isGivenKind(T_NS_SEPARATOR)) { + $fullName .= $token->getContent(); + } elseif ($token->isGivenKind(T_AS)) { + $aliased = true; + } + } + + return new NamespaceUseAnalysis( + trim($fullName), + $shortName, + $aliased, + $startIndex, + $endIndex, + $type + ); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/NamespacesAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/NamespacesAnalyzer.php new file mode 100644 index 0000000..fc8f414 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/NamespacesAnalyzer.php @@ -0,0 +1,91 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +final class NamespacesAnalyzer +{ + /** + * @return NamespaceAnalysis[] + */ + public function getDeclarations(Tokens $tokens) + { + $namespaces = []; + + for ($index = 1, $count = \count($tokens); $index < $count; ++$index) { + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_NAMESPACE)) { + continue; + } + + $declarationEndIndex = $tokens->getNextTokenOfKind($index, [';', '{']); + $namespace = trim($tokens->generatePartialCode($index + 1, $declarationEndIndex - 1)); + $declarationParts = explode('\\', $namespace); + $shortName = end($declarationParts); + + if ($tokens[$declarationEndIndex]->equals('{')) { + $scopeEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $declarationEndIndex); + } else { + $scopeEndIndex = $tokens->getNextTokenOfKind($declarationEndIndex, [[T_NAMESPACE]]); + if (null === $scopeEndIndex) { + $scopeEndIndex = \count($tokens); + } + --$scopeEndIndex; + } + + $namespaces[] = new NamespaceAnalysis( + $namespace, + $shortName, + $index, + $declarationEndIndex, + $index, + $scopeEndIndex + ); + + // Continue the analysis after the end of this namespace to find the next one + $index = $scopeEndIndex; + } + + if (0 === \count($namespaces)) { + $namespaces[] = new NamespaceAnalysis('', '', 0, 0, 0, \count($tokens) - 1); + } + + return $namespaces; + } + + /** + * @param int $index + * + * @return NamespaceAnalysis + */ + public function getNamespaceAt(Tokens $tokens, $index) + { + if (!$tokens->offsetExists($index)) { + throw new \InvalidArgumentException("Token index {$index} does not exist."); + } + + foreach ($this->getDeclarations($tokens) as $namespace) { + if ($namespace->getScopeStartIndex() <= $index && $namespace->getScopeEndIndex() >= $index) { + return $namespace; + } + } + + throw new \LogicException("Unable to get the namespace at index {$index}."); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ReferenceAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ReferenceAnalyzer.php new file mode 100644 index 0000000..0e8e31c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/ReferenceAnalyzer.php @@ -0,0 +1,52 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Kuba Werłos <werlos@gmail.com> + * + * @internal + */ +final class ReferenceAnalyzer +{ + /** + * @param int $index + * + * @return bool + */ + public function isReference(Tokens $tokens, $index) + { + if ($tokens[$index]->isGivenKind(CT::T_RETURN_REF)) { + return true; + } + + if (!$tokens[$index]->equals('&')) { + return false; + } + + /** @var int $index */ + $index = $tokens->getPrevMeaningfulToken($index); + if ($tokens[$index]->equalsAny(['=', [T_AS], [T_CALLABLE], [T_DOUBLE_ARROW], [CT::T_ARRAY_TYPEHINT]])) { + return true; + } + + if ($tokens[$index]->isGivenKind(T_STRING)) { + $index = $tokens->getPrevMeaningfulToken($index); + } + + return $tokens[$index]->equalsAny(['(', ',', [T_NS_SEPARATOR], [CT::T_NULLABLE_TYPE]]); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/SwitchAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/SwitchAnalyzer.php new file mode 100644 index 0000000..a81e3bc --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/SwitchAnalyzer.php @@ -0,0 +1,140 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\Analyzer\Analysis\CaseAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\SwitchAnalysis; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Kuba Werłos <werlos@gmail.com> + * + * @internal + */ +final class SwitchAnalyzer +{ + /** + * @param int $switchIndex + * + * @return SwitchAnalysis + */ + public function getSwitchAnalysis(Tokens $tokens, $switchIndex) + { + if (!$tokens[$switchIndex]->isGivenKind(T_SWITCH)) { + throw new \InvalidArgumentException(sprintf('Index %d is not "switch".', $switchIndex)); + } + + $casesStartIndex = $this->getCasesStart($tokens, $switchIndex); + $casesEndIndex = $this->getCasesEnd($tokens, $casesStartIndex); + + $cases = []; + $index = $casesStartIndex; + while ($index < $casesEndIndex) { + $index = $this->getNextSameLevelToken($tokens, $index); + + if (!$tokens[$index]->isGivenKind([T_CASE, T_DEFAULT])) { + continue; + } + + $caseAnalysis = $this->getCaseAnalysis($tokens, $index); + + $cases[] = $caseAnalysis; + } + + return new SwitchAnalysis($casesStartIndex, $casesEndIndex, $cases); + } + + /** + * @param int $switchIndex + * + * @return int + */ + private function getCasesStart(Tokens $tokens, $switchIndex) + { + /** @var int $parenthesisStartIndex */ + $parenthesisStartIndex = $tokens->getNextMeaningfulToken($switchIndex); + $parenthesisEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $parenthesisStartIndex); + + $casesStartIndex = $tokens->getNextMeaningfulToken($parenthesisEndIndex); + \assert(\is_int($casesStartIndex)); + + return $casesStartIndex; + } + + /** + * @param int $casesStartIndex + * + * @return int + */ + private function getCasesEnd(Tokens $tokens, $casesStartIndex) + { + if ($tokens[$casesStartIndex]->equals('{')) { + return $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $casesStartIndex); + } + + $index = $casesStartIndex; + while ($index < $tokens->count()) { + $index = $this->getNextSameLevelToken($tokens, $index); + + if ($tokens[$index]->isGivenKind(T_ENDSWITCH)) { + break; + } + } + + $afterEndswitchIndex = $tokens->getNextMeaningfulToken($index); + + $afterEndswitchToken = $tokens[$afterEndswitchIndex]; + + return $afterEndswitchToken->equalsAny([';', [T_CLOSE_TAG]]) ? $afterEndswitchIndex : $index; + } + + /** + * @param int $index + * + * @return CaseAnalysis + */ + private function getCaseAnalysis(Tokens $tokens, $index) + { + while ($index < $tokens->count()) { + $index = $this->getNextSameLevelToken($tokens, $index); + + if ($tokens[$index]->equalsAny([':', ';'])) { + break; + } + } + + return new CaseAnalysis($index); + } + + /** + * @param int $index + * + * @return int + */ + private function getNextSameLevelToken(Tokens $tokens, $index) + { + $index = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$index]->isGivenKind(T_SWITCH)) { + return (new self())->getSwitchAnalysis($tokens, $index)->getCasesEnd(); + } + + /** @var null|array{isStart: bool, type: int} $blockType */ + $blockType = Tokens::detectBlockType($tokens[$index]); + if (null !== $blockType && $blockType['isStart']) { + return $tokens->findBlockEnd($blockType['type'], $index) + 1; + } + + return $index; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/WhitespacesAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/WhitespacesAnalyzer.php new file mode 100644 index 0000000..645dfcf --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Analyzer/WhitespacesAnalyzer.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Analyzer; + +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +final class WhitespacesAnalyzer +{ + /** + * @param int $index + * + * @return string + */ + public static function detectIndent(Tokens $tokens, $index) + { + while (true) { + $whitespaceIndex = $tokens->getPrevTokenOfKind($index, [[T_WHITESPACE]]); + + if (null === $whitespaceIndex) { + return ''; + } + + $whitespaceToken = $tokens[$whitespaceIndex]; + + if (false !== strpos($whitespaceToken->getContent(), "\n")) { + break; + } + + $prevToken = $tokens[$whitespaceIndex - 1]; + + if ($prevToken->isGivenKind([T_OPEN_TAG, T_COMMENT]) && "\n" === substr($prevToken->getContent(), -1)) { + break; + } + + $index = $whitespaceIndex; + } + + $explodedContent = explode("\n", $whitespaceToken->getContent()); + + return end($explodedContent); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/CT.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/CT.php new file mode 100644 index 0000000..06734d9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/CT.php @@ -0,0 +1,101 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class CT +{ + const T_ARRAY_INDEX_CURLY_BRACE_CLOSE = 10001; + const T_ARRAY_INDEX_CURLY_BRACE_OPEN = 10002; + const T_ARRAY_SQUARE_BRACE_CLOSE = 10003; + const T_ARRAY_SQUARE_BRACE_OPEN = 10004; + const T_ARRAY_TYPEHINT = 10005; + const T_BRACE_CLASS_INSTANTIATION_CLOSE = 10006; + const T_BRACE_CLASS_INSTANTIATION_OPEN = 10007; + const T_CLASS_CONSTANT = 10008; + const T_CONST_IMPORT = 10009; + const T_CURLY_CLOSE = 10010; + const T_DESTRUCTURING_SQUARE_BRACE_CLOSE = 10011; + const T_DESTRUCTURING_SQUARE_BRACE_OPEN = 10012; + const T_DOLLAR_CLOSE_CURLY_BRACES = 10013; + const T_DYNAMIC_PROP_BRACE_CLOSE = 10014; + const T_DYNAMIC_PROP_BRACE_OPEN = 10015; + const T_DYNAMIC_VAR_BRACE_CLOSE = 10016; + const T_DYNAMIC_VAR_BRACE_OPEN = 10017; + const T_FUNCTION_IMPORT = 10018; + const T_GROUP_IMPORT_BRACE_CLOSE = 10019; + const T_GROUP_IMPORT_BRACE_OPEN = 10020; + const T_NAMESPACE_OPERATOR = 10021; + const T_NULLABLE_TYPE = 10022; + const T_RETURN_REF = 10023; + const T_TYPE_ALTERNATION = 10024; + const T_TYPE_COLON = 10025; + const T_USE_LAMBDA = 10026; + const T_USE_TRAIT = 10027; + const T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC = 10028; + const T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED = 10029; + const T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE = 10030; + const T_ATTRIBUTE_CLOSE = 10031; + const T_NAMED_ARGUMENT_NAME = 10032; + const T_NAMED_ARGUMENT_COLON = 10033; + + private function __construct() + { + } + + /** + * Get name for custom token. + * + * @param int $value custom token value + * + * @return string + */ + public static function getName($value) + { + if (!self::has($value)) { + throw new \InvalidArgumentException(sprintf('No custom token was found for "%s".', $value)); + } + + $tokens = self::getMapById(); + + return 'CT::'.$tokens[$value]; + } + + /** + * Check if given custom token exists. + * + * @param int $value custom token value + * + * @return bool + */ + public static function has($value) + { + $tokens = self::getMapById(); + + return isset($tokens[$value]); + } + + private static function getMapById() + { + static $constants; + + if (null === $constants) { + $reflection = new \ReflectionClass(__CLASS__); + $constants = array_flip($reflection->getConstants()); + } + + return $constants; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/CodeHasher.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/CodeHasher.php new file mode 100644 index 0000000..27683c1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/CodeHasher.php @@ -0,0 +1,38 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class CodeHasher +{ + private function __construct() + { + // cannot create instance of util. class + } + + /** + * Calculate hash for code. + * + * @param string $code + * + * @return string + */ + public static function calculateCodeHash($code) + { + return (string) crc32($code); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Generator/NamespacedStringTokenGenerator.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Generator/NamespacedStringTokenGenerator.php new file mode 100644 index 0000000..aeb50c4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Generator/NamespacedStringTokenGenerator.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Generator; + +use PhpCsFixer\Tokenizer\Token; + +/** + * @internal + */ +final class NamespacedStringTokenGenerator +{ + /** + * Parse a string that contains a namespace into tokens. + * + * @param string $input + * + * @return Token[] + */ + public function generate($input) + { + $tokens = []; + $parts = explode('\\', $input); + + foreach ($parts as $index => $part) { + $tokens[] = new Token([T_STRING, $part]); + if ($index !== \count($parts) - 1) { + $tokens[] = new Token([T_NS_SEPARATOR, '\\']); + } + } + + return $tokens; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Resolver/TypeShortNameResolver.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Resolver/TypeShortNameResolver.php new file mode 100644 index 0000000..65bbd0e --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Resolver/TypeShortNameResolver.php @@ -0,0 +1,94 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Resolver; + +use PhpCsFixer\Preg; +use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis; +use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; +use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @internal + */ +final class TypeShortNameResolver +{ + /** + * This method will resolve the shortName of a FQCN if possible or otherwise return the inserted type name. + * E.g.: use Foo\Bar => "Bar". + * + * @param string $typeName + * + * @return string + */ + public function resolve(Tokens $tokens, $typeName) + { + // First match explicit imports: + $useMap = $this->getUseMapFromTokens($tokens); + foreach ($useMap as $shortName => $fullName) { + $regex = '/^\\\\?'.preg_quote($fullName, '/').'$/'; + if (Preg::match($regex, $typeName)) { + return $shortName; + } + } + + // Next try to match (partial) classes inside the same namespace + // For now only support one namespace per file: + $namespaces = $this->getNamespacesFromTokens($tokens); + if (1 === \count($namespaces)) { + foreach ($namespaces as $fullName) { + $matches = []; + $regex = '/^\\\\?'.preg_quote($fullName, '/').'\\\\(?P<className>.+)$/'; + if (Preg::match($regex, $typeName, $matches)) { + return $matches['className']; + } + } + } + + // Next: Try to match partial use statements: + + foreach ($useMap as $shortName => $fullName) { + $matches = []; + $regex = '/^\\\\?'.preg_quote($fullName, '/').'\\\\(?P<className>.+)$/'; + if (Preg::match($regex, $typeName, $matches)) { + return $shortName.'\\'.$matches['className']; + } + } + + return $typeName; + } + + /** + * @return array<string, string> A list of all FQN namespaces in the file with the short name as key + */ + private function getNamespacesFromTokens(Tokens $tokens) + { + return array_map(static function (NamespaceAnalysis $info) { + return $info->getFullName(); + }, (new NamespacesAnalyzer())->getDeclarations($tokens)); + } + + /** + * @return array<string, string> A list of all FQN use statements in the file with the short name as key + */ + private function getUseMapFromTokens(Tokens $tokens) + { + $map = []; + + foreach ((new NamespaceUsesAnalyzer())->getDeclarationsFromTokens($tokens) as $useDeclaration) { + $map[$useDeclaration->getShortName()] = $useDeclaration->getFullName(); + } + + return $map; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Token.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Token.php new file mode 100644 index 0000000..b592847 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Token.php @@ -0,0 +1,655 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer; + +use PhpCsFixer\Utils; + +/** + * Representation of single token. + * As a token prototype you should understand a single element generated by token_get_all. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +class Token +{ + /** + * Content of token prototype. + * + * @var string + */ + private $content; + + /** + * ID of token prototype, if available. + * + * @var null|int + */ + private $id; + + /** + * If token prototype is an array. + * + * @var bool + */ + private $isArray; + + /** + * Flag is token was changed. + * + * @var bool + */ + private $changed = false; + + /** + * @param array|string $token token prototype + */ + public function __construct($token) + { + if (\is_array($token)) { + if (!\is_int($token[0])) { + throw new \InvalidArgumentException(sprintf( + 'Id must be an int, got "%s".', + \is_object($token[0]) ? \get_class($token[0]) : \gettype($token[0]) + )); + } + + if (!\is_string($token[1])) { + throw new \InvalidArgumentException(sprintf( + 'Content must be a string, got "%s".', + \is_object($token[1]) ? \get_class($token[1]) : \gettype($token[1]) + )); + } + + if ('' === $token[1]) { + throw new \InvalidArgumentException('Cannot set empty content for id-based Token.'); + } + + $this->isArray = true; + $this->id = $token[0]; + $this->content = $token[1]; + } elseif (\is_string($token)) { + $this->isArray = false; + $this->content = $token; + } else { + throw new \InvalidArgumentException(sprintf( + 'Cannot recognize input value as valid Token prototype, got "%s".', + // @phpstan-ignore-next-line due to lack of strong typing of method parameter + \is_object($token) ? \get_class($token) : \gettype($token) + )); + } + } + + /** + * @return int[] + */ + public static function getCastTokenKinds() + { + static $castTokens = [T_ARRAY_CAST, T_BOOL_CAST, T_DOUBLE_CAST, T_INT_CAST, T_OBJECT_CAST, T_STRING_CAST, T_UNSET_CAST]; + + return $castTokens; + } + + /** + * Get classy tokens kinds: T_CLASS, T_INTERFACE and T_TRAIT. + * + * @return int[] + */ + public static function getClassyTokenKinds() + { + static $classTokens = [T_CLASS, T_TRAIT, T_INTERFACE]; + + return $classTokens; + } + + /** + * Get object operator tokens kinds: T_OBJECT_OPERATOR and (if available) T_NULLSAFE_OBJECT_OPERATOR. + * + * @return int[] + */ + public static function getObjectOperatorKinds() + { + static $objectOperators = null; + + if (null === $objectOperators) { + $objectOperators = [T_OBJECT_OPERATOR]; + if (\defined('T_NULLSAFE_OBJECT_OPERATOR')) { + $objectOperators[] = T_NULLSAFE_OBJECT_OPERATOR; + } + } + + return $objectOperators; + } + + /** + * Clear token at given index. + * + * Clearing means override token by empty string. + * + * @deprecated since 2.4 + */ + public function clear() + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated and will be removed in 3.0.')); + Tokens::setLegacyMode(true); + + $this->content = ''; + $this->id = null; + $this->isArray = false; + } + + /** + * Clear internal flag if token was changed. + * + * @deprecated since 2.4 + */ + public function clearChanged() + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated and will be removed in 3.0.')); + Tokens::setLegacyMode(true); + + $this->changed = false; + } + + /** + * Check if token is equals to given one. + * + * If tokens are arrays, then only keys defined in parameter token are checked. + * + * @param array|string|Token $other token or it's prototype + * @param bool $caseSensitive perform a case sensitive comparison + * + * @return bool + */ + public function equals($other, $caseSensitive = true) + { + if ($other instanceof self) { + // Inlined getPrototype() on this very hot path. + // We access the private properties of $other directly to save function call overhead. + // This is only possible because $other is of the same class as `self`. + if (!$other->isArray) { + $otherPrototype = $other->content; + } else { + $otherPrototype = [ + $other->id, + $other->content, + ]; + } + } else { + $otherPrototype = $other; + } + + if ($this->isArray !== \is_array($otherPrototype)) { + return false; + } + + if (!$this->isArray) { + return $this->content === $otherPrototype; + } + + if ($this->id !== $otherPrototype[0]) { + return false; + } + + if (isset($otherPrototype[1])) { + if ($caseSensitive) { + if ($this->content !== $otherPrototype[1]) { + return false; + } + } elseif (0 !== strcasecmp($this->content, $otherPrototype[1])) { + return false; + } + } + + // detect unknown keys + unset($otherPrototype[0], $otherPrototype[1]); + + return empty($otherPrototype); + } + + /** + * Check if token is equals to one of given. + * + * @param array $others array of tokens or token prototypes + * @param bool $caseSensitive perform a case sensitive comparison + * + * @return bool + */ + public function equalsAny(array $others, $caseSensitive = true) + { + foreach ($others as $other) { + if ($this->equals($other, $caseSensitive)) { + return true; + } + } + + return false; + } + + /** + * A helper method used to find out whether or not a certain input token has to be case-sensitively matched. + * + * @param array<int, bool>|bool $caseSensitive global case sensitiveness or an array of booleans, whose keys should match + * the ones used in $others. If any is missing, the default case-sensitive + * comparison is used + * @param int $key the key of the token that has to be looked up + * + * @return bool + */ + public static function isKeyCaseSensitive($caseSensitive, $key) + { + if (\is_array($caseSensitive)) { + return isset($caseSensitive[$key]) ? $caseSensitive[$key] : true; + } + + return $caseSensitive; + } + + /** + * @return array|string token prototype + */ + public function getPrototype() + { + if (!$this->isArray) { + return $this->content; + } + + return [ + $this->id, + $this->content, + ]; + } + + /** + * Get token's content. + * + * It shall be used only for getting the content of token, not for checking it against excepted value. + * + * @return string + */ + public function getContent() + { + return $this->content; + } + + /** + * Get token's id. + * + * It shall be used only for getting the internal id of token, not for checking it against excepted value. + * + * @return null|int + */ + public function getId() + { + return $this->id; + } + + /** + * Get token's name. + * + * It shall be used only for getting the name of token, not for checking it against excepted value. + * + * @return null|string token name + */ + public function getName() + { + if (null === $this->id) { + return null; + } + + return self::getNameForId($this->id); + } + + /** + * Get token's name. + * + * It shall be used only for getting the name of token, not for checking it against excepted value. + * + * @param int $id + * + * @return null|string token name + */ + public static function getNameForId($id) + { + if (CT::has($id)) { + return CT::getName($id); + } + + $name = token_name($id); + + return 'UNKNOWN' === $name ? null : $name; + } + + /** + * Generate array containing all keywords that exists in PHP version in use. + * + * @return array<int, int> + */ + public static function getKeywords() + { + static $keywords = null; + + if (null === $keywords) { + $keywords = self::getTokenKindsForNames(['T_ABSTRACT', 'T_ARRAY', 'T_AS', 'T_BREAK', 'T_CALLABLE', 'T_CASE', + 'T_CATCH', 'T_CLASS', 'T_CLONE', 'T_CONST', 'T_CONTINUE', 'T_DECLARE', 'T_DEFAULT', 'T_DO', + 'T_ECHO', 'T_ELSE', 'T_ELSEIF', 'T_EMPTY', 'T_ENDDECLARE', 'T_ENDFOR', 'T_ENDFOREACH', + 'T_ENDIF', 'T_ENDSWITCH', 'T_ENDWHILE', 'T_EVAL', 'T_EXIT', 'T_EXTENDS', 'T_FINAL', + 'T_FINALLY', 'T_FN', 'T_FOR', 'T_FOREACH', 'T_FUNCTION', 'T_GLOBAL', 'T_GOTO', 'T_HALT_COMPILER', + 'T_IF', 'T_IMPLEMENTS', 'T_INCLUDE', 'T_INCLUDE_ONCE', 'T_INSTANCEOF', 'T_INSTEADOF', + 'T_INTERFACE', 'T_ISSET', 'T_LIST', 'T_LOGICAL_AND', 'T_LOGICAL_OR', 'T_LOGICAL_XOR', + 'T_NAMESPACE', 'T_MATCH', 'T_NEW', 'T_PRINT', 'T_PRIVATE', 'T_PROTECTED', 'T_PUBLIC', 'T_REQUIRE', + 'T_REQUIRE_ONCE', 'T_RETURN', 'T_STATIC', 'T_SWITCH', 'T_THROW', 'T_TRAIT', 'T_TRY', + 'T_UNSET', 'T_USE', 'T_VAR', 'T_WHILE', 'T_YIELD', 'T_YIELD_FROM', + ]) + [ + CT::T_ARRAY_TYPEHINT => CT::T_ARRAY_TYPEHINT, + CT::T_CLASS_CONSTANT => CT::T_CLASS_CONSTANT, + CT::T_CONST_IMPORT => CT::T_CONST_IMPORT, + CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE, + CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, + CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC => CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, + CT::T_FUNCTION_IMPORT => CT::T_FUNCTION_IMPORT, + CT::T_NAMESPACE_OPERATOR => CT::T_NAMESPACE_OPERATOR, + CT::T_USE_LAMBDA => CT::T_USE_LAMBDA, + CT::T_USE_TRAIT => CT::T_USE_TRAIT, + ]; + } + + return $keywords; + } + + /** + * Generate array containing all predefined constants that exists in PHP version in use. + * + * @see https://php.net/manual/en/language.constants.predefined.php + * + * @return array<int, int> + */ + public static function getMagicConstants() + { + static $magicConstants = null; + + if (null === $magicConstants) { + $magicConstants = self::getTokenKindsForNames(['T_CLASS_C', 'T_DIR', 'T_FILE', 'T_FUNC_C', 'T_LINE', 'T_METHOD_C', 'T_NS_C', 'T_TRAIT_C']); + } + + return $magicConstants; + } + + /** + * Check if token prototype is an array. + * + * @return bool is array + */ + public function isArray() + { + return $this->isArray; + } + + /** + * Check if token is one of type cast tokens. + * + * @return bool + */ + public function isCast() + { + return $this->isGivenKind(self::getCastTokenKinds()); + } + + /** + * Check if token was changed. + * + * @return bool + * + * @deprecated since 2.4 + */ + public function isChanged() + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated and will be removed in 3.0.')); + + return $this->changed; + } + + /** + * Check if token is one of classy tokens: T_CLASS, T_INTERFACE or T_TRAIT. + * + * @return bool + */ + public function isClassy() + { + return $this->isGivenKind(self::getClassyTokenKinds()); + } + + /** + * Check if token is one of comment tokens: T_COMMENT or T_DOC_COMMENT. + * + * @return bool + */ + public function isComment() + { + static $commentTokens = [T_COMMENT, T_DOC_COMMENT]; + + return $this->isGivenKind($commentTokens); + } + + /** + * Check if token is one of object operator tokens: T_OBJECT_OPERATOR or T_NULLSAFE_OBJECT_OPERATOR. + * + * @return bool + */ + public function isObjectOperator() + { + return $this->isGivenKind(self::getObjectOperatorKinds()); + } + + /** + * Check if token is empty, e.g. because of clearing. + * + * @return bool + * + * @deprecated since 2.4 + */ + public function isEmpty() + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated and will be removed in 3.0.')); + + return null === $this->id && ('' === $this->content || null === $this->content); + } + + /** + * Check if token is one of given kind. + * + * @param int|int[] $possibleKind kind or array of kinds + * + * @return bool + */ + public function isGivenKind($possibleKind) + { + return $this->isArray && (\is_array($possibleKind) ? \in_array($this->id, $possibleKind, true) : $this->id === $possibleKind); + } + + /** + * Check if token is a keyword. + * + * @return bool + */ + public function isKeyword() + { + $keywords = static::getKeywords(); + + return $this->isArray && isset($keywords[$this->id]); + } + + /** + * Check if token is a native PHP constant: true, false or null. + * + * @return bool + */ + public function isNativeConstant() + { + static $nativeConstantStrings = ['true', 'false', 'null']; + + return $this->isArray && \in_array(strtolower($this->content), $nativeConstantStrings, true); + } + + /** + * Returns if the token is of a Magic constants type. + * + * @see https://php.net/manual/en/language.constants.predefined.php + * + * @return bool + */ + public function isMagicConstant() + { + $magicConstants = static::getMagicConstants(); + + return $this->isArray && isset($magicConstants[$this->id]); + } + + /** + * Check if token is whitespace. + * + * @param null|string $whitespaces whitespace characters, default is " \t\n\r\0\x0B" + * + * @return bool + */ + public function isWhitespace($whitespaces = " \t\n\r\0\x0B") + { + if (null === $whitespaces) { + $whitespaces = " \t\n\r\0\x0B"; + } + + if ($this->isArray && !$this->isGivenKind(T_WHITESPACE)) { + return false; + } + + return '' === trim($this->content, $whitespaces); + } + + /** + * Override token. + * + * If called on Token inside Tokens collection please use `Tokens::overrideAt` instead. + * + * @param array|string|Token $other token prototype + * + * @deprecated since 2.4 + */ + public function override($other) + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated and will be removed in 3.0.')); + Tokens::setLegacyMode(true); + + $prototype = $other instanceof self ? $other->getPrototype() : $other; + + if ($this->equals($prototype)) { + return; + } + + $this->changed = true; + + if (\is_array($prototype)) { + $this->isArray = true; + $this->id = $prototype[0]; + $this->content = $prototype[1]; + + return; + } + + $this->isArray = false; + $this->id = null; + $this->content = $prototype; + } + + /** + * @param string $content + * + * @deprecated since 2.4 + */ + public function setContent($content) + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated and will be removed in 3.0.')); + Tokens::setLegacyMode(true); + + if ($this->content === $content) { + return; + } + + $this->changed = true; + $this->content = $content; + + // setting empty content is clearing the token + if ('' === $content) { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' shall not be used to clear token, use Tokens::clearAt instead.')); + $this->id = null; + $this->isArray = false; + } + } + + public function toArray() + { + return [ + 'id' => $this->id, + 'name' => $this->getName(), + 'content' => $this->content, + 'isArray' => $this->isArray, + 'changed' => $this->changed, + ]; + } + + /** + * @param null|string[] $options JSON encode option + * + * @return string + */ + public function toJson(array $options = null) + { + if (null !== $options) { + Utils::triggerDeprecation(new \RuntimeException(sprintf( + 'Arguments of "%s()" is deprecated since 2.19 and will be removed in 3.0.', + __METHOD__ + ))); + } + + $options = $options ? Utils::calculateBitmask($options) : (JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK); + $jsonResult = json_encode($this->toArray(), $options); + + if (JSON_ERROR_NONE !== json_last_error()) { + $jsonResult = json_encode( + [ + 'errorDescription' => 'Can not encode Tokens to JSON.', + 'rawErrorMessage' => json_last_error_msg(), + ], + $options + ); + } + + return $jsonResult; + } + + /** + * @param string[] $tokenNames + * + * @return array<int, int> + */ + private static function getTokenKindsForNames(array $tokenNames) + { + $keywords = []; + foreach ($tokenNames as $keywordName) { + if (\defined($keywordName)) { + $keyword = \constant($keywordName); + $keywords[$keyword] = $keyword; + } + } + + return $keywords; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Tokens.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Tokens.php new file mode 100644 index 0000000..205991a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Tokens.php @@ -0,0 +1,1646 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer; + +use PhpCsFixer\Preg; +use PhpCsFixer\Utils; + +/** + * Collection of code tokens. + * + * Its role is to provide the ability to manage collection and navigate through it. + * + * As a token prototype you should understand a single element generated by token_get_all. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @extends \SplFixedArray<Token> + */ +class Tokens extends \SplFixedArray +{ + const BLOCK_TYPE_PARENTHESIS_BRACE = 1; + const BLOCK_TYPE_CURLY_BRACE = 2; + const BLOCK_TYPE_INDEX_SQUARE_BRACE = 3; + const BLOCK_TYPE_ARRAY_SQUARE_BRACE = 4; + const BLOCK_TYPE_DYNAMIC_PROP_BRACE = 5; + const BLOCK_TYPE_DYNAMIC_VAR_BRACE = 6; + const BLOCK_TYPE_ARRAY_INDEX_CURLY_BRACE = 7; + const BLOCK_TYPE_GROUP_IMPORT_BRACE = 8; + const BLOCK_TYPE_DESTRUCTURING_SQUARE_BRACE = 9; + const BLOCK_TYPE_BRACE_CLASS_INSTANTIATION = 10; + const BLOCK_TYPE_ATTRIBUTE = 11; + + /** + * Static class cache. + * + * @var array + */ + private static $cache = []; + + /** + * Cache of block starts. Any change in collection will invalidate it. + * + * @var array<int, int> + */ + private $blockStartCache = []; + + /** + * Cache of block ends. Any change in collection will invalidate it. + * + * @var array<int, int> + */ + private $blockEndCache = []; + + /** + * crc32 hash of code string. + * + * @var string + */ + private $codeHash; + + /** + * Flag is collection was changed. + * + * It doesn't know about change of collection's items. To check it run `isChanged` method. + * + * @var bool + */ + private $changed = false; + + /** + * Set of found token kinds. + * + * When the token kind is present in this set it means that given token kind + * was ever seen inside the collection (but may not be part of it any longer). + * The key is token kind and the value is always true. + * + * @var array<int|string, int> + */ + private $foundTokenKinds = []; + + /** + * @var bool + * + * @todo remove at 3.0 + */ + private static $isLegacyMode = false; + + /** + * Clone tokens collection. + */ + public function __clone() + { + foreach ($this as $key => $val) { + $this[$key] = clone $val; + } + } + + /** + * @return bool + * + * @internal + * + * @todo remove at 3.0 + */ + public static function isLegacyMode() + { + return self::$isLegacyMode; + } + + /** + * @param bool $isLegacy + * + * @internal + * + * @todo remove at 3.0 + */ + public static function setLegacyMode($isLegacy) + { + if (getenv('PHP_CS_FIXER_FUTURE_MODE') && $isLegacy) { + throw new \RuntimeException('Cannot enable `legacy mode` when using `future mode`. This check was performed as `PHP_CS_FIXER_FUTURE_MODE` env var is set.'); + } + + self::$isLegacyMode = $isLegacy; + } + + /** + * Clear cache - one position or all of them. + * + * @param null|string $key position to clear, when null clear all + */ + public static function clearCache($key = null) + { + if (null === $key) { + self::$cache = []; + + return; + } + + if (self::hasCache($key)) { + unset(self::$cache[$key]); + } + } + + /** + * Detect type of block. + * + * @param Token $token token + * + * @return null|array array with 'type' and 'isStart' keys or null if not found + */ + public static function detectBlockType(Token $token) + { + foreach (self::getBlockEdgeDefinitions() as $type => $definition) { + if ($token->equals($definition['start'])) { + return ['type' => $type, 'isStart' => true]; + } + + if ($token->equals($definition['end'])) { + return ['type' => $type, 'isStart' => false]; + } + } + + return null; + } + + /** + * Create token collection from array. + * + * @param Token[] $array the array to import + * @param bool $saveIndexes save the numeric indexes used in the original array, default is yes + * + * @return Tokens + */ + public static function fromArray($array, $saveIndexes = null) + { + $tokens = new self(\count($array)); + + if (null === $saveIndexes || $saveIndexes) { + foreach ($array as $key => $val) { + $tokens[$key] = $val; + } + } else { + $index = 0; + + foreach ($array as $val) { + $tokens[$index++] = $val; + } + } + + $tokens->generateCode(); // regenerate code to calculate code hash + $tokens->clearChanged(); + + return $tokens; + } + + /** + * Create token collection directly from code. + * + * @param string $code PHP code + * + * @return Tokens + */ + public static function fromCode($code) + { + $codeHash = self::calculateCodeHash($code); + + if (self::hasCache($codeHash)) { + $tokens = self::getCache($codeHash); + + // generate the code to recalculate the hash + $tokens->generateCode(); + + if ($codeHash === $tokens->codeHash) { + $tokens->clearEmptyTokens(); + $tokens->clearChanged(); + + return $tokens; + } + } + + $tokens = new self(); + $tokens->setCode($code); + $tokens->clearChanged(); + + return $tokens; + } + + /** + * @return array + */ + public static function getBlockEdgeDefinitions() + { + $definitions = [ + self::BLOCK_TYPE_CURLY_BRACE => [ + 'start' => '{', + 'end' => '}', + ], + self::BLOCK_TYPE_PARENTHESIS_BRACE => [ + 'start' => '(', + 'end' => ')', + ], + self::BLOCK_TYPE_INDEX_SQUARE_BRACE => [ + 'start' => '[', + 'end' => ']', + ], + self::BLOCK_TYPE_ARRAY_SQUARE_BRACE => [ + 'start' => [CT::T_ARRAY_SQUARE_BRACE_OPEN, '['], + 'end' => [CT::T_ARRAY_SQUARE_BRACE_CLOSE, ']'], + ], + self::BLOCK_TYPE_DYNAMIC_PROP_BRACE => [ + 'start' => [CT::T_DYNAMIC_PROP_BRACE_OPEN, '{'], + 'end' => [CT::T_DYNAMIC_PROP_BRACE_CLOSE, '}'], + ], + self::BLOCK_TYPE_DYNAMIC_VAR_BRACE => [ + 'start' => [CT::T_DYNAMIC_VAR_BRACE_OPEN, '{'], + 'end' => [CT::T_DYNAMIC_VAR_BRACE_CLOSE, '}'], + ], + self::BLOCK_TYPE_ARRAY_INDEX_CURLY_BRACE => [ + 'start' => [CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN, '{'], + 'end' => [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE, '}'], + ], + self::BLOCK_TYPE_GROUP_IMPORT_BRACE => [ + 'start' => [CT::T_GROUP_IMPORT_BRACE_OPEN, '{'], + 'end' => [CT::T_GROUP_IMPORT_BRACE_CLOSE, '}'], + ], + self::BLOCK_TYPE_DESTRUCTURING_SQUARE_BRACE => [ + 'start' => [CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN, '['], + 'end' => [CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE, ']'], + ], + self::BLOCK_TYPE_BRACE_CLASS_INSTANTIATION => [ + 'start' => [CT::T_BRACE_CLASS_INSTANTIATION_OPEN, '('], + 'end' => [CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, ')'], + ], + ]; + + // @TODO: drop condition when PHP 8.0+ is required + if (\defined('T_ATTRIBUTE')) { + $definitions[self::BLOCK_TYPE_ATTRIBUTE] = [ + 'start' => [T_ATTRIBUTE, '#['], + 'end' => [CT::T_ATTRIBUTE_CLOSE, ']'], + ]; + } + + return $definitions; + } + + /** + * Set new size of collection. + * + * @param int $size + * + * @return bool + */ + public function setSize($size) + { + if ($this->getSize() !== $size) { + $this->changed = true; + + return parent::setSize($size); + } + + return true; + } + + /** + * Unset collection item. + * + * @param int $index + */ + public function offsetUnset($index) + { + $this->changed = true; + $this->unregisterFoundToken($this[$index]); + parent::offsetUnset($index); + } + + /** + * Set collection item. + * + * Warning! `$newval` must not be typehinted to be compatible with `ArrayAccess::offsetSet` method. + * + * @param int $index + * @param Token $newval + */ + public function offsetSet($index, $newval) + { + $this->blockStartCache = []; + $this->blockEndCache = []; + + if (!isset($this[$index]) || !$this[$index]->equals($newval)) { + $this->changed = true; + + if (isset($this[$index])) { + $this->unregisterFoundToken($this[$index]); + } + + $this->registerFoundToken($newval); + } + + parent::offsetSet($index, $newval); + } + + /** + * Clear internal flag if collection was changed and flag for all collection's items. + */ + public function clearChanged() + { + $this->changed = false; + + if (self::isLegacyMode()) { + foreach ($this as $token) { + $token->clearChanged(); + } + } + } + + /** + * Clear empty tokens. + * + * Empty tokens can occur e.g. after calling clear on item of collection. + */ + public function clearEmptyTokens() + { + $limit = $this->count(); + $index = 0; + + for (; $index < $limit; ++$index) { + if ($this->isEmptyAt($index)) { + break; + } + } + + // no empty token found, therefore there is no need to override collection + if ($limit === $index) { + return; + } + + for ($count = $index; $index < $limit; ++$index) { + if (!$this->isEmptyAt($index)) { + $this[$count++] = $this[$index]; // @phpstan-ignore-line as we know that index exists + } + } + + $this->setSize($count); + } + + /** + * Ensure that on given index is a whitespace with given kind. + * + * If there is a whitespace then it's content will be modified. + * If not - the new Token will be added. + * + * @param int $index index + * @param int $indexOffset index offset for Token insertion + * @param string $whitespace whitespace to set + * + * @return bool if new Token was added + */ + public function ensureWhitespaceAtIndex($index, $indexOffset, $whitespace) + { + $removeLastCommentLine = static function (self $tokens, $index, $indexOffset, $whitespace) { + $token = $tokens[$index]; + + if (1 === $indexOffset && $token->isGivenKind(T_OPEN_TAG)) { + if (0 === strpos($whitespace, "\r\n")) { + $tokens[$index] = new Token([T_OPEN_TAG, rtrim($token->getContent())."\r\n"]); + + return \strlen($whitespace) > 2 // can be removed on PHP 7; https://php.net/manual/en/function.substr.php + ? substr($whitespace, 2) + : '' + ; + } + + $tokens[$index] = new Token([T_OPEN_TAG, rtrim($token->getContent()).$whitespace[0]]); + + return \strlen($whitespace) > 1 // can be removed on PHP 7; https://php.net/manual/en/function.substr.php + ? substr($whitespace, 1) + : '' + ; + } + + return $whitespace; + }; + + if ($this[$index]->isWhitespace()) { + $whitespace = $removeLastCommentLine($this, $index - 1, $indexOffset, $whitespace); + + if ('' === $whitespace) { + $this->clearAt($index); + } else { + $this[$index] = new Token([T_WHITESPACE, $whitespace]); + } + + return false; + } + + $whitespace = $removeLastCommentLine($this, $index, $indexOffset, $whitespace); + + if ('' === $whitespace) { + return false; + } + + $this->insertAt( + $index + $indexOffset, + [new Token([T_WHITESPACE, $whitespace])] + ); + + return true; + } + + /** + * @param int $type type of block, one of BLOCK_TYPE_* + * @param int $searchIndex index of opening brace + * @param bool $findEnd if method should find block's end, default true, otherwise method find block's start + * + * @return int index of closing brace + */ + public function findBlockEnd($type, $searchIndex, $findEnd = true) + { + if (3 === \func_num_args()) { + if ($findEnd) { + Utils::triggerDeprecation(new \RuntimeException('Argument #3 of Tokens::findBlockEnd is deprecated and will be removed in 3.0, you can safely drop the argument.')); + } else { + Utils::triggerDeprecation(new \RuntimeException('Argument #3 of Tokens::findBlockEnd is deprecated and will be removed in 3.0, use Tokens::findBlockStart instead.')); + } + } + + return $this->findOppositeBlockEdge($type, $searchIndex, $findEnd); + } + + /** + * @param int $type type of block, one of BLOCK_TYPE_* + * @param int $searchIndex index of closing brace + * + * @return int index of opening brace + */ + public function findBlockStart($type, $searchIndex) + { + return $this->findOppositeBlockEdge($type, $searchIndex, false); + } + + /** + * @param array|int $possibleKind kind or array of kind + * @param int $start optional offset + * @param null|int $end optional limit + * + * @return array array of tokens of given kinds or assoc array of arrays + */ + public function findGivenKind($possibleKind, $start = 0, $end = null) + { + if (null === $end) { + $end = $this->count(); + } + + $elements = []; + $possibleKinds = (array) $possibleKind; + + foreach ($possibleKinds as $kind) { + $elements[$kind] = []; + } + + if (!self::isLegacyMode()) { + $possibleKinds = array_filter($possibleKinds, function ($kind) { + return $this->isTokenKindFound($kind); + }); + } + + if (\count($possibleKinds)) { + for ($i = $start; $i < $end; ++$i) { + $token = $this[$i]; + if ($token->isGivenKind($possibleKinds)) { + $elements[$token->getId()][$i] = $token; + } + } + } + + return \is_array($possibleKind) ? $elements : $elements[$possibleKind]; + } + + /** + * @return string + */ + public function generateCode() + { + $code = $this->generatePartialCode(0, \count($this) - 1); + $this->changeCodeHash(self::calculateCodeHash($code)); + + return $code; + } + + /** + * Generate code from tokens between given indexes. + * + * @param int $start start index + * @param int $end end index + * + * @return string + */ + public function generatePartialCode($start, $end) + { + $code = ''; + + for ($i = $start; $i <= $end; ++$i) { + $code .= $this[$i]->getContent(); + } + + return $code; + } + + /** + * Get hash of code. + * + * @return string + */ + public function getCodeHash() + { + return $this->codeHash; + } + + /** + * Get index for closest next token which is non whitespace. + * + * This method is shorthand for getNonWhitespaceSibling method. + * + * @param int $index token index + * @param null|string $whitespaces whitespaces characters for Token::isWhitespace + * + * @return null|int + */ + public function getNextNonWhitespace($index, $whitespaces = null) + { + return $this->getNonWhitespaceSibling($index, 1, $whitespaces); + } + + /** + * Get index for closest next token of given kind. + * + * This method is shorthand for getTokenOfKindSibling method. + * + * @param int $index token index + * @param array $tokens possible tokens + * @param bool $caseSensitive perform a case sensitive comparison + * + * @return null|int + */ + public function getNextTokenOfKind($index, array $tokens = [], $caseSensitive = true) + { + return $this->getTokenOfKindSibling($index, 1, $tokens, $caseSensitive); + } + + /** + * Get index for closest sibling token which is non whitespace. + * + * @param int $index token index + * @param int $direction direction for looking, +1 or -1 + * @param null|string $whitespaces whitespaces characters for Token::isWhitespace + * + * @return null|int + */ + public function getNonWhitespaceSibling($index, $direction, $whitespaces = null) + { + while (true) { + $index += $direction; + + if (!$this->offsetExists($index)) { + return null; + } + + if (!$this[$index]->isWhitespace($whitespaces)) { + return $index; + } + } + } + + /** + * Get index for closest previous token which is non whitespace. + * + * This method is shorthand for getNonWhitespaceSibling method. + * + * @param int $index token index + * @param null|string $whitespaces whitespaces characters for Token::isWhitespace + * + * @return null|int + */ + public function getPrevNonWhitespace($index, $whitespaces = null) + { + return $this->getNonWhitespaceSibling($index, -1, $whitespaces); + } + + /** + * Get index for closest previous token of given kind. + * This method is shorthand for getTokenOfKindSibling method. + * + * @param int $index token index + * @param array $tokens possible tokens + * @param bool $caseSensitive perform a case sensitive comparison + * + * @return null|int + */ + public function getPrevTokenOfKind($index, array $tokens = [], $caseSensitive = true) + { + return $this->getTokenOfKindSibling($index, -1, $tokens, $caseSensitive); + } + + /** + * Get index for closest sibling token of given kind. + * + * @param int $index token index + * @param int $direction direction for looking, +1 or -1 + * @param array $tokens possible tokens + * @param bool $caseSensitive perform a case sensitive comparison + * + * @return null|int + */ + public function getTokenOfKindSibling($index, $direction, array $tokens = [], $caseSensitive = true) + { + if (!self::isLegacyMode()) { + $tokens = array_filter($tokens, function ($token) { + return $this->isTokenKindFound($this->extractTokenKind($token)); + }); + } + + if (!\count($tokens)) { + return null; + } + + while (true) { + $index += $direction; + + if (!$this->offsetExists($index)) { + return null; + } + + if ($this[$index]->equalsAny($tokens, $caseSensitive)) { + return $index; + } + } + } + + /** + * Get index for closest sibling token not of given kind. + * + * @param int $index token index + * @param int $direction direction for looking, +1 or -1 + * @param array $tokens possible tokens + * + * @return null|int + */ + public function getTokenNotOfKindSibling($index, $direction, array $tokens = []) + { + return $this->getTokenNotOfKind( + $index, + $direction, + function ($a) use ($tokens) { + return $this[$a]->equalsAny($tokens); + } + ); + } + + /** + * Get index for closest sibling token not of given kind. + * + * @param int $index token index + * @param int $direction direction for looking, +1 or -1 + * @param array $kinds possible tokens kinds + * + * @return null|int + */ + public function getTokenNotOfKindsSibling($index, $direction, array $kinds = []) + { + return $this->getTokenNotOfKind( + $index, + $direction, + function ($index) use ($kinds) { + return $this[$index]->isGivenKind($kinds); + } + ); + } + + /** + * Get index for closest sibling token that is not a whitespace, comment or attribute. + * + * @param int $index token index + * @param int $direction direction for looking, +1 or -1 + * + * @return null|int + */ + public function getMeaningfulTokenSibling($index, $direction) + { + return $this->getTokenNotOfKindsSibling( + $index, + $direction, + [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT] + ); + } + + /** + * Get index for closest sibling token which is not empty. + * + * @param int $index token index + * @param int $direction direction for looking, +1 or -1 + * + * @return null|int + */ + public function getNonEmptySibling($index, $direction) + { + while (true) { + $index += $direction; + + if (!$this->offsetExists($index)) { + return null; + } + + if (!$this->isEmptyAt($index)) { + return $index; + } + } + } + + /** + * Get index for closest next token that is not a whitespace or comment. + * + * @param int $index token index + * + * @return null|int + */ + public function getNextMeaningfulToken($index) + { + return $this->getMeaningfulTokenSibling($index, 1); + } + + /** + * Get index for closest previous token that is not a whitespace or comment. + * + * @param int $index token index + * + * @return null|int + */ + public function getPrevMeaningfulToken($index) + { + return $this->getMeaningfulTokenSibling($index, -1); + } + + /** + * Find a sequence of meaningful tokens and returns the array of their locations. + * + * @param array $sequence an array of tokens (kinds) (same format used by getNextTokenOfKind) + * @param int $start start index, defaulting to the start of the file + * @param int $end end index, defaulting to the end of the file + * @param array<int, bool>|bool $caseSensitive global case sensitiveness or an array of booleans, whose keys should match + * the ones used in $others. If any is missing, the default case-sensitive + * comparison is used + * + * @return null|array<int, Token> an array containing the tokens matching the sequence elements, indexed by their position + */ + public function findSequence(array $sequence, $start = 0, $end = null, $caseSensitive = true) + { + $sequenceCount = \count($sequence); + if (0 === $sequenceCount) { + throw new \InvalidArgumentException('Invalid sequence.'); + } + + // $end defaults to the end of the collection + $end = null === $end ? \count($this) - 1 : min($end, \count($this) - 1); + + if ($start + $sequenceCount - 1 > $end) { + return null; + } + + $nonMeaningFullKind = [T_COMMENT, T_DOC_COMMENT, T_WHITESPACE]; + + // make sure the sequence content is "meaningful" + foreach ($sequence as $key => $token) { + // if not a Token instance already, we convert it to verify the meaningfulness + if (!$token instanceof Token) { + if (\is_array($token) && !isset($token[1])) { + // fake some content as it is required by the Token constructor, + // although optional for search purposes + $token[1] = 'DUMMY'; + } + + $token = new Token($token); + } + + if ($token->isGivenKind($nonMeaningFullKind)) { + throw new \InvalidArgumentException(sprintf('Non-meaningful token at position: "%s".', $key)); + } + + if ('' === $token->getContent()) { + throw new \InvalidArgumentException(sprintf('Non-meaningful (empty) token at position: "%s".', $key)); + } + } + + if (!self::isLegacyMode()) { + foreach ($sequence as $token) { + if (!$this->isTokenKindFound($this->extractTokenKind($token))) { + return null; + } + } + } + + // remove the first token from the sequence, so we can freely iterate through the sequence after a match to + // the first one is found + $key = key($sequence); + $firstCs = Token::isKeyCaseSensitive($caseSensitive, $key); + $firstToken = $sequence[$key]; + unset($sequence[$key]); + + // begin searching for the first token in the sequence (start included) + $index = $start - 1; + while (null !== $index && $index <= $end) { + $index = $this->getNextTokenOfKind($index, [$firstToken], $firstCs); + + // ensure we found a match and didn't get past the end index + if (null === $index || $index > $end) { + return null; + } + + // initialise the result array with the current index + $result = [$index => $this[$index]]; + + // advance cursor to the current position + $currIdx = $index; + + // iterate through the remaining tokens in the sequence + foreach ($sequence as $key => $token) { + $currIdx = $this->getNextMeaningfulToken($currIdx); + + // ensure we didn't go too far + if (null === $currIdx || $currIdx > $end) { + return null; + } + + if (!$this[$currIdx]->equals($token, Token::isKeyCaseSensitive($caseSensitive, $key))) { + // not a match, restart the outer loop + continue 2; + } + + // append index to the result array + $result[$currIdx] = $this[$currIdx]; + } + + // do we have a complete match? + // hint: $result is bigger than $sequence since the first token has been removed from the latter + if (\count($sequence) < \count($result)) { + return $result; + } + } + + return null; + } + + /** + * Insert instances of Token inside collection. + * + * @param int $index start inserting index + * @param array<Token>|Token|Tokens $items instances of Token to insert + */ + public function insertAt($index, $items) + { + $items = \is_array($items) || $items instanceof self ? $items : [$items]; + + $this->insertSlices([$index => $items]); + } + + /** + * Insert a slices or individual Tokens into multiple places in a single run. + * + * This approach is kind-of an experiment - it's proven to improve performance a lot for big files that needs plenty of new tickets to be inserted, + * like edge case example of 3.7h vs 4s (https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues/3996#issuecomment-455617637), + * yet at same time changing a logic of fixers in not-always easy way. + * + * To be discuss: + * - should we always aim to use this method? + * - should we deprecate `insertAt` method ? + * + * The `$slices` parameter is an assoc array, in which: + * - index: starting point for inserting of individual slice, with indexes being relatives to original array collection before any Token inserted + * - value under index: a slice of Tokens to be inserted + * + * @internal + * + * @param array<int, array<Token>|Token|Tokens> $slices + */ + public function insertSlices(array $slices) + { + $itemsCount = 0; + foreach ($slices as $slice) { + $slice = \is_array($slice) || $slice instanceof self ? $slice : [$slice]; + $itemsCount += \count($slice); + } + + if (0 === $itemsCount) { + return; + } + + $oldSize = \count($this); + $this->changed = true; + $this->blockStartCache = []; + $this->blockEndCache = []; + $this->setSize($oldSize + $itemsCount); + + krsort($slices); + + $insertBound = $oldSize - 1; + + // since we only move already existing items around, we directly call into SplFixedArray::offset* methods. + // that way we get around additional overhead this class adds with overridden offset* methods. + foreach ($slices as $index => $slice) { + $slice = \is_array($slice) || $slice instanceof self ? $slice : [$slice]; + $sliceCount = \count($slice); + + for ($i = $insertBound; $i >= $index; --$i) { + $oldItem = parent::offsetExists($i) ? parent::offsetGet($i) : new Token(''); + parent::offsetSet($i + $itemsCount, $oldItem); + } + + $insertBound = $index - $sliceCount; + $itemsCount -= $sliceCount; + + foreach ($slice as $indexItem => $item) { + if ('' === $item->getContent()) { + throw new \InvalidArgumentException('Must not add empty token to collection.'); + } + + $this->registerFoundToken($item); + $newOffset = $index + $itemsCount + $indexItem; + parent::offsetSet($newOffset, $item); + } + } + } + + /** + * Check if collection was change: collection itself (like insert new tokens) or any of collection's elements. + * + * @return bool + */ + public function isChanged() + { + if ($this->changed) { + return true; + } + + if (self::isLegacyMode()) { + foreach ($this as $token) { + if ($token->isChanged()) { + return true; + } + } + } + + return false; + } + + /** + * @param int $index + * + * @return bool + */ + public function isEmptyAt($index) + { + $token = $this[$index]; + + return null === $token->getId() && '' === $token->getContent(); + } + + public function clearAt($index) + { + $this[$index] = new Token(''); + } + + /** + * Override token at given index and register it. + * + * @param int $index + * @param array|string|Token $token token prototype + * + * @deprecated since 2.4, use offsetSet instead + */ + public function overrideAt($index, $token) + { + Utils::triggerDeprecation(new \RuntimeException(__METHOD__.' is deprecated and will be removed in 3.0, use offsetSet instead.')); + self::$isLegacyMode = true; + + $this[$index]->override($token); + $this->registerFoundToken($token); + } + + /** + * Override tokens at given range. + * + * @param int $indexStart start overriding index + * @param int $indexEnd end overriding index + * @param array<Token>|Tokens $items tokens to insert + */ + public function overrideRange($indexStart, $indexEnd, $items) + { + $indexToChange = $indexEnd - $indexStart + 1; + $itemsCount = \count($items); + + // If we want to add more items than passed range contains we need to + // add placeholders for overhead items. + if ($itemsCount > $indexToChange) { + $placeholders = []; + + while ($itemsCount > $indexToChange) { + $placeholders[] = new Token('__PLACEHOLDER__'); + ++$indexToChange; + } + + $this->insertAt($indexEnd + 1, $placeholders); + } + + // Override each items. + foreach ($items as $itemIndex => $item) { + $this[$indexStart + $itemIndex] = $item; + } + + // If we want to add less tokens than passed range contains then clear + // not needed tokens. + if ($itemsCount < $indexToChange) { + $this->clearRange($indexStart + $itemsCount, $indexEnd); + } + } + + /** + * @param int $index + * @param null|string $whitespaces optional whitespaces characters for Token::isWhitespace + */ + public function removeLeadingWhitespace($index, $whitespaces = null) + { + $this->removeWhitespaceSafely($index, -1, $whitespaces); + } + + /** + * @param int $index + * @param null|string $whitespaces optional whitespaces characters for Token::isWhitespace + */ + public function removeTrailingWhitespace($index, $whitespaces = null) + { + $this->removeWhitespaceSafely($index, 1, $whitespaces); + } + + /** + * Set code. Clear all current content and replace it by new Token items generated from code directly. + * + * @param string $code PHP code + */ + public function setCode($code) + { + // No need to work when the code is the same. + // That is how we avoid a lot of work and setting changed flag. + if ($code === $this->generateCode()) { + return; + } + + // clear memory + $this->setSize(0); + + $tokens = \defined('TOKEN_PARSE') // @TODO: drop condition when PHP 7.0+ is required + ? token_get_all($code, TOKEN_PARSE) + : token_get_all($code); + + $this->setSize(\count($tokens)); + + foreach ($tokens as $index => $token) { + $this[$index] = new Token($token); + } + + $this->applyTransformers(); + + $this->foundTokenKinds = []; + + foreach ($this as $token) { + $this->registerFoundToken($token); + } + + if (\PHP_VERSION_ID < 80000) { + $this->rewind(); + } + + $this->changeCodeHash(self::calculateCodeHash($code)); + $this->changed = true; + } + + public function toJson() + { + $output = new \SplFixedArray(\count($this)); + + foreach ($this as $index => $token) { + $output[$index] = $token->toArray(); + } + + if (\PHP_VERSION_ID < 80000) { + $this->rewind(); + } + + return json_encode($output, JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK); + } + + /** + * Check if all token kinds given as argument are found. + * + * @return bool + */ + public function isAllTokenKindsFound(array $tokenKinds) + { + foreach ($tokenKinds as $tokenKind) { + if (empty($this->foundTokenKinds[$tokenKind])) { + return false; + } + } + + return true; + } + + /** + * Check if any token kind given as argument is found. + * + * @return bool + */ + public function isAnyTokenKindsFound(array $tokenKinds) + { + foreach ($tokenKinds as $tokenKind) { + if (!empty($this->foundTokenKinds[$tokenKind])) { + return true; + } + } + + return false; + } + + /** + * Check if token kind given as argument is found. + * + * @param int|string $tokenKind + * + * @return bool + */ + public function isTokenKindFound($tokenKind) + { + return !empty($this->foundTokenKinds[$tokenKind]); + } + + /** + * @param int|string $tokenKind + * + * @return int + */ + public function countTokenKind($tokenKind) + { + if (self::isLegacyMode()) { + throw new \RuntimeException(sprintf('"%s" is not available in legacy mode.', __METHOD__)); + } + + return isset($this->foundTokenKinds[$tokenKind]) ? $this->foundTokenKinds[$tokenKind] : 0; + } + + /** + * Clear tokens in the given range. + * + * @param int $indexStart + * @param int $indexEnd + */ + public function clearRange($indexStart, $indexEnd) + { + for ($i = $indexStart; $i <= $indexEnd; ++$i) { + $this->clearAt($i); + } + } + + /** + * Checks for monolithic PHP code. + * + * Checks that the code is pure PHP code, in a single code block, starting + * with an open tag. + * + * @return bool + */ + public function isMonolithicPhp() + { + $size = $this->count(); + + if (0 === $size) { + return false; + } + + if (self::isLegacyMode()) { + // If code is not monolithic there is a great chance that first or last token is `T_INLINE_HTML`: + if ($this[0]->isGivenKind(T_INLINE_HTML) || $this[$size - 1]->isGivenKind(T_INLINE_HTML)) { + return false; + } + + for ($index = 1; $index < $size; ++$index) { + if ($this[$index]->isGivenKind([T_INLINE_HTML, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO])) { + return false; + } + } + + return true; + } + + if ($this->isTokenKindFound(T_INLINE_HTML)) { + return false; + } + + return 1 >= ($this->countTokenKind(T_OPEN_TAG) + $this->countTokenKind(T_OPEN_TAG_WITH_ECHO)); + } + + /** + * @param int $start start index + * @param int $end end index + * + * @return bool + */ + public function isPartialCodeMultiline($start, $end) + { + for ($i = $start; $i <= $end; ++$i) { + if (false !== strpos($this[$i]->getContent(), "\n")) { + return true; + } + } + + return false; + } + + /** + * @return bool + */ + public function hasAlternativeSyntax() + { + return $this->isAnyTokenKindsFound([ + T_ENDDECLARE, + T_ENDFOR, + T_ENDFOREACH, + T_ENDIF, + T_ENDSWITCH, + T_ENDWHILE, + ]); + } + + /** + * @param int $index + */ + public function clearTokenAndMergeSurroundingWhitespace($index) + { + $count = \count($this); + $this->clearAt($index); + + if ($index === $count - 1) { + return; + } + + $nextIndex = $this->getNonEmptySibling($index, 1); + + if (null === $nextIndex || !$this[$nextIndex]->isWhitespace()) { + return; + } + + $prevIndex = $this->getNonEmptySibling($index, -1); + + if ($this[$prevIndex]->isWhitespace()) { + $this[$prevIndex] = new Token([T_WHITESPACE, $this[$prevIndex]->getContent().$this[$nextIndex]->getContent()]); + } elseif ($this->isEmptyAt($prevIndex + 1)) { + $this[$prevIndex + 1] = new Token([T_WHITESPACE, $this[$nextIndex]->getContent()]); + } + + $this->clearAt($nextIndex); + } + + /** + * @internal + * + * @deprecated Do not call directly, not available on PHP8 and will be removed in the future + */ + public function current() + { + $this->warnPhp8SplFixerArrayChange(__METHOD__); + + return parent::current(); + } + + /** + * @internal + * + * @deprecated Do not call directly, not available on PHP8 and will be removed in the future + */ + public function key() + { + $this->warnPhp8SplFixerArrayChange(__METHOD__); + + return parent::key(); + } + + /** + * @internal + * + * @deprecated Do not call directly, not available on PHP8 and will be removed in the future + */ + public function next() + { + $this->warnPhp8SplFixerArrayChange(__METHOD__); + + parent::next(); + } + + /** + * @internal + * + * @deprecated Do not call directly, not available on PHP8 and will be removed in the future + */ + public function rewind() + { + $this->warnPhp8SplFixerArrayChange(__METHOD__); + + parent::rewind(); + } + + /** + * @internal + * + * @deprecated Do not call directly, not available on PHP8 and will be removed in the future + */ + public function valid() + { + $this->warnPhp8SplFixerArrayChange(__METHOD__); + + return parent::valid(); + } + + /** + * @internal + */ + protected function applyTransformers() + { + $transformers = Transformers::createSingleton(); + $transformers->transform($this); + } + + private function warnPhp8SplFixerArrayChange($method) + { + if (80000 <= \PHP_VERSION_ID) { + throw new \BadMethodCallException(sprintf('"%s" has been removed on PHP8, use ::getIterator() in place.', $method)); + } + } + + private function removeWhitespaceSafely($index, $direction, $whitespaces = null) + { + $whitespaceIndex = $this->getNonEmptySibling($index, $direction); + if (isset($this[$whitespaceIndex]) && $this[$whitespaceIndex]->isWhitespace()) { + $newContent = ''; + $tokenToCheck = $this[$whitespaceIndex]; + + // if the token candidate to remove is preceded by single line comment we do not consider the new line after this comment as part of T_WHITESPACE + if (isset($this[$whitespaceIndex - 1]) && $this[$whitespaceIndex - 1]->isComment() && '/*' !== substr($this[$whitespaceIndex - 1]->getContent(), 0, 2)) { + list($emptyString, $newContent, $whitespacesToCheck) = Preg::split('/^(\R)/', $this[$whitespaceIndex]->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + + if ('' === $whitespacesToCheck) { + return; + } + + $tokenToCheck = new Token([T_WHITESPACE, $whitespacesToCheck]); + } + + if (!$tokenToCheck->isWhitespace($whitespaces)) { + return; + } + + if ('' === $newContent) { + $this->clearAt($whitespaceIndex); + } else { + $this[$whitespaceIndex] = new Token([T_WHITESPACE, $newContent]); + } + } + } + + /** + * @param int $type type of block, one of BLOCK_TYPE_* + * @param int $searchIndex index of starting brace + * @param bool $findEnd if method should find block's end or start + * + * @return int index of opposite brace + */ + private function findOppositeBlockEdge($type, $searchIndex, $findEnd) + { + $blockEdgeDefinitions = self::getBlockEdgeDefinitions(); + + if (!isset($blockEdgeDefinitions[$type])) { + throw new \InvalidArgumentException(sprintf('Invalid param type: "%s".', $type)); + } + + if (!self::isLegacyMode()) { + if ($findEnd && isset($this->blockStartCache[$searchIndex])) { + return $this->blockStartCache[$searchIndex]; + } + if (!$findEnd && isset($this->blockEndCache[$searchIndex])) { + return $this->blockEndCache[$searchIndex]; + } + } + + $startEdge = $blockEdgeDefinitions[$type]['start']; + $endEdge = $blockEdgeDefinitions[$type]['end']; + $startIndex = $searchIndex; + $endIndex = $this->count() - 1; + $indexOffset = 1; + + if (!$findEnd) { + list($startEdge, $endEdge) = [$endEdge, $startEdge]; + $indexOffset = -1; + $endIndex = 0; + } + + if (!$this[$startIndex]->equals($startEdge)) { + throw new \InvalidArgumentException(sprintf('Invalid param $startIndex - not a proper block "%s".', $findEnd ? 'start' : 'end')); + } + + $blockLevel = 0; + + for ($index = $startIndex; $index !== $endIndex; $index += $indexOffset) { + $token = $this[$index]; + + if ($token->equals($startEdge)) { + ++$blockLevel; + + continue; + } + + if ($token->equals($endEdge)) { + --$blockLevel; + + if (0 === $blockLevel) { + break; + } + + continue; + } + } + + if (!$this[$index]->equals($endEdge)) { + throw new \UnexpectedValueException(sprintf('Missing block "%s".', $findEnd ? 'end' : 'start')); + } + + if ($startIndex < $index) { + $this->blockStartCache[$startIndex] = $index; + $this->blockEndCache[$index] = $startIndex; + } else { + $this->blockStartCache[$index] = $startIndex; + $this->blockEndCache[$startIndex] = $index; + } + + return $index; + } + + /** + * Calculate hash for code. + * + * @param string $code + * + * @return string + */ + private static function calculateCodeHash($code) + { + return CodeHasher::calculateCodeHash($code); + } + + /** + * Get cache value for given key. + * + * @param string $key item key + * + * @return Tokens + */ + private static function getCache($key) + { + if (!self::hasCache($key)) { + throw new \OutOfBoundsException(sprintf('Unknown cache key: "%s".', $key)); + } + + return self::$cache[$key]; + } + + /** + * Check if given key exists in cache. + * + * @param string $key item key + * + * @return bool + */ + private static function hasCache($key) + { + return isset(self::$cache[$key]); + } + + /** + * @param string $key item key + * @param Tokens $value item value + */ + private static function setCache($key, self $value) + { + self::$cache[$key] = $value; + } + + /** + * Change code hash. + * + * Remove old cache and set new one. + * + * @param string $codeHash new code hash + */ + private function changeCodeHash($codeHash) + { + if (null !== $this->codeHash) { + self::clearCache($this->codeHash); + } + + $this->codeHash = $codeHash; + self::setCache($this->codeHash, $this); + } + + /** + * Register token as found. + * + * @param array|string|Token $token token prototype + */ + private function registerFoundToken($token) + { + // inlined extractTokenKind() call on the hot path + $tokenKind = $token instanceof Token + ? ($token->isArray() ? $token->getId() : $token->getContent()) + : (\is_array($token) ? $token[0] : $token) + ; + + if (!isset($this->foundTokenKinds[$tokenKind])) { + $this->foundTokenKinds[$tokenKind] = 0; + } + + ++$this->foundTokenKinds[$tokenKind]; + } + + /** + * Register token as found. + * + * @param array|string|Token $token token prototype + */ + private function unregisterFoundToken($token) + { + // inlined extractTokenKind() call on the hot path + $tokenKind = $token instanceof Token + ? ($token->isArray() ? $token->getId() : $token->getContent()) + : (\is_array($token) ? $token[0] : $token) + ; + + if (!isset($this->foundTokenKinds[$tokenKind])) { + return; + } + + --$this->foundTokenKinds[$tokenKind]; + } + + /** + * @param array|string|Token $token token prototype + * + * @return int|string + */ + private function extractTokenKind($token) + { + return $token instanceof Token + ? ($token->isArray() ? $token->getId() : $token->getContent()) + : (\is_array($token) ? $token[0] : $token) + ; + } + + /** + * @param int $index token index + * @param int $direction direction for looking, +1 or -1 + * @param callable $filter + * + * @return null|int + */ + private function getTokenNotOfKind($index, $direction, $filter) + { + while (true) { + $index += $direction; + + if (!$this->offsetExists($index)) { + return null; + } + + if ($this->isEmptyAt($index) || $filter($index)) { + continue; + } + + return $index; + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/TokensAnalyzer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/TokensAnalyzer.php new file mode 100644 index 0000000..81e98d7 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/TokensAnalyzer.php @@ -0,0 +1,822 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer; + +use PhpCsFixer\Tokenizer\Analyzer\GotoLabelAnalyzer; + +/** + * Analyzer of Tokens collection. + * + * Its role is to provide the ability to analyze collection. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Gregor Harlan <gharlan@web.de> + * @author SpacePossum + * + * @internal + */ +final class TokensAnalyzer +{ + /** + * Tokens collection instance. + * + * @var Tokens + */ + private $tokens; + + /** + * @var ?GotoLabelAnalyzer + */ + private $gotoLabelAnalyzer; + + public function __construct(Tokens $tokens) + { + $this->tokens = $tokens; + } + + /** + * Get indexes of methods and properties in classy code (classes, interfaces and traits). + * + * @param bool $returnTraitsImports TODO on v3 remove flag and return the imports + * + * @return array[] + */ + public function getClassyElements($returnTraitsImports = false) + { + $elements = []; + + for ($index = 1, $count = \count($this->tokens) - 2; $index < $count; ++$index) { + if ($this->tokens[$index]->isClassy()) { + list($index, $newElements) = $this->findClassyElements($index, $index, $returnTraitsImports); + $elements += $newElements; + } + } + + ksort($elements); + + return $elements; + } + + /** + * Get indexes of namespace uses. + * + * @param bool $perNamespace Return namespace uses per namespace + * + * @return int[]|int[][] + */ + public function getImportUseIndexes($perNamespace = false) + { + $tokens = $this->tokens; + + $uses = []; + $namespaceIndex = 0; + + for ($index = 0, $limit = $tokens->count(); $index < $limit; ++$index) { + $token = $tokens[$index]; + + if ($token->isGivenKind(T_NAMESPACE)) { + $nextTokenIndex = $tokens->getNextTokenOfKind($index, [';', '{']); + $nextToken = $tokens[$nextTokenIndex]; + + if ($nextToken->equals('{')) { + $index = $nextTokenIndex; + } + + if ($perNamespace) { + ++$namespaceIndex; + } + + continue; + } + + if ($token->isGivenKind(T_USE)) { + $uses[$namespaceIndex][] = $index; + } + } + + if (!$perNamespace && isset($uses[$namespaceIndex])) { + return $uses[$namespaceIndex]; + } + + return $uses; + } + + /** + * Check if there is an array at given index. + * + * @param int $index + * + * @return bool + */ + public function isArray($index) + { + return $this->tokens[$index]->isGivenKind([T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN]); + } + + /** + * Check if the array at index is multiline. + * + * This only checks the root-level of the array. + * + * @param int $index + * + * @return bool + */ + public function isArrayMultiLine($index) + { + if (!$this->isArray($index)) { + throw new \InvalidArgumentException(sprintf('Not an array at given index %d.', $index)); + } + + $tokens = $this->tokens; + + // Skip only when its an array, for short arrays we need the brace for correct + // level counting + if ($tokens[$index]->isGivenKind(T_ARRAY)) { + $index = $tokens->getNextMeaningfulToken($index); + } + + return $this->isBlockMultiline($tokens, $index); + } + + /** + * @param int $index + * + * @return bool + */ + public function isBlockMultiline(Tokens $tokens, $index) + { + $blockType = Tokens::detectBlockType($tokens[$index]); + + if (null === $blockType || !$blockType['isStart']) { + throw new \InvalidArgumentException(sprintf('Not an block start at given index %d.', $index)); + } + + $endIndex = $tokens->findBlockEnd($blockType['type'], $index); + + for (++$index; $index < $endIndex; ++$index) { + $token = $tokens[$index]; + $blockType = Tokens::detectBlockType($token); + + if ($blockType && $blockType['isStart']) { + $index = $tokens->findBlockEnd($blockType['type'], $index); + + continue; + } + + if ( + $token->isWhitespace() + && !$tokens[$index - 1]->isGivenKind(T_END_HEREDOC) + && false !== strpos($token->getContent(), "\n") + ) { + return true; + } + } + + return false; + } + + /** + * Returns the attributes of the method under the given index. + * + * The array has the following items: + * 'visibility' int|null T_PRIVATE, T_PROTECTED or T_PUBLIC + * 'static' bool + * 'abstract' bool + * 'final' bool + * + * @param int $index Token index of the method (T_FUNCTION) + * + * @return array + */ + public function getMethodAttributes($index) + { + $tokens = $this->tokens; + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_FUNCTION)) { + throw new \LogicException(sprintf('No T_FUNCTION at given index %d, got "%s".', $index, $token->getName())); + } + + $attributes = [ + 'visibility' => null, + 'static' => false, + 'abstract' => false, + 'final' => false, + ]; + + for ($i = $index; $i >= 0; --$i) { + $tokenIndex = $tokens->getPrevMeaningfulToken($i); + + $i = $tokenIndex; + $token = $tokens[$tokenIndex]; + + if ($token->isGivenKind(T_STATIC)) { + $attributes['static'] = true; + + continue; + } + + if ($token->isGivenKind(T_FINAL)) { + $attributes['final'] = true; + + continue; + } + + if ($token->isGivenKind(T_ABSTRACT)) { + $attributes['abstract'] = true; + + continue; + } + + // visibility + + if ($token->isGivenKind(T_PRIVATE)) { + $attributes['visibility'] = T_PRIVATE; + + continue; + } + + if ($token->isGivenKind(T_PROTECTED)) { + $attributes['visibility'] = T_PROTECTED; + + continue; + } + + if ($token->isGivenKind(T_PUBLIC)) { + $attributes['visibility'] = T_PUBLIC; + + continue; + } + + // found a meaningful token that is not part of + // the function signature; stop looking + break; + } + + return $attributes; + } + + /** + * Check if there is an anonymous class under given index. + * + * @param int $index + * + * @return bool + */ + public function isAnonymousClass($index) + { + if (!$this->tokens[$index]->isClassy()) { + throw new \LogicException(sprintf('No classy token at given index %d.', $index)); + } + + if (!$this->tokens[$index]->isGivenKind(T_CLASS)) { + return false; + } + + return $this->tokens[$this->tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_NEW); + } + + /** + * Check if the function under given index is a lambda. + * + * @param int $index + * + * @return bool + */ + public function isLambda($index) + { + if ( + !$this->tokens[$index]->isGivenKind(T_FUNCTION) + && (\PHP_VERSION_ID < 70400 || !$this->tokens[$index]->isGivenKind(T_FN)) + ) { + throw new \LogicException(sprintf('No T_FUNCTION or T_FN at given index %d, got "%s".', $index, $this->tokens[$index]->getName())); + } + + $startParenthesisIndex = $this->tokens->getNextMeaningfulToken($index); + $startParenthesisToken = $this->tokens[$startParenthesisIndex]; + + // skip & for `function & () {}` syntax + if ($startParenthesisToken->isGivenKind(CT::T_RETURN_REF)) { + $startParenthesisIndex = $this->tokens->getNextMeaningfulToken($startParenthesisIndex); + $startParenthesisToken = $this->tokens[$startParenthesisIndex]; + } + + return $startParenthesisToken->equals('('); + } + + /** + * Check if the T_STRING under given index is a constant invocation. + * + * @param int $index + * + * @return bool + */ + public function isConstantInvocation($index) + { + if (!$this->tokens[$index]->isGivenKind(T_STRING)) { + throw new \LogicException(sprintf('No T_STRING at given index %d, got "%s".', $index, $this->tokens[$index]->getName())); + } + + $nextIndex = $this->tokens->getNextMeaningfulToken($index); + + if ( + $this->tokens[$nextIndex]->equalsAny(['(', '{']) + || $this->tokens[$nextIndex]->isGivenKind([T_AS, T_DOUBLE_COLON, T_ELLIPSIS, T_NS_SEPARATOR, CT::T_RETURN_REF, CT::T_TYPE_ALTERNATION, T_VARIABLE]) + ) { + return false; + } + + $prevIndex = $this->tokens->getPrevMeaningfulToken($index); + + if ($this->tokens[$prevIndex]->isGivenKind([T_AS, T_CLASS, T_CONST, T_DOUBLE_COLON, T_FUNCTION, T_GOTO, CT::T_GROUP_IMPORT_BRACE_OPEN, T_INTERFACE, T_TRAIT, CT::T_TYPE_COLON]) || $this->tokens[$prevIndex]->isObjectOperator()) { + return false; + } + + while ($this->tokens[$prevIndex]->isGivenKind([CT::T_NAMESPACE_OPERATOR, T_NS_SEPARATOR, T_STRING])) { + $prevIndex = $this->tokens->getPrevMeaningfulToken($prevIndex); + } + + if ($this->tokens[$prevIndex]->isGivenKind([CT::T_CONST_IMPORT, T_EXTENDS, CT::T_FUNCTION_IMPORT, T_IMPLEMENTS, T_INSTANCEOF, T_INSTEADOF, T_NAMESPACE, T_NEW, CT::T_NULLABLE_TYPE, CT::T_TYPE_COLON, T_USE, CT::T_USE_TRAIT])) { + return false; + } + + // `FOO & $bar` could be: + // - function reference parameter: function baz(Foo & $bar) {} + // - bit operator: $x = FOO & $bar; + if ($this->tokens[$nextIndex]->equals('&') && $this->tokens[$this->tokens->getNextMeaningfulToken($nextIndex)]->isGivenKind(T_VARIABLE)) { + $checkIndex = $this->tokens->getPrevTokenOfKind($prevIndex, [';', '{', '}', [T_FUNCTION], [T_OPEN_TAG], [T_OPEN_TAG_WITH_ECHO]]); + + if ($this->tokens[$checkIndex]->isGivenKind(T_FUNCTION)) { + return false; + } + } + + // check for `extends`/`implements`/`use` list + if ($this->tokens[$prevIndex]->equals(',')) { + $checkIndex = $prevIndex; + while ($this->tokens[$checkIndex]->equalsAny([',', [T_AS], [CT::T_NAMESPACE_OPERATOR], [T_NS_SEPARATOR], [T_STRING]])) { + $checkIndex = $this->tokens->getPrevMeaningfulToken($checkIndex); + } + + if ($this->tokens[$checkIndex]->isGivenKind([T_EXTENDS, CT::T_GROUP_IMPORT_BRACE_OPEN, T_IMPLEMENTS, T_USE, CT::T_USE_TRAIT])) { + return false; + } + } + + // check for array in double quoted string: `"..$foo[bar].."` + if ($this->tokens[$prevIndex]->equals('[') && $this->tokens[$nextIndex]->equals(']')) { + $checkToken = $this->tokens[$this->tokens->getNextMeaningfulToken($nextIndex)]; + + if ($checkToken->equals('"') || $checkToken->isGivenKind([T_CURLY_OPEN, T_DOLLAR_OPEN_CURLY_BRACES, T_ENCAPSED_AND_WHITESPACE, T_VARIABLE])) { + return false; + } + } + + // check for attribute: `#[Foo]` + if ( + \defined('T_ATTRIBUTE') // @TODO: drop condition when PHP 8.0+ is required + && $this->tokens[$prevIndex]->isGivenKind(T_ATTRIBUTE) + ) { + return false; + } + + // check for goto label + if ($this->tokens[$nextIndex]->equals(':')) { + if (null === $this->gotoLabelAnalyzer) { + $this->gotoLabelAnalyzer = new GotoLabelAnalyzer(); + } + + if ($this->gotoLabelAnalyzer->belongsToGoToLabel($this->tokens, $nextIndex)) { + return false; + } + } + + // check for non-capturing catches + while ($this->tokens[$prevIndex]->isGivenKind([CT::T_TYPE_ALTERNATION, T_STRING])) { + $prevIndex = $this->tokens->getPrevMeaningfulToken($prevIndex); + } + + if ($this->tokens[$prevIndex]->equals('(')) { + $prevPrevIndex = $this->tokens->getPrevMeaningfulToken($prevIndex); + if ($this->tokens[$prevPrevIndex]->isGivenKind(T_CATCH)) { + return false; + } + } + + return true; + } + + /** + * Checks if there is an unary successor operator under given index. + * + * @param int $index + * + * @return bool + */ + public function isUnarySuccessorOperator($index) + { + static $allowedPrevToken = [ + ']', + [T_STRING], + [T_VARIABLE], + [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE], + [CT::T_DYNAMIC_PROP_BRACE_CLOSE], + [CT::T_DYNAMIC_VAR_BRACE_CLOSE], + ]; + + $tokens = $this->tokens; + $token = $tokens[$index]; + + if (!$token->isGivenKind([T_INC, T_DEC])) { + return false; + } + + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; + + return $prevToken->equalsAny($allowedPrevToken); + } + + /** + * Checks if there is an unary predecessor operator under given index. + * + * @param int $index + * + * @return bool + */ + public function isUnaryPredecessorOperator($index) + { + static $potentialSuccessorOperator = [T_INC, T_DEC]; + + static $potentialBinaryOperator = ['+', '-', '&', [CT::T_RETURN_REF]]; + + static $otherOperators; + if (null === $otherOperators) { + $otherOperators = ['!', '~', '@', [T_ELLIPSIS]]; + } + + static $disallowedPrevTokens; + if (null === $disallowedPrevTokens) { + $disallowedPrevTokens = [ + ']', + '}', + ')', + '"', + '`', + [CT::T_ARRAY_SQUARE_BRACE_CLOSE], + [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE], + [CT::T_DYNAMIC_PROP_BRACE_CLOSE], + [CT::T_DYNAMIC_VAR_BRACE_CLOSE], + [T_CLASS_C], + [T_CONSTANT_ENCAPSED_STRING], + [T_DEC], + [T_DIR], + [T_DNUMBER], + [T_FILE], + [T_FUNC_C], + [T_INC], + [T_LINE], + [T_LNUMBER], + [T_METHOD_C], + [T_NS_C], + [T_STRING], + [T_TRAIT_C], + [T_VARIABLE], + ]; + } + + $tokens = $this->tokens; + $token = $tokens[$index]; + + if ($token->isGivenKind($potentialSuccessorOperator)) { + return !$this->isUnarySuccessorOperator($index); + } + + if ($token->equalsAny($otherOperators)) { + return true; + } + + if (!$token->equalsAny($potentialBinaryOperator)) { + return false; + } + + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; + + if (!$prevToken->equalsAny($disallowedPrevTokens)) { + return true; + } + + if (!$token->equals('&') || !$prevToken->isGivenKind(T_STRING)) { + return false; + } + + static $searchTokens = [ + ';', + '{', + '}', + [T_FUNCTION], + [T_OPEN_TAG], + [T_OPEN_TAG_WITH_ECHO], + ]; + $prevToken = $tokens[$tokens->getPrevTokenOfKind($index, $searchTokens)]; + + return $prevToken->isGivenKind(T_FUNCTION); + } + + /** + * Checks if there is a binary operator under given index. + * + * @param int $index + * + * @return bool + */ + public function isBinaryOperator($index) + { + static $nonArrayOperators = [ + '=' => true, + '*' => true, + '/' => true, + '%' => true, + '<' => true, + '>' => true, + '|' => true, + '^' => true, + '.' => true, + ]; + + static $potentialUnaryNonArrayOperators = [ + '+' => true, + '-' => true, + '&' => true, + ]; + + static $arrayOperators; + if (null === $arrayOperators) { + $arrayOperators = [ + T_AND_EQUAL => true, // &= + T_BOOLEAN_AND => true, // && + T_BOOLEAN_OR => true, // || + T_CONCAT_EQUAL => true, // .= + T_DIV_EQUAL => true, // /= + T_DOUBLE_ARROW => true, // => + T_IS_EQUAL => true, // == + T_IS_GREATER_OR_EQUAL => true, // >= + T_IS_IDENTICAL => true, // === + T_IS_NOT_EQUAL => true, // !=, <> + T_IS_NOT_IDENTICAL => true, // !== + T_IS_SMALLER_OR_EQUAL => true, // <= + T_LOGICAL_AND => true, // and + T_LOGICAL_OR => true, // or + T_LOGICAL_XOR => true, // xor + T_MINUS_EQUAL => true, // -= + T_MOD_EQUAL => true, // %= + T_MUL_EQUAL => true, // *= + T_OR_EQUAL => true, // |= + T_PLUS_EQUAL => true, // += + T_POW => true, // ** + T_POW_EQUAL => true, // **= + T_SL => true, // << + T_SL_EQUAL => true, // <<= + T_SR => true, // >> + T_SR_EQUAL => true, // >>= + T_XOR_EQUAL => true, // ^= + ]; + + // @TODO: drop condition when PHP 7.0+ is required + if (\defined('T_SPACESHIP')) { + $arrayOperators[T_SPACESHIP] = true; // <=> + } + + // @TODO: drop condition when PHP 7.0+ is required + if (\defined('T_COALESCE')) { + $arrayOperators[T_COALESCE] = true; // ?? + } + + // @TODO: drop condition when PHP 7.4+ is required + if (\defined('T_COALESCE_EQUAL')) { + $arrayOperators[T_COALESCE_EQUAL] = true; // ??= + } + } + + $tokens = $this->tokens; + $token = $tokens[$index]; + + if ($token->isArray()) { + return isset($arrayOperators[$token->getId()]); + } + + if (isset($nonArrayOperators[$token->getContent()])) { + return true; + } + + if (isset($potentialUnaryNonArrayOperators[$token->getContent()])) { + return !$this->isUnaryPredecessorOperator($index); + } + + return false; + } + + /** + * Check if `T_WHILE` token at given index is `do { ... } while ();` syntax + * and not `while () { ...}`. + * + * @param int $index + * + * @return bool + */ + public function isWhilePartOfDoWhile($index) + { + $tokens = $this->tokens; + $token = $tokens[$index]; + + if (!$token->isGivenKind(T_WHILE)) { + throw new \LogicException(sprintf('No T_WHILE at given index %d, got "%s".', $index, $token->getName())); + } + + $endIndex = $tokens->getPrevMeaningfulToken($index); + if (!$tokens[$endIndex]->equals('}')) { + return false; + } + + $startIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_CURLY_BRACE, $endIndex); + $beforeStartIndex = $tokens->getPrevMeaningfulToken($startIndex); + + return $tokens[$beforeStartIndex]->isGivenKind(T_DO); + } + + /** + * @param int $index + * + * @return bool + */ + public function isSuperGlobal($index) + { + static $superNames = [ + '$_COOKIE' => true, + '$_ENV' => true, + '$_FILES' => true, + '$_GET' => true, + '$_POST' => true, + '$_REQUEST' => true, + '$_SERVER' => true, + '$_SESSION' => true, + '$GLOBALS' => true, + ]; + + $token = $this->tokens[$index]; + + if (!$token->isGivenKind(T_VARIABLE)) { + return false; + } + + return isset($superNames[strtoupper($token->getContent())]); + } + + /** + * Find classy elements. + * + * Searches in tokens from the classy (start) index till the end (index) of the classy. + * Returns an array; first value is the index until the method has analysed (int), second the found classy elements (array). + * + * @param int $classIndex classy index + * @param int $index + * @param bool $returnTraitsImports + * + * @return array + */ + private function findClassyElements($classIndex, $index, $returnTraitsImports = false) + { + $elements = []; + $curlyBracesLevel = 0; + $bracesLevel = 0; + ++$index; // skip the classy index itself + + for ($count = \count($this->tokens); $index < $count; ++$index) { + $token = $this->tokens[$index]; + + if ($token->isGivenKind(T_ENCAPSED_AND_WHITESPACE)) { + continue; + } + + if ($token->isClassy()) { // anonymous class in class + // check for nested anonymous classes inside the new call of an anonymous class, + // for example `new class(function (){new class(function (){new class(function (){}){};}){};}){};` etc. + // if class(XYZ) {} skip till `(` as XYZ might contain functions etc. + + $nestedClassIndex = $index; + $index = $this->tokens->getNextMeaningfulToken($index); + + if ($this->tokens[$index]->equals('(')) { + ++$index; // move after `(` + + for ($nestedBracesLevel = 1; $index < $count; ++$index) { + $token = $this->tokens[$index]; + + if ($token->equals('(')) { + ++$nestedBracesLevel; + + continue; + } + + if ($token->equals(')')) { + --$nestedBracesLevel; + + if (0 === $nestedBracesLevel) { + list($index, $newElements) = $this->findClassyElements($nestedClassIndex, $index, $returnTraitsImports); + $elements += $newElements; + + break; + } + + continue; + } + + if ($token->isClassy()) { // anonymous class in class + list($index, $newElements) = $this->findClassyElements($index, $index, $returnTraitsImports); + $elements += $newElements; + } + } + } else { + list($index, $newElements) = $this->findClassyElements($nestedClassIndex, $nestedClassIndex, $returnTraitsImports); + $elements += $newElements; + } + + continue; + } + + if ($token->equals('(')) { + ++$bracesLevel; + + continue; + } + + if ($token->equals(')')) { + --$bracesLevel; + + continue; + } + + if ($token->equals('{')) { + ++$curlyBracesLevel; + + continue; + } + + if ($token->equals('}')) { + --$curlyBracesLevel; + + if (0 === $curlyBracesLevel) { + break; + } + + continue; + } + + if (1 !== $curlyBracesLevel || !$token->isArray()) { + continue; + } + + if (0 === $bracesLevel && $token->isGivenKind(T_VARIABLE)) { + $elements[$index] = [ + 'token' => $token, + 'type' => 'property', + 'classIndex' => $classIndex, + ]; + + continue; + } + + if ($token->isGivenKind(T_FUNCTION)) { + $elements[$index] = [ + 'token' => $token, + 'type' => 'method', + 'classIndex' => $classIndex, + ]; + } elseif ($token->isGivenKind(T_CONST)) { + $elements[$index] = [ + 'token' => $token, + 'type' => 'const', + 'classIndex' => $classIndex, + ]; + } elseif ($returnTraitsImports && $token->isGivenKind(CT::T_USE_TRAIT)) { + $elements[$index] = [ + 'token' => $token, + 'type' => 'trait_import', + 'classIndex' => $classIndex, + ]; + } + } + + return [$index, $elements]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ArrayTypehintTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ArrayTypehintTransformer.php new file mode 100644 index 0000000..c6b0dba --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ArrayTypehintTransformer.php @@ -0,0 +1,61 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform `array` typehint from T_ARRAY into CT::T_ARRAY_TYPEHINT. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ArrayTypehintTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 50000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$token->isGivenKind(T_ARRAY)) { + return; + } + + $nextIndex = $tokens->getNextMeaningfulToken($index); + $nextToken = $tokens[$nextIndex]; + + if (!$nextToken->equals('(')) { + $tokens[$index] = new Token([CT::T_ARRAY_TYPEHINT, $token->getContent()]); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [CT::T_ARRAY_TYPEHINT]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/AttributeTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/AttributeTransformer.php new file mode 100644 index 0000000..613a5c6 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/AttributeTransformer.php @@ -0,0 +1,77 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transforms attribute related Tokens. + * + * @internal + */ +final class AttributeTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getPriority() + { + // must run before all other transformers that might touch attributes + return 200; + } + + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 80000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$tokens[$index]->isGivenKind(T_ATTRIBUTE)) { + return; + } + + $level = 1; + + do { + ++$index; + + if ($tokens[$index]->equals('[')) { + ++$level; + } elseif ($tokens[$index]->equals(']')) { + --$level; + } + } while (0 < $level); + + $tokens[$index] = new Token([CT::T_ATTRIBUTE_CLOSE, ']']); + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [ + CT::T_ATTRIBUTE_CLOSE, + ]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/BraceClassInstantiationTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/BraceClassInstantiationTransformer.php new file mode 100644 index 0000000..781e08c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/BraceClassInstantiationTransformer.php @@ -0,0 +1,88 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform braced class instantiation braces in `(new Foo())` into CT::T_BRACE_CLASS_INSTANTIATION_OPEN + * and CT::T_BRACE_CLASS_INSTANTIATION_CLOSE. + * + * @author Sebastiaans Stok <s.stok@rollerscapes.net> + * + * @internal + */ +final class BraceClassInstantiationTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getPriority() + { + // must run after CurlyBraceTransformer and SquareBraceTransformer + return -2; + } + + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 50000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$tokens[$index]->equals('(') || !$tokens[$tokens->getNextMeaningfulToken($index)]->equals([T_NEW])) { + return; + } + + if ($tokens[$tokens->getPrevMeaningfulToken($index)]->equalsAny([ + ']', + [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE], + [CT::T_ARRAY_SQUARE_BRACE_CLOSE], + [T_ARRAY], + [T_CLASS], + [T_ELSEIF], + [T_FOR], + [T_FOREACH], + [T_IF], + [T_STATIC], + [T_STRING], + [T_SWITCH], + [T_VARIABLE], + [T_WHILE], + ])) { + return; + } + + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index); + + $tokens[$index] = new Token([CT::T_BRACE_CLASS_INSTANTIATION_OPEN, '(']); + $tokens[$closeIndex] = new Token([CT::T_BRACE_CLASS_INSTANTIATION_CLOSE, ')']); + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [CT::T_BRACE_CLASS_INSTANTIATION_OPEN, CT::T_BRACE_CLASS_INSTANTIATION_CLOSE]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ClassConstantTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ClassConstantTransformer.php new file mode 100644 index 0000000..6903e23 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ClassConstantTransformer.php @@ -0,0 +1,64 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform `class` class' constant from T_CLASS into CT::T_CLASS_CONSTANT. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ClassConstantTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 50500; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$token->equalsAny([ + [T_CLASS, 'class'], + [T_STRING, 'class'], + ], false)) { + return; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + $prevToken = $tokens[$prevIndex]; + + if ($prevToken->isGivenKind(T_DOUBLE_COLON)) { + $tokens[$index] = new Token([CT::T_CLASS_CONSTANT, $token->getContent()]); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [CT::T_CLASS_CONSTANT]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ConstructorPromotionTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ConstructorPromotionTransformer.php new file mode 100644 index 0000000..1e93cb4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ConstructorPromotionTransformer.php @@ -0,0 +1,78 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transforms for Constructor Property Promotion. + * + * Transform T_PUBLIC, T_PROTECTED and T_PRIVATE of Constructor Property Promotion into custom tokens. + * + * @internal + */ +final class ConstructorPromotionTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 80000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$tokens[$index]->isGivenKind(T_FUNCTION)) { + return; + } + + $index = $tokens->getNextMeaningfulToken($index); + + if (!$tokens[$index]->isGivenKind(T_STRING) || '__construct' !== strtolower($tokens[$index]->getContent())) { + return; + } + + /** @var int $openIndex */ + $openIndex = $tokens->getNextMeaningfulToken($index); // we are @ '(' now + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex); + + for ($index = $openIndex; $index < $closeIndex; ++$index) { + if ($tokens[$index]->isGivenKind(T_PUBLIC)) { + $tokens[$index] = new Token([CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, $tokens[$index]->getContent()]); + } elseif ($tokens[$index]->isGivenKind(T_PROTECTED)) { + $tokens[$index] = new Token([CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, $tokens[$index]->getContent()]); + } elseif ($tokens[$index]->isGivenKind(T_PRIVATE)) { + $tokens[$index] = new Token([CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE, $tokens[$index]->getContent()]); + } + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [ + CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, + CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, + CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE, + ]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/CurlyBraceTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/CurlyBraceTransformer.php new file mode 100644 index 0000000..74cd9c2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/CurlyBraceTransformer.php @@ -0,0 +1,221 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform discriminate overloaded curly braces tokens. + * + * Performed transformations: + * - closing `}` for T_CURLY_OPEN into CT::T_CURLY_CLOSE, + * - closing `}` for T_DOLLAR_OPEN_CURLY_BRACES into CT::T_DOLLAR_CLOSE_CURLY_BRACES, + * - in `$foo->{$bar}` into CT::T_DYNAMIC_PROP_BRACE_OPEN and CT::T_DYNAMIC_PROP_BRACE_CLOSE, + * - in `${$foo}` into CT::T_DYNAMIC_VAR_BRACE_OPEN and CT::T_DYNAMIC_VAR_BRACE_CLOSE, + * - in `$array{$index}` into CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN and CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE, + * - in `use some\a\{ClassA, ClassB, ClassC as C}` into CT::T_GROUP_IMPORT_BRACE_OPEN, CT::T_GROUP_IMPORT_BRACE_CLOSE. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class CurlyBraceTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 50000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + $this->transformIntoCurlyCloseBrace($tokens, $token, $index); + $this->transformIntoDollarCloseBrace($tokens, $token, $index); + $this->transformIntoDynamicPropBraces($tokens, $token, $index); + $this->transformIntoDynamicVarBraces($tokens, $token, $index); + $this->transformIntoCurlyIndexBraces($tokens, $token, $index); + + if (\PHP_VERSION_ID >= 70000) { + $this->transformIntoGroupUseBraces($tokens, $token, $index); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [ + CT::T_CURLY_CLOSE, + CT::T_DOLLAR_CLOSE_CURLY_BRACES, + CT::T_DYNAMIC_PROP_BRACE_OPEN, + CT::T_DYNAMIC_PROP_BRACE_CLOSE, + CT::T_DYNAMIC_VAR_BRACE_OPEN, + CT::T_DYNAMIC_VAR_BRACE_CLOSE, + CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN, + CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE, + CT::T_GROUP_IMPORT_BRACE_OPEN, + CT::T_GROUP_IMPORT_BRACE_CLOSE, + ]; + } + + /** + * Transform closing `}` for T_CURLY_OPEN into CT::T_CURLY_CLOSE. + * + * This should be done at very beginning of curly braces transformations. + * + * @param int $index + */ + private function transformIntoCurlyCloseBrace(Tokens $tokens, Token $token, $index) + { + if (!$token->isGivenKind(T_CURLY_OPEN)) { + return; + } + + $level = 1; + $nestIndex = $index; + + while (0 < $level) { + ++$nestIndex; + + // we count all kind of { + if ($tokens[$nestIndex]->equals('{')) { + ++$level; + + continue; + } + + // we count all kind of } + if ($tokens[$nestIndex]->equals('}')) { + --$level; + } + } + + $tokens[$nestIndex] = new Token([CT::T_CURLY_CLOSE, '}']); + } + + private function transformIntoDollarCloseBrace(Tokens $tokens, Token $token, $index) + { + if ($token->isGivenKind(T_DOLLAR_OPEN_CURLY_BRACES)) { + $nextIndex = $tokens->getNextTokenOfKind($index, ['}']); + $tokens[$nextIndex] = new Token([CT::T_DOLLAR_CLOSE_CURLY_BRACES, '}']); + } + } + + private function transformIntoDynamicPropBraces(Tokens $tokens, Token $token, $index) + { + if (!$token->isObjectOperator()) { + return; + } + + if (!$tokens[$index + 1]->equals('{')) { + return; + } + + $openIndex = $index + 1; + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $openIndex); + + $tokens[$openIndex] = new Token([CT::T_DYNAMIC_PROP_BRACE_OPEN, '{']); + $tokens[$closeIndex] = new Token([CT::T_DYNAMIC_PROP_BRACE_CLOSE, '}']); + } + + private function transformIntoDynamicVarBraces(Tokens $tokens, Token $token, $index) + { + if (!$token->equals('$')) { + return; + } + + $openIndex = $tokens->getNextMeaningfulToken($index); + + if (null === $openIndex) { + return; + } + + $openToken = $tokens[$openIndex]; + + if (!$openToken->equals('{')) { + return; + } + + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $openIndex); + + $tokens[$openIndex] = new Token([CT::T_DYNAMIC_VAR_BRACE_OPEN, '{']); + $tokens[$closeIndex] = new Token([CT::T_DYNAMIC_VAR_BRACE_CLOSE, '}']); + } + + private function transformIntoCurlyIndexBraces(Tokens $tokens, Token $token, $index) + { + if (!$token->equals('{')) { + return; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + + if (!$tokens[$prevIndex]->equalsAny([ + [T_STRING], + [T_VARIABLE], + [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE], + ']', + ')', + ])) { + return; + } + + if ( + $tokens[$prevIndex]->isGivenKind(T_STRING) + && !$tokens[$tokens->getPrevMeaningfulToken($prevIndex)]->isObjectOperator() + ) { + return; + } + + if ( + $tokens[$prevIndex]->equals(')') + && !$tokens[$tokens->getPrevMeaningfulToken( + $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $prevIndex) + )]->isGivenKind(T_ARRAY) + ) { + return; + } + + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + $tokens[$index] = new Token([CT::T_ARRAY_INDEX_CURLY_BRACE_OPEN, '{']); + $tokens[$closeIndex] = new Token([CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE, '}']); + } + + private function transformIntoGroupUseBraces(Tokens $tokens, Token $token, $index) + { + if (!$token->equals('{')) { + return; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + + if (!$tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) { + return; + } + + $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + $tokens[$index] = new Token([CT::T_GROUP_IMPORT_BRACE_OPEN, '{']); + $tokens[$closeIndex] = new Token([CT::T_GROUP_IMPORT_BRACE_CLOSE, '}']); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ImportTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ImportTransformer.php new file mode 100644 index 0000000..93ff434 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ImportTransformer.php @@ -0,0 +1,67 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform const/function import tokens. + * + * Performed transformations: + * - T_CONST into CT::T_CONST_IMPORT + * - T_FUNCTION into CT::T_FUNCTION_IMPORT + * + * @author Gregor Harlan <gharlan@web.de> + * + * @internal + */ +final class ImportTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 50600; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$token->isGivenKind([T_CONST, T_FUNCTION])) { + return; + } + + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; + + if ($prevToken->isGivenKind(T_USE)) { + $tokens[$index] = new Token([ + $token->isGivenKind(T_FUNCTION) ? CT::T_FUNCTION_IMPORT : CT::T_CONST_IMPORT, + $token->getContent(), + ]); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [CT::T_CONST_IMPORT, CT::T_FUNCTION_IMPORT]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NameQualifiedTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NameQualifiedTransformer.php new file mode 100644 index 0000000..b5b0264 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NameQualifiedTransformer.php @@ -0,0 +1,103 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED and T_NAME_RELATIVE into T_NAMESPACE T_NS_SEPARATOR T_STRING. + * + * @author SpacePossum + * + * @internal + */ +final class NameQualifiedTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 1; // must run before NamespaceOperatorTransformer + } + + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 80000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if ($token->isGivenKind([T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED])) { + return $this->transformQualified($tokens, $token, $index); + } + + if ($token->isGivenKind(T_NAME_RELATIVE)) { + return $this->transformRelative($tokens, $token, $index); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return []; + } + + private function transformQualified(Tokens $tokens, Token $token, $index) + { + $parts = explode('\\', $token->getContent()); + $newTokens = []; + + if ('' === $parts[0]) { + $newTokens[] = new Token([T_NS_SEPARATOR, '\\']); + array_shift($parts); + } + + foreach ($parts as $part) { + $newTokens[] = new Token([T_STRING, $part]); + $newTokens[] = new Token([T_NS_SEPARATOR, '\\']); + } + + array_pop($newTokens); + + $tokens->overrideRange($index, $index, $newTokens); + } + + private function transformRelative(Tokens $tokens, Token $token, $index) + { + $parts = explode('\\', $token->getContent()); + $newTokens = [ + new Token([T_NAMESPACE, array_shift($parts)]), + new Token([T_NS_SEPARATOR, '\\']), + ]; + + foreach ($parts as $part) { + $newTokens[] = new Token([T_STRING, $part]); + $newTokens[] = new Token([T_NS_SEPARATOR, '\\']); + } + + array_pop($newTokens); + + $tokens->overrideRange($index, $index, $newTokens); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NamedArgumentTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NamedArgumentTransformer.php new file mode 100644 index 0000000..cb7327a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NamedArgumentTransformer.php @@ -0,0 +1,85 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform named argument tokens. + * + * @author SpacePossum + * + * @internal + */ +final class NamedArgumentTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getPriority() + { + // needs to run after TypeColonTransformer + return -15; + } + + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 80000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$tokens[$index]->equals(':')) { + return; + } + + $stringIndex = $tokens->getPrevMeaningfulToken($index); + + if (!$tokens[$stringIndex]->isGivenKind(T_STRING)) { + return; + } + + $preStringIndex = $tokens->getPrevMeaningfulToken($stringIndex); + + // if equals any [';', '{', '}', [T_OPEN_TAG]] than it is a goto label + // if equals ')' than likely it is a type colon, but sure not a name argument + // if equals '?' than it is part of ternary statement + + if (!$tokens[$preStringIndex]->equalsAny([',', '('])) { + return; + } + + $tokens[$stringIndex] = new Token([CT::T_NAMED_ARGUMENT_NAME, $tokens[$stringIndex]->getContent()]); + $tokens[$index] = new Token([CT::T_NAMED_ARGUMENT_COLON, ':']); + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [ + CT::T_NAMED_ARGUMENT_COLON, + CT::T_NAMED_ARGUMENT_NAME, + ]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NamespaceOperatorTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NamespaceOperatorTransformer.php new file mode 100644 index 0000000..0a2ec19 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NamespaceOperatorTransformer.php @@ -0,0 +1,60 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform `namespace` operator from T_NAMESPACE into CT::T_NAMESPACE_OPERATOR. + * + * @author Gregor Harlan <gharlan@web.de> + * + * @internal + */ +final class NamespaceOperatorTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 50300; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$token->isGivenKind(T_NAMESPACE)) { + return; + } + + $nextIndex = $tokens->getNextMeaningfulToken($index); + + if ($tokens[$nextIndex]->isGivenKind(T_NS_SEPARATOR)) { + $tokens[$index] = new Token([CT::T_NAMESPACE_OPERATOR, $token->getContent()]); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [CT::T_NAMESPACE_OPERATOR]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NullableTypeTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NullableTypeTransformer.php new file mode 100644 index 0000000..295880a --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/NullableTypeTransformer.php @@ -0,0 +1,83 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform `?` operator into CT::T_NULLABLE_TYPE in `function foo(?Bar $b) {}`. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class NullableTypeTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getPriority() + { + // needs to run after TypeColonTransformer + return -20; + } + + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 70100; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$token->equals('?')) { + return; + } + + $prevIndex = $tokens->getPrevMeaningfulToken($index); + $prevToken = $tokens[$prevIndex]; + + if ($prevToken->equalsAny([ + '(', + ',', + [CT::T_TYPE_COLON], + [CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC], + [CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED], + [CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE], + [CT::T_ATTRIBUTE_CLOSE], + [T_PRIVATE], + [T_PROTECTED], + [T_PUBLIC], + [T_VAR], + [T_STATIC], + ])) { + $tokens[$index] = new Token([CT::T_NULLABLE_TYPE, '?']); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [CT::T_NULLABLE_TYPE]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ReturnRefTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ReturnRefTransformer.php new file mode 100644 index 0000000..6690a15 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/ReturnRefTransformer.php @@ -0,0 +1,62 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform `&` operator into CT::T_RETURN_REF in `function & foo() {}`. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ReturnRefTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 50000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + $prevKinds = [T_FUNCTION]; + if (\PHP_VERSION_ID >= 70400) { + $prevKinds[] = T_FN; + } + + if ( + $token->equals('&') + && $tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind($prevKinds) + ) { + $tokens[$index] = new Token([CT::T_RETURN_REF, '&']); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [CT::T_RETURN_REF]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/SquareBraceTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/SquareBraceTransformer.php new file mode 100644 index 0000000..24b25d2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/SquareBraceTransformer.php @@ -0,0 +1,196 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform discriminate overloaded square braces tokens. + * + * Performed transformations: + * - in `[1, 2, 3]` into CT::T_ARRAY_SQUARE_BRACE_OPEN and CT::T_ARRAY_SQUARE_BRACE_CLOSE, + * - in `[$a, &$b, [$c]] = array(1, 2, array(3))` into CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN and CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + * + * @internal + */ +final class SquareBraceTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getPriority() + { + // must run after CurlyBraceTransformer and AttributeTransformer + return -1; + } + + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + // Short array syntax was introduced in PHP 5.4, but the fixer is smart + // enough to handle it even before 5.4. + // Same for array destructing syntax sugar `[` introduced in PHP 7.1. + return 50000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if ($this->isArrayDestructing($tokens, $index)) { + $this->transformIntoDestructuringSquareBrace($tokens, $index); + + return; + } + + if ($this->isShortArray($tokens, $index)) { + $this->transformIntoArraySquareBrace($tokens, $index); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [ + CT::T_ARRAY_SQUARE_BRACE_OPEN, + CT::T_ARRAY_SQUARE_BRACE_CLOSE, + CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN, + CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE, + ]; + } + + /** + * @param int $index + */ + private function transformIntoArraySquareBrace(Tokens $tokens, $index) + { + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE, $index); + + $tokens[$index] = new Token([CT::T_ARRAY_SQUARE_BRACE_OPEN, '[']); + $tokens[$endIndex] = new Token([CT::T_ARRAY_SQUARE_BRACE_CLOSE, ']']); + } + + /** + * @param int $index + */ + private function transformIntoDestructuringSquareBrace(Tokens $tokens, $index) + { + $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE, $index); + + $tokens[$index] = new Token([CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN, '[']); + $tokens[$endIndex] = new Token([CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE, ']']); + + $previousMeaningfulIndex = $index; + $index = $tokens->getNextMeaningfulToken($index); + + while ($index < $endIndex) { + if ($tokens[$index]->equals('[') && $tokens[$previousMeaningfulIndex]->equalsAny([[CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN], ','])) { + $tokens[$tokens->findBlockEnd(Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE, $index)] = new Token([CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE, ']']); + $tokens[$index] = new Token([CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN, '[']); + } + + $previousMeaningfulIndex = $index; + $index = $tokens->getNextMeaningfulToken($index); + } + } + + /** + * Check if token under given index is short array opening. + * + * @param int $index + * + * @return bool + */ + private function isShortArray(Tokens $tokens, $index) + { + if (!$tokens[$index]->equals('[')) { + return false; + } + + static $disallowedPrevTokens = [ + ')', + ']', + '}', + '"', + [T_CONSTANT_ENCAPSED_STRING], + [T_STRING], + [T_STRING_VARNAME], + [T_VARIABLE], + [CT::T_ARRAY_SQUARE_BRACE_CLOSE], + [CT::T_DYNAMIC_PROP_BRACE_CLOSE], + [CT::T_DYNAMIC_VAR_BRACE_CLOSE], + [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE], + ]; + + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; + if ($prevToken->equalsAny($disallowedPrevTokens)) { + return false; + } + + $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)]; + if ($nextToken->equals(']')) { + return true; + } + + return !$this->isArrayDestructing($tokens, $index); + } + + /** + * @param int $index + * + * @return bool + */ + private function isArrayDestructing(Tokens $tokens, $index) + { + if (\PHP_VERSION_ID < 70100 || !$tokens[$index]->equals('[')) { + return false; + } + + static $disallowedPrevTokens = [ + ')', + ']', + '"', + [T_CONSTANT_ENCAPSED_STRING], + [T_STRING], + [T_STRING_VARNAME], + [T_VARIABLE], + [CT::T_ARRAY_SQUARE_BRACE_CLOSE], + [CT::T_DYNAMIC_PROP_BRACE_CLOSE], + [CT::T_DYNAMIC_VAR_BRACE_CLOSE], + [CT::T_ARRAY_INDEX_CURLY_BRACE_CLOSE], + ]; + + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; + if ($prevToken->equalsAny($disallowedPrevTokens)) { + return false; + } + + $type = Tokens::detectBlockType($tokens[$index]); + $end = $tokens->findBlockEnd($type['type'], $index); + + $nextToken = $tokens[$tokens->getNextMeaningfulToken($end)]; + + return $nextToken->equals('='); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/TypeAlternationTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/TypeAlternationTransformer.php new file mode 100644 index 0000000..9e25658 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/TypeAlternationTransformer.php @@ -0,0 +1,117 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform `|` operator into CT::T_TYPE_ALTERNATION in `function foo(Type1 | Type2 $x) {` + * or `} catch (ExceptionType1 | ExceptionType2 $e) {`. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class TypeAlternationTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getPriority() + { + // needs to run after ArrayTypehintTransformer and TypeColonTransformer + return -15; + } + + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 70100; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$token->equals('|')) { + return; + } + + $prevIndex = $tokens->getTokenNotOfKindsSibling($index, -1, [T_NS_SEPARATOR, T_STRING, CT::T_ARRAY_TYPEHINT, T_WHITESPACE, T_COMMENT, T_DOC_COMMENT]); + + /** @var Token $prevToken */ + $prevToken = $tokens[$prevIndex]; + + if ($prevToken->isGivenKind([ + CT::T_TYPE_COLON, // `:` is part of a function return type `foo(): X|Y` + CT::T_TYPE_ALTERNATION, // `|` is part of a union (chain) `X|Y` + T_STATIC, T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, // `var X|Y $a;`, `private X|Y $a` or `public static X|Y $a` + ])) { + $this->replaceToken($tokens, $index); + + return; + } + + if (!$prevToken->equalsAny(['(', ','])) { + return; + } + + $prevPrevTokenIndex = $tokens->getPrevMeaningfulToken($prevIndex); + + if ($tokens[$prevPrevTokenIndex]->isGivenKind([T_CATCH])) { + $this->replaceToken($tokens, $index); + + return; + } + + $functionKinds = [[T_FUNCTION]]; + + if (\defined('T_FN')) { + $functionKinds[] = [T_FN]; + } + + $functionIndex = $tokens->getPrevTokenOfKind($prevIndex, $functionKinds); + + if (null === $functionIndex) { + return; + } + + $braceOpenIndex = $tokens->getNextTokenOfKind($functionIndex, ['(']); + $braceCloseIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $braceOpenIndex); + + if ($braceCloseIndex < $index) { + return; + } + + $this->replaceToken($tokens, $index); + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [CT::T_TYPE_ALTERNATION]; + } + + private function replaceToken(Tokens $tokens, $index) + { + $tokens[$index] = new Token([CT::T_TYPE_ALTERNATION, '|']); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/TypeColonTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/TypeColonTransformer.php new file mode 100644 index 0000000..7d85ca3 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/TypeColonTransformer.php @@ -0,0 +1,90 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform `:` operator into CT::T_TYPE_COLON in `function foo() : int {}`. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class TypeColonTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getPriority() + { + // needs to run after ReturnRefTransformer and UseTransformer + // and before TypeAlternationTransformer + return -10; + } + + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 70000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$token->equals(':')) { + return; + } + + $endIndex = $tokens->getPrevMeaningfulToken($index); + + if (!$tokens[$endIndex]->equals(')')) { + return; + } + + $startIndex = $tokens->findBlockStart(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $endIndex); + $prevIndex = $tokens->getPrevMeaningfulToken($startIndex); + $prevToken = $tokens[$prevIndex]; + + // if this could be a function name we need to take one more step + if ($prevToken->isGivenKind(T_STRING)) { + $prevIndex = $tokens->getPrevMeaningfulToken($prevIndex); + $prevToken = $tokens[$prevIndex]; + } + + $prevKinds = [T_FUNCTION, CT::T_RETURN_REF, CT::T_USE_LAMBDA]; + + if (\PHP_VERSION_ID >= 70400) { + $prevKinds[] = T_FN; + } + + if ($prevToken->isGivenKind($prevKinds)) { + $tokens[$index] = new Token([CT::T_TYPE_COLON, ':']); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [CT::T_TYPE_COLON]; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/UseTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/UseTransformer.php new file mode 100644 index 0000000..36e6e08 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/UseTransformer.php @@ -0,0 +1,110 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\CT; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Transform T_USE into: + * - CT::T_USE_TRAIT for imports, + * - CT::T_USE_LAMBDA for lambda variable uses. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class UseTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getPriority() + { + // Should run after CurlyBraceTransformer and before TypeColonTransformer + return -5; + } + + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 50300; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if ($token->isGivenKind(T_USE) && $this->isUseForLambda($tokens, $index)) { + $tokens[$index] = new Token([CT::T_USE_LAMBDA, $token->getContent()]); + + return; + } + + // Only search inside class/trait body for `T_USE` for traits. + // Cannot import traits inside interfaces or anywhere else + + if (!$token->isGivenKind([T_CLASS, T_TRAIT])) { + return; + } + + if ($tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_DOUBLE_COLON)) { + return; + } + + $index = $tokens->getNextTokenOfKind($index, ['{']); + $innerLimit = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + while ($index < $innerLimit) { + $token = $tokens[++$index]; + + if (!$token->isGivenKind(T_USE)) { + continue; + } + + if ($this->isUseForLambda($tokens, $index)) { + $tokens[$index] = new Token([CT::T_USE_LAMBDA, $token->getContent()]); + } else { + $tokens[$index] = new Token([CT::T_USE_TRAIT, $token->getContent()]); + } + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return [CT::T_USE_TRAIT, CT::T_USE_LAMBDA]; + } + + /** + * Check if token under given index is `use` statement for lambda function. + * + * @param int $index + * + * @return bool + */ + private function isUseForLambda(Tokens $tokens, $index) + { + $nextToken = $tokens[$tokens->getNextMeaningfulToken($index)]; + + // test `function () use ($foo) {}` case + return $nextToken->equals('('); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/WhitespacyCommentTransformer.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/WhitespacyCommentTransformer.php new file mode 100644 index 0000000..345e593 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformer/WhitespacyCommentTransformer.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer\Transformer; + +use PhpCsFixer\Tokenizer\AbstractTransformer; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * Move trailing whitespaces from comments and docs into following T_WHITESPACE token. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class WhitespacyCommentTransformer extends AbstractTransformer +{ + /** + * {@inheritdoc} + */ + public function getRequiredPhpVersionId() + { + return 50000; + } + + /** + * {@inheritdoc} + */ + public function process(Tokens $tokens, Token $token, $index) + { + if (!$token->isComment()) { + return; + } + + $content = $token->getContent(); + $trimmedContent = rtrim($content); + + // nothing trimmed, nothing to do + if ($content === $trimmedContent) { + return; + } + + $whitespaces = substr($content, \strlen($trimmedContent)); + + $tokens[$index] = new Token([$token->getId(), $trimmedContent]); + + if (isset($tokens[$index + 1]) && $tokens[$index + 1]->isWhitespace()) { + $tokens[$index + 1] = new Token([T_WHITESPACE, $whitespaces.$tokens[$index + 1]->getContent()]); + } else { + $tokens->insertAt($index + 1, new Token([T_WHITESPACE, $whitespaces])); + } + } + + /** + * {@inheritdoc} + */ + public function getCustomTokens() + { + return []; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/TransformerInterface.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/TransformerInterface.php similarity index 58% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/TransformerInterface.php rename to vendor/friendsofphp/php-cs-fixer/src/Tokenizer/TransformerInterface.php index 2ebb6df..ad5aa99 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Tokenizer/TransformerInterface.php +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/TransformerInterface.php @@ -10,7 +10,7 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Tokenizer; +namespace PhpCsFixer\Tokenizer; /** * Interface for Transformer class. @@ -21,30 +21,20 @@ * For example T_ARRAY is a token for both creating new array and typehinting a parameter. This two meaning should have two token types. * * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal */ interface TransformerInterface { /** - * Process Tokens collection to transform tokens into custom tokens when needed. + * Get tokens created by Transformer. * - * @param Tokens $tokens Tokens collection + * @return int[] */ - public function process(Tokens $tokens); + public function getCustomTokens(); /** - * Register constants for custom tokens created by Transformer. - */ - public function registerCustomTokens(); - - /** - * Get names of custom tokens created by Transformer. - * - * @return array - */ - public function getCustomTokenNames(); - - /** - * Returns the name of the fixer. + * Return the name of the transformer. * * The name must be all lowercase and without any spaces. * @@ -53,11 +43,30 @@ public function getCustomTokenNames(); public function getName(); /** - * Returns the priority of the Transformer. + * Returns the priority of the transformer. * * The default priority is 0 and higher priorities are executed first. * * @return int */ public function getPriority(); + + /** + * Return minimal required PHP version id to transform the code. + * + * Custom Token kinds from Transformers are always registered, but sometimes + * there is no need to analyse the Tokens if for sure we cannot find examined + * token kind, eg transforming `T_FUNCTION` in `<?php use function Foo\\bar;` + * code. + * + * @return int + */ + public function getRequiredPhpVersionId(); + + /** + * Process Token to transform it into custom token when needed. + * + * @param int $index + */ + public function process(Tokens $tokens, Token $token, $index); } diff --git a/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformers.php b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformers.php new file mode 100644 index 0000000..3e2fff1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Tokenizer/Transformers.php @@ -0,0 +1,113 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tokenizer; + +use PhpCsFixer\Utils; +use Symfony\Component\Finder\Finder; +use Symfony\Component\Finder\SplFileInfo; + +/** + * Collection of Transformer classes. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class Transformers +{ + /** + * The registered transformers. + * + * @var TransformerInterface[] + */ + private $items = []; + + /** + * Register built in Transformers. + */ + private function __construct() + { + $this->registerBuiltInTransformers(); + + usort($this->items, static function (TransformerInterface $a, TransformerInterface $b) { + return Utils::cmpInt($b->getPriority(), $a->getPriority()); // TODO: update to use spaceship operator (PHP 7.0 required) + }); + } + + /** + * @return Transformers + */ + public static function createSingleton() + { + static $instance = null; + + if (!$instance) { + $instance = new self(); + } + + return $instance; + } + + /** + * Transform given Tokens collection through all Transformer classes. + * + * @param Tokens $tokens Tokens collection + */ + public function transform(Tokens $tokens) + { + foreach ($this->items as $transformer) { + foreach ($tokens as $index => $token) { + $transformer->process($tokens, $token, $index); + } + } + } + + /** + * @param TransformerInterface $transformer Transformer + */ + private function registerTransformer(TransformerInterface $transformer) + { + if (\PHP_VERSION_ID >= $transformer->getRequiredPhpVersionId()) { + $this->items[] = $transformer; + } + } + + private function registerBuiltInTransformers() + { + static $registered = false; + + if ($registered) { + return; + } + + $registered = true; + + foreach ($this->findBuiltInTransformers() as $transformer) { + $this->registerTransformer($transformer); + } + } + + /** + * @return \Generator|TransformerInterface[] + */ + private function findBuiltInTransformers() + { + /** @var SplFileInfo $file */ + foreach (Finder::create()->files()->in(__DIR__.'/Transformer') as $file) { + $relativeNamespace = $file->getRelativePath(); + $class = __NAMESPACE__.'\\Transformer\\'.($relativeNamespace ? $relativeNamespace.'\\' : '').$file->getBasename('.php'); + + yield new $class(); + } + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/ToolInfo.php b/vendor/friendsofphp/php-cs-fixer/src/ToolInfo.php new file mode 100644 index 0000000..98e3e2b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/ToolInfo.php @@ -0,0 +1,111 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Console\Application; + +/** + * Obtain information about using version of tool. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class ToolInfo implements ToolInfoInterface +{ + const COMPOSER_PACKAGE_NAME = 'friendsofphp/php-cs-fixer'; + + const COMPOSER_LEGACY_PACKAGE_NAME = 'fabpot/php-cs-fixer'; + + /** + * @var null|array + */ + private $composerInstallationDetails; + + /** + * @var null|bool + */ + private $isInstalledByComposer; + + public function getComposerInstallationDetails() + { + if (!$this->isInstalledByComposer()) { + throw new \LogicException('Cannot get composer version for tool not installed by composer.'); + } + + if (null === $this->composerInstallationDetails) { + $composerInstalled = json_decode(file_get_contents($this->getComposerInstalledFile()), true); + + $packages = isset($composerInstalled['packages']) ? $composerInstalled['packages'] : $composerInstalled; + + foreach ($packages as $package) { + if (\in_array($package['name'], [self::COMPOSER_PACKAGE_NAME, self::COMPOSER_LEGACY_PACKAGE_NAME], true)) { + $this->composerInstallationDetails = $package; + + break; + } + } + } + + return $this->composerInstallationDetails; + } + + public function getComposerVersion() + { + $package = $this->getComposerInstallationDetails(); + + $versionSuffix = ''; + + if (isset($package['dist']['reference'])) { + $versionSuffix = '#'.$package['dist']['reference']; + } + + return $package['version'].$versionSuffix; + } + + public function getVersion() + { + if ($this->isInstalledByComposer()) { + return Application::VERSION.':'.$this->getComposerVersion(); + } + + return Application::VERSION; + } + + public function isInstalledAsPhar() + { + return 'phar://' === substr(__DIR__, 0, 7); + } + + public function isInstalledByComposer() + { + if (null === $this->isInstalledByComposer) { + $this->isInstalledByComposer = !$this->isInstalledAsPhar() && file_exists($this->getComposerInstalledFile()); + } + + return $this->isInstalledByComposer; + } + + public function getPharDownloadUri($version) + { + return sprintf( + 'https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/%s/php-cs-fixer.phar', + $version + ); + } + + private function getComposerInstalledFile() + { + return __DIR__.'/../../../composer/installed.json'; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/ToolInfoInterface.php b/vendor/friendsofphp/php-cs-fixer/src/ToolInfoInterface.php new file mode 100644 index 0000000..d5c3708 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/ToolInfoInterface.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * @internal + */ +interface ToolInfoInterface +{ + public function getComposerInstallationDetails(); + + public function getComposerVersion(); + + public function getVersion(); + + public function isInstalledAsPhar(); + + public function isInstalledByComposer(); + + public function getPharDownloadUri($version); +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/Utils.php b/vendor/friendsofphp/php-cs-fixer/src/Utils.php new file mode 100644 index 0000000..5197bb4 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/Utils.php @@ -0,0 +1,217 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\Tokenizer\Token; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author Graham Campbell <graham@alt-three.com> + * @author Odín del Río <odin.drp@gmail.com> + * + * @internal + */ +final class Utils +{ + /** + * @var array<string,true> + */ + private static $deprecations = []; + + /** + * Calculate a bitmask for given constant names. + * + * @param string[] $options constant names + * + * @return int + */ + public static function calculateBitmask(array $options) + { + $bitmask = 0; + + foreach ($options as $optionName) { + if (\defined($optionName)) { + $bitmask |= \constant($optionName); + } + } + + return $bitmask; + } + + /** + * Converts a camel cased string to a snake cased string. + * + * @param string $string + * + * @return string + */ + public static function camelCaseToUnderscore($string) + { + return strtolower(Preg::replace('/(?<!^)((?=[A-Z][^A-Z])|(?<![A-Z])(?=[A-Z]))/', '_', $string)); + } + + /** + * Compare two integers for equality. + * + * We'll return 0 if they're equal, 1 if the first is bigger than the + * second, and -1 if the second is bigger than the first. + * + * @param int $a + * @param int $b + * + * @return int + */ + public static function cmpInt($a, $b) + { + if ($a === $b) { + return 0; + } + + return $a < $b ? -1 : 1; + } + + /** + * Calculate the trailing whitespace. + * + * What we're doing here is grabbing everything after the final newline. + * + * @return string + */ + public static function calculateTrailingWhitespaceIndent(Token $token) + { + if (!$token->isWhitespace()) { + throw new \InvalidArgumentException(sprintf('The given token must be whitespace, got "%s".', $token->getName())); + } + + $str = strrchr( + str_replace(["\r\n", "\r"], "\n", $token->getContent()), + "\n" + ); + + if (false === $str) { + return ''; + } + + return ltrim($str, "\n"); + } + + /** + * Perform stable sorting using provided comparison function. + * + * Stability is ensured by using Schwartzian transform. + * + * @param mixed[] $elements + * @param callable $getComparedValue a callable that takes a single element and returns the value to compare + * @param callable $compareValues a callable that compares two values + * + * @return mixed[] + */ + public static function stableSort(array $elements, callable $getComparedValue, callable $compareValues) + { + array_walk($elements, static function (&$element, $index) use ($getComparedValue) { + $element = [$element, $index, $getComparedValue($element)]; + }); + + usort($elements, static function ($a, $b) use ($compareValues) { + $comparison = $compareValues($a[2], $b[2]); + + if (0 !== $comparison) { + return $comparison; + } + + return self::cmpInt($a[1], $b[1]); + }); + + return array_map(static function (array $item) { + return $item[0]; + }, $elements); + } + + /** + * Sort fixers by their priorities. + * + * @param FixerInterface[] $fixers + * + * @return FixerInterface[] + */ + public static function sortFixers(array $fixers) + { + // Schwartzian transform is used to improve the efficiency and avoid + // `usort(): Array was modified by the user comparison function` warning for mocked objects. + return self::stableSort( + $fixers, + static function (FixerInterface $fixer) { + return $fixer->getPriority(); + }, + static function ($a, $b) { + return self::cmpInt($b, $a); + } + ); + } + + /** + * Join names in natural language wrapped in backticks, e.g. `a`, `b` and `c`. + * + * @param string[] $names + * + * @throws \InvalidArgumentException + * + * @return string + */ + public static function naturalLanguageJoinWithBackticks(array $names) + { + if (empty($names)) { + throw new \InvalidArgumentException('Array of names cannot be empty.'); + } + + $names = array_map(static function ($name) { + return sprintf('`%s`', $name); + }, $names); + + $last = array_pop($names); + + if ($names) { + return implode(', ', $names).' and '.$last; + } + + return $last; + } + + /** + * Handle triggering deprecation error. + */ + public static function triggerDeprecation(\Exception $futureException) + { + if (getenv('PHP_CS_FIXER_FUTURE_MODE')) { + throw new \RuntimeException( + 'Your are using something deprecated, see previous exception. Aborting execution because `PHP_CS_FIXER_FUTURE_MODE` environment variable is set.', + 0, + $futureException + ); + } + + $message = $futureException->getMessage(); + + self::$deprecations[$message] = true; + @trigger_error($message, E_USER_DEPRECATED); + } + + public static function getTriggeredDeprecations() + { + $triggeredDeprecations = array_keys(self::$deprecations); + sort($triggeredDeprecations); + + return $triggeredDeprecations; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/WhitespacesFixerConfig.php b/vendor/friendsofphp/php-cs-fixer/src/WhitespacesFixerConfig.php new file mode 100644 index 0000000..c2e6227 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/WhitespacesFixerConfig.php @@ -0,0 +1,63 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + */ +final class WhitespacesFixerConfig +{ + /** + * @var string + */ + private $indent; + + /** + * @var string + */ + private $lineEnding; + + /** + * @param string $indent + * @param string $lineEnding + */ + public function __construct($indent = ' ', $lineEnding = "\n") + { + if (!\in_array($indent, [' ', ' ', "\t"], true)) { + throw new \InvalidArgumentException('Invalid "indent" param, expected tab or two or four spaces.'); + } + + if (!\in_array($lineEnding, ["\n", "\r\n"], true)) { + throw new \InvalidArgumentException('Invalid "lineEnding" param, expected "\n" or "\r\n".'); + } + + $this->indent = $indent; + $this->lineEnding = $lineEnding; + } + + /** + * @return string + */ + public function getIndent() + { + return $this->indent; + } + + /** + * @return string + */ + public function getLineEnding() + { + return $this->lineEnding; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/src/WordMatcher.php b/vendor/friendsofphp/php-cs-fixer/src/WordMatcher.php new file mode 100644 index 0000000..d0f529d --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/src/WordMatcher.php @@ -0,0 +1,57 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * @author SpacePossum + * + * @internal + */ +final class WordMatcher +{ + /** + * @var string[] + */ + private $candidates; + + /** + * @param string[] $candidates + */ + public function __construct(array $candidates) + { + $this->candidates = $candidates; + } + + /** + * @param string $needle + * + * @return null|string + */ + public function match($needle) + { + $word = null; + $distance = ceil(\strlen($needle) * 0.35); + + foreach ($this->candidates as $candidate) { + $candidateDistance = levenshtein($needle, $candidate); + + if ($candidateDistance < $distance) { + $word = $candidate; + $distance = $candidateDistance; + } + } + + return $word; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractFixerTestCase.php b/vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractFixerTestCase.php new file mode 100644 index 0000000..a05a056 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractFixerTestCase.php @@ -0,0 +1,584 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Test; + +use PhpCsFixer\AbstractFixer; +use PhpCsFixer\AbstractProxyFixer; +use PhpCsFixer\Fixer\Comment\HeaderCommentFixer; +use PhpCsFixer\Fixer\ConfigurationDefinitionFixerInterface; +use PhpCsFixer\Fixer\DefinedFixerInterface; +use PhpCsFixer\Fixer\DeprecatedFixerInterface; +use PhpCsFixer\Fixer\Whitespace\SingleBlankLineAtEofFixer; +use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface; +use PhpCsFixer\FixerConfiguration\FixerOptionInterface; +use PhpCsFixer\FixerDefinition\CodeSampleInterface; +use PhpCsFixer\FixerDefinition\FileSpecificCodeSampleInterface; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSampleInterface; +use PhpCsFixer\Linter\CachingLinter; +use PhpCsFixer\Linter\Linter; +use PhpCsFixer\Linter\LinterInterface; +use PhpCsFixer\Linter\ProcessLinter; +use PhpCsFixer\Preg; +use PhpCsFixer\StdinFileInfo; +use PhpCsFixer\Tests\Test\Assert\AssertTokensTrait; +use PhpCsFixer\Tests\TestCase; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use Prophecy\Argument; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +abstract class AbstractFixerTestCase extends TestCase +{ + use AssertTokensTrait; + use IsIdenticalConstraint; + + /** + * @var null|LinterInterface + */ + protected $linter; + + /** + * @var null|AbstractFixer + */ + protected $fixer; + + // do not modify this structure without prior discussion + private $allowedRequiredOptions = [ + 'header_comment' => ['header' => true], + ]; + + // do not modify this structure without prior discussion + private $allowedFixersWithoutDefaultCodeSample = [ + 'general_phpdoc_annotation_remove' => true, + 'general_phpdoc_tag_rename' => true, + ]; + + protected function doSetUp() + { + parent::doSetUp(); + + $this->linter = $this->getLinter(); + $this->fixer = $this->createFixer(); + + // @todo remove at 3.0 together with env var itself + if (getenv('PHP_CS_FIXER_TEST_USE_LEGACY_TOKENIZER')) { + Tokens::setLegacyMode(true); + } + } + + protected function doTearDown() + { + parent::doTearDown(); + + $this->linter = null; + $this->fixer = null; + + // @todo remove at 3.0 + Tokens::setLegacyMode(false); + } + + final public function testIsRisky() + { + static::assertIsBool($this->fixer->isRisky(), sprintf('Return type for ::isRisky of "%s" is invalid.', $this->fixer->getName())); + + if ($this->fixer->isRisky()) { + self::assertValidDescription($this->fixer->getName(), 'risky description', $this->fixer->getDefinition()->getRiskyDescription()); + } else { + static::assertNull($this->fixer->getDefinition()->getRiskyDescription(), sprintf('[%s] Fixer is not risky so no description of it expected.', $this->fixer->getName())); + } + + if ($this->fixer instanceof AbstractProxyFixer) { + return; + } + + $reflection = new \ReflectionMethod($this->fixer, 'isRisky'); + + // If fixer is not risky then the method `isRisky` from `AbstractFixer` must be used + static::assertSame( + !$this->fixer->isRisky(), + AbstractFixer::class === $reflection->getDeclaringClass()->getName() + ); + } + + final public function testFixerDefinitions() + { + static::assertInstanceOf(DefinedFixerInterface::class, $this->fixer); + + $fixerName = $this->fixer->getName(); + $definition = $this->fixer->getDefinition(); + $fixerIsConfigurable = $this->fixer instanceof ConfigurationDefinitionFixerInterface; + + self::assertValidDescription($fixerName, 'summary', $definition->getSummary()); + + $samples = $definition->getCodeSamples(); + static::assertNotEmpty($samples, sprintf('[%s] Code samples are required.', $fixerName)); + + $configSamplesProvided = []; + $dummyFileInfo = new StdinFileInfo(); + foreach ($samples as $sampleCounter => $sample) { + static::assertInstanceOf(CodeSampleInterface::class, $sample, sprintf('[%s] Sample #%d', $fixerName, $sampleCounter)); + static::assertIsInt($sampleCounter); + + $code = $sample->getCode(); + + static::assertIsString($code, sprintf('[%s] Sample #%d', $fixerName, $sampleCounter)); + static::assertNotEmpty($code, sprintf('[%s] Sample #%d', $fixerName, $sampleCounter)); + + if (!($this->fixer instanceof SingleBlankLineAtEofFixer)) { + static::assertSame("\n", substr($code, -1), sprintf('[%s] Sample #%d must end with linebreak', $fixerName, $sampleCounter)); + } + + $config = $sample->getConfiguration(); + if (null !== $config) { + static::assertTrue($fixerIsConfigurable, sprintf('[%s] Sample #%d has configuration, but the fixer is not configurable.', $fixerName, $sampleCounter)); + static::assertIsArray($config, sprintf('[%s] Sample #%d configuration must be an array or null.', $fixerName, $sampleCounter)); + + $configSamplesProvided[$sampleCounter] = $config; + } elseif ($fixerIsConfigurable) { + if (!$sample instanceof VersionSpecificCodeSampleInterface) { + static::assertArrayNotHasKey('default', $configSamplesProvided, sprintf('[%s] Multiple non-versioned samples with default configuration.', $fixerName)); + } + + $configSamplesProvided['default'] = true; + } + + if ($sample instanceof VersionSpecificCodeSampleInterface && !$sample->isSuitableFor(\PHP_VERSION_ID)) { + continue; + } + + if ($fixerIsConfigurable) { + // always re-configure as the fixer might have been configured with diff. configuration form previous sample + $this->fixer->configure(null === $config ? [] : $config); + } + + Tokens::clearCache(); + $tokens = Tokens::fromCode($code); + $this->fixer->fix( + $sample instanceof FileSpecificCodeSampleInterface ? $sample->getSplFileInfo() : $dummyFileInfo, + $tokens + ); + + static::assertTrue($tokens->isChanged(), sprintf('[%s] Sample #%d is not changed during fixing.', $fixerName, $sampleCounter)); + + $duplicatedCodeSample = array_search( + $sample, + \array_slice($samples, 0, $sampleCounter), + false + ); + + static::assertFalse( + $duplicatedCodeSample, + sprintf('[%s] Sample #%d duplicates #%d.', $fixerName, $sampleCounter, $duplicatedCodeSample) + ); + } + + if ($fixerIsConfigurable) { + if (isset($configSamplesProvided['default'])) { + reset($configSamplesProvided); + static::assertSame('default', key($configSamplesProvided), sprintf('[%s] First sample must be for the default configuration.', $fixerName)); + } elseif (!isset($this->allowedFixersWithoutDefaultCodeSample[$fixerName])) { + static::assertArrayHasKey($fixerName, $this->allowedRequiredOptions, sprintf('[%s] Has no sample for default configuration.', $fixerName)); + } + + // It may only shrink, never add anything to it. + $fixerNamesWithKnownMissingSamplesWithConfig = [ // @TODO 3.0 - remove this + 'is_null', // has only one option which is deprecated + ]; + + if (\count($configSamplesProvided) < 2) { + if (\in_array($fixerName, $fixerNamesWithKnownMissingSamplesWithConfig, true)) { + static::markTestIncomplete(sprintf('[%s] Configurable fixer only provides a default configuration sample and none for its configuration options, please help and add it.', $fixerName)); + } + + static::fail(sprintf('[%s] Configurable fixer only provides a default configuration sample and none for its configuration options.', $fixerName)); + } elseif (\in_array($fixerName, $fixerNamesWithKnownMissingSamplesWithConfig, true)) { + static::fail(sprintf('[%s] Invalid listed as missing code samples, please update the list.', $fixerName)); + } + + $options = $this->fixer->getConfigurationDefinition()->getOptions(); + + foreach ($options as $option) { + static::assertMatchesRegularExpression('/^[a-z_]+[a-z]$/', $option->getName(), sprintf('[%s] Option %s is not snake_case.', $fixerName, $option->getName())); + } + } + } + + /** + * @group legacy + */ + final public function testLegacyFixerDefinitions() + { + $this->expectDeprecation('PhpCsFixer\\FixerDefinition\\FixerDefinition::getConfigurationDescription is deprecated and will be removed in 3.0.'); + $this->expectDeprecation('PhpCsFixer\\FixerDefinition\\FixerDefinition::getDefaultConfiguration is deprecated and will be removed in 3.0.'); + $definition = $this->fixer->getDefinition(); + + static::assertNull($definition->getConfigurationDescription(), sprintf('[%s] No configuration description expected.', $this->fixer->getName())); + static::assertNull($definition->getDefaultConfiguration(), sprintf('[%s] No default configuration expected.', $this->fixer->getName())); + } + + final public function testFixersAreFinal() + { + $reflection = new \ReflectionClass($this->fixer); + + static::assertTrue( + $reflection->isFinal(), + sprintf('Fixer "%s" must be declared "final".', $this->fixer->getName()) + ); + } + + final public function testFixersAreDefined() + { + static::assertInstanceOf(DefinedFixerInterface::class, $this->fixer); + } + + final public function testDeprecatedFixersHaveCorrectSummary() + { + $reflection = new \ReflectionClass($this->fixer); + $comment = $reflection->getDocComment(); + + static::assertStringNotContainsString( + 'DEPRECATED', + $this->fixer->getDefinition()->getSummary(), + 'Fixer cannot contain word "DEPRECATED" in summary' + ); + + if ($this->fixer instanceof DeprecatedFixerInterface) { + static::assertStringContainsString('@deprecated', $comment); + } elseif (\is_string($comment)) { + static::assertStringNotContainsString('@deprecated', $comment); + } + } + + /** + * Blur filter that find candidate fixer for performance optimization to use only `insertSlices` instead of multiple `insertAt` if there is no other collection manipulation. + */ + public function testFixerUseInsertSlicesWhenOnlyInsertionsArePerformed() + { + $reflection = new \ReflectionClass($this->fixer); + $tokens = Tokens::fromCode(file_get_contents($reflection->getFileName())); + + $sequences = $this->findAllTokenSequences($tokens, [[T_VARIABLE, '$tokens'], [T_OBJECT_OPERATOR], [T_STRING]]); + + $usedMethods = array_unique(array_map(function (array $sequence) { + $last = end($sequence); + + return $last->getContent(); + }, $sequences)); + + // if there is no `insertAt`, it's not a candidate + if (!\in_array('insertAt', $usedMethods, true)) { + $this->addToAssertionCount(1); + + return; + } + + $usedMethods = array_filter($usedMethods, function ($method) { + return 0 === Preg::match('/^(count|find|generate|get|is|rewind)/', $method); + }); + + $allowedMethods = ['insertAt']; + $nonAllowedMethods = array_diff($usedMethods, $allowedMethods); + + if ([] === $nonAllowedMethods) { + $fixerName = $this->fixer->getName(); + if (\in_array($fixerName, [ + // DO NOT add anything to this list at ease, align with core contributors whether it makes sense to insert tokens individually or by bulk for your case. + // The original list of the fixers being exceptions and insert tokens individually came from legacy reasons when it was the only available methods to insert tokens. + 'blank_line_after_namespace', + 'blank_line_after_opening_tag', + 'blank_line_before_statement', + 'class_attributes_separation', + 'date_time_immutable', + 'declare_strict_types', + 'doctrine_annotation_braces', + 'doctrine_annotation_spaces', + 'final_internal_class', + 'final_public_method_for_abstract_class', + 'function_typehint_space', + 'heredoc_indentation', + 'method_chaining_indentation', + 'native_constant_invocation', + 'new_with_braces', + 'no_short_echo_tag', + 'not_operator_with_space', + 'not_operator_with_successor_space', + 'php_unit_internal_class', + 'php_unit_no_expectation_annotation', + 'php_unit_set_up_tear_down_visibility', + 'php_unit_size_class', + 'php_unit_test_annotation', + 'php_unit_test_class_requires_covers', + 'phpdoc_to_param_type', + 'phpdoc_to_property_type', + 'phpdoc_to_return_type', + 'random_api_migration', + 'semicolon_after_instruction', + 'single_line_after_imports', + 'static_lambda', + 'strict_param', + 'void_return', + ], true)) { + static::markTestIncomplete(sprintf('Fixer "%s" may be optimized to use `Tokens::insertSlices` instead of `%s`, please help and optimize it.', $fixerName, implode(', ', $allowedMethods))); + } + static::fail(sprintf('Fixer "%s" shall be optimized to use `Tokens::insertSlices` instead of `%s`.', $fixerName, implode(', ', $allowedMethods))); + } + + $this->addToAssertionCount(1); + } + + final public function testFixerConfigurationDefinitions() + { + if (!$this->fixer instanceof ConfigurationDefinitionFixerInterface) { + $this->addToAssertionCount(1); // not applied to the fixer without configuration + + return; + } + + $configurationDefinition = $this->fixer->getConfigurationDefinition(); + + static::assertInstanceOf(FixerConfigurationResolverInterface::class, $configurationDefinition); + + foreach ($configurationDefinition->getOptions() as $option) { + static::assertInstanceOf(FixerOptionInterface::class, $option); + static::assertNotEmpty($option->getDescription()); + + static::assertSame( + !isset($this->allowedRequiredOptions[$this->fixer->getName()][$option->getName()]), + $option->hasDefault(), + sprintf( + $option->hasDefault() + ? 'Option `%s` of fixer `%s` is wrongly listed in `$allowedRequiredOptions` structure, as it is not required. If you just changed that option to not be required anymore, please adjust mentioned structure.' + : 'Option `%s` of fixer `%s` shall not be required. If you want to introduce new required option please adjust `$allowedRequiredOptions` structure.', + $option->getName(), + $this->fixer->getName() + ) + ); + + static::assertStringNotContainsString( + 'DEPRECATED', + $option->getDescription(), + 'Option description cannot contain word "DEPRECATED"' + ); + } + } + + final public function testFixersReturnTypes() + { + $tokens = Tokens::fromCode('<?php '); + $emptyTokens = new Tokens(); + + static::assertIsInt($this->fixer->getPriority(), sprintf('Return type for ::getPriority of "%s" is invalid.', $this->fixer->getName())); + static::assertIsBool($this->fixer->supports(new \SplFileInfo(__FILE__)), sprintf('Return type for ::supports of "%s" is invalid.', $this->fixer->getName())); + + static::assertIsBool($this->fixer->isCandidate($emptyTokens), sprintf('Return type for ::isCandidate with empty tokens of "%s" is invalid.', $this->fixer->getName())); + static::assertFalse($emptyTokens->isChanged()); + + static::assertIsBool($this->fixer->isCandidate($tokens), sprintf('Return type for ::isCandidate of "%s" is invalid.', $this->fixer->getName())); + static::assertFalse($tokens->isChanged()); + + if ($this->fixer instanceof HeaderCommentFixer) { + $this->fixer->configure(['header' => 'a']); + } + + static::assertNull($this->fixer->fix(new \SplFileInfo(__FILE__), $emptyTokens), sprintf('Return type for ::fix with empty tokens of "%s" is invalid.', $this->fixer->getName())); + static::assertFalse($emptyTokens->isChanged()); + + static::assertNull($this->fixer->fix(new \SplFileInfo(__FILE__), $tokens), sprintf('Return type for ::fix of "%s" is invalid.', $this->fixer->getName())); + } + + /** + * @return AbstractFixer + */ + protected function createFixer() + { + $fixerClassName = preg_replace('/^(PhpCsFixer)\\\\Tests(\\\\.+)Test$/', '$1$2', static::class); + + return new $fixerClassName(); + } + + /** + * @param string $filename + * + * @return \SplFileInfo + */ + protected function getTestFile($filename = __FILE__) + { + static $files = []; + + if (!isset($files[$filename])) { + $files[$filename] = new \SplFileInfo($filename); + } + + return $files[$filename]; + } + + /** + * Tests if a fixer fixes a given string to match the expected result. + * + * It is used both if you want to test if something is fixed or if it is not touched by the fixer. + * It also makes sure that the expected output does not change when run through the fixer. That means that you + * do not need two test cases like [$expected] and [$expected, $input] (where $expected is the same in both cases) + * as the latter covers both of them. + * This method throws an exception if $expected and $input are equal to prevent test cases that accidentally do + * not test anything. + * + * @param string $expected The expected fixer output + * @param null|string $input The fixer input, or null if it should intentionally be equal to the output + * @param null|\SplFileInfo $file The file to fix, or null if unneeded + */ + protected function doTest($expected, $input = null, \SplFileInfo $file = null) + { + if ($expected === $input) { + throw new \InvalidArgumentException('Input parameter must not be equal to expected parameter.'); + } + + $file = $file ?: $this->getTestFile(); + $fileIsSupported = $this->fixer->supports($file); + + if (null !== $input) { + static::assertNull($this->lintSource($input)); + + Tokens::clearCache(); + $tokens = Tokens::fromCode($input); + + if ($fileIsSupported) { + static::assertTrue($this->fixer->isCandidate($tokens), 'Fixer must be a candidate for input code.'); + static::assertFalse($tokens->isChanged(), 'Fixer must not touch Tokens on candidate check.'); + $fixResult = $this->fixer->fix($file, $tokens); + static::assertNull($fixResult, '->fix method must return null.'); + } + + static::assertThat( + $tokens->generateCode(), + self::createIsIdenticalStringConstraint($expected), + 'Code build on input code must match expected code.' + ); + static::assertTrue($tokens->isChanged(), 'Tokens collection built on input code must be marked as changed after fixing.'); + + $tokens->clearEmptyTokens(); + + static::assertSame( + \count($tokens), + \count(array_unique(array_map(static function (Token $token) { + return spl_object_hash($token); + }, $tokens->toArray()))), + 'Token items inside Tokens collection must be unique.' + ); + + Tokens::clearCache(); + $expectedTokens = Tokens::fromCode($expected); + static::assertTokens($expectedTokens, $tokens); + } + + static::assertNull($this->lintSource($expected)); + + Tokens::clearCache(); + $tokens = Tokens::fromCode($expected); + + if ($fileIsSupported) { + $fixResult = $this->fixer->fix($file, $tokens); + static::assertNull($fixResult, '->fix method must return null.'); + } + + static::assertThat( + $tokens->generateCode(), + self::createIsIdenticalStringConstraint($expected), + 'Code build on expected code must not change.' + ); + static::assertFalse($tokens->isChanged(), 'Tokens collection built on expected code must not be marked as changed after fixing.'); + } + + /** + * @param string $source + * + * @return null|string + */ + protected function lintSource($source) + { + try { + $this->linter->lintSource($source)->check(); + } catch (\Exception $e) { + return $e->getMessage()."\n\nSource:\n{$source}"; + } + + return null; + } + + /** + * @return LinterInterface + */ + private function getLinter() + { + static $linter = null; + + if (null === $linter) { + if (getenv('SKIP_LINT_TEST_CASES')) { + $linterProphecy = $this->prophesize(\PhpCsFixer\Linter\LinterInterface::class); + $linterProphecy + ->lintSource(Argument::type('string')) + ->willReturn($this->prophesize(\PhpCsFixer\Linter\LintingResultInterface::class)->reveal()) + ; + + $linter = $linterProphecy->reveal(); + } else { + $linter = new CachingLinter( + getenv('FAST_LINT_TEST_CASES') ? new Linter() : new ProcessLinter() + ); + } + } + + return $linter; + } + + /** + * @param string $fixerName + * @param string $descriptionType + * @param mixed $description + */ + private static function assertValidDescription($fixerName, $descriptionType, $description) + { + static::assertIsString($description); + static::assertMatchesRegularExpression('/^[A-Z`][^"]+\.$/', $description, sprintf('[%s] The %s must start with capital letter or a ` and end with dot.', $fixerName, $descriptionType)); + static::assertStringNotContainsString('phpdocs', $description, sprintf('[%s] `PHPDoc` must not be in the plural in %s.', $fixerName, $descriptionType)); + static::assertCorrectCasing($description, 'PHPDoc', sprintf('[%s] `PHPDoc` must be in correct casing in %s.', $fixerName, $descriptionType)); + static::assertCorrectCasing($description, 'PHPUnit', sprintf('[%s] `PHPUnit` must be in correct casing in %s.', $fixerName, $descriptionType)); + static::assertFalse(strpos($descriptionType, '``'), sprintf('[%s] The %s must no contain sequential backticks.', $fixerName, $descriptionType)); + } + + /** + * @param string $needle + * @param string $haystack + * @param string $message + */ + private static function assertCorrectCasing($needle, $haystack, $message) + { + static::assertSame(substr_count(strtolower($haystack), strtolower($needle)), substr_count($haystack, $needle), $message); + } + + private function findAllTokenSequences($tokens, $sequence) + { + $lastIndex = 0; + $sequences = []; + while ($found = $tokens->findSequence($sequence, $lastIndex)) { + $keys = array_keys($found); + $sequences[] = $found; + $lastIndex = $keys[2]; + } + + return $sequences; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationCaseFactory.php b/vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationCaseFactory.php new file mode 100644 index 0000000..159f45b --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationCaseFactory.php @@ -0,0 +1,252 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Test; + +use PhpCsFixer\RuleSet\RuleSet; +use Symfony\Component\Finder\SplFileInfo; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +abstract class AbstractIntegrationCaseFactory implements IntegrationCaseFactoryInterface +{ + /** + * @return IntegrationCase + */ + public function create(SplFileInfo $file) + { + try { + if (!preg_match( + '/^ + --TEST-- \r?\n(?<title> .*?) + \s --RULESET-- \r?\n(?<ruleset> .*?) + (?:\s --CONFIG-- \r?\n(?<config> .*?))? + (?:\s --SETTINGS-- \r?\n(?<settings> .*?))? + (?:\s --REQUIREMENTS-- \r?\n(?<requirements> .*?))? + (?:\s --EXPECT-- \r?\n(?<expect> .*?\r?\n*))? + (?:\s --INPUT-- \r?\n(?<input> .*))? + $/sx', + $file->getContents(), + $match + )) { + throw new \InvalidArgumentException('File format is invalid.'); + } + + $match = array_merge( + [ + 'config' => null, + 'settings' => null, + 'requirements' => null, + 'expect' => null, + 'input' => null, + ], + $match + ); + + return new IntegrationCase( + $file->getRelativePathname(), + $this->determineTitle($file, $match['title']), + $this->determineSettings($file, $match['settings']), + $this->determineRequirements($file, $match['requirements']), + $this->determineConfig($file, $match['config']), + $this->determineRuleset($file, $match['ruleset']), + $this->determineExpectedCode($file, $match['expect']), + $this->determineInputCode($file, $match['input']) + ); + } catch (\InvalidArgumentException $e) { + throw new \InvalidArgumentException( + sprintf('%s Test file: "%s".', $e->getMessage(), $file->getRelativePathname()), + $e->getCode(), + $e + ); + } + } + + /** + * Parses the '--CONFIG--' block of a '.test' file. + * + * @param ?string $config + * + * @return array + */ + protected function determineConfig(SplFileInfo $file, $config) + { + $parsed = $this->parseJson($config, [ + 'indent' => ' ', + 'lineEnding' => "\n", + ]); + + if (!\is_string($parsed['indent'])) { + throw new \InvalidArgumentException(sprintf( + 'Expected string value for "indent", got "%s".', + \is_object($parsed['indent']) ? \get_class($parsed['indent']) : \gettype($parsed['indent']).'#'.$parsed['indent'] + )); + } + + if (!\is_string($parsed['lineEnding'])) { + throw new \InvalidArgumentException(sprintf( + 'Expected string value for "lineEnding", got "%s".', + \is_object($parsed['lineEnding']) ? \get_class($parsed['lineEnding']) : \gettype($parsed['lineEnding']).'#'.$parsed['lineEnding'] + )); + } + + return $parsed; + } + + /** + * Parses the '--REQUIREMENTS--' block of a '.test' file and determines requirements. + * + * @param ?string $config + * + * @return array + */ + protected function determineRequirements(SplFileInfo $file, $config) + { + $parsed = $this->parseJson($config, [ + 'php' => \PHP_VERSION_ID, + ]); + + if (!\is_int($parsed['php'])) { + throw new \InvalidArgumentException(sprintf( + 'Expected int value like 50509 for "php", got "%s".', + \is_object($parsed['php']) ? \get_class($parsed['php']) : \gettype($parsed['php']).'#'.$parsed['php'] + )); + } + + return $parsed; + } + + /** + * Parses the '--RULESET--' block of a '.test' file and determines what fixers should be used. + * + * @param string $config + * + * @return RuleSet + */ + protected function determineRuleset(SplFileInfo $file, $config) + { + return new RuleSet($this->parseJson($config)); + } + + /** + * Parses the '--TEST--' block of a '.test' file and determines title. + * + * @param string $config + * + * @return string + */ + protected function determineTitle(SplFileInfo $file, $config) + { + return $config; + } + + /** + * Parses the '--SETTINGS--' block of a '.test' file and determines settings. + * + * @param ?string $config + * + * @return array + */ + protected function determineSettings(SplFileInfo $file, $config) + { + $parsed = $this->parseJson($config, [ + 'checkPriority' => true, + ]); + + if (!\is_bool($parsed['checkPriority'])) { + throw new \InvalidArgumentException(sprintf( + 'Expected bool value for "checkPriority", got "%s".', + \is_object($parsed['checkPriority']) ? \get_class($parsed['checkPriority']) : \gettype($parsed['checkPriority']).'#'.$parsed['checkPriority'] + )); + } + + return $parsed; + } + + /** + * @param null|string $code + * + * @return string + */ + protected function determineExpectedCode(SplFileInfo $file, $code) + { + $code = $this->determineCode($file, $code, '-out.php'); + + if (null === $code) { + throw new \InvalidArgumentException('Missing expected code.'); + } + + return $code; + } + + /** + * @param null|string $code + * + * @return null|string + */ + protected function determineInputCode(SplFileInfo $file, $code) + { + return $this->determineCode($file, $code, '-in.php'); + } + + /** + * @param null|string $code + * @param string $suffix + * + * @return null|string + */ + private function determineCode(SplFileInfo $file, $code, $suffix) + { + if (null !== $code) { + return $code; + } + + $candidateFile = new SplFileInfo($file->getPathname().$suffix, '', ''); + if ($candidateFile->isFile()) { + return $candidateFile->getContents(); + } + + return null; + } + + /** + * @param null|string $encoded + * + * @return array + */ + private function parseJson($encoded, array $template = null) + { + // content is optional if template is provided + if (!$encoded && null !== $template) { + $decoded = []; + } else { + $decoded = json_decode($encoded, true); + + if (JSON_ERROR_NONE !== json_last_error()) { + throw new \InvalidArgumentException(sprintf('Malformed JSON: "%s", error: "%s".', $encoded, json_last_error_msg())); + } + } + + if (null !== $template) { + foreach ($template as $index => $value) { + if (!\array_key_exists($index, $decoded)) { + $decoded[$index] = $value; + } + } + } + + return $decoded; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationTestCase.php b/vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationTestCase.php new file mode 100644 index 0000000..2c10f7c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/tests/Test/AbstractIntegrationTestCase.php @@ -0,0 +1,410 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Test; + +use PhpCsFixer\Cache\NullCacheManager; +use PhpCsFixer\Differ\SebastianBergmannDiffer; +use PhpCsFixer\Error\Error; +use PhpCsFixer\Error\ErrorsManager; +use PhpCsFixer\FileRemoval; +use PhpCsFixer\Fixer\FixerInterface; +use PhpCsFixer\FixerFactory; +use PhpCsFixer\Linter\CachingLinter; +use PhpCsFixer\Linter\Linter; +use PhpCsFixer\Linter\LinterInterface; +use PhpCsFixer\Linter\ProcessLinter; +use PhpCsFixer\Runner\Runner; +use PhpCsFixer\Tests\TestCase; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\WhitespacesFixerConfig; +use Prophecy\Argument; +use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Finder\Finder; +use Symfony\Component\Finder\SplFileInfo; + +/** + * Integration test base class. + * + * This test searches for '.test' fixture files in the given directory. + * Each fixture file will be parsed and tested against the expected result. + * + * Fixture files have the following format: + * + * --TEST-- + * Example test description. + * --RULESET-- + * {"@PSR2": true, "strict": true} + * --CONFIG--* + * {"indent": " ", "lineEnding": "\n"} + * --SETTINGS--* + * {"key": "value"} # optional extension point for custom IntegrationTestCase class + * --EXPECT-- + * Expected code after fixing + * --INPUT--* + * Code to fix + * + * * Section or any line in it may be omitted. + * ** PHP minimum version. Default to current running php version (no effect). + * + * @author SpacePossum + * + * @internal + */ +abstract class AbstractIntegrationTestCase extends TestCase +{ + use IsIdenticalConstraint; + + /** + * @var null|LinterInterface + */ + protected $linter; + + /** + * @var null|FileRemoval + */ + private static $fileRemoval; + + public static function doSetUpBeforeClass() + { + parent::doSetUpBeforeClass(); + + $tmpFile = static::getTempFile(); + self::$fileRemoval = new FileRemoval(); + self::$fileRemoval->observe($tmpFile); + + if (!is_file($tmpFile)) { + $dir = \dirname($tmpFile); + + if (!is_dir($dir)) { + $fs = new Filesystem(); + $fs->mkdir($dir, 0766); + } + } + } + + public static function doTearDownAfterClass() + { + parent::doTearDownAfterClass(); + + $tmpFile = static::getTempFile(); + + self::$fileRemoval->delete($tmpFile); + self::$fileRemoval = null; + } + + protected function doSetUp() + { + parent::doSetUp(); + + $this->linter = $this->getLinter(); + + // @todo remove at 3.0 together with env var itself + if (getenv('PHP_CS_FIXER_TEST_USE_LEGACY_TOKENIZER')) { + Tokens::setLegacyMode(true); + } + } + + protected function doTearDown() + { + parent::doTearDown(); + + $this->linter = null; + + // @todo remove at 3.0 + Tokens::setLegacyMode(false); + } + + /** + * @dataProvider provideIntegrationCases + * + * @see doTest() + * @large + */ + public function testIntegration(IntegrationCase $case) + { + $this->doTest($case); + } + + /** + * Creates test data by parsing '.test' files. + * + * @return IntegrationCase[][] + */ + public function provideIntegrationCases() + { + $dir = static::getFixturesDir(); + $fixturesDir = realpath($dir); + + if (!is_dir($fixturesDir)) { + throw new \UnexpectedValueException(sprintf('Given fixture dir "%s" is not a directory.', \is_string($fixturesDir) ? $fixturesDir : $dir)); + } + + $factory = static::createIntegrationCaseFactory(); + $tests = []; + + /** @var SplFileInfo $file */ + foreach (Finder::create()->files()->in($fixturesDir) as $file) { + if ('test' !== $file->getExtension()) { + continue; + } + + $tests[$file->getPathname()] = [ + $factory->create($file), + ]; + } + + return $tests; + } + + /** + * @return IntegrationCaseFactoryInterface + */ + protected static function createIntegrationCaseFactory() + { + return new IntegrationCaseFactory(); + } + + /** + * Returns the full path to directory which contains the tests. + * + * @return string + */ + protected static function getFixturesDir() + { + throw new \BadMethodCallException('Method "getFixturesDir" must be overridden by the extending class.'); + } + + /** + * Returns the full path to the temporary file where the test will write to. + * + * @return string + */ + protected static function getTempFile() + { + throw new \BadMethodCallException('Method "getTempFile" must be overridden by the extending class.'); + } + + /** + * Applies the given fixers on the input and checks the result. + * + * It will write the input to a temp file. The file will be fixed by a Fixer instance + * configured with the given fixers. The result is compared with the expected output. + * It checks if no errors were reported during the fixing. + */ + protected function doTest(IntegrationCase $case) + { + if (\PHP_VERSION_ID < $case->getRequirement('php')) { + static::markTestSkipped(sprintf('PHP %d (or later) is required for "%s", current "%d".', $case->getRequirement('php'), $case->getFileName(), \PHP_VERSION_ID)); + } + + $input = $case->getInputCode(); + $expected = $case->getExpectedCode(); + + $input = $case->hasInputCode() ? $input : $expected; + + $tmpFile = static::getTempFile(); + + if (false === @file_put_contents($tmpFile, $input)) { + throw new IOException(sprintf('Failed to write to tmp. file "%s".', $tmpFile)); + } + + $errorsManager = new ErrorsManager(); + $fixers = static::createFixers($case); + $runner = new Runner( + new \ArrayIterator([new \SplFileInfo($tmpFile)]), + $fixers, + new SebastianBergmannDiffer(), + null, + $errorsManager, + $this->linter, + false, + new NullCacheManager() + ); + + Tokens::clearCache(); + $result = $runner->fix(); + $changed = array_pop($result); + + if (!$errorsManager->isEmpty()) { + $errors = $errorsManager->getExceptionErrors(); + static::assertEmpty($errors, sprintf('Errors reported during fixing of file "%s": %s', $case->getFileName(), $this->implodeErrors($errors))); + + $errors = $errorsManager->getInvalidErrors(); + static::assertEmpty($errors, sprintf('Errors reported during linting before fixing file "%s": %s.', $case->getFileName(), $this->implodeErrors($errors))); + + $errors = $errorsManager->getLintErrors(); + static::assertEmpty($errors, sprintf('Errors reported during linting after fixing file "%s": %s.', $case->getFileName(), $this->implodeErrors($errors))); + } + + if (!$case->hasInputCode()) { + static::assertEmpty( + $changed, + sprintf( + "Expected no changes made to test \"%s\" in \"%s\".\nFixers applied:\n%s.\nDiff.:\n%s.", + $case->getTitle(), + $case->getFileName(), + null === $changed ? '[None]' : implode(',', $changed['appliedFixers']), + null === $changed ? '[None]' : $changed['diff'] + ) + ); + + return; + } + + static::assertNotEmpty($changed, sprintf('Expected changes made to test "%s" in "%s".', $case->getTitle(), $case->getFileName())); + $fixedInputCode = file_get_contents($tmpFile); + static::assertThat( + $fixedInputCode, + self::createIsIdenticalStringConstraint($expected), + sprintf( + "Expected changes do not match result for \"%s\" in \"%s\".\nFixers applied:\n%s.", + $case->getTitle(), + $case->getFileName(), + null === $changed ? '[None]' : implode(',', $changed['appliedFixers']) + ) + ); + + if (1 < \count($fixers)) { + $tmpFile = static::getTempFile(); + if (false === @file_put_contents($tmpFile, $input)) { + throw new IOException(sprintf('Failed to write to tmp. file "%s".', $tmpFile)); + } + + $runner = new Runner( + new \ArrayIterator([new \SplFileInfo($tmpFile)]), + array_reverse($fixers), + new SebastianBergmannDiffer(), + null, + $errorsManager, + $this->linter, + false, + new NullCacheManager() + ); + + Tokens::clearCache(); + $runner->fix(); + $fixedInputCodeWithReversedFixers = file_get_contents($tmpFile); + + static::assertRevertedOrderFixing($case, $fixedInputCode, $fixedInputCodeWithReversedFixers); + } + + // run the test again with the `expected` part, this should always stay the same + $this->testIntegration( + new IntegrationCase( + $case->getFileName(), + $case->getTitle().' "--EXPECT-- part run"', + $case->getSettings(), + $case->getRequirements(), + $case->getConfig(), + $case->getRuleset(), + $case->getExpectedCode(), + null + ) + ); + } + + /** + * @param string $fixedInputCode + * @param string $fixedInputCodeWithReversedFixers + */ + protected static function assertRevertedOrderFixing(IntegrationCase $case, $fixedInputCode, $fixedInputCodeWithReversedFixers) + { + // If output is different depends on rules order - we need to verify that the rules are ordered by priority. + // If not, any order is valid. + if ($fixedInputCode !== $fixedInputCodeWithReversedFixers) { + static::assertGreaterThan( + 1, + \count(array_unique(array_map( + static function (FixerInterface $fixer) { + return $fixer->getPriority(); + }, + static::createFixers($case) + ))), + sprintf( + 'Rules priorities are not differential enough. If rules would be used in reverse order then final output would be different than the expected one. For that, different priorities must be set up for used rules to ensure stable order of them. In "%s".', + $case->getFileName() + ) + ); + } + } + + /** + * @return FixerInterface[] + */ + private static function createFixers(IntegrationCase $case) + { + $config = $case->getConfig(); + + return (new FixerFactory()) + ->registerBuiltInFixers() + ->useRuleSet($case->getRuleset()) + ->setWhitespacesConfig( + new WhitespacesFixerConfig($config['indent'], $config['lineEnding']) + ) + ->getFixers() + ; + } + + /** + * @param Error[] $errors + * + * @return string + */ + private function implodeErrors(array $errors) + { + $errorStr = ''; + foreach ($errors as $error) { + $source = $error->getSource(); + $errorStr .= sprintf("%d: %s%s\n", $error->getType(), $error->getFilePath(), null === $source ? '' : ' '.$source->getMessage()."\n\n".$source->getTraceAsString()); + } + + return $errorStr; + } + + /** + * @return LinterInterface + */ + private function getLinter() + { + static $linter = null; + + if (null === $linter) { + if (getenv('SKIP_LINT_TEST_CASES')) { + $linterProphecy = $this->prophesize(\PhpCsFixer\Linter\LinterInterface::class); + $linterProphecy + ->lintSource(Argument::type('string')) + ->willReturn($this->prophesize(\PhpCsFixer\Linter\LintingResultInterface::class)->reveal()) + ; + + $linterProphecy + ->lintFile(Argument::type('string')) + ->willReturn($this->prophesize(\PhpCsFixer\Linter\LintingResultInterface::class)->reveal()) + ; + + $linterProphecy + ->isAsync() + ->willReturn(false) + ; + + $linter = $linterProphecy->reveal(); + } else { + $linter = new CachingLinter( + getenv('FAST_LINT_TEST_CASES') ? new Linter() : new ProcessLinter() + ); + } + } + + return $linter; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/tests/Test/Assert/AssertTokensTrait.php b/vendor/friendsofphp/php-cs-fixer/tests/Test/Assert/AssertTokensTrait.php new file mode 100644 index 0000000..7a7d2ce --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/tests/Test/Assert/AssertTokensTrait.php @@ -0,0 +1,52 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Test\Assert; + +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +trait AssertTokensTrait +{ + private static function assertTokens(Tokens $expectedTokens, Tokens $inputTokens) + { + foreach ($expectedTokens as $index => $expectedToken) { + if (!isset($inputTokens[$index])) { + static::fail(sprintf("The token at index %d must be:\n%s, but is not set in the input collection.", $index, $expectedToken->toJson())); + } + + $inputToken = $inputTokens[$index]; + + static::assertTrue( + $expectedToken->equals($inputToken), + sprintf("The token at index %d must be:\n%s,\ngot:\n%s.", $index, $expectedToken->toJson(), $inputToken->toJson()) + ); + + $expectedTokenKind = $expectedToken->isArray() ? $expectedToken->getId() : $expectedToken->getContent(); + static::assertTrue( + $inputTokens->isTokenKindFound($expectedTokenKind), + sprintf( + 'The token kind %s (%s) must be found in tokens collection.', + $expectedTokenKind, + \is_string($expectedTokenKind) ? $expectedTokenKind : Token::getNameForId($expectedTokenKind) + ) + ); + } + + static::assertSame($expectedTokens->count(), $inputTokens->count(), 'Both collections must have the same length.'); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Test/IntegrationCase.php b/vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCase.php similarity index 54% rename from vendor/friendsofphp/php-cs-fixer/Symfony/CS/Test/IntegrationCase.php rename to vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCase.php index 3208c9d..2dc8bff 100644 --- a/vendor/friendsofphp/php-cs-fixer/Symfony/CS/Test/IntegrationCase.php +++ b/vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCase.php @@ -10,15 +10,19 @@ * with this source code in the file LICENSE. */ -namespace Symfony\CS\Test; +namespace PhpCsFixer\Tests\Test; -use Symfony\CS\FixerInterface; +use PhpCsFixer\RuleSet\RuleSet; /** * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal */ final class IntegrationCase { + private $config; + /** * @var string */ @@ -30,37 +34,58 @@ final class IntegrationCase private $fileName; /** - * @var FixerInterface[] - */ - private $fixers = array(); - - /** - * @var string|null + * @var null|string */ private $inputCode; /** - * Env requirements (possible keys: php, hhvm). + * Env requirements (possible keys: php). * * @var array */ - private $requirements = array(); + private $requirements; /** - * Settings how to perform the test (possible keys: checkPriority). + * @var RuleSet + */ + private $ruleset; + + /** + * Settings how to perform the test (possible keys: none in base class, use as extension point for custom IntegrationTestCase). * * @var array */ - private $settings = array(); + private $settings; /** * @var string */ private $title; - public static function create() - { - return new self(); + /** + * @param string $fileName + * @param string $title + * @param string $expectedCode + * @param null|string $inputCode + */ + public function __construct( + $fileName, + $title, + array $settings, + array $requirements, + array $config, + RuleSet $ruleset, + $expectedCode, + $inputCode + ) { + $this->fileName = $fileName; + $this->title = $title; + $this->settings = $settings; + $this->requirements = $requirements; + $this->config = $config; + $this->ruleset = $ruleset; + $this->expectedCode = $expectedCode; + $this->inputCode = $inputCode; } public function hasInputCode() @@ -68,6 +93,11 @@ public function hasInputCode() return null !== $this->inputCode; } + public function getConfig() + { + return $this->config; + } + public function getExpectedCode() { return $this->expectedCode; @@ -78,18 +108,26 @@ public function getFileName() return $this->fileName; } - public function getFixers() - { - return $this->fixers; - } - public function getInputCode() { return $this->inputCode; } + /** + * @param string $name + * + * @return mixed + */ public function getRequirement($name) { + if (!\array_key_exists($name, $this->requirements)) { + throw new \InvalidArgumentException(sprintf( + 'Unknown requirement key "%s", expected any of "%s".', + $name, + implode('","', array_keys($this->requirements)) + )); + } + return $this->requirements[$name]; } @@ -98,6 +136,11 @@ public function getRequirements() return $this->requirements; } + public function getRuleset() + { + return $this->ruleset; + } + public function getSettings() { return $this->settings; @@ -107,58 +150,4 @@ public function getTitle() { return $this->title; } - - public function setExpectedCode($expectedCode) - { - $this->expectedCode = $expectedCode; - - return $this; - } - - public function setFileName($fileName) - { - $this->fileName = $fileName; - - return $this; - } - - public function setFixers(array $fixers) - { - $this->fixers = $fixers; - - return $this; - } - - public function setInputCode($inputCode) - { - $this->inputCode = $inputCode; - - return $this; - } - - public function setRequirements(array $requirements) - { - $this->requirements = $requirements; - - return $this; - } - - public function setSettings($settings) - { - $this->settings = $settings; - - return $this; - } - - public function setTitle($title) - { - $this->title = $title; - - return $this; - } - - public function shouldCheckPriority() - { - return $this->settings['checkPriority']; - } } diff --git a/vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactory.php b/vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactory.php new file mode 100644 index 0000000..14702f2 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactory.php @@ -0,0 +1,22 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Test; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class IntegrationCaseFactory extends AbstractIntegrationCaseFactory +{ +} diff --git a/vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactoryInterface.php b/vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactoryInterface.php new file mode 100644 index 0000000..f69a2eb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/tests/Test/IntegrationCaseFactoryInterface.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Test; + +use Symfony\Component\Finder\SplFileInfo; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +interface IntegrationCaseFactoryInterface +{ + /** + * @return IntegrationCase + */ + public function create(SplFileInfo $file); +} diff --git a/vendor/friendsofphp/php-cs-fixer/tests/Test/InternalIntegrationCaseFactory.php b/vendor/friendsofphp/php-cs-fixer/tests/Test/InternalIntegrationCaseFactory.php new file mode 100644 index 0000000..0228b2c --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/tests/Test/InternalIntegrationCaseFactory.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Test; + +use Symfony\Component\Finder\SplFileInfo; + +/** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class InternalIntegrationCaseFactory extends AbstractIntegrationCaseFactory +{ + /** + * {@inheritdoc} + */ + protected function determineSettings(SplFileInfo $file, $config) + { + $parsed = parent::determineSettings($file, $config); + + $parsed['isExplicitPriorityCheck'] = \in_array('priority', explode(\DIRECTORY_SEPARATOR, $file->getRelativePathname()), true); + + return $parsed; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/tests/Test/IsIdenticalConstraint.php b/vendor/friendsofphp/php-cs-fixer/tests/Test/IsIdenticalConstraint.php new file mode 100644 index 0000000..114d9cb --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/tests/Test/IsIdenticalConstraint.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Test; + +use PhpCsFixer\PhpunitConstraintIsIdenticalString\Constraint\IsIdenticalString; +use PHPUnit\Framework\Constraint\IsIdentical as PhpUnitIsIdentical; + +/** + * @internal + * + * @todo Remove me when usages will end up in dedicated package. + */ +trait IsIdenticalConstraint +{ + /** + * @todo Remove me when this class will end up in dedicated package. + * + * @param string $expected + * + * @return IsIdenticalString|\PHPUnit_Framework_Constraint_IsIdentical|PhpUnitIsIdentical + */ + private static function createIsIdenticalStringConstraint($expected) + { + $candidate = self::getIsIdenticalStringConstraintClassName(); + + return new $candidate($expected); + } + + /** + * @return string + */ + private static function getIsIdenticalStringConstraintClassName() + { + foreach ([ + IsIdenticalString::class, + PhpUnitIsIdentical::class, + 'PHPUnit_Framework_Constraint_IsIdentical', + ] as $className) { + if (class_exists($className)) { + return $className; + } + } + + throw new \RuntimeException('PHPUnit not installed?!'); + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/tests/Test/TokensWithObservedTransformers.php b/vendor/friendsofphp/php-cs-fixer/tests/Test/TokensWithObservedTransformers.php new file mode 100644 index 0000000..366a7e1 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/tests/Test/TokensWithObservedTransformers.php @@ -0,0 +1,68 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Test; + +use PhpCsFixer\AccessibleObject\AccessibleObject; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; +use PhpCsFixer\Tokenizer\Transformers; + +class TokensWithObservedTransformers extends Tokens +{ + /** + * @var null|string + */ + public $currentTransformer; + public $observedModificationsPerTransformer = []; + + public function offsetSet($index, $newval) + { + if (null !== $this->currentTransformer) { + $this->observedModificationsPerTransformer[$this->currentTransformer][] = $this->extractTokenKind($newval); + } + parent::offsetSet($index, $newval); + } + + /** + * @internal + */ + protected function applyTransformers() + { + $this->observedModificationsPerTransformer = []; + + $transformers = Transformers::createSingleton(); + foreach (AccessibleObject::create($transformers)->items as $transformer) { + $this->currentTransformer = $transformer->getName(); + $this->observedModificationsPerTransformer[$this->currentTransformer] = []; + + foreach ($this as $index => $token) { + $transformer->process($this, $token, $index); + } + } + + $this->currentTransformer = null; + } + + /** + * @param array|string|Token $token token prototype + * + * @return int|string + */ + private function extractTokenKind($token) + { + return $token instanceof Token + ? ($token->isArray() ? $token->getId() : $token->getContent()) + : (\is_array($token) ? $token[0] : $token) + ; + } +} diff --git a/vendor/friendsofphp/php-cs-fixer/tests/TestCase.php b/vendor/friendsofphp/php-cs-fixer/tests/TestCase.php new file mode 100644 index 0000000..8ccf9b9 --- /dev/null +++ b/vendor/friendsofphp/php-cs-fixer/tests/TestCase.php @@ -0,0 +1,76 @@ +<?php + +/* + * This file is part of PHP CS Fixer. + * + * (c) Fabien Potencier <fabien@symfony.com> + * Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests; + +use LegacyPHPUnit\TestCase as BaseTestCase; +use PHPUnitGoodPractices\Polyfill\PolyfillTrait; +use PHPUnitGoodPractices\Traits\ExpectationViaCodeOverAnnotationTrait; +use PHPUnitGoodPractices\Traits\ExpectOverSetExceptionTrait; +use PHPUnitGoodPractices\Traits\IdentityOverEqualityTrait; +use PHPUnitGoodPractices\Traits\ProphecyOverMockObjectTrait; +use PHPUnitGoodPractices\Traits\ProphesizeOnlyInterfaceTrait; +use Prophecy\PhpUnit\ProphecyTrait; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; + +// we check single, example DEV dependency - if it's there, we have the dev dependencies, if not, we are using PHP-CS-Fixer as library and trying to use internal TestCase... +if (trait_exists(ProphesizeOnlyInterfaceTrait::class)) { + if (trait_exists(ProphecyTrait::class)) { + /** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ + abstract class InterimTestCase extends BaseTestCase + { + use ProphecyTrait; + } + } else { + /** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ + abstract class InterimTestCase extends BaseTestCase + { + } + } + + /** + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ + abstract class TestCase extends InterimTestCase + { + use ExpectationViaCodeOverAnnotationTrait; + use ExpectDeprecationTrait; + use ExpectOverSetExceptionTrait; + use IdentityOverEqualityTrait; + use PolyfillTrait; + use ProphecyOverMockObjectTrait; + use ProphesizeOnlyInterfaceTrait; + } +} else { + /** + * Version without traits for cases when this class is used as a lib. + * + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + * + * @todo 3.0 To be removed when we clean up composer prod-autoloader from dev-packages. + */ + abstract class TestCase extends BaseTestCase + { + } +} diff --git a/vendor/guzzlehttp/guzzle/CHANGELOG.md b/vendor/guzzlehttp/guzzle/CHANGELOG.md index 17badd7..1144eb7 100644 --- a/vendor/guzzlehttp/guzzle/CHANGELOG.md +++ b/vendor/guzzlehttp/guzzle/CHANGELOG.md @@ -1,5 +1,312 @@ # Change Log +Please refer to [UPGRADING](UPGRADING.md) guide for upgrading to a major version. + + +## 7.7.0 - 2023-05-21 + +### Added + +- Support `guzzlehttp/promises` v2 + + +## 7.6.1 - 2023-05-15 + +### Fixed + +- Fix `SetCookie::fromString` MaxAge deprecation warning and skip invalid MaxAge values + + +## 7.6.0 - 2023-05-14 + +### Added + +- Support for setting the minimum TLS version in a unified way +- Apply on request the version set in options parameters + + +## 7.5.2 - 2023-05-14 + +### Fixed + +- Fixed set cookie constructor validation +- Fixed handling of files with `'0'` body + +### Changed + +- Corrected docs and default connect timeout value to 300 seconds + + +## 7.5.1 - 2023-04-17 + +### Fixed + +- Fixed `NO_PROXY` settings so that setting the `proxy` option to `no` overrides the env variable + +### Changed + +- Adjusted `guzzlehttp/psr7` version constraint to `^1.9.1 || ^2.4.5` + + +## 7.5.0 - 2022-08-28 + +### Added + +- Support PHP 8.2 +- Add request to delay closure params + + +## 7.4.5 - 2022-06-20 + +### Fixed + +* Fix change in port should be considered a change in origin +* Fix `CURLOPT_HTTPAUTH` option not cleared on change of origin + + +## 7.4.4 - 2022-06-09 + +### Fixed + +* Fix failure to strip Authorization header on HTTP downgrade +* Fix failure to strip the Cookie header on change in host or HTTP downgrade + + +## 7.4.3 - 2022-05-25 + +### Fixed + +* Fix cross-domain cookie leakage + + +## 7.4.2 - 2022-03-20 + +### Fixed + +- Remove curl auth on cross-domain redirects to align with the Authorization HTTP header +- Reject non-HTTP schemes in StreamHandler +- Set a default ssl.peer_name context in StreamHandler to allow `force_ip_resolve` + + +## 7.4.1 - 2021-12-06 + +### Changed + +- Replaced implicit URI to string coercion [#2946](https://github.com/guzzle/guzzle/pull/2946) +- Allow `symfony/deprecation-contracts` version 3 [#2961](https://github.com/guzzle/guzzle/pull/2961) + +### Fixed + +- Only close curl handle if it's done [#2950](https://github.com/guzzle/guzzle/pull/2950) + + +## 7.4.0 - 2021-10-18 + +### Added + +- Support PHP 8.1 [#2929](https://github.com/guzzle/guzzle/pull/2929), [#2939](https://github.com/guzzle/guzzle/pull/2939) +- Support `psr/log` version 2 and 3 [#2943](https://github.com/guzzle/guzzle/pull/2943) + +### Fixed + +- Make sure we always call `restore_error_handler()` [#2915](https://github.com/guzzle/guzzle/pull/2915) +- Fix progress parameter type compatibility between the cURL and stream handlers [#2936](https://github.com/guzzle/guzzle/pull/2936) +- Throw `InvalidArgumentException` when an incorrect `headers` array is provided [#2916](https://github.com/guzzle/guzzle/pull/2916), [#2942](https://github.com/guzzle/guzzle/pull/2942) + +### Changed + +- Be more strict with types [#2914](https://github.com/guzzle/guzzle/pull/2914), [#2917](https://github.com/guzzle/guzzle/pull/2917), [#2919](https://github.com/guzzle/guzzle/pull/2919), [#2945](https://github.com/guzzle/guzzle/pull/2945) + + +## 7.3.0 - 2021-03-23 + +### Added + +- Support for DER and P12 certificates [#2413](https://github.com/guzzle/guzzle/pull/2413) +- Support the cURL (http://) scheme for StreamHandler proxies [#2850](https://github.com/guzzle/guzzle/pull/2850) +- Support for `guzzlehttp/psr7:^2.0` [#2878](https://github.com/guzzle/guzzle/pull/2878) + +### Fixed + +- Handle exceptions on invalid header consistently between PHP versions and handlers [#2872](https://github.com/guzzle/guzzle/pull/2872) + + +## 7.2.0 - 2020-10-10 + +### Added + +- Support for PHP 8 [#2712](https://github.com/guzzle/guzzle/pull/2712), [#2715](https://github.com/guzzle/guzzle/pull/2715), [#2789](https://github.com/guzzle/guzzle/pull/2789) +- Support passing a body summarizer to the http errors middleware [#2795](https://github.com/guzzle/guzzle/pull/2795) + +### Fixed + +- Handle exceptions during response creation [#2591](https://github.com/guzzle/guzzle/pull/2591) +- Fix CURLOPT_ENCODING not to be overwritten [#2595](https://github.com/guzzle/guzzle/pull/2595) +- Make sure the Request always has a body object [#2804](https://github.com/guzzle/guzzle/pull/2804) + +### Changed + +- The `TooManyRedirectsException` has a response [#2660](https://github.com/guzzle/guzzle/pull/2660) +- Avoid "functions" from dependencies [#2712](https://github.com/guzzle/guzzle/pull/2712) + +### Deprecated + +- Using environment variable GUZZLE_CURL_SELECT_TIMEOUT [#2786](https://github.com/guzzle/guzzle/pull/2786) + + +## 7.1.1 - 2020-09-30 + +### Fixed + +- Incorrect EOF detection for response body streams on Windows. + +### Changed + +- We dont connect curl `sink` on HEAD requests. +- Removed some PHP 5 workarounds + + +## 7.1.0 - 2020-09-22 + +### Added + +- `GuzzleHttp\MessageFormatterInterface` + +### Fixed + +- Fixed issue that caused cookies with no value not to be stored. +- On redirects, we allow all safe methods like GET, HEAD and OPTIONS. +- Fixed logging on empty responses. +- Make sure MessageFormatter::format returns string + +### Deprecated + +- All functions in `GuzzleHttp` has been deprecated. Use static methods on `Utils` instead. +- `ClientInterface::getConfig()` +- `Client::getConfig()` +- `Client::__call()` +- `Utils::defaultCaBundle()` +- `CurlFactory::LOW_CURL_VERSION_NUMBER` + + +## 7.0.1 - 2020-06-27 + +* Fix multiply defined functions fatal error [#2699](https://github.com/guzzle/guzzle/pull/2699) + + +## 7.0.0 - 2020-06-27 + +No changes since 7.0.0-rc1. + + +## 7.0.0-rc1 - 2020-06-15 + +### Changed + +* Use error level for logging errors in Middleware [#2629](https://github.com/guzzle/guzzle/pull/2629) +* Disabled IDN support by default and require ext-intl to use it [#2675](https://github.com/guzzle/guzzle/pull/2675) + + +## 7.0.0-beta2 - 2020-05-25 + +### Added + +* Using `Utils` class instead of functions in the `GuzzleHttp` namespace. [#2546](https://github.com/guzzle/guzzle/pull/2546) +* `ClientInterface::MAJOR_VERSION` [#2583](https://github.com/guzzle/guzzle/pull/2583) + +### Changed + +* Avoid the `getenv` function when unsafe [#2531](https://github.com/guzzle/guzzle/pull/2531) +* Added real client methods [#2529](https://github.com/guzzle/guzzle/pull/2529) +* Avoid functions due to global install conflicts [#2546](https://github.com/guzzle/guzzle/pull/2546) +* Use Symfony intl-idn polyfill [#2550](https://github.com/guzzle/guzzle/pull/2550) +* Adding methods for HTTP verbs like `Client::get()`, `Client::head()`, `Client::patch()` etc [#2529](https://github.com/guzzle/guzzle/pull/2529) +* `ConnectException` extends `TransferException` [#2541](https://github.com/guzzle/guzzle/pull/2541) +* Updated the default User Agent to "GuzzleHttp/7" [#2654](https://github.com/guzzle/guzzle/pull/2654) + +### Fixed + +* Various intl icu issues [#2626](https://github.com/guzzle/guzzle/pull/2626) + +### Removed + +* Pool option `pool_size` [#2528](https://github.com/guzzle/guzzle/pull/2528) + + +## 7.0.0-beta1 - 2019-12-30 + +The diff might look very big but 95% of Guzzle users will be able to upgrade without modification. +Please see [the upgrade document](UPGRADING.md) that describes all BC breaking changes. + +### Added + +* Implement PSR-18 and dropped PHP 5 support [#2421](https://github.com/guzzle/guzzle/pull/2421) [#2474](https://github.com/guzzle/guzzle/pull/2474) +* PHP 7 types [#2442](https://github.com/guzzle/guzzle/pull/2442) [#2449](https://github.com/guzzle/guzzle/pull/2449) [#2466](https://github.com/guzzle/guzzle/pull/2466) [#2497](https://github.com/guzzle/guzzle/pull/2497) [#2499](https://github.com/guzzle/guzzle/pull/2499) +* IDN support for redirects [2424](https://github.com/guzzle/guzzle/pull/2424) + +### Changed + +* Dont allow passing null as third argument to `BadResponseException::__construct()` [#2427](https://github.com/guzzle/guzzle/pull/2427) +* Use SAPI constant instead of method call [#2450](https://github.com/guzzle/guzzle/pull/2450) +* Use native function invocation [#2444](https://github.com/guzzle/guzzle/pull/2444) +* Better defaults for PHP installations with old ICU lib [2454](https://github.com/guzzle/guzzle/pull/2454) +* Added visibility to all constants [#2462](https://github.com/guzzle/guzzle/pull/2462) +* Dont allow passing `null` as URI to `Client::request()` and `Client::requestAsync()` [#2461](https://github.com/guzzle/guzzle/pull/2461) +* Widen the exception argument to throwable [#2495](https://github.com/guzzle/guzzle/pull/2495) + +### Fixed + +* Logging when Promise rejected with a string [#2311](https://github.com/guzzle/guzzle/pull/2311) + +### Removed + +* Class `SeekException` [#2162](https://github.com/guzzle/guzzle/pull/2162) +* `RequestException::getResponseBodySummary()` [#2425](https://github.com/guzzle/guzzle/pull/2425) +* `CookieJar::getCookieValue()` [#2433](https://github.com/guzzle/guzzle/pull/2433) +* `uri_template()` and `UriTemplate` [#2440](https://github.com/guzzle/guzzle/pull/2440) +* Request options `save_to` and `exceptions` [#2464](https://github.com/guzzle/guzzle/pull/2464) + + +## 6.5.2 - 2019-12-23 + +* idn_to_ascii() fix for old PHP versions [#2489](https://github.com/guzzle/guzzle/pull/2489) + + +## 6.5.1 - 2019-12-21 + +* Better defaults for PHP installations with old ICU lib [#2454](https://github.com/guzzle/guzzle/pull/2454) +* IDN support for redirects [#2424](https://github.com/guzzle/guzzle/pull/2424) + + +## 6.5.0 - 2019-12-07 + +* Improvement: Added support for reset internal queue in MockHandler. [#2143](https://github.com/guzzle/guzzle/pull/2143) +* Improvement: Added support to pass arbitrary options to `curl_multi_init`. [#2287](https://github.com/guzzle/guzzle/pull/2287) +* Fix: Gracefully handle passing `null` to the `header` option. [#2132](https://github.com/guzzle/guzzle/pull/2132) +* Fix: `RetryMiddleware` did not do exponential delay between retires due unit mismatch. [#2132](https://github.com/guzzle/guzzle/pull/2132) +* Fix: Prevent undefined offset when using array for ssl_key options. [#2348](https://github.com/guzzle/guzzle/pull/2348) +* Deprecated `ClientInterface::VERSION` + + +## 6.4.1 - 2019-10-23 + +* No `guzzle.phar` was created in 6.4.0 due expired API token. This release will fix that +* Added `parent::__construct()` to `FileCookieJar` and `SessionCookieJar` + + +## 6.4.0 - 2019-10-23 + +* Improvement: Improved error messages when using curl < 7.21.2 [#2108](https://github.com/guzzle/guzzle/pull/2108) +* Fix: Test if response is readable before returning a summary in `RequestException::getResponseBodySummary()` [#2081](https://github.com/guzzle/guzzle/pull/2081) +* Fix: Add support for GUZZLE_CURL_SELECT_TIMEOUT environment variable [#2161](https://github.com/guzzle/guzzle/pull/2161) +* Improvement: Added `GuzzleHttp\Exception\InvalidArgumentException` [#2163](https://github.com/guzzle/guzzle/pull/2163) +* Improvement: Added `GuzzleHttp\_current_time()` to use `hrtime()` if that function exists. [#2242](https://github.com/guzzle/guzzle/pull/2242) +* Improvement: Added curl's `appconnect_time` in `TransferStats` [#2284](https://github.com/guzzle/guzzle/pull/2284) +* Improvement: Make GuzzleException extend Throwable wherever it's available [#2273](https://github.com/guzzle/guzzle/pull/2273) +* Fix: Prevent concurrent writes to file when saving `CookieJar` [#2335](https://github.com/guzzle/guzzle/pull/2335) +* Improvement: Update `MockHandler` so we can test transfer time [#2362](https://github.com/guzzle/guzzle/pull/2362) + + ## 6.3.3 - 2018-04-22 * Fix: Default headers when decode_content is specified @@ -41,13 +348,14 @@ * Bug fix: Fill `CURLOPT_CAPATH` and `CURLOPT_CAINFO` properly [#1684](https://github.com/guzzle/guzzle/pull/1684) * Improvement: Use `\GuzzleHttp\Promise\rejection_for` function instead of object init [#1827](https://github.com/guzzle/guzzle/pull/1827) - + Minor code cleanups, documentation fixes and clarifications. + ## 6.2.3 - 2017-02-28 * Fix deprecations with guzzle/psr7 version 1.4 + ## 6.2.2 - 2016-10-08 * Allow to pass nullable Response to delay callable @@ -55,6 +363,7 @@ * Fix drain case where content-length is the literal string zero * Obfuscate in-URL credentials in exceptions + ## 6.2.1 - 2016-07-18 * Address HTTP_PROXY security vulnerability, CVE-2016-5385: @@ -65,6 +374,7 @@ a server does not honor `Connection: close`. * Ignore URI fragment when sending requests. + ## 6.2.0 - 2016-03-21 * Feature: added `GuzzleHttp\json_encode` and `GuzzleHttp\json_decode`. @@ -84,6 +394,7 @@ * Bug fix: provide an empty string to `http_build_query` for HHVM workaround. https://github.com/guzzle/guzzle/pull/1367 + ## 6.1.1 - 2015-11-22 * Bug fix: Proxy::wrapSync() now correctly proxies to the appropriate handler @@ -99,6 +410,7 @@ * Bug fix: fixed regression where MockHandler was not using `sink`. https://github.com/guzzle/guzzle/pull/1292 + ## 6.1.0 - 2015-09-08 * Feature: Added the `on_stats` request option to provide access to transfer @@ -133,6 +445,7 @@ * Bug fix: Adding a Content-Length to PHP stream wrapper requests if not set. https://github.com/guzzle/guzzle/pull/1189 + ## 6.0.2 - 2015-07-04 * Fixed a memory leak in the curl handlers in which references to callbacks @@ -150,6 +463,7 @@ * Functions are now conditionally required using an additional level of indirection to help with global Composer installations. + ## 6.0.1 - 2015-05-27 * Fixed a bug with serializing the `query` request option where the `&` @@ -158,6 +472,7 @@ use `form_params` or `multipart` instead. * Various doc fixes. + ## 6.0.0 - 2015-05-26 * See the UPGRADING.md document for more information. @@ -182,6 +497,7 @@ * `$maxHandles` has been removed from CurlMultiHandler. * `MultipartPostBody` is now part of the `guzzlehttp/psr7` package. + ## 5.3.0 - 2015-05-19 * Mock now supports `save_to` @@ -192,6 +508,7 @@ * Marked `GuzzleHttp\Client::getDefaultUserAgent` as deprecated. * URL scheme is now always lowercased. + ## 6.0.0-beta.1 * Requires PHP >= 5.5 @@ -244,6 +561,7 @@ * `GuzzleHttp\QueryParser` has been replaced with the `GuzzleHttp\Psr7\parse_query`. + ## 5.2.0 - 2015-01-27 * Added `AppliesHeadersInterface` to make applying headers to a request based @@ -254,6 +572,7 @@ RingBridge. * Added a guard in the Pool class to not use recursion for request retries. + ## 5.1.0 - 2014-12-19 * Pool class no longer uses recursion when a request is intercepted. @@ -274,6 +593,7 @@ * Exceptions thrown in the `end` event are now correctly wrapped with Guzzle specific exceptions if necessary. + ## 5.0.3 - 2014-11-03 This change updates query strings so that they are treated as un-encoded values @@ -288,6 +608,7 @@ string that should not be parsed or encoded (unless a call to getQuery() is subsequently made, forcing the query-string to be converted into a Query object). + ## 5.0.2 - 2014-10-30 * Added a trailing `\r\n` to multipart/form-data payloads. See @@ -307,7 +628,8 @@ object). * Note: This has been changed in 5.0.3 to now encode query string values by default unless the `rawString` argument is provided when setting the query string on a URL: Now allowing many more characters to be present in the - query string without being percent encoded. See http://tools.ietf.org/html/rfc3986#appendix-A + query string without being percent encoded. See https://tools.ietf.org/html/rfc3986#appendix-A + ## 5.0.1 - 2014-10-16 @@ -320,6 +642,7 @@ Bugfix release. * Fixed an issue where transfer statistics were not being populated in the RingBridge. https://github.com/guzzle/guzzle/issues/866 + ## 5.0.0 - 2014-10-12 Adding support for non-blocking responses and some minor API cleanup. @@ -349,7 +672,7 @@ interfaces. responses, `GuzzleHttp\Collection`, `GuzzleHttp\Url`, `GuzzleHttp\Query`, `GuzzleHttp\Post\PostBody`, and `GuzzleHttp\Cookie\SetCookie`. This blog post provides a good outline of - why I did this: http://ocramius.github.io/blog/fluent-interfaces-are-evil/. + why I did this: https://ocramius.github.io/blog/fluent-interfaces-are-evil/. This also makes the Guzzle message interfaces compatible with the current PSR-7 message proposal. * Removed "functions.php", so that Guzzle is truly PSR-4 compliant. Except @@ -401,6 +724,7 @@ interfaces. argument. They now accept an associative array of options, including the "size" key and "metadata" key which can be used to provide custom metadata. + ## 4.2.2 - 2014-09-08 * Fixed a memory leak in the CurlAdapter when reusing cURL handles. @@ -535,8 +859,6 @@ interfaces. ## 4.0.0 - 2014-03-29 -* For more information on the 4.0 transition, see: - http://mtdowling.com/blog/2014/03/15/guzzle-4-rc/ * For information on changes and upgrading, see: https://github.com/guzzle/guzzle/blob/master/UPGRADING.md#3x-to-40 * Added `GuzzleHttp\batch()` as a convenience function for sending requests in @@ -845,7 +1167,7 @@ interfaces. ## 3.4.0 - 2013-04-11 -* Bug fix: URLs are now resolved correctly based on http://tools.ietf.org/html/rfc3986#section-5.2. #289 +* Bug fix: URLs are now resolved correctly based on https://tools.ietf.org/html/rfc3986#section-5.2. #289 * Bug fix: Absolute URLs with a path in a service description will now properly override the base URL. #289 * Bug fix: Parsing a query string with a single PHP array value will now result in an array. #263 * Bug fix: Better normalization of the User-Agent header to prevent duplicate headers. #264. diff --git a/vendor/guzzlehttp/guzzle/LICENSE b/vendor/guzzlehttp/guzzle/LICENSE index 50a177b..fd2375d 100644 --- a/vendor/guzzlehttp/guzzle/LICENSE +++ b/vendor/guzzlehttp/guzzle/LICENSE @@ -1,4 +1,12 @@ -Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com> +The MIT License (MIT) + +Copyright (c) 2011 Michael Dowling <mtdowling@gmail.com> +Copyright (c) 2012 Jeremy Lindblom <jeremeamia@gmail.com> +Copyright (c) 2014 Graham Campbell <hello@gjcampbell.co.uk> +Copyright (c) 2015 Márk Sági-Kazár <mark.sagikazar@gmail.com> +Copyright (c) 2015 Tobias Schultze <webmaster@tubo-world.de> +Copyright (c) 2016 Tobias Nyholm <tobias.nyholm@gmail.com> +Copyright (c) 2016 George Mponos <gmponos@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/guzzlehttp/guzzle/README.md b/vendor/guzzlehttp/guzzle/README.md index bcd18b8..0786462 100644 --- a/vendor/guzzlehttp/guzzle/README.md +++ b/vendor/guzzlehttp/guzzle/README.md @@ -1,8 +1,9 @@ -Guzzle, PHP HTTP client -======================= +![Guzzle](.github/logo.png?raw=true) + +# Guzzle, PHP HTTP client [![Latest Version](https://img.shields.io/github/release/guzzle/guzzle.svg?style=flat-square)](https://github.com/guzzle/guzzle/releases) -[![Build Status](https://img.shields.io/travis/guzzle/guzzle.svg?style=flat-square)](https://travis-ci.org/guzzle/guzzle) +[![Build Status](https://img.shields.io/github/workflow/status/guzzle/guzzle/CI?label=ci%20build&style=flat-square)](https://github.com/guzzle/guzzle/actions?query=workflow%3ACI) [![Total Downloads](https://img.shields.io/packagist/dt/guzzlehttp/guzzle.svg?style=flat-square)](https://packagist.org/packages/guzzlehttp/guzzle) Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and @@ -14,6 +15,7 @@ trivial to integrate with web services. - Can send both synchronous and asynchronous requests using the same interface. - Uses PSR-7 interfaces for requests, responses, and streams. This allows you to utilize other PSR-7 compatible libraries with Guzzle. +- Supports PSR-18 allowing interoperability between other PSR-18 HTTP Clients. - Abstracts away the underlying HTTP transport, allowing you to write environment and transport agnostic code; i.e., no hard dependency on cURL, PHP streams, sockets, or non-blocking event loops. @@ -21,71 +23,72 @@ trivial to integrate with web services. ```php $client = new \GuzzleHttp\Client(); -$res = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle'); -echo $res->getStatusCode(); -// 200 -echo $res->getHeaderLine('content-type'); -// 'application/json; charset=utf8' -echo $res->getBody(); -// '{"id": 1420053, "name": "guzzle", ...}' +$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle'); + +echo $response->getStatusCode(); // 200 +echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8' +echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}' // Send an asynchronous request. $request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org'); $promise = $client->sendAsync($request)->then(function ($response) { echo 'I completed! ' . $response->getBody(); }); + $promise->wait(); ``` ## Help and docs -- [Documentation](http://guzzlephp.org/) -- [Stack Overflow](http://stackoverflow.com/questions/tagged/guzzle) +We use GitHub issues only to discuss bugs and new features. For support please refer to: + +- [Documentation](https://docs.guzzlephp.org) +- [Stack Overflow](https://stackoverflow.com/questions/tagged/guzzle) +- [#guzzle](https://app.slack.com/client/T0D2S9JCT/CE6UAAKL4) channel on [PHP-HTTP Slack](https://slack.httplug.io/) - [Gitter](https://gitter.im/guzzle/guzzle) ## Installing Guzzle The recommended way to install Guzzle is through -[Composer](http://getcomposer.org). +[Composer](https://getcomposer.org/). ```bash -# Install Composer -curl -sS https://getcomposer.org/installer | php +composer require guzzlehttp/guzzle ``` -Next, run the Composer command to install the latest stable version of Guzzle: -```bash -php composer.phar require guzzlehttp/guzzle -``` +## Version Guidance -After installing, you need to require Composer's autoloader: +| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version | +|---------|---------------------|---------------------|--------------|---------------------|---------------------|-------|--------------| +| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >=5.3.3,<7.0 | +| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >=5.4,<7.0 | +| 5.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >=5.4,<7.4 | +| 6.x | Security fixes only | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >=5.5,<8.0 | +| 7.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes | >=7.2.5,<8.3 | -```php -require 'vendor/autoload.php'; -``` +[guzzle-3-repo]: https://github.com/guzzle/guzzle3 +[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x +[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3 +[guzzle-6-repo]: https://github.com/guzzle/guzzle/tree/6.5 +[guzzle-7-repo]: https://github.com/guzzle/guzzle +[guzzle-3-docs]: https://guzzle3.readthedocs.io/ +[guzzle-5-docs]: https://docs.guzzlephp.org/en/5.3/ +[guzzle-6-docs]: https://docs.guzzlephp.org/en/6.5/ +[guzzle-7-docs]: https://docs.guzzlephp.org/en/latest/ -You can then later update Guzzle using composer: - ```bash -composer.phar update - ``` +## Security +If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/guzzle/security/policy) for more information. -## Version Guidance +## License -| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version | -|---------|------------|---------------------|--------------|---------------------|---------------------|-------|-------------| -| 3.x | EOL | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >= 5.3.3 | -| 4.x | EOL | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >= 5.4 | -| 5.x | Maintained | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >= 5.4 | -| 6.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >= 5.5 | +Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information. -[guzzle-3-repo]: https://github.com/guzzle/guzzle3 -[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x -[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3 -[guzzle-6-repo]: https://github.com/guzzle/guzzle -[guzzle-3-docs]: http://guzzle3.readthedocs.org/en/latest/ -[guzzle-5-docs]: http://guzzle.readthedocs.org/en/5.3/ -[guzzle-6-docs]: http://guzzle.readthedocs.org/en/latest/ +## For Enterprise + +Available as part of the Tidelift Subscription + +The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-guzzle?utm_source=packagist-guzzlehttp-guzzle&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) diff --git a/vendor/guzzlehttp/guzzle/UPGRADING.md b/vendor/guzzlehttp/guzzle/UPGRADING.md index 91d1dcc..45417a7 100644 --- a/vendor/guzzlehttp/guzzle/UPGRADING.md +++ b/vendor/guzzlehttp/guzzle/UPGRADING.md @@ -1,10 +1,60 @@ Guzzle Upgrade Guide ==================== +6.0 to 7.0 +---------- + +In order to take advantage of the new features of PHP, Guzzle dropped the support +of PHP 5. The minimum supported PHP version is now PHP 7.2. Type hints and return +types for functions and methods have been added wherever possible. + +Please make sure: +- You are calling a function or a method with the correct type. +- If you extend a class of Guzzle; update all signatures on methods you override. + +#### Other backwards compatibility breaking changes + +- Class `GuzzleHttp\UriTemplate` is removed. +- Class `GuzzleHttp\Exception\SeekException` is removed. +- Classes `GuzzleHttp\Exception\BadResponseException`, `GuzzleHttp\Exception\ClientException`, + `GuzzleHttp\Exception\ServerException` can no longer be initialized with an empty + Response as argument. +- Class `GuzzleHttp\Exception\ConnectException` now extends `GuzzleHttp\Exception\TransferException` + instead of `GuzzleHttp\Exception\RequestException`. +- Function `GuzzleHttp\Exception\ConnectException::getResponse()` is removed. +- Function `GuzzleHttp\Exception\ConnectException::hasResponse()` is removed. +- Constant `GuzzleHttp\ClientInterface::VERSION` is removed. Added `GuzzleHttp\ClientInterface::MAJOR_VERSION` instead. +- Function `GuzzleHttp\Exception\RequestException::getResponseBodySummary` is removed. + Use `\GuzzleHttp\Psr7\get_message_body_summary` as an alternative. +- Function `GuzzleHttp\Cookie\CookieJar::getCookieValue` is removed. +- Request option `exception` is removed. Please use `http_errors`. +- Request option `save_to` is removed. Please use `sink`. +- Pool option `pool_size` is removed. Please use `concurrency`. +- We now look for environment variables in the `$_SERVER` super global, due to thread safety issues with `getenv`. We continue to fallback to `getenv` in CLI environments, for maximum compatibility. +- The `get`, `head`, `put`, `post`, `patch`, `delete`, `getAsync`, `headAsync`, `putAsync`, `postAsync`, `patchAsync`, and `deleteAsync` methods are now implemented as genuine methods on `GuzzleHttp\Client`, with strong typing. The original `__call` implementation remains unchanged for now, for maximum backwards compatibility, but won't be invoked under normal operation. +- The `log` middleware will log the errors with level `error` instead of `notice` +- Support for international domain names (IDN) is now disabled by default, and enabling it requires installing ext-intl, linked against a modern version of the C library (ICU 4.6 or higher). + +#### Native functions calls + +All internal native functions calls of Guzzle are now prefixed with a slash. This +change makes it impossible for method overloading by other libraries or applications. +Example: + +```php +// Before: +curl_version(); + +// After: +\curl_version(); +``` + +For the full diff you can check [here](https://github.com/guzzle/guzzle/compare/6.5.4..master). + 5.0 to 6.0 ---------- -Guzzle now uses [PSR-7](http://www.php-fig.org/psr/psr-7/) for HTTP messages. +Guzzle now uses [PSR-7](https://www.php-fig.org/psr/psr-7/) for HTTP messages. Due to the fact that these messages are immutable, this prompted a refactoring of Guzzle to use a middleware based system rather than an event system. Any HTTP message interaction (e.g., `GuzzleHttp\Message\Request`) need to be @@ -167,7 +217,7 @@ passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP ## Removed Fluent Interfaces -[Fluent interfaces were removed](http://ocramius.github.io/blog/fluent-interfaces-are-evil) +[Fluent interfaces were removed](https://ocramius.github.io/blog/fluent-interfaces-are-evil/) from the following classes: - `GuzzleHttp\Collection` @@ -820,7 +870,7 @@ HeaderInterface (e.g. toArray(), getAll(), etc.). 3.3 to 3.4 ---------- -Base URLs of a client now follow the rules of http://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs. +Base URLs of a client now follow the rules of https://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs. 3.2 to 3.3 ---------- diff --git a/vendor/guzzlehttp/guzzle/composer.json b/vendor/guzzlehttp/guzzle/composer.json index 1f328e3..3207f8c 100644 --- a/vendor/guzzlehttp/guzzle/composer.json +++ b/vendor/guzzlehttp/guzzle/composer.json @@ -1,44 +1,103 @@ { "name": "guzzlehttp/guzzle", - "type": "library", "description": "Guzzle is a PHP HTTP client library", - "keywords": ["framework", "http", "rest", "web service", "curl", "client", "HTTP client"], - "homepage": "http://guzzlephp.org/", + "keywords": [ + "framework", + "http", + "rest", + "web service", + "curl", + "client", + "HTTP client", + "PSR-7", + "PSR-18" + ], "license": "MIT", "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], "require": { - "php": ">=5.5", - "guzzlehttp/psr7": "^1.4", - "guzzlehttp/promises": "^1.0" + "php": "^7.2.5 || ^8.0", + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.0" + "bamarni/composer-bin-plugin": "^1.8.1", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "config": { + "allow-plugins": { + "bamarni/composer-bin-plugin": true + }, + "preferred-install": "dist", + "sort-packages": true + }, + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } }, "autoload": { - "files": ["src/functions_include.php"], "psr-4": { "GuzzleHttp\\": "src/" - } + }, + "files": [ + "src/functions_include.php" + ] }, "autoload-dev": { "psr-4": { "GuzzleHttp\\Tests\\": "tests/" } - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "extra": { - "branch-alias": { - "dev-master": "6.3-dev" - } } } diff --git a/vendor/guzzlehttp/guzzle/src/BodySummarizer.php b/vendor/guzzlehttp/guzzle/src/BodySummarizer.php new file mode 100644 index 0000000..6eca94e --- /dev/null +++ b/vendor/guzzlehttp/guzzle/src/BodySummarizer.php @@ -0,0 +1,28 @@ +<?php + +namespace GuzzleHttp; + +use Psr\Http\Message\MessageInterface; + +final class BodySummarizer implements BodySummarizerInterface +{ + /** + * @var int|null + */ + private $truncateAt; + + public function __construct(int $truncateAt = null) + { + $this->truncateAt = $truncateAt; + } + + /** + * Returns a summarized message body. + */ + public function summarize(MessageInterface $message): ?string + { + return $this->truncateAt === null + ? \GuzzleHttp\Psr7\Message::bodySummary($message) + : \GuzzleHttp\Psr7\Message::bodySummary($message, $this->truncateAt); + } +} diff --git a/vendor/guzzlehttp/guzzle/src/BodySummarizerInterface.php b/vendor/guzzlehttp/guzzle/src/BodySummarizerInterface.php new file mode 100644 index 0000000..3e02e03 --- /dev/null +++ b/vendor/guzzlehttp/guzzle/src/BodySummarizerInterface.php @@ -0,0 +1,13 @@ +<?php + +namespace GuzzleHttp; + +use Psr\Http\Message\MessageInterface; + +interface BodySummarizerInterface +{ + /** + * Returns a summarized message body. + */ + public function summarize(MessageInterface $message): ?string; +} diff --git a/vendor/guzzlehttp/guzzle/src/Client.php b/vendor/guzzlehttp/guzzle/src/Client.php index bd14c7b..9b0d710 100644 --- a/vendor/guzzlehttp/guzzle/src/Client.php +++ b/vendor/guzzlehttp/guzzle/src/Client.php @@ -1,30 +1,26 @@ <?php + namespace GuzzleHttp; use GuzzleHttp\Cookie\CookieJar; -use GuzzleHttp\Promise; -use GuzzleHttp\Psr7; -use Psr\Http\Message\UriInterface; +use GuzzleHttp\Exception\GuzzleException; +use GuzzleHttp\Exception\InvalidArgumentException; +use GuzzleHttp\Promise as P; +use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\UriInterface; /** - * @method ResponseInterface get(string|UriInterface $uri, array $options = []) - * @method ResponseInterface head(string|UriInterface $uri, array $options = []) - * @method ResponseInterface put(string|UriInterface $uri, array $options = []) - * @method ResponseInterface post(string|UriInterface $uri, array $options = []) - * @method ResponseInterface patch(string|UriInterface $uri, array $options = []) - * @method ResponseInterface delete(string|UriInterface $uri, array $options = []) - * @method Promise\PromiseInterface getAsync(string|UriInterface $uri, array $options = []) - * @method Promise\PromiseInterface headAsync(string|UriInterface $uri, array $options = []) - * @method Promise\PromiseInterface putAsync(string|UriInterface $uri, array $options = []) - * @method Promise\PromiseInterface postAsync(string|UriInterface $uri, array $options = []) - * @method Promise\PromiseInterface patchAsync(string|UriInterface $uri, array $options = []) - * @method Promise\PromiseInterface deleteAsync(string|UriInterface $uri, array $options = []) + * @final */ -class Client implements ClientInterface +class Client implements ClientInterface, \Psr\Http\Client\ClientInterface { - /** @var array Default request options */ + use ClientTrait; + + /** + * @var array Default request options + */ private $config; /** @@ -46,9 +42,8 @@ class Client implements ClientInterface * wire. The function is called with a Psr7\Http\Message\RequestInterface * and array of transfer options, and must return a * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a - * Psr7\Http\Message\ResponseInterface on success. "handler" is a - * constructor only option that cannot be overridden in per/request - * options. If no handler is provided, a default handler will be created + * Psr7\Http\Message\ResponseInterface on success. + * If no handler is provided, a default handler will be created * that enables all of the request options below by attaching all of the * default middleware to the handler. * - base_uri: (string|UriInterface) Base URI of the client that is merged @@ -63,33 +58,47 @@ public function __construct(array $config = []) { if (!isset($config['handler'])) { $config['handler'] = HandlerStack::create(); - } elseif (!is_callable($config['handler'])) { - throw new \InvalidArgumentException('handler must be a callable'); + } elseif (!\is_callable($config['handler'])) { + throw new InvalidArgumentException('handler must be a callable'); } // Convert the base_uri to a UriInterface if (isset($config['base_uri'])) { - $config['base_uri'] = Psr7\uri_for($config['base_uri']); + $config['base_uri'] = Psr7\Utils::uriFor($config['base_uri']); } $this->configureDefaults($config); } + /** + * @param string $method + * @param array $args + * + * @return PromiseInterface|ResponseInterface + * + * @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0. + */ public function __call($method, $args) { - if (count($args) < 1) { - throw new \InvalidArgumentException('Magic request methods require a URI and optional options array'); + if (\count($args) < 1) { + throw new InvalidArgumentException('Magic request methods require a URI and optional options array'); } $uri = $args[0]; - $opts = isset($args[1]) ? $args[1] : []; + $opts = $args[1] ?? []; - return substr($method, -5) === 'Async' - ? $this->requestAsync(substr($method, 0, -5), $uri, $opts) + return \substr($method, -5) === 'Async' + ? $this->requestAsync(\substr($method, 0, -5), $uri, $opts) : $this->request($method, $uri, $opts); } - public function sendAsync(RequestInterface $request, array $options = []) + /** + * Asynchronously send an HTTP request. + * + * @param array $options Request options to apply to the given + * request and to the transfer. See \GuzzleHttp\RequestOptions. + */ + public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface { // Merge the base URI into the request URI if needed. $options = $this->prepareDefaults($options); @@ -100,23 +109,58 @@ public function sendAsync(RequestInterface $request, array $options = []) ); } - public function send(RequestInterface $request, array $options = []) + /** + * Send an HTTP request. + * + * @param array $options Request options to apply to the given + * request and to the transfer. See \GuzzleHttp\RequestOptions. + * + * @throws GuzzleException + */ + public function send(RequestInterface $request, array $options = []): ResponseInterface + { + $options[RequestOptions::SYNCHRONOUS] = true; + + return $this->sendAsync($request, $options)->wait(); + } + + /** + * The HttpClient PSR (PSR-18) specify this method. + * + * {@inheritDoc} + */ + public function sendRequest(RequestInterface $request): ResponseInterface { $options[RequestOptions::SYNCHRONOUS] = true; + $options[RequestOptions::ALLOW_REDIRECTS] = false; + $options[RequestOptions::HTTP_ERRORS] = false; + return $this->sendAsync($request, $options)->wait(); } - public function requestAsync($method, $uri = '', array $options = []) + /** + * Create and send an asynchronous HTTP request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. Use an array to provide a URL + * template and additional variables to use in the URL template expansion. + * + * @param string $method HTTP method + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions. + */ + public function requestAsync(string $method, $uri = '', array $options = []): PromiseInterface { $options = $this->prepareDefaults($options); // Remove request modifying parameter because it can be done up-front. - $headers = isset($options['headers']) ? $options['headers'] : []; - $body = isset($options['body']) ? $options['body'] : null; - $version = isset($options['version']) ? $options['version'] : '1.1'; + $headers = $options['headers'] ?? []; + $body = $options['body'] ?? null; + $version = $options['version'] ?? '1.1'; // Merge the URI into the base URI. - $uri = $this->buildUri($uri, $options); - if (is_array($body)) { - $this->invalidBody(); + $uri = $this->buildUri(Psr7\Utils::uriFor($uri), $options); + if (\is_array($body)) { + throw $this->invalidBody(); } $request = new Psr7\Request($method, $uri, $headers, $body, $version); // Remove the option so that they are not doubly-applied. @@ -125,26 +169,55 @@ public function requestAsync($method, $uri = '', array $options = []) return $this->transfer($request, $options); } - public function request($method, $uri = '', array $options = []) + /** + * Create and send an HTTP request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. + * + * @param string $method HTTP method. + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions. + * + * @throws GuzzleException + */ + public function request(string $method, $uri = '', array $options = []): ResponseInterface { $options[RequestOptions::SYNCHRONOUS] = true; + return $this->requestAsync($method, $uri, $options)->wait(); } - public function getConfig($option = null) + /** + * Get a client configuration option. + * + * These options include default request options of the client, a "handler" + * (if utilized by the concrete client), and a "base_uri" if utilized by + * the concrete client. + * + * @param string|null $option The config option to retrieve. + * + * @return mixed + * + * @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0. + */ + public function getConfig(?string $option = null) { return $option === null ? $this->config - : (isset($this->config[$option]) ? $this->config[$option] : null); + : ($this->config[$option] ?? null); } - private function buildUri($uri, array $config) + private function buildUri(UriInterface $uri, array $config): UriInterface { - // for BC we accept null which would otherwise fail in uri_for - $uri = Psr7\uri_for($uri === null ? '' : $uri); - if (isset($config['base_uri'])) { - $uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri); + $uri = Psr7\UriResolver::resolve(Psr7\Utils::uriFor($config['base_uri']), $uri); + } + + if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) { + $idnOptions = ($config['idn_conversion'] === true) ? \IDNA_DEFAULT : $config['idn_conversion']; + $uri = Utils::idnUriConvert($uri, $idnOptions); } return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri; @@ -152,17 +225,16 @@ private function buildUri($uri, array $config) /** * Configures the default options for a client. - * - * @param array $config */ - private function configureDefaults(array $config) + private function configureDefaults(array $config): void { $defaults = [ 'allow_redirects' => RedirectMiddleware::$defaultSettings, - 'http_errors' => true, - 'decode_content' => true, - 'verify' => false, - 'cookies' => false + 'http_errors' => true, + 'decode_content' => true, + 'verify' => true, + 'cookies' => false, + 'idn_conversion' => false, ]; // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set. @@ -170,17 +242,17 @@ private function configureDefaults(array $config) // We can only trust the HTTP_PROXY environment variable in a CLI // process due to the fact that PHP has no reliable mechanism to // get environment variables that start with "HTTP_". - if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) { - $defaults['proxy']['http'] = getenv('HTTP_PROXY'); + if (\PHP_SAPI === 'cli' && ($proxy = Utils::getenv('HTTP_PROXY'))) { + $defaults['proxy']['http'] = $proxy; } - if ($proxy = getenv('HTTPS_PROXY')) { + if ($proxy = Utils::getenv('HTTPS_PROXY')) { $defaults['proxy']['https'] = $proxy; } - if ($noProxy = getenv('NO_PROXY')) { - $cleanedNoProxy = str_replace(' ', '', $noProxy); - $defaults['proxy']['no'] = explode(',', $cleanedNoProxy); + if ($noProxy = Utils::getenv('NO_PROXY')) { + $cleanedNoProxy = \str_replace(' ', '', $noProxy); + $defaults['proxy']['no'] = \explode(',', $cleanedNoProxy); } $this->config = $config + $defaults; @@ -191,15 +263,15 @@ private function configureDefaults(array $config) // Add the default user-agent header. if (!isset($this->config['headers'])) { - $this->config['headers'] = ['User-Agent' => default_user_agent()]; + $this->config['headers'] = ['User-Agent' => Utils::defaultUserAgent()]; } else { // Add the User-Agent header if one was not already set. - foreach (array_keys($this->config['headers']) as $name) { - if (strtolower($name) === 'user-agent') { + foreach (\array_keys($this->config['headers']) as $name) { + if (\strtolower($name) === 'user-agent') { return; } } - $this->config['headers']['User-Agent'] = default_user_agent(); + $this->config['headers']['User-Agent'] = Utils::defaultUserAgent(); } } @@ -207,10 +279,8 @@ private function configureDefaults(array $config) * Merges default options into the array. * * @param array $options Options to modify by reference - * - * @return array */ - private function prepareDefaults($options) + private function prepareDefaults(array $options): array { $defaults = $this->config; @@ -222,13 +292,13 @@ private function prepareDefaults($options) // Special handling for headers is required as they are added as // conditional headers and as headers passed to a request ctor. - if (array_key_exists('headers', $options)) { + if (\array_key_exists('headers', $options)) { // Allows default headers to be unset. if ($options['headers'] === null) { - $defaults['_conditional'] = null; + $defaults['_conditional'] = []; unset($options['headers']); - } elseif (!is_array($options['headers'])) { - throw new \InvalidArgumentException('headers must be an array'); + } elseif (!\is_array($options['headers'])) { + throw new InvalidArgumentException('headers must be an array'); } } @@ -251,66 +321,50 @@ private function prepareDefaults($options) * The URI of the request is not modified and the request options are used * as-is without merging in default options. * - * @param RequestInterface $request - * @param array $options - * - * @return Promise\PromiseInterface + * @param array $options See \GuzzleHttp\RequestOptions. */ - private function transfer(RequestInterface $request, array $options) + private function transfer(RequestInterface $request, array $options): PromiseInterface { - // save_to -> sink - if (isset($options['save_to'])) { - $options['sink'] = $options['save_to']; - unset($options['save_to']); - } - - // exceptions -> http_errors - if (isset($options['exceptions'])) { - $options['http_errors'] = $options['exceptions']; - unset($options['exceptions']); - } - $request = $this->applyOptions($request, $options); + /** @var HandlerStack $handler */ $handler = $options['handler']; try { - return Promise\promise_for($handler($request, $options)); + return P\Create::promiseFor($handler($request, $options)); } catch (\Exception $e) { - return Promise\rejection_for($e); + return P\Create::rejectionFor($e); } } /** * Applies the array of request options to a request. - * - * @param RequestInterface $request - * @param array $options - * - * @return RequestInterface */ - private function applyOptions(RequestInterface $request, array &$options) + private function applyOptions(RequestInterface $request, array &$options): RequestInterface { $modify = [ 'set_headers' => [], ]; if (isset($options['headers'])) { + if (array_keys($options['headers']) === range(0, count($options['headers']) - 1)) { + throw new InvalidArgumentException('The headers array must have header name as keys.'); + } $modify['set_headers'] = $options['headers']; unset($options['headers']); } if (isset($options['form_params'])) { if (isset($options['multipart'])) { - throw new \InvalidArgumentException('You cannot use ' - . 'form_params and multipart at the same time. Use the ' - . 'form_params option if you want to send application/' - . 'x-www-form-urlencoded requests, and the multipart ' - . 'option to send multipart/form-data requests.'); + throw new InvalidArgumentException('You cannot use ' + .'form_params and multipart at the same time. Use the ' + .'form_params option if you want to send application/' + .'x-www-form-urlencoded requests, and the multipart ' + .'option to send multipart/form-data requests.'); } - $options['body'] = http_build_query($options['form_params'], '', '&'); + $options['body'] = \http_build_query($options['form_params'], '', '&'); unset($options['form_params']); // Ensure that we don't have the header in different case and set the new value. - $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']); + $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded'; } @@ -320,10 +374,10 @@ private function applyOptions(RequestInterface $request, array &$options) } if (isset($options['json'])) { - $options['body'] = \GuzzleHttp\json_encode($options['json']); + $options['body'] = Utils::jsonEncode($options['json']); unset($options['json']); // Ensure that we don't have the header in different case and set the new value. - $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']); + $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'application/json'; } @@ -331,47 +385,47 @@ private function applyOptions(RequestInterface $request, array &$options) && $options['decode_content'] !== true ) { // Ensure that we don't have the header in different case and set the new value. - $options['_conditional'] = Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']); + $options['_conditional'] = Psr7\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']); $modify['set_headers']['Accept-Encoding'] = $options['decode_content']; } if (isset($options['body'])) { - if (is_array($options['body'])) { - $this->invalidBody(); + if (\is_array($options['body'])) { + throw $this->invalidBody(); } - $modify['body'] = Psr7\stream_for($options['body']); + $modify['body'] = Psr7\Utils::streamFor($options['body']); unset($options['body']); } - if (!empty($options['auth']) && is_array($options['auth'])) { + if (!empty($options['auth']) && \is_array($options['auth'])) { $value = $options['auth']; - $type = isset($value[2]) ? strtolower($value[2]) : 'basic'; + $type = isset($value[2]) ? \strtolower($value[2]) : 'basic'; switch ($type) { case 'basic': // Ensure that we don't have the header in different case and set the new value. - $modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']); + $modify['set_headers'] = Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']); $modify['set_headers']['Authorization'] = 'Basic ' - . base64_encode("$value[0]:$value[1]"); + .\base64_encode("$value[0]:$value[1]"); break; case 'digest': // @todo: Do not rely on curl - $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST; - $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]"; + $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_DIGEST; + $options['curl'][\CURLOPT_USERPWD] = "$value[0]:$value[1]"; break; case 'ntlm': - $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM; - $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]"; + $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM; + $options['curl'][\CURLOPT_USERPWD] = "$value[0]:$value[1]"; break; } } if (isset($options['query'])) { $value = $options['query']; - if (is_array($value)) { - $value = http_build_query($value, null, '&', PHP_QUERY_RFC3986); + if (\is_array($value)) { + $value = \http_build_query($value, '', '&', \PHP_QUERY_RFC3986); } - if (!is_string($value)) { - throw new \InvalidArgumentException('query must be a string or array'); + if (!\is_string($value)) { + throw new InvalidArgumentException('query must be a string or array'); } $modify['query'] = $value; unset($options['query']); @@ -380,18 +434,22 @@ private function applyOptions(RequestInterface $request, array &$options) // Ensure that sink is not an invalid value. if (isset($options['sink'])) { // TODO: Add more sink validation? - if (is_bool($options['sink'])) { - throw new \InvalidArgumentException('sink must not be a boolean'); + if (\is_bool($options['sink'])) { + throw new InvalidArgumentException('sink must not be a boolean'); } } - $request = Psr7\modify_request($request, $modify); + if (isset($options['version'])) { + $modify['version'] = $options['version']; + } + + $request = Psr7\Utils::modifyRequest($request, $modify); if ($request->getBody() instanceof Psr7\MultipartStream) { // Use a multipart/form-data POST if a Content-Type is not set. // Ensure that we don't have the header in different case and set the new value. - $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']); + $options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' - . $request->getBody()->getBoundary(); + .$request->getBody()->getBoundary(); } // Merge in conditional headers if they are not present. @@ -403,7 +461,7 @@ private function applyOptions(RequestInterface $request, array &$options) $modify['set_headers'][$k] = $v; } } - $request = Psr7\modify_request($request, $modify); + $request = Psr7\Utils::modifyRequest($request, $modify); // Don't pass this internal value along to middleware/handlers. unset($options['_conditional']); } @@ -411,12 +469,15 @@ private function applyOptions(RequestInterface $request, array &$options) return $request; } - private function invalidBody() + /** + * Return an InvalidArgumentException with pre-set message. + */ + private function invalidBody(): InvalidArgumentException { - throw new \InvalidArgumentException('Passing in the "body" request ' - . 'option as an array to send a POST request has been deprecated. ' - . 'Please use the "form_params" request option to send a ' - . 'application/x-www-form-urlencoded request, or the "multipart" ' - . 'request option to send a multipart/form-data request.'); + return new InvalidArgumentException('Passing in the "body" request ' + .'option as an array to send a request is not supported. ' + .'Please use the "form_params" request option to send a ' + .'application/x-www-form-urlencoded request, or the "multipart" ' + .'request option to send a multipart/form-data request.'); } } diff --git a/vendor/guzzlehttp/guzzle/src/ClientInterface.php b/vendor/guzzlehttp/guzzle/src/ClientInterface.php index 2dbcffa..6aaee61 100644 --- a/vendor/guzzlehttp/guzzle/src/ClientInterface.php +++ b/vendor/guzzlehttp/guzzle/src/ClientInterface.php @@ -1,8 +1,9 @@ <?php + namespace GuzzleHttp; -use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Exception\GuzzleException; +use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; @@ -12,7 +13,10 @@ */ interface ClientInterface { - const VERSION = '6.3.3'; + /** + * The Guzzle major version. + */ + public const MAJOR_VERSION = 7; /** * Send an HTTP request. @@ -21,10 +25,9 @@ interface ClientInterface * @param array $options Request options to apply to the given * request and to the transfer. * - * @return ResponseInterface * @throws GuzzleException */ - public function send(RequestInterface $request, array $options = []); + public function send(RequestInterface $request, array $options = []): ResponseInterface; /** * Asynchronously send an HTTP request. @@ -32,10 +35,8 @@ public function send(RequestInterface $request, array $options = []); * @param RequestInterface $request Request to send * @param array $options Request options to apply to the given * request and to the transfer. - * - * @return PromiseInterface */ - public function sendAsync(RequestInterface $request, array $options = []); + public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface; /** * Create and send an HTTP request. @@ -48,10 +49,9 @@ public function sendAsync(RequestInterface $request, array $options = []); * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * - * @return ResponseInterface * @throws GuzzleException */ - public function request($method, $uri, array $options = []); + public function request(string $method, $uri, array $options = []): ResponseInterface; /** * Create and send an asynchronous HTTP request. @@ -64,10 +64,8 @@ public function request($method, $uri, array $options = []); * @param string $method HTTP method * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. - * - * @return PromiseInterface */ - public function requestAsync($method, $uri, array $options = []); + public function requestAsync(string $method, $uri, array $options = []): PromiseInterface; /** * Get a client configuration option. @@ -79,6 +77,8 @@ public function requestAsync($method, $uri, array $options = []); * @param string|null $option The config option to retrieve. * * @return mixed + * + * @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0. */ - public function getConfig($option = null); + public function getConfig(?string $option = null); } diff --git a/vendor/guzzlehttp/guzzle/src/ClientTrait.php b/vendor/guzzlehttp/guzzle/src/ClientTrait.php new file mode 100644 index 0000000..c584c76 --- /dev/null +++ b/vendor/guzzlehttp/guzzle/src/ClientTrait.php @@ -0,0 +1,241 @@ +<?php + +namespace GuzzleHttp; + +use GuzzleHttp\Exception\GuzzleException; +use GuzzleHttp\Promise\PromiseInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\UriInterface; + +/** + * Client interface for sending HTTP requests. + */ +trait ClientTrait +{ + /** + * Create and send an HTTP request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. + * + * @param string $method HTTP method. + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + * + * @throws GuzzleException + */ + abstract public function request(string $method, $uri, array $options = []): ResponseInterface; + + /** + * Create and send an HTTP GET request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + * + * @throws GuzzleException + */ + public function get($uri, array $options = []): ResponseInterface + { + return $this->request('GET', $uri, $options); + } + + /** + * Create and send an HTTP HEAD request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + * + * @throws GuzzleException + */ + public function head($uri, array $options = []): ResponseInterface + { + return $this->request('HEAD', $uri, $options); + } + + /** + * Create and send an HTTP PUT request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + * + * @throws GuzzleException + */ + public function put($uri, array $options = []): ResponseInterface + { + return $this->request('PUT', $uri, $options); + } + + /** + * Create and send an HTTP POST request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + * + * @throws GuzzleException + */ + public function post($uri, array $options = []): ResponseInterface + { + return $this->request('POST', $uri, $options); + } + + /** + * Create and send an HTTP PATCH request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + * + * @throws GuzzleException + */ + public function patch($uri, array $options = []): ResponseInterface + { + return $this->request('PATCH', $uri, $options); + } + + /** + * Create and send an HTTP DELETE request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + * + * @throws GuzzleException + */ + public function delete($uri, array $options = []): ResponseInterface + { + return $this->request('DELETE', $uri, $options); + } + + /** + * Create and send an asynchronous HTTP request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. Use an array to provide a URL + * template and additional variables to use in the URL template expansion. + * + * @param string $method HTTP method + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + */ + abstract public function requestAsync(string $method, $uri, array $options = []): PromiseInterface; + + /** + * Create and send an asynchronous HTTP GET request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. Use an array to provide a URL + * template and additional variables to use in the URL template expansion. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + */ + public function getAsync($uri, array $options = []): PromiseInterface + { + return $this->requestAsync('GET', $uri, $options); + } + + /** + * Create and send an asynchronous HTTP HEAD request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. Use an array to provide a URL + * template and additional variables to use in the URL template expansion. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + */ + public function headAsync($uri, array $options = []): PromiseInterface + { + return $this->requestAsync('HEAD', $uri, $options); + } + + /** + * Create and send an asynchronous HTTP PUT request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. Use an array to provide a URL + * template and additional variables to use in the URL template expansion. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + */ + public function putAsync($uri, array $options = []): PromiseInterface + { + return $this->requestAsync('PUT', $uri, $options); + } + + /** + * Create and send an asynchronous HTTP POST request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. Use an array to provide a URL + * template and additional variables to use in the URL template expansion. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + */ + public function postAsync($uri, array $options = []): PromiseInterface + { + return $this->requestAsync('POST', $uri, $options); + } + + /** + * Create and send an asynchronous HTTP PATCH request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. Use an array to provide a URL + * template and additional variables to use in the URL template expansion. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + */ + public function patchAsync($uri, array $options = []): PromiseInterface + { + return $this->requestAsync('PATCH', $uri, $options); + } + + /** + * Create and send an asynchronous HTTP DELETE request. + * + * Use an absolute path to override the base path of the client, or a + * relative path to append to the base path of the client. The URL can + * contain the query string as well. Use an array to provide a URL + * template and additional variables to use in the URL template expansion. + * + * @param string|UriInterface $uri URI object or string. + * @param array $options Request options to apply. + */ + public function deleteAsync($uri, array $options = []): PromiseInterface + { + return $this->requestAsync('DELETE', $uri, $options); + } +} diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php b/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php index 78f2b79..b4ced5a 100644 --- a/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php +++ b/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php @@ -1,4 +1,5 @@ <?php + namespace GuzzleHttp\Cookie; use Psr\Http\Message\RequestInterface; @@ -9,20 +10,24 @@ */ class CookieJar implements CookieJarInterface { - /** @var SetCookie[] Loaded cookie data */ + /** + * @var SetCookie[] Loaded cookie data + */ private $cookies = []; - /** @var bool */ + /** + * @var bool + */ private $strictMode; /** - * @param bool $strictMode Set to true to throw exceptions when invalid + * @param bool $strictMode Set to true to throw exceptions when invalid * cookies are added to the cookie jar. * @param array $cookieArray Array of SetCookie objects or a hash of * arrays that can be used with the SetCookie * constructor */ - public function __construct($strictMode = false, $cookieArray = []) + public function __construct(bool $strictMode = false, array $cookieArray = []) { $this->strictMode = $strictMode; @@ -39,44 +44,31 @@ public function __construct($strictMode = false, $cookieArray = []) * * @param array $cookies Cookies to create the jar from * @param string $domain Domain to set the cookies to - * - * @return self */ - public static function fromArray(array $cookies, $domain) + public static function fromArray(array $cookies, string $domain): self { $cookieJar = new self(); foreach ($cookies as $name => $value) { $cookieJar->setCookie(new SetCookie([ - 'Domain' => $domain, - 'Name' => $name, - 'Value' => $value, - 'Discard' => true + 'Domain' => $domain, + 'Name' => $name, + 'Value' => $value, + 'Discard' => true, ])); } return $cookieJar; } - /** - * @deprecated - */ - public static function getCookieValue($value) - { - return $value; - } - /** * Evaluate if this cookie should be persisted to storage * that survives between requests. * - * @param SetCookie $cookie Being evaluated. - * @param bool $allowSessionCookies If we should persist session cookies - * @return bool + * @param SetCookie $cookie Being evaluated. + * @param bool $allowSessionCookies If we should persist session cookies */ - public static function shouldPersist( - SetCookie $cookie, - $allowSessionCookies = false - ) { + public static function shouldPersist(SetCookie $cookie, bool $allowSessionCookies = false): bool + { if ($cookie->getExpires() || $allowSessionCookies) { if (!$cookie->getDiscard()) { return true; @@ -90,52 +82,58 @@ public static function shouldPersist( * Finds and returns the cookie based on the name * * @param string $name cookie name to search for + * * @return SetCookie|null cookie that was found or null if not found */ - public function getCookieByName($name) + public function getCookieByName(string $name): ?SetCookie { - // don't allow a null name - if ($name === null) { - return null; - } foreach ($this->cookies as $cookie) { - if ($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) { + if ($cookie->getName() !== null && \strcasecmp($cookie->getName(), $name) === 0) { return $cookie; } } + + return null; } - public function toArray() + /** + * {@inheritDoc} + */ + public function toArray(): array { - return array_map(function (SetCookie $cookie) { + return \array_map(static function (SetCookie $cookie): array { return $cookie->toArray(); }, $this->getIterator()->getArrayCopy()); } - public function clear($domain = null, $path = null, $name = null) + /** + * {@inheritDoc} + */ + public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void { if (!$domain) { $this->cookies = []; + return; } elseif (!$path) { - $this->cookies = array_filter( + $this->cookies = \array_filter( $this->cookies, - function (SetCookie $cookie) use ($path, $domain) { + static function (SetCookie $cookie) use ($domain): bool { return !$cookie->matchesDomain($domain); } ); } elseif (!$name) { - $this->cookies = array_filter( + $this->cookies = \array_filter( $this->cookies, - function (SetCookie $cookie) use ($path, $domain) { + static function (SetCookie $cookie) use ($path, $domain): bool { return !($cookie->matchesPath($path) && $cookie->matchesDomain($domain)); } ); } else { - $this->cookies = array_filter( + $this->cookies = \array_filter( $this->cookies, - function (SetCookie $cookie) use ($path, $domain, $name) { + static function (SetCookie $cookie) use ($path, $domain, $name) { return !($cookie->getName() == $name && $cookie->matchesPath($path) && $cookie->matchesDomain($domain)); @@ -144,17 +142,23 @@ function (SetCookie $cookie) use ($path, $domain, $name) { } } - public function clearSessionCookies() + /** + * {@inheritDoc} + */ + public function clearSessionCookies(): void { - $this->cookies = array_filter( + $this->cookies = \array_filter( $this->cookies, - function (SetCookie $cookie) { + static function (SetCookie $cookie): bool { return !$cookie->getDiscard() && $cookie->getExpires(); } ); } - public function setCookie(SetCookie $cookie) + /** + * {@inheritDoc} + */ + public function setCookie(SetCookie $cookie): bool { // If the name string is empty (but not 0), ignore the set-cookie // string entirely. @@ -167,16 +171,15 @@ public function setCookie(SetCookie $cookie) $result = $cookie->validate(); if ($result !== true) { if ($this->strictMode) { - throw new \RuntimeException('Invalid cookie: ' . $result); - } else { - $this->removeCookieIfEmpty($cookie); - return false; + throw new \RuntimeException('Invalid cookie: '.$result); } + $this->removeCookieIfEmpty($cookie); + + return false; } // Resolve conflicts with previously set cookies foreach ($this->cookies as $i => $c) { - // Two cookies are identical, when their path, and domain are // identical. if ($c->getPath() != $cookie->getPath() || @@ -215,29 +218,35 @@ public function setCookie(SetCookie $cookie) return true; } - public function count() + public function count(): int { - return count($this->cookies); + return \count($this->cookies); } - public function getIterator() + /** + * @return \ArrayIterator<int, SetCookie> + */ + public function getIterator(): \ArrayIterator { - return new \ArrayIterator(array_values($this->cookies)); + return new \ArrayIterator(\array_values($this->cookies)); } - public function extractCookies( - RequestInterface $request, - ResponseInterface $response - ) { + public function extractCookies(RequestInterface $request, ResponseInterface $response): void + { if ($cookieHeader = $response->getHeader('Set-Cookie')) { foreach ($cookieHeader as $cookie) { $sc = SetCookie::fromString($cookie); if (!$sc->getDomain()) { $sc->setDomain($request->getUri()->getHost()); } - if (0 !== strpos($sc->getPath(), '/')) { + if (0 !== \strpos($sc->getPath(), '/')) { $sc->setPath($this->getCookiePathFromRequest($request)); } + if (!$sc->matchesDomain($request->getUri()->getHost())) { + continue; + } + // Note: At this point `$sc->getDomain()` being a public suffix should + // be rejected, but we don't want to pull in the full PSL dependency. $this->setCookie($sc); } } @@ -246,31 +255,29 @@ public function extractCookies( /** * Computes cookie path following RFC 6265 section 5.1.4 * - * @link https://tools.ietf.org/html/rfc6265#section-5.1.4 - * - * @param RequestInterface $request - * @return string + * @see https://tools.ietf.org/html/rfc6265#section-5.1.4 */ - private function getCookiePathFromRequest(RequestInterface $request) + private function getCookiePathFromRequest(RequestInterface $request): string { $uriPath = $request->getUri()->getPath(); - if ('' === $uriPath) { + if ('' === $uriPath) { return '/'; } - if (0 !== strpos($uriPath, '/')) { + if (0 !== \strpos($uriPath, '/')) { return '/'; } if ('/' === $uriPath) { return '/'; } - if (0 === $lastSlashPos = strrpos($uriPath, '/')) { + $lastSlashPos = \strrpos($uriPath, '/'); + if (0 === $lastSlashPos || false === $lastSlashPos) { return '/'; } - return substr($uriPath, 0, $lastSlashPos); + return \substr($uriPath, 0, $lastSlashPos); } - public function withCookieHeader(RequestInterface $request) + public function withCookieHeader(RequestInterface $request): RequestInterface { $values = []; $uri = $request->getUri(); @@ -284,23 +291,21 @@ public function withCookieHeader(RequestInterface $request) !$cookie->isExpired() && (!$cookie->getSecure() || $scheme === 'https') ) { - $values[] = $cookie->getName() . '=' - . $cookie->getValue(); + $values[] = $cookie->getName().'=' + .$cookie->getValue(); } } return $values - ? $request->withHeader('Cookie', implode('; ', $values)) + ? $request->withHeader('Cookie', \implode('; ', $values)) : $request; } /** * If a cookie already exists and the server asks to set it again with a * null value, the cookie must be deleted. - * - * @param SetCookie $cookie */ - private function removeCookieIfEmpty(SetCookie $cookie) + private function removeCookieIfEmpty(SetCookie $cookie): void { $cookieValue = $cookie->getValue(); if ($cookieValue === null || $cookieValue === '') { diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php b/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php index 2cf298a..50bc363 100644 --- a/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php +++ b/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php @@ -1,4 +1,5 @@ <?php + namespace GuzzleHttp\Cookie; use Psr\Http\Message\RequestInterface; @@ -12,7 +13,8 @@ * necessary. Subclasses are also responsible for storing and retrieving * cookies from a file, database, etc. * - * @link http://docs.python.org/2/library/cookielib.html Inspiration + * @see https://docs.python.org/2/library/cookielib.html Inspiration + * @extends \IteratorAggregate<SetCookie> */ interface CookieJarInterface extends \Countable, \IteratorAggregate { @@ -26,7 +28,7 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate * * @return RequestInterface returns the modified request. */ - public function withCookieHeader(RequestInterface $request); + public function withCookieHeader(RequestInterface $request): RequestInterface; /** * Extract cookies from an HTTP response and store them in the CookieJar. @@ -34,10 +36,7 @@ public function withCookieHeader(RequestInterface $request); * @param RequestInterface $request Request that was sent * @param ResponseInterface $response Response that was received */ - public function extractCookies( - RequestInterface $request, - ResponseInterface $response - ); + public function extractCookies(RequestInterface $request, ResponseInterface $response): void; /** * Sets a cookie in the cookie jar. @@ -46,7 +45,7 @@ public function extractCookies( * * @return bool Returns true on success or false on failure */ - public function setCookie(SetCookie $cookie); + public function setCookie(SetCookie $cookie): bool; /** * Remove cookies currently held in the cookie jar. @@ -58,13 +57,11 @@ public function setCookie(SetCookie $cookie); * arguments, then the cookie with the specified name, path and domain is * removed. * - * @param string $domain Clears cookies matching a domain - * @param string $path Clears cookies matching a domain and path - * @param string $name Clears cookies matching a domain, path, and name - * - * @return CookieJarInterface + * @param string|null $domain Clears cookies matching a domain + * @param string|null $path Clears cookies matching a domain and path + * @param string|null $name Clears cookies matching a domain, path, and name */ - public function clear($domain = null, $path = null, $name = null); + public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void; /** * Discard all sessions cookies. @@ -73,12 +70,10 @@ public function clear($domain = null, $path = null, $name = null); * field set to true. To be called when the user agent shuts down according * to RFC 2965. */ - public function clearSessionCookies(); + public function clearSessionCookies(): void; /** * Converts the cookie jar to an array. - * - * @return array */ - public function toArray(); + public function toArray(): array; } diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php b/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php index 9887c1d..290236d 100644 --- a/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php +++ b/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php @@ -1,32 +1,40 @@ <?php + namespace GuzzleHttp\Cookie; +use GuzzleHttp\Utils; + /** * Persists non-session cookies using a JSON formatted file */ class FileCookieJar extends CookieJar { - /** @var string filename */ + /** + * @var string filename + */ private $filename; - /** @var bool Control whether to persist session cookies or not. */ + /** + * @var bool Control whether to persist session cookies or not. + */ private $storeSessionCookies; /** * Create a new FileCookieJar object * - * @param string $cookieFile File to store the cookie data - * @param bool $storeSessionCookies Set to true to store session cookies - * in the cookie jar. + * @param string $cookieFile File to store the cookie data + * @param bool $storeSessionCookies Set to true to store session cookies + * in the cookie jar. * * @throws \RuntimeException if the file cannot be found or created */ - public function __construct($cookieFile, $storeSessionCookies = false) + public function __construct(string $cookieFile, bool $storeSessionCookies = false) { + parent::__construct(); $this->filename = $cookieFile; $this->storeSessionCookies = $storeSessionCookies; - if (file_exists($cookieFile)) { + if (\file_exists($cookieFile)) { $this->load($cookieFile); } } @@ -43,20 +51,21 @@ public function __destruct() * Saves the cookies to a file. * * @param string $filename File to save + * * @throws \RuntimeException if the file cannot be found or created */ - public function save($filename) + public function save(string $filename): void { $json = []; + /** @var SetCookie $cookie */ foreach ($this as $cookie) { - /** @var SetCookie $cookie */ if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { $json[] = $cookie->toArray(); } } - $jsonStr = \GuzzleHttp\json_encode($json); - if (false === file_put_contents($filename, $jsonStr)) { + $jsonStr = Utils::jsonEncode($json); + if (false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) { throw new \RuntimeException("Unable to save file {$filename}"); } } @@ -67,23 +76,25 @@ public function save($filename) * Old cookies are kept unless overwritten by newly loaded ones. * * @param string $filename Cookie file to load. + * * @throws \RuntimeException if the file cannot be loaded. */ - public function load($filename) + public function load(string $filename): void { - $json = file_get_contents($filename); + $json = \file_get_contents($filename); if (false === $json) { throw new \RuntimeException("Unable to load file {$filename}"); - } elseif ($json === '') { + } + if ($json === '') { return; } - $data = \GuzzleHttp\json_decode($json, true); - if (is_array($data)) { - foreach (json_decode($json, true) as $cookie) { + $data = Utils::jsonDecode($json, true); + if (\is_array($data)) { + foreach ($data as $cookie) { $this->setCookie(new SetCookie($cookie)); } - } elseif (strlen($data)) { + } elseif (\is_scalar($data) && !empty($data)) { throw new \RuntimeException("Invalid cookie file: {$filename}"); } } diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php b/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php index 4497bcf..cb3e67c 100644 --- a/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php +++ b/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php @@ -1,4 +1,5 @@ <?php + namespace GuzzleHttp\Cookie; /** @@ -6,22 +7,27 @@ */ class SessionCookieJar extends CookieJar { - /** @var string session key */ + /** + * @var string session key + */ private $sessionKey; - - /** @var bool Control whether to persist session cookies or not. */ + + /** + * @var bool Control whether to persist session cookies or not. + */ private $storeSessionCookies; /** * Create a new SessionCookieJar object * - * @param string $sessionKey Session key name to store the cookie - * data in session - * @param bool $storeSessionCookies Set to true to store session cookies - * in the cookie jar. + * @param string $sessionKey Session key name to store the cookie + * data in session + * @param bool $storeSessionCookies Set to true to store session cookies + * in the cookie jar. */ - public function __construct($sessionKey, $storeSessionCookies = false) + public function __construct(string $sessionKey, bool $storeSessionCookies = false) { + parent::__construct(); $this->sessionKey = $sessionKey; $this->storeSessionCookies = $storeSessionCookies; $this->load(); @@ -38,34 +44,34 @@ public function __destruct() /** * Save cookies to the client session */ - public function save() + public function save(): void { $json = []; + /** @var SetCookie $cookie */ foreach ($this as $cookie) { - /** @var SetCookie $cookie */ if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { $json[] = $cookie->toArray(); } } - $_SESSION[$this->sessionKey] = json_encode($json); + $_SESSION[$this->sessionKey] = \json_encode($json); } /** * Load the contents of the client session into the data array */ - protected function load() + protected function load(): void { if (!isset($_SESSION[$this->sessionKey])) { return; } - $data = json_decode($_SESSION[$this->sessionKey], true); - if (is_array($data)) { + $data = \json_decode($_SESSION[$this->sessionKey], true); + if (\is_array($data)) { foreach ($data as $cookie) { $this->setCookie(new SetCookie($cookie)); } - } elseif (strlen($data)) { - throw new \RuntimeException("Invalid cookie data"); + } elseif (\strlen($data)) { + throw new \RuntimeException('Invalid cookie data'); } } } diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php b/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php index f699394..d74915b 100644 --- a/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php +++ b/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php @@ -1,4 +1,5 @@ <?php + namespace GuzzleHttp\Cookie; /** @@ -6,56 +7,64 @@ */ class SetCookie { - /** @var array */ + /** + * @var array + */ private static $defaults = [ - 'Name' => null, - 'Value' => null, - 'Domain' => null, - 'Path' => '/', - 'Max-Age' => null, - 'Expires' => null, - 'Secure' => false, - 'Discard' => false, - 'HttpOnly' => false + 'Name' => null, + 'Value' => null, + 'Domain' => null, + 'Path' => '/', + 'Max-Age' => null, + 'Expires' => null, + 'Secure' => false, + 'Discard' => false, + 'HttpOnly' => false, ]; - /** @var array Cookie data */ + /** + * @var array Cookie data + */ private $data; /** - * Create a new SetCookie object from a string + * Create a new SetCookie object from a string. * * @param string $cookie Set-Cookie header string - * - * @return self */ - public static function fromString($cookie) + public static function fromString(string $cookie): self { // Create the default return array $data = self::$defaults; // Explode the cookie string using a series of semicolons - $pieces = array_filter(array_map('trim', explode(';', $cookie))); + $pieces = \array_filter(\array_map('trim', \explode(';', $cookie))); // The name of the cookie (first kvp) must exist and include an equal sign. - if (empty($pieces[0]) || !strpos($pieces[0], '=')) { + if (!isset($pieces[0]) || \strpos($pieces[0], '=') === false) { return new self($data); } // Add the cookie pieces into the parsed data array foreach ($pieces as $part) { - $cookieParts = explode('=', $part, 2); - $key = trim($cookieParts[0]); + $cookieParts = \explode('=', $part, 2); + $key = \trim($cookieParts[0]); $value = isset($cookieParts[1]) - ? trim($cookieParts[1], " \n\r\t\0\x0B") + ? \trim($cookieParts[1], " \n\r\t\0\x0B") : true; // Only check for non-cookies when cookies have been found - if (empty($data['Name'])) { + if (!isset($data['Name'])) { $data['Name'] = $key; $data['Value'] = $value; } else { - foreach (array_keys(self::$defaults) as $search) { - if (!strcasecmp($search, $key)) { - $data[$search] = $value; + foreach (\array_keys(self::$defaults) as $search) { + if (!\strcasecmp($search, $key)) { + if ($search === 'Max-Age') { + if (is_numeric($value)) { + $data[$search] = (int) $value; + } + } else { + $data[$search] = $value; + } continue 2; } } @@ -71,39 +80,81 @@ public static function fromString($cookie) */ public function __construct(array $data = []) { - $this->data = array_replace(self::$defaults, $data); + $this->data = self::$defaults; + + if (isset($data['Name'])) { + $this->setName($data['Name']); + } + + if (isset($data['Value'])) { + $this->setValue($data['Value']); + } + + if (isset($data['Domain'])) { + $this->setDomain($data['Domain']); + } + + if (isset($data['Path'])) { + $this->setPath($data['Path']); + } + + if (isset($data['Max-Age'])) { + $this->setMaxAge($data['Max-Age']); + } + + if (isset($data['Expires'])) { + $this->setExpires($data['Expires']); + } + + if (isset($data['Secure'])) { + $this->setSecure($data['Secure']); + } + + if (isset($data['Discard'])) { + $this->setDiscard($data['Discard']); + } + + if (isset($data['HttpOnly'])) { + $this->setHttpOnly($data['HttpOnly']); + } + + // Set the remaining values that don't have extra validation logic + foreach (array_diff(array_keys($data), array_keys(self::$defaults)) as $key) { + $this->data[$key] = $data[$key]; + } + // Extract the Expires value and turn it into a UNIX timestamp if needed if (!$this->getExpires() && $this->getMaxAge()) { // Calculate the Expires date - $this->setExpires(time() + $this->getMaxAge()); - } elseif ($this->getExpires() && !is_numeric($this->getExpires())) { - $this->setExpires($this->getExpires()); + $this->setExpires(\time() + $this->getMaxAge()); + } elseif (null !== ($expires = $this->getExpires()) && !\is_numeric($expires)) { + $this->setExpires($expires); } } public function __toString() { - $str = $this->data['Name'] . '=' . $this->data['Value'] . '; '; + $str = $this->data['Name'].'='.($this->data['Value'] ?? '').'; '; foreach ($this->data as $k => $v) { if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) { if ($k === 'Expires') { - $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; '; + $str .= 'Expires='.\gmdate('D, d M Y H:i:s \G\M\T', $v).'; '; } else { - $str .= ($v === true ? $k : "{$k}={$v}") . '; '; + $str .= ($v === true ? $k : "{$k}={$v}").'; '; } } } - return rtrim($str, '; '); + return \rtrim($str, '; '); } - public function toArray() + public function toArray(): array { return $this->data; } /** - * Get the cookie name + * Get the cookie name. * * @return string */ @@ -113,19 +164,23 @@ public function getName() } /** - * Set the cookie name + * Set the cookie name. * * @param string $name Cookie name */ - public function setName($name) + public function setName($name): void { - $this->data['Name'] = $name; + if (!is_string($name)) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + + $this->data['Name'] = (string) $name; } /** - * Get the cookie value + * Get the cookie value. * - * @return string + * @return string|null */ public function getValue() { @@ -133,17 +188,21 @@ public function getValue() } /** - * Set the cookie value + * Set the cookie value. * * @param string $value Cookie value */ - public function setValue($value) + public function setValue($value): void { - $this->data['Value'] = $value; + if (!is_string($value)) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + + $this->data['Value'] = (string) $value; } /** - * Get the domain + * Get the domain. * * @return string|null */ @@ -153,17 +212,21 @@ public function getDomain() } /** - * Set the domain of the cookie + * Set the domain of the cookie. * - * @param string $domain + * @param string|null $domain */ - public function setDomain($domain) + public function setDomain($domain): void { - $this->data['Domain'] = $domain; + if (!is_string($domain) && null !== $domain) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + + $this->data['Domain'] = null === $domain ? null : (string) $domain; } /** - * Get the path + * Get the path. * * @return string */ @@ -173,39 +236,47 @@ public function getPath() } /** - * Set the path of the cookie + * Set the path of the cookie. * * @param string $path Path of the cookie */ - public function setPath($path) + public function setPath($path): void { - $this->data['Path'] = $path; + if (!is_string($path)) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + + $this->data['Path'] = (string) $path; } /** - * Maximum lifetime of the cookie in seconds + * Maximum lifetime of the cookie in seconds. * * @return int|null */ public function getMaxAge() { - return $this->data['Max-Age']; + return null === $this->data['Max-Age'] ? null : (int) $this->data['Max-Age']; } /** - * Set the max-age of the cookie + * Set the max-age of the cookie. * - * @param int $maxAge Max age of the cookie in seconds + * @param int|null $maxAge Max age of the cookie in seconds */ - public function setMaxAge($maxAge) + public function setMaxAge($maxAge): void { - $this->data['Max-Age'] = $maxAge; + if (!is_int($maxAge) && null !== $maxAge) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + + $this->data['Max-Age'] = $maxAge === null ? null : (int) $maxAge; } /** - * The UNIX timestamp when the cookie Expires + * The UNIX timestamp when the cookie Expires. * - * @return mixed + * @return string|int|null */ public function getExpires() { @@ -213,21 +284,23 @@ public function getExpires() } /** - * Set the unix timestamp for which the cookie will expire + * Set the unix timestamp for which the cookie will expire. * - * @param int $timestamp Unix timestamp + * @param int|string|null $timestamp Unix timestamp or any English textual datetime description. */ - public function setExpires($timestamp) + public function setExpires($timestamp): void { - $this->data['Expires'] = is_numeric($timestamp) - ? (int) $timestamp - : strtotime($timestamp); + if (!is_int($timestamp) && !is_string($timestamp) && null !== $timestamp) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int, string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + + $this->data['Expires'] = null === $timestamp ? null : (\is_numeric($timestamp) ? (int) $timestamp : \strtotime((string) $timestamp)); } /** - * Get whether or not this is a secure cookie + * Get whether or not this is a secure cookie. * - * @return null|bool + * @return bool */ public function getSecure() { @@ -235,19 +308,23 @@ public function getSecure() } /** - * Set whether or not the cookie is secure + * Set whether or not the cookie is secure. * * @param bool $secure Set to true or false if secure */ - public function setSecure($secure) + public function setSecure($secure): void { - $this->data['Secure'] = $secure; + if (!is_bool($secure)) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + + $this->data['Secure'] = (bool) $secure; } /** - * Get whether or not this is a session cookie + * Get whether or not this is a session cookie. * - * @return null|bool + * @return bool|null */ public function getDiscard() { @@ -255,17 +332,21 @@ public function getDiscard() } /** - * Set whether or not this is a session cookie + * Set whether or not this is a session cookie. * * @param bool $discard Set to true or false if this is a session cookie */ - public function setDiscard($discard) + public function setDiscard($discard): void { - $this->data['Discard'] = $discard; + if (!is_bool($discard)) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + + $this->data['Discard'] = (bool) $discard; } /** - * Get whether or not this is an HTTP only cookie + * Get whether or not this is an HTTP only cookie. * * @return bool */ @@ -275,13 +356,17 @@ public function getHttpOnly() } /** - * Set whether or not this is an HTTP only cookie + * Set whether or not this is an HTTP only cookie. * * @param bool $httpOnly Set to true or false if this is HTTP only */ - public function setHttpOnly($httpOnly) + public function setHttpOnly($httpOnly): void { - $this->data['HttpOnly'] = $httpOnly; + if (!is_bool($httpOnly)) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + + $this->data['HttpOnly'] = (bool) $httpOnly; } /** @@ -298,10 +383,8 @@ public function setHttpOnly($httpOnly) * path is a %x2F ("/") character. * * @param string $requestPath Path to check against - * - * @return bool */ - public function matchesPath($requestPath) + public function matchesPath(string $requestPath): bool { $cookiePath = $this->getPath(); @@ -311,90 +394,92 @@ public function matchesPath($requestPath) } // Ensure that the cookie-path is a prefix of the request path. - if (0 !== strpos($requestPath, $cookiePath)) { + if (0 !== \strpos($requestPath, $cookiePath)) { return false; } // Match if the last character of the cookie-path is "/" - if (substr($cookiePath, -1, 1) === '/') { + if (\substr($cookiePath, -1, 1) === '/') { return true; } // Match if the first character not included in cookie path is "/" - return substr($requestPath, strlen($cookiePath), 1) === '/'; + return \substr($requestPath, \strlen($cookiePath), 1) === '/'; } /** - * Check if the cookie matches a domain value + * Check if the cookie matches a domain value. * * @param string $domain Domain to check against - * - * @return bool */ - public function matchesDomain($domain) + public function matchesDomain(string $domain): bool { + $cookieDomain = $this->getDomain(); + if (null === $cookieDomain) { + return true; + } + // Remove the leading '.' as per spec in RFC 6265. - // http://tools.ietf.org/html/rfc6265#section-5.2.3 - $cookieDomain = ltrim($this->getDomain(), '.'); + // https://tools.ietf.org/html/rfc6265#section-5.2.3 + $cookieDomain = \ltrim(\strtolower($cookieDomain), '.'); + + $domain = \strtolower($domain); // Domain not set or exact match. - if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) { + if ('' === $cookieDomain || $domain === $cookieDomain) { return true; } // Matching the subdomain according to RFC 6265. - // http://tools.ietf.org/html/rfc6265#section-5.1.3 - if (filter_var($domain, FILTER_VALIDATE_IP)) { + // https://tools.ietf.org/html/rfc6265#section-5.1.3 + if (\filter_var($domain, \FILTER_VALIDATE_IP)) { return false; } - return (bool) preg_match('/\.' . preg_quote($cookieDomain, '/') . '$/', $domain); + return (bool) \preg_match('/\.'.\preg_quote($cookieDomain, '/').'$/', $domain); } /** - * Check if the cookie is expired - * - * @return bool + * Check if the cookie is expired. */ - public function isExpired() + public function isExpired(): bool { - return $this->getExpires() !== null && time() > $this->getExpires(); + return $this->getExpires() !== null && \time() > $this->getExpires(); } /** - * Check if the cookie is valid according to RFC 6265 + * Check if the cookie is valid according to RFC 6265. * * @return bool|string Returns true if valid or an error message if invalid */ public function validate() { - // Names must not be empty, but can be 0 $name = $this->getName(); - if (empty($name) && !is_numeric($name)) { + if ($name === '') { return 'The cookie name must not be empty'; } // Check if any of the invalid characters are present in the cookie name - if (preg_match( + if (\preg_match( '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/', $name )) { return 'Cookie name must not contain invalid characters: ASCII ' - . 'Control characters (0-31;127), space, tab and the ' - . 'following characters: ()<>@,;:\"/?={}'; + .'Control characters (0-31;127), space, tab and the ' + .'following characters: ()<>@,;:\"/?={}'; } - // Value must not be empty, but can be 0 + // Value must not be null. 0 and empty string are valid. Empty strings + // are technically against RFC 6265, but known to happen in the wild. $value = $this->getValue(); - if (empty($value) && !is_numeric($value)) { + if ($value === null) { return 'The cookie value must not be empty'; } - // Domains must not be empty, but can be 0 - // A "0" is not a valid internet domain, but may be used as server name - // in a private network. + // Domains must not be empty, but can be 0. "0" is not a valid internet + // domain, but may be used as server name in a private network. $domain = $this->getDomain(); - if (empty($domain) && !is_numeric($domain)) { + if ($domain === null || $domain === '') { return 'The cookie domain must not be empty'; } diff --git a/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php b/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php index 427d896..a80956c 100644 --- a/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php +++ b/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php @@ -1,4 +1,5 @@ <?php + namespace GuzzleHttp\Exception; use Psr\Http\Message\RequestInterface; @@ -10,18 +11,29 @@ class BadResponseException extends RequestException { public function __construct( - $message, + string $message, RequestInterface $request, - ResponseInterface $response = null, - \Exception $previous = null, + ResponseInterface $response, + \Throwable $previous = null, array $handlerContext = [] ) { - if (null === $response) { - @trigger_error( - 'Instantiating the ' . __CLASS__ . ' class without a Response is deprecated since version 6.3 and will be removed in 7.0.', - E_USER_DEPRECATED - ); - } parent::__construct($message, $request, $response, $previous, $handlerContext); } + + /** + * Current exception and the ones that extend it will always have a response. + */ + public function hasResponse(): bool + { + return true; + } + + /** + * This function narrows the return type from the parent class and does not allow it to be nullable. + */ + public function getResponse(): ResponseInterface + { + /** @var ResponseInterface */ + return parent::getResponse(); + } } diff --git a/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php b/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php index f95c09f..12fa5e3 100644 --- a/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php +++ b/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php @@ -1,7 +1,10 @@ <?php + namespace GuzzleHttp\Exception; /** * Exception when a client error is encountered (4xx codes) */ -class ClientException extends BadResponseException {} +class ClientException extends BadResponseException +{ +} diff --git a/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php b/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php index d33b0cc..e1a3151 100644 --- a/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php +++ b/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php @@ -1,6 +1,8 @@ <?php + namespace GuzzleHttp\Exception; +use Psr\Http\Client\NetworkExceptionInterface; use Psr\Http\Message\RequestInterface; /** @@ -8,30 +10,47 @@ * * Note that no response is present for a ConnectException */ -class ConnectException extends RequestException +class ConnectException extends TransferException implements NetworkExceptionInterface { + /** + * @var RequestInterface + */ + private $request; + + /** + * @var array + */ + private $handlerContext; + public function __construct( - $message, + string $message, RequestInterface $request, - \Exception $previous = null, + \Throwable $previous = null, array $handlerContext = [] ) { - parent::__construct($message, $request, null, $previous, $handlerContext); + parent::__construct($message, 0, $previous); + $this->request = $request; + $this->handlerContext = $handlerContext; } /** - * @return null + * Get the request that caused the exception */ - public function getResponse() + public function getRequest(): RequestInterface { - return null; + return $this->request; } /** - * @return bool + * Get contextual information about the error from the underlying handler. + * + * The contents of this array will vary depending on which handler you are + * using. It may also be just an empty array. Relying on this data will + * couple you to a specific handler, but can give more debug information + * when needed. */ - public function hasResponse() + public function getHandlerContext(): array { - return false; + return $this->handlerContext; } } diff --git a/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php b/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php index 510778f..fa3ed69 100644 --- a/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php +++ b/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php @@ -1,13 +1,9 @@ <?php + namespace GuzzleHttp\Exception; -/** - * @method string getMessage() - * @method \Throwable|null getPrevious() - * @method mixed getCode() - * @method string getFile() - * @method int getLine() - * @method array getTrace() - * @method string getTraceAsString() - */ -interface GuzzleException {} +use Psr\Http\Client\ClientExceptionInterface; + +interface GuzzleException extends ClientExceptionInterface +{ +} diff --git a/vendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php b/vendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..bfd20e2 --- /dev/null +++ b/vendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php @@ -0,0 +1,7 @@ +<?php + +namespace GuzzleHttp\Exception; + +final class InvalidArgumentException extends \InvalidArgumentException implements GuzzleException +{ +} diff --git a/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php b/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php index 39de327..c2d0a9c 100644 --- a/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php +++ b/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php @@ -1,36 +1,43 @@ <?php + namespace GuzzleHttp\Exception; +use GuzzleHttp\BodySummarizer; +use GuzzleHttp\BodySummarizerInterface; +use Psr\Http\Client\RequestExceptionInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; -use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\UriInterface; /** * HTTP Request exception */ -class RequestException extends TransferException +class RequestException extends TransferException implements RequestExceptionInterface { - /** @var RequestInterface */ + /** + * @var RequestInterface + */ private $request; - /** @var ResponseInterface */ + /** + * @var ResponseInterface|null + */ private $response; - /** @var array */ + /** + * @var array + */ private $handlerContext; public function __construct( - $message, + string $message, RequestInterface $request, ResponseInterface $response = null, - \Exception $previous = null, + \Throwable $previous = null, array $handlerContext = [] ) { // Set the code of the exception if the response is set and not future. - $code = $response && !($response instanceof PromiseInterface) - ? $response->getStatusCode() - : 0; + $code = $response ? $response->getStatusCode() : 0; parent::__construct($message, $code, $previous); $this->request = $request; $this->response = $response; @@ -39,46 +46,39 @@ public function __construct( /** * Wrap non-RequestExceptions with a RequestException - * - * @param RequestInterface $request - * @param \Exception $e - * - * @return RequestException */ - public static function wrapException(RequestInterface $request, \Exception $e) + public static function wrapException(RequestInterface $request, \Throwable $e): RequestException { - return $e instanceof RequestException - ? $e - : new RequestException($e->getMessage(), $request, null, $e); + return $e instanceof RequestException ? $e : new RequestException($e->getMessage(), $request, null, $e); } /** * Factory method to create a new exception with a normalized error message * - * @param RequestInterface $request Request - * @param ResponseInterface $response Response received - * @param \Exception $previous Previous exception - * @param array $ctx Optional handler context. - * - * @return self + * @param RequestInterface $request Request sent + * @param ResponseInterface $response Response received + * @param \Throwable|null $previous Previous exception + * @param array $handlerContext Optional handler context + * @param BodySummarizerInterface|null $bodySummarizer Optional body summarizer */ public static function create( RequestInterface $request, ResponseInterface $response = null, - \Exception $previous = null, - array $ctx = [] - ) { + \Throwable $previous = null, + array $handlerContext = [], + BodySummarizerInterface $bodySummarizer = null + ): self { if (!$response) { return new self( 'Error completing request', $request, null, $previous, - $ctx + $handlerContext ); } - $level = (int) floor($response->getStatusCode() / 100); + $level = (int) \floor($response->getStatusCode() / 100); if ($level === 4) { $label = 'Client error'; $className = ClientException::class; @@ -95,76 +95,33 @@ public static function create( // Client Error: `GET /` resulted in a `404 Not Found` response: // <html> ... (truncated) - $message = sprintf( + $message = \sprintf( '%s: `%s %s` resulted in a `%s %s` response', $label, $request->getMethod(), - $uri, + $uri->__toString(), $response->getStatusCode(), $response->getReasonPhrase() ); - $summary = static::getResponseBodySummary($response); + $summary = ($bodySummarizer ?? new BodySummarizer())->summarize($response); if ($summary !== null) { $message .= ":\n{$summary}\n"; } - return new $className($message, $request, $response, $previous, $ctx); - } - - /** - * Get a short summary of the response - * - * Will return `null` if the response is not printable. - * - * @param ResponseInterface $response - * - * @return string|null - */ - public static function getResponseBodySummary(ResponseInterface $response) - { - $body = $response->getBody(); - - if (!$body->isSeekable()) { - return null; - } - - $size = $body->getSize(); - - if ($size === 0) { - return null; - } - - $summary = $body->read(120); - $body->rewind(); - - if ($size > 120) { - $summary .= ' (truncated...)'; - } - - // Matches any printable character, including unicode characters: - // letters, marks, numbers, punctuation, spacing, and separators. - if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) { - return null; - } - - return $summary; + return new $className($message, $request, $response, $previous, $handlerContext); } /** - * Obfuscates URI if there is an username and a password present - * - * @param UriInterface $uri - * - * @return UriInterface + * Obfuscates URI if there is a username and a password present */ - private static function obfuscateUri($uri) + private static function obfuscateUri(UriInterface $uri): UriInterface { $userInfo = $uri->getUserInfo(); - if (false !== ($pos = strpos($userInfo, ':'))) { - return $uri->withUserInfo(substr($userInfo, 0, $pos), '***'); + if (false !== ($pos = \strpos($userInfo, ':'))) { + return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***'); } return $uri; @@ -172,30 +129,24 @@ private static function obfuscateUri($uri) /** * Get the request that caused the exception - * - * @return RequestInterface */ - public function getRequest() + public function getRequest(): RequestInterface { return $this->request; } /** * Get the associated response - * - * @return ResponseInterface|null */ - public function getResponse() + public function getResponse(): ?ResponseInterface { return $this->response; } /** * Check if a response was received - * - * @return bool */ - public function hasResponse() + public function hasResponse(): bool { return $this->response !== null; } @@ -207,10 +158,8 @@ public function hasResponse() * using. It may also be just an empty array. Relying on this data will * couple you to a specific handler, but can give more debug information * when needed. - * - * @return array */ - public function getHandlerContext() + public function getHandlerContext(): array { return $this->handlerContext; } diff --git a/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php b/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php deleted file mode 100644 index a77c289..0000000 --- a/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php -namespace GuzzleHttp\Exception; - -use Psr\Http\Message\StreamInterface; - -/** - * Exception thrown when a seek fails on a stream. - */ -class SeekException extends \RuntimeException implements GuzzleException -{ - private $stream; - - public function __construct(StreamInterface $stream, $pos = 0, $msg = '') - { - $this->stream = $stream; - $msg = $msg ?: 'Could not seek the stream to position ' . $pos; - parent::__construct($msg); - } - - /** - * @return StreamInterface - */ - public function getStream() - { - return $this->stream; - } -} diff --git a/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php b/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php index 7cdd340..8055e06 100644 --- a/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php +++ b/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php @@ -1,7 +1,10 @@ <?php + namespace GuzzleHttp\Exception; /** * Exception when a server error is encountered (5xx codes) */ -class ServerException extends BadResponseException {} +class ServerException extends BadResponseException +{ +} diff --git a/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php b/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php index b60a967..fad3a57 100644 --- a/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php +++ b/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php @@ -1,4 +1,7 @@ <?php + namespace GuzzleHttp\Exception; -class TooManyRedirectsException extends RequestException {} +class TooManyRedirectsException extends RequestException +{ +} diff --git a/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php b/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php index b92071c..5076336 100644 --- a/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php +++ b/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php @@ -1,4 +1,7 @@ <?php + namespace GuzzleHttp\Exception; -class TransferException extends \RuntimeException implements GuzzleException {} +class TransferException extends \RuntimeException implements GuzzleException +{ +} diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php index e092371..3a6a8db 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php @@ -1,41 +1,57 @@ <?php + namespace GuzzleHttp\Handler; -use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\ConnectException; +use GuzzleHttp\Exception\RequestException; +use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\FulfilledPromise; -use GuzzleHttp\Psr7; +use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Psr7\LazyOpenStream; use GuzzleHttp\TransferStats; +use GuzzleHttp\Utils; use Psr\Http\Message\RequestInterface; /** * Creates curl resources from a request + * + * @final */ class CurlFactory implements CurlFactoryInterface { - /** @var array */ + public const CURL_VERSION_STR = 'curl_version'; + + /** + * @deprecated + */ + public const LOW_CURL_VERSION_NUMBER = '7.21.2'; + + /** + * @var resource[]|\CurlHandle[] + */ private $handles = []; - /** @var int Total number of idle handles to keep in cache */ + /** + * @var int Total number of idle handles to keep in cache + */ private $maxHandles; /** * @param int $maxHandles Maximum number of idle handles. */ - public function __construct($maxHandles) + public function __construct(int $maxHandles) { $this->maxHandles = $maxHandles; } - public function create(RequestInterface $request, array $options) + public function create(RequestInterface $request, array $options): EasyHandle { if (isset($options['curl']['body_as_string'])) { $options['_body_as_string'] = $options['curl']['body_as_string']; unset($options['curl']['body_as_string']); } - $easy = new EasyHandle; + $easy = new EasyHandle(); $easy->request = $request; $easy->options = $options; $conf = $this->getDefaultConf($easy); @@ -46,35 +62,33 @@ public function create(RequestInterface $request, array $options) // Add handler options from the request configuration options if (isset($options['curl'])) { - $conf = array_replace($conf, $options['curl']); + $conf = \array_replace($conf, $options['curl']); } - $conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy); - $easy->handle = $this->handles - ? array_pop($this->handles) - : curl_init(); + $conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy); + $easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init(); curl_setopt_array($easy->handle, $conf); return $easy; } - public function release(EasyHandle $easy) + public function release(EasyHandle $easy): void { $resource = $easy->handle; unset($easy->handle); - if (count($this->handles) >= $this->maxHandles) { - curl_close($resource); + if (\count($this->handles) >= $this->maxHandles) { + \curl_close($resource); } else { // Remove all callback functions as they can hold onto references // and are not cleaned up by curl_reset. Using curl_setopt_array // does not work for some reason, so removing each one // individually. - curl_setopt($resource, CURLOPT_HEADERFUNCTION, null); - curl_setopt($resource, CURLOPT_READFUNCTION, null); - curl_setopt($resource, CURLOPT_WRITEFUNCTION, null); - curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null); - curl_reset($resource); + \curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null); + \curl_setopt($resource, \CURLOPT_READFUNCTION, null); + \curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null); + \curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null); + \curl_reset($resource); $this->handles[] = $resource; } } @@ -83,17 +97,11 @@ public function release(EasyHandle $easy) * Completes a cURL transaction, either returning a response promise or a * rejected promise. * - * @param callable $handler - * @param EasyHandle $easy - * @param CurlFactoryInterface $factory Dictates how the handle is released - * - * @return \GuzzleHttp\Promise\PromiseInterface + * @param callable(RequestInterface, array): PromiseInterface $handler + * @param CurlFactoryInterface $factory Dictates how the handle is released */ - public static function finish( - callable $handler, - EasyHandle $easy, - CurlFactoryInterface $factory - ) { + public static function finish(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface + { if (isset($easy->options['on_stats'])) { self::invokeStats($easy); } @@ -114,9 +122,10 @@ public static function finish( return new FulfilledPromise($easy->response); } - private static function invokeStats(EasyHandle $easy) + private static function invokeStats(EasyHandle $easy): void { - $curlStats = curl_getinfo($easy->handle); + $curlStats = \curl_getinfo($easy->handle); + $curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME); $stats = new TransferStats( $easy->request, $easy->response, @@ -124,45 +133,57 @@ private static function invokeStats(EasyHandle $easy) $easy->errno, $curlStats ); - call_user_func($easy->options['on_stats'], $stats); + ($easy->options['on_stats'])($stats); } - private static function finishError( - callable $handler, - EasyHandle $easy, - CurlFactoryInterface $factory - ) { + /** + * @param callable(RequestInterface, array): PromiseInterface $handler + */ + private static function finishError(callable $handler, EasyHandle $easy, CurlFactoryInterface $factory): PromiseInterface + { // Get error information and release the handle to the factory. $ctx = [ 'errno' => $easy->errno, - 'error' => curl_error($easy->handle), - ] + curl_getinfo($easy->handle); + 'error' => \curl_error($easy->handle), + 'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME), + ] + \curl_getinfo($easy->handle); + $ctx[self::CURL_VERSION_STR] = \curl_version()['version']; $factory->release($easy); // Retry when nothing is present or when curl failed to rewind. - if (empty($easy->options['_err_message']) - && (!$easy->errno || $easy->errno == 65) - ) { + if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) { return self::retryFailedRewind($handler, $easy, $ctx); } return self::createRejection($easy, $ctx); } - private static function createRejection(EasyHandle $easy, array $ctx) + private static function createRejection(EasyHandle $easy, array $ctx): PromiseInterface { static $connectionErrors = [ - CURLE_OPERATION_TIMEOUTED => true, - CURLE_COULDNT_RESOLVE_HOST => true, - CURLE_COULDNT_CONNECT => true, - CURLE_SSL_CONNECT_ERROR => true, - CURLE_GOT_NOTHING => true, + \CURLE_OPERATION_TIMEOUTED => true, + \CURLE_COULDNT_RESOLVE_HOST => true, + \CURLE_COULDNT_CONNECT => true, + \CURLE_SSL_CONNECT_ERROR => true, + \CURLE_GOT_NOTHING => true, ]; + if ($easy->createResponseException) { + return P\Create::rejectionFor( + new RequestException( + 'An error was encountered while creating the response', + $easy->request, + $easy->response, + $easy->createResponseException, + $ctx + ) + ); + } + // If an exception was encountered during the onHeaders event, then // return a rejected promise that wraps that exception. if ($easy->onHeadersException) { - return \GuzzleHttp\Promise\rejection_for( + return P\Create::rejectionFor( new RequestException( 'An error was encountered during the on_headers event', $easy->request, @@ -173,76 +194,84 @@ private static function createRejection(EasyHandle $easy, array $ctx) ); } - $message = sprintf( + $message = \sprintf( 'cURL error %s: %s (%s)', $ctx['errno'], $ctx['error'], - 'see http://curl.haxx.se/libcurl/c/libcurl-errors.html' + 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html' ); + $uriString = (string) $easy->request->getUri(); + if ($uriString !== '' && false === \strpos($ctx['error'], $uriString)) { + $message .= \sprintf(' for %s', $uriString); + } // Create a connection exception if it was a specific error code. $error = isset($connectionErrors[$easy->errno]) ? new ConnectException($message, $easy->request, null, $ctx) : new RequestException($message, $easy->request, $easy->response, null, $ctx); - return \GuzzleHttp\Promise\rejection_for($error); + return P\Create::rejectionFor($error); } - private function getDefaultConf(EasyHandle $easy) + /** + * @return array<int|string, mixed> + */ + private function getDefaultConf(EasyHandle $easy): array { $conf = [ - '_headers' => $easy->request->getHeaders(), - CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), - CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), - CURLOPT_RETURNTRANSFER => false, - CURLOPT_HEADER => false, - CURLOPT_CONNECTTIMEOUT => 150, + '_headers' => $easy->request->getHeaders(), + \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), + \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), + \CURLOPT_RETURNTRANSFER => false, + \CURLOPT_HEADER => false, + \CURLOPT_CONNECTTIMEOUT => 300, ]; - if (defined('CURLOPT_PROTOCOLS')) { - $conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS; + if (\defined('CURLOPT_PROTOCOLS')) { + $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS; } $version = $easy->request->getProtocolVersion(); if ($version == 1.1) { - $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1; + $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1; } elseif ($version == 2.0) { - $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0; + $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0; } else { - $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0; + $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0; } return $conf; } - private function applyMethod(EasyHandle $easy, array &$conf) + private function applyMethod(EasyHandle $easy, array &$conf): void { $body = $easy->request->getBody(); $size = $body->getSize(); if ($size === null || $size > 0) { $this->applyBody($easy->request, $easy->options, $conf); + return; } $method = $easy->request->getMethod(); if ($method === 'PUT' || $method === 'POST') { - // See http://tools.ietf.org/html/rfc7230#section-3.3.2 + // See https://tools.ietf.org/html/rfc7230#section-3.3.2 if (!$easy->request->hasHeader('Content-Length')) { - $conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0'; + $conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0'; } } elseif ($method === 'HEAD') { - $conf[CURLOPT_NOBODY] = true; + $conf[\CURLOPT_NOBODY] = true; unset( - $conf[CURLOPT_WRITEFUNCTION], - $conf[CURLOPT_READFUNCTION], - $conf[CURLOPT_FILE], - $conf[CURLOPT_INFILE] + $conf[\CURLOPT_WRITEFUNCTION], + $conf[\CURLOPT_READFUNCTION], + $conf[\CURLOPT_FILE], + $conf[\CURLOPT_INFILE] ); } } - private function applyBody(RequestInterface $request, array $options, array &$conf) + private function applyBody(RequestInterface $request, array $options, array &$conf): void { $size = $request->hasHeader('Content-Length') ? (int) $request->getHeaderLine('Content-Length') @@ -250,40 +279,38 @@ private function applyBody(RequestInterface $request, array $options, array &$co // Send the body as a string if the size is less than 1MB OR if the // [curl][body_as_string] request value is set. - if (($size !== null && $size < 1000000) || - !empty($options['_body_as_string']) - ) { - $conf[CURLOPT_POSTFIELDS] = (string) $request->getBody(); + if (($size !== null && $size < 1000000) || !empty($options['_body_as_string'])) { + $conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody(); // Don't duplicate the Content-Length header $this->removeHeader('Content-Length', $conf); $this->removeHeader('Transfer-Encoding', $conf); } else { - $conf[CURLOPT_UPLOAD] = true; + $conf[\CURLOPT_UPLOAD] = true; if ($size !== null) { - $conf[CURLOPT_INFILESIZE] = $size; + $conf[\CURLOPT_INFILESIZE] = $size; $this->removeHeader('Content-Length', $conf); } $body = $request->getBody(); if ($body->isSeekable()) { $body->rewind(); } - $conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) { + $conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use ($body) { return $body->read($length); }; } // If the Expect header is not present, prevent curl from adding it if (!$request->hasHeader('Expect')) { - $conf[CURLOPT_HTTPHEADER][] = 'Expect:'; + $conf[\CURLOPT_HTTPHEADER][] = 'Expect:'; } // cURL sometimes adds a content-type by default. Prevent this. if (!$request->hasHeader('Content-Type')) { - $conf[CURLOPT_HTTPHEADER][] = 'Content-Type:'; + $conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:'; } } - private function applyHeaders(EasyHandle $easy, array &$conf) + private function applyHeaders(EasyHandle $easy, array &$conf): void { foreach ($conf['_headers'] as $name => $values) { foreach ($values as $value) { @@ -291,16 +318,16 @@ private function applyHeaders(EasyHandle $easy, array &$conf) if ($value === '') { // cURL requires a special format for empty headers. // See https://github.com/guzzle/guzzle/issues/1882 for more details. - $conf[CURLOPT_HTTPHEADER][] = "$name;"; + $conf[\CURLOPT_HTTPHEADER][] = "$name;"; } else { - $conf[CURLOPT_HTTPHEADER][] = "$name: $value"; + $conf[\CURLOPT_HTTPHEADER][] = "$name: $value"; } } } // Remove the Accept header if one was not set if (!$easy->request->hasHeader('Accept')) { - $conf[CURLOPT_HTTPHEADER][] = 'Accept:'; + $conf[\CURLOPT_HTTPHEADER][] = 'Accept:'; } } @@ -310,169 +337,198 @@ private function applyHeaders(EasyHandle $easy, array &$conf) * @param string $name Case-insensitive header to remove * @param array $options Array of options to modify */ - private function removeHeader($name, array &$options) + private function removeHeader(string $name, array &$options): void { - foreach (array_keys($options['_headers']) as $key) { - if (!strcasecmp($key, $name)) { + foreach (\array_keys($options['_headers']) as $key) { + if (!\strcasecmp($key, $name)) { unset($options['_headers'][$key]); + return; } } } - private function applyHandlerOptions(EasyHandle $easy, array &$conf) + private function applyHandlerOptions(EasyHandle $easy, array &$conf): void { $options = $easy->options; if (isset($options['verify'])) { if ($options['verify'] === false) { - unset($conf[CURLOPT_CAINFO]); - $conf[CURLOPT_SSL_VERIFYHOST] = 0; - $conf[CURLOPT_SSL_VERIFYPEER] = false; + unset($conf[\CURLOPT_CAINFO]); + $conf[\CURLOPT_SSL_VERIFYHOST] = 0; + $conf[\CURLOPT_SSL_VERIFYPEER] = false; } else { - $conf[CURLOPT_SSL_VERIFYHOST] = 2; - $conf[CURLOPT_SSL_VERIFYPEER] = true; - if (is_string($options['verify'])) { + $conf[\CURLOPT_SSL_VERIFYHOST] = 2; + $conf[\CURLOPT_SSL_VERIFYPEER] = true; + if (\is_string($options['verify'])) { // Throw an error if the file/folder/link path is not valid or doesn't exist. - if (!file_exists($options['verify'])) { - throw new \InvalidArgumentException( - "SSL CA bundle not found: {$options['verify']}" - ); + if (!\file_exists($options['verify'])) { + throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}"); } // If it's a directory or a link to a directory use CURLOPT_CAPATH. // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO. - if (is_dir($options['verify']) || - (is_link($options['verify']) && is_dir(readlink($options['verify'])))) { - $conf[CURLOPT_CAPATH] = $options['verify']; + if ( + \is_dir($options['verify']) || + ( + \is_link($options['verify']) === true && + ($verifyLink = \readlink($options['verify'])) !== false && + \is_dir($verifyLink) + ) + ) { + $conf[\CURLOPT_CAPATH] = $options['verify']; } else { - $conf[CURLOPT_CAINFO] = $options['verify']; + $conf[\CURLOPT_CAINFO] = $options['verify']; } } } } - if (!empty($options['decode_content'])) { + if (!isset($options['curl'][\CURLOPT_ENCODING]) && !empty($options['decode_content'])) { $accept = $easy->request->getHeaderLine('Accept-Encoding'); if ($accept) { - $conf[CURLOPT_ENCODING] = $accept; + $conf[\CURLOPT_ENCODING] = $accept; } else { - $conf[CURLOPT_ENCODING] = ''; - // Don't let curl send the header over the wire - $conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:'; + // The empty string enables all available decoders and implicitly + // sets a matching 'Accept-Encoding' header. + $conf[\CURLOPT_ENCODING] = ''; + // But as the user did not specify any acceptable encodings we need + // to overwrite this implicit header with an empty one. + $conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:'; } } - if (isset($options['sink'])) { - $sink = $options['sink']; - if (!is_string($sink)) { - $sink = \GuzzleHttp\Psr7\stream_for($sink); - } elseif (!is_dir(dirname($sink))) { - // Ensure that the directory exists before failing in curl. - throw new \RuntimeException(sprintf( - 'Directory %s does not exist for sink value of %s', - dirname($sink), - $sink - )); - } else { - $sink = new LazyOpenStream($sink, 'w+'); - } - $easy->sink = $sink; - $conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) { - return $sink->write($write); - }; - } else { + if (!isset($options['sink'])) { // Use a default temp stream if no sink was set. - $conf[CURLOPT_FILE] = fopen('php://temp', 'w+'); - $easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]); + $options['sink'] = \GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+'); + } + $sink = $options['sink']; + if (!\is_string($sink)) { + $sink = \GuzzleHttp\Psr7\Utils::streamFor($sink); + } elseif (!\is_dir(\dirname($sink))) { + // Ensure that the directory exists before failing in curl. + throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink)); + } else { + $sink = new LazyOpenStream($sink, 'w+'); } + $easy->sink = $sink; + $conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use ($sink): int { + return $sink->write($write); + }; + $timeoutRequiresNoSignal = false; if (isset($options['timeout'])) { $timeoutRequiresNoSignal |= $options['timeout'] < 1; - $conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000; + $conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000; } // CURL default value is CURL_IPRESOLVE_WHATEVER if (isset($options['force_ip_resolve'])) { if ('v4' === $options['force_ip_resolve']) { - $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4; + $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4; } elseif ('v6' === $options['force_ip_resolve']) { - $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6; + $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6; } } if (isset($options['connect_timeout'])) { $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1; - $conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000; + $conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000; } - if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { - $conf[CURLOPT_NOSIGNAL] = true; + if ($timeoutRequiresNoSignal && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') { + $conf[\CURLOPT_NOSIGNAL] = true; } if (isset($options['proxy'])) { - if (!is_array($options['proxy'])) { - $conf[CURLOPT_PROXY] = $options['proxy']; + if (!\is_array($options['proxy'])) { + $conf[\CURLOPT_PROXY] = $options['proxy']; } else { $scheme = $easy->request->getUri()->getScheme(); if (isset($options['proxy'][$scheme])) { $host = $easy->request->getUri()->getHost(); - if (!isset($options['proxy']['no']) || - !\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no']) - ) { - $conf[CURLOPT_PROXY] = $options['proxy'][$scheme]; + if (isset($options['proxy']['no']) && Utils::isHostInNoProxy($host, $options['proxy']['no'])) { + unset($conf[\CURLOPT_PROXY]); + } else { + $conf[\CURLOPT_PROXY] = $options['proxy'][$scheme]; } } } } + if (isset($options['crypto_method'])) { + if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) { + if (!defined('CURL_SSLVERSION_TLSv1_0')) { + throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL'); + } + $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0; + } elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) { + if (!defined('CURL_SSLVERSION_TLSv1_1')) { + throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL'); + } + $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1; + } elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) { + if (!defined('CURL_SSLVERSION_TLSv1_2')) { + throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL'); + } + $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2; + } elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) { + if (!defined('CURL_SSLVERSION_TLSv1_3')) { + throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL'); + } + $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3; + } else { + throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); + } + } + if (isset($options['cert'])) { $cert = $options['cert']; - if (is_array($cert)) { - $conf[CURLOPT_SSLCERTPASSWD] = $cert[1]; + if (\is_array($cert)) { + $conf[\CURLOPT_SSLCERTPASSWD] = $cert[1]; $cert = $cert[0]; } - if (!file_exists($cert)) { - throw new \InvalidArgumentException( - "SSL certificate not found: {$cert}" - ); + if (!\file_exists($cert)) { + throw new \InvalidArgumentException("SSL certificate not found: {$cert}"); + } + // OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files. + // see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html + $ext = pathinfo($cert, \PATHINFO_EXTENSION); + if (preg_match('#^(der|p12)$#i', $ext)) { + $conf[\CURLOPT_SSLCERTTYPE] = strtoupper($ext); } - $conf[CURLOPT_SSLCERT] = $cert; + $conf[\CURLOPT_SSLCERT] = $cert; } if (isset($options['ssl_key'])) { - $sslKey = $options['ssl_key']; - if (is_array($sslKey)) { - $conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1]; - $sslKey = $sslKey[0]; + if (\is_array($options['ssl_key'])) { + if (\count($options['ssl_key']) === 2) { + [$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key']; + } else { + [$sslKey] = $options['ssl_key']; + } } - if (!file_exists($sslKey)) { - throw new \InvalidArgumentException( - "SSL private key not found: {$sslKey}" - ); + + $sslKey = $sslKey ?? $options['ssl_key']; + + if (!\file_exists($sslKey)) { + throw new \InvalidArgumentException("SSL private key not found: {$sslKey}"); } - $conf[CURLOPT_SSLKEY] = $sslKey; + $conf[\CURLOPT_SSLKEY] = $sslKey; } if (isset($options['progress'])) { $progress = $options['progress']; - if (!is_callable($progress)) { - throw new \InvalidArgumentException( - 'progress client option must be callable' - ); + if (!\is_callable($progress)) { + throw new \InvalidArgumentException('progress client option must be callable'); } - $conf[CURLOPT_NOPROGRESS] = false; - $conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) { - $args = func_get_args(); - // PHP 5.5 pushed the handle onto the start of the args - if (is_resource($args[0])) { - array_shift($args); - } - call_user_func_array($progress, $args); + $conf[\CURLOPT_NOPROGRESS] = false; + $conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use ($progress) { + $progress($downloadSize, $downloaded, $uploadSize, $uploaded); }; } if (!empty($options['debug'])) { - $conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']); - $conf[CURLOPT_VERBOSE] = true; + $conf[\CURLOPT_STDERR] = Utils::debugResource($options['debug']); + $conf[\CURLOPT_VERBOSE] = true; } } @@ -484,12 +540,11 @@ private function applyHandlerOptions(EasyHandle $easy, array &$conf) * stream, and then encountered a "necessary data rewind wasn't possible" * error, causing the request to be sent through curl_multi_info_read() * without an error status. + * + * @param callable(RequestInterface, array): PromiseInterface $handler */ - private static function retryFailedRewind( - callable $handler, - EasyHandle $easy, - array $ctx - ) { + private static function retryFailedRewind(callable $handler, EasyHandle $easy, array $ctx): PromiseInterface + { try { // Only rewind if the body has been read from. $body = $easy->request->getBody(); @@ -498,9 +553,10 @@ private static function retryFailedRewind( } } catch (\RuntimeException $e) { $ctx['error'] = 'The connection unexpectedly failed without ' - . 'providing an error. The request would have been retried, ' - . 'but attempting to rewind the request body failed. ' - . 'Exception: ' . $e; + .'providing an error. The request would have been retried, ' + .'but attempting to rewind the request body failed. ' + .'Exception: '.$e; + return self::createRejection($easy, $ctx); } @@ -509,40 +565,47 @@ private static function retryFailedRewind( $easy->options['_curl_retries'] = 1; } elseif ($easy->options['_curl_retries'] == 2) { $ctx['error'] = 'The cURL request was retried 3 times ' - . 'and did not succeed. The most likely reason for the failure ' - . 'is that cURL was unable to rewind the body of the request ' - . 'and subsequent retries resulted in the same error. Turn on ' - . 'the debug option to see what went wrong. See ' - . 'https://bugs.php.net/bug.php?id=47204 for more information.'; + .'and did not succeed. The most likely reason for the failure ' + .'is that cURL was unable to rewind the body of the request ' + .'and subsequent retries resulted in the same error. Turn on ' + .'the debug option to see what went wrong. See ' + .'https://bugs.php.net/bug.php?id=47204 for more information.'; + return self::createRejection($easy, $ctx); } else { - $easy->options['_curl_retries']++; + ++$easy->options['_curl_retries']; } return $handler($easy->request, $easy->options); } - private function createHeaderFn(EasyHandle $easy) + private function createHeaderFn(EasyHandle $easy): callable { if (isset($easy->options['on_headers'])) { $onHeaders = $easy->options['on_headers']; - if (!is_callable($onHeaders)) { + if (!\is_callable($onHeaders)) { throw new \InvalidArgumentException('on_headers must be callable'); } } else { $onHeaders = null; } - return function ($ch, $h) use ( + return static function ($ch, $h) use ( $onHeaders, $easy, &$startingResponse ) { - $value = trim($h); + $value = \trim($h); if ($value === '') { $startingResponse = true; - $easy->createResponse(); + try { + $easy->createResponse(); + } catch (\Exception $e) { + $easy->createResponseException = $e; + + return -1; + } if ($onHeaders !== null) { try { $onHeaders($easy->response); @@ -550,6 +613,7 @@ private function createHeaderFn(EasyHandle $easy) // Associate the exception with the handle and trigger // a curl header write error by returning 0. $easy->onHeadersException = $e; + return -1; } } @@ -559,7 +623,8 @@ private function createHeaderFn(EasyHandle $easy) } else { $easy->headers[] = $value; } - return strlen($h); + + return \strlen($h); }; } } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php index b0fc236..fe57ed5 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php @@ -1,4 +1,5 @@ <?php + namespace GuzzleHttp\Handler; use Psr\Http\Message\RequestInterface; @@ -11,17 +12,14 @@ interface CurlFactoryInterface * @param RequestInterface $request Request * @param array $options Transfer options * - * @return EasyHandle * @throws \RuntimeException when an option cannot be applied */ - public function create(RequestInterface $request, array $options); + public function create(RequestInterface $request, array $options): EasyHandle; /** * Release an easy handle, allowing it to be reused or closed. * * This function must call unset on the easy handle's "handle" property. - * - * @param EasyHandle $easy */ - public function release(EasyHandle $easy); + public function release(EasyHandle $easy): void; } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php index 43577da..9ad10a9 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php @@ -1,7 +1,8 @@ <?php + namespace GuzzleHttp\Handler; -use GuzzleHttp\Psr7; +use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; /** @@ -10,35 +11,38 @@ * When using the CurlHandler, custom curl options can be specified as an * associative array of curl option constants mapping to values in the * **curl** key of the "client" key of the request. + * + * @final */ class CurlHandler { - /** @var CurlFactoryInterface */ + /** + * @var CurlFactoryInterface + */ private $factory; /** * Accepts an associative array of options: * - * - factory: Optional curl factory used to create cURL handles. + * - handle_factory: Optional curl factory used to create cURL handles. * - * @param array $options Array of options to use with the handler + * @param array{handle_factory?: ?CurlFactoryInterface} $options Array of options to use with the handler */ public function __construct(array $options = []) { - $this->factory = isset($options['handle_factory']) - ? $options['handle_factory'] - : new CurlFactory(3); + $this->factory = $options['handle_factory'] + ?? new CurlFactory(3); } - public function __invoke(RequestInterface $request, array $options) + public function __invoke(RequestInterface $request, array $options): PromiseInterface { if (isset($options['delay'])) { - usleep($options['delay'] * 1000); + \usleep($options['delay'] * 1000); } $easy = $this->factory->create($request, $options); - curl_exec($easy->handle); - $easy->errno = curl_errno($easy->handle); + \curl_exec($easy->handle); + $easy->errno = \curl_errno($easy->handle); return CurlFactory::finish($this, $easy, $this->factory); } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php index 2754d8e..f0acde1 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php @@ -1,9 +1,11 @@ <?php + namespace GuzzleHttp\Handler; use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\Promise; -use GuzzleHttp\Psr7; +use GuzzleHttp\Promise\PromiseInterface; +use GuzzleHttp\Utils; use Psr\Http\Message\RequestInterface; /** @@ -13,52 +15,111 @@ * associative array of curl option constants mapping to values in the * **curl** key of the provided request options. * - * @property resource $_mh Internal use only. Lazy loaded multi-handle. + * @property resource|\CurlMultiHandle $_mh Internal use only. Lazy loaded multi-handle. + * + * @final */ +#[\AllowDynamicProperties] class CurlMultiHandler { - /** @var CurlFactoryInterface */ + /** + * @var CurlFactoryInterface + */ private $factory; + + /** + * @var int + */ private $selectTimeout; - private $active; + + /** + * @var int Will be higher than 0 when `curl_multi_exec` is still running. + */ + private $active = 0; + + /** + * @var array Request entry handles, indexed by handle id in `addRequest`. + * + * @see CurlMultiHandler::addRequest + */ private $handles = []; + + /** + * @var array<int, float> An array of delay times, indexed by handle id in `addRequest`. + * + * @see CurlMultiHandler::addRequest + */ private $delays = []; + /** + * @var array<mixed> An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt() + */ + private $options = []; + /** * This handler accepts the following options: * * - handle_factory: An optional factory used to create curl handles * - select_timeout: Optional timeout (in seconds) to block before timing * out while selecting curl handles. Defaults to 1 second. - * - * @param array $options + * - options: An associative array of CURLMOPT_* options and + * corresponding values for curl_multi_setopt() */ public function __construct(array $options = []) { - $this->factory = isset($options['handle_factory']) - ? $options['handle_factory'] : new CurlFactory(50); - $this->selectTimeout = isset($options['select_timeout']) - ? $options['select_timeout'] : 1; + $this->factory = $options['handle_factory'] ?? new CurlFactory(50); + + if (isset($options['select_timeout'])) { + $this->selectTimeout = $options['select_timeout']; + } elseif ($selectTimeout = Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) { + @trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED); + $this->selectTimeout = (int) $selectTimeout; + } else { + $this->selectTimeout = 1; + } + + $this->options = $options['options'] ?? []; } + /** + * @param string $name + * + * @return resource|\CurlMultiHandle + * + * @throws \BadMethodCallException when another field as `_mh` will be gotten + * @throws \RuntimeException when curl can not initialize a multi handle + */ public function __get($name) { - if ($name === '_mh') { - return $this->_mh = curl_multi_init(); + if ($name !== '_mh') { + throw new \BadMethodCallException("Can not get other property as '_mh'."); + } + + $multiHandle = \curl_multi_init(); + + if (false === $multiHandle) { + throw new \RuntimeException('Can not initialize curl multi handle.'); + } + + $this->_mh = $multiHandle; + + foreach ($this->options as $option => $value) { + // A warning is raised in case of a wrong option. + curl_multi_setopt($this->_mh, $option, $value); } - throw new \BadMethodCallException(); + return $this->_mh; } public function __destruct() { if (isset($this->_mh)) { - curl_multi_close($this->_mh); + \curl_multi_close($this->_mh); unset($this->_mh); } } - public function __invoke(RequestInterface $request, array $options) + public function __invoke(RequestInterface $request, array $options): PromiseInterface { $easy = $this->factory->create($request, $options); $id = (int) $easy->handle; @@ -78,15 +139,15 @@ function () use ($id) { /** * Ticks the curl event loop. */ - public function tick() + public function tick(): void { // Add any delayed handles if needed. if ($this->delays) { - $currentTime = microtime(true); + $currentTime = Utils::currentTime(); foreach ($this->delays as $id => $delay) { if ($currentTime >= $delay) { unset($this->delays[$id]); - curl_multi_add_handle( + \curl_multi_add_handle( $this->_mh, $this->handles[$id]['easy']->handle ); @@ -95,17 +156,16 @@ public function tick() } // Step through the task queue which may add additional requests. - P\queue()->run(); + P\Utils::queue()->run(); - if ($this->active && - curl_multi_select($this->_mh, $this->selectTimeout) === -1 - ) { + if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) { // Perform a usleep if a select returns -1. // See: https://bugs.php.net/bug.php?id=61141 - usleep(250); + \usleep(250); } - while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM); + while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) { + } $this->processMessages(); } @@ -113,28 +173,28 @@ public function tick() /** * Runs until all outstanding connections have completed. */ - public function execute() + public function execute(): void { - $queue = P\queue(); + $queue = P\Utils::queue(); while ($this->handles || !$queue->isEmpty()) { // If there are no transfers, then sleep for the next delay if (!$this->active && $this->delays) { - usleep($this->timeToNext()); + \usleep($this->timeToNext()); } $this->tick(); } } - private function addRequest(array $entry) + private function addRequest(array $entry): void { $easy = $entry['easy']; $id = (int) $easy->handle; $this->handles[$id] = $entry; if (empty($easy->options['delay'])) { - curl_multi_add_handle($this->_mh, $easy->handle); + \curl_multi_add_handle($this->_mh, $easy->handle); } else { - $this->delays[$id] = microtime(true) + ($easy->options['delay'] / 1000); + $this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000); } } @@ -145,8 +205,12 @@ private function addRequest(array $entry) * * @return bool True on success, false on failure. */ - private function cancel($id) + private function cancel($id): bool { + if (!is_int($id)) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + // Cannot cancel if it has been processed. if (!isset($this->handles[$id])) { return false; @@ -154,17 +218,21 @@ private function cancel($id) $handle = $this->handles[$id]['easy']->handle; unset($this->delays[$id], $this->handles[$id]); - curl_multi_remove_handle($this->_mh, $handle); - curl_close($handle); + \curl_multi_remove_handle($this->_mh, $handle); + \curl_close($handle); return true; } - private function processMessages() + private function processMessages(): void { - while ($done = curl_multi_info_read($this->_mh)) { + while ($done = \curl_multi_info_read($this->_mh)) { + if ($done['msg'] !== \CURLMSG_DONE) { + // if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216 + continue; + } $id = (int) $done['handle']; - curl_multi_remove_handle($this->_mh, $done['handle']); + \curl_multi_remove_handle($this->_mh, $done['handle']); if (!isset($this->handles[$id])) { // Probably was cancelled. @@ -175,25 +243,21 @@ private function processMessages() unset($this->handles[$id], $this->delays[$id]); $entry['easy']->errno = $done['result']; $entry['deferred']->resolve( - CurlFactory::finish( - $this, - $entry['easy'], - $this->factory - ) + CurlFactory::finish($this, $entry['easy'], $this->factory) ); } } - private function timeToNext() + private function timeToNext(): int { - $currentTime = microtime(true); - $nextTime = PHP_INT_MAX; + $currentTime = Utils::currentTime(); + $nextTime = \PHP_INT_MAX; foreach ($this->delays as $time) { if ($time < $nextTime) { $nextTime = $time; } } - return max(0, $nextTime - $currentTime) * 1000000; + return ((int) \max(0, $nextTime - $currentTime)) * 1000000; } } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php b/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php index 7754e91..1bc39f4 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php @@ -1,7 +1,9 @@ <?php + namespace GuzzleHttp\Handler; use GuzzleHttp\Psr7\Response; +use GuzzleHttp\Utils; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; @@ -13,55 +15,68 @@ */ final class EasyHandle { - /** @var resource cURL resource */ + /** + * @var resource|\CurlHandle cURL resource + */ public $handle; - /** @var StreamInterface Where data is being written */ + /** + * @var StreamInterface Where data is being written + */ public $sink; - /** @var array Received HTTP headers so far */ + /** + * @var array Received HTTP headers so far + */ public $headers = []; - /** @var ResponseInterface Received response (if any) */ + /** + * @var ResponseInterface|null Received response (if any) + */ public $response; - /** @var RequestInterface Request being sent */ + /** + * @var RequestInterface Request being sent + */ public $request; - /** @var array Request options */ + /** + * @var array Request options + */ public $options = []; - /** @var int cURL error number (if any) */ + /** + * @var int cURL error number (if any) + */ public $errno = 0; - /** @var \Exception Exception during on_headers (if any) */ + /** + * @var \Throwable|null Exception during on_headers (if any) + */ public $onHeadersException; + /** + * @var \Exception|null Exception during createResponse (if any) + */ + public $createResponseException; + /** * Attach a response to the easy handle based on the received headers. * - * @throws \RuntimeException if no headers have been received. + * @throws \RuntimeException if no headers have been received or the first + * header line is invalid. */ - public function createResponse() + public function createResponse(): void { - if (empty($this->headers)) { - throw new \RuntimeException('No headers have been received'); - } + [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($this->headers); - // HTTP-version SP status-code SP reason-phrase - $startLine = explode(' ', array_shift($this->headers), 3); - $headers = \GuzzleHttp\headers_from_lines($this->headers); - $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers); + $normalizedKeys = Utils::normalizeHeaderKeys($headers); - if (!empty($this->options['decode_content']) - && isset($normalizedKeys['content-encoding']) - ) { - $headers['x-encoded-content-encoding'] - = $headers[$normalizedKeys['content-encoding']]; + if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) { + $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; unset($headers[$normalizedKeys['content-encoding']]); if (isset($normalizedKeys['content-length'])) { - $headers['x-encoded-content-length'] - = $headers[$normalizedKeys['content-length']]; + $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; $bodyLength = (int) $this->sink->getSize(); if ($bodyLength) { @@ -74,19 +89,24 @@ public function createResponse() // Attach a response to the easy handle with the parsed headers. $this->response = new Response( - $startLine[1], + $status, $headers, $this->sink, - substr($startLine[0], 5), - isset($startLine[2]) ? (string) $startLine[2] : null + $ver, + $reason ); } + /** + * @param string $name + * + * @return void + * + * @throws \BadMethodCallException + */ public function __get($name) { - $msg = $name === 'handle' - ? 'The EasyHandle has been released' - : 'Invalid property: ' . $name; + $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: '.$name; throw new \BadMethodCallException($msg); } } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php b/vendor/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php new file mode 100644 index 0000000..5554b8f --- /dev/null +++ b/vendor/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php @@ -0,0 +1,42 @@ +<?php + +namespace GuzzleHttp\Handler; + +use GuzzleHttp\Utils; + +/** + * @internal + */ +final class HeaderProcessor +{ + /** + * Returns the HTTP version, status code, reason phrase, and headers. + * + * @param string[] $headers + * + * @return array{0:string, 1:int, 2:?string, 3:array} + * + * @throws \RuntimeException + */ + public static function parseHeaders(array $headers): array + { + if ($headers === []) { + throw new \RuntimeException('Expected a non-empty array of header data'); + } + + $parts = \explode(' ', \array_shift($headers), 3); + $version = \explode('/', $parts[0])[1] ?? null; + + if ($version === null) { + throw new \RuntimeException('HTTP version missing from header data'); + } + + $status = $parts[1] ?? null; + + if ($status === null) { + throw new \RuntimeException('HTTP status code missing from header data'); + } + + return [$version, (int) $status, $parts[2] ?? null, Utils::headersFromLines($headers)]; + } +} diff --git a/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php index d892061..77ffed5 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php @@ -1,81 +1,98 @@ <?php + namespace GuzzleHttp\Handler; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\HandlerStack; +use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\PromiseInterface; -use GuzzleHttp\Promise\RejectedPromise; use GuzzleHttp\TransferStats; +use GuzzleHttp\Utils; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamInterface; /** * Handler that returns responses or throw exceptions from a queue. + * + * @final */ class MockHandler implements \Countable { + /** + * @var array + */ private $queue = []; + + /** + * @var RequestInterface|null + */ private $lastRequest; - private $lastOptions; + + /** + * @var array + */ + private $lastOptions = []; + + /** + * @var callable|null + */ private $onFulfilled; + + /** + * @var callable|null + */ private $onRejected; /** * Creates a new MockHandler that uses the default handler stack list of * middlewares. * - * @param array $queue Array of responses, callables, or exceptions. - * @param callable $onFulfilled Callback to invoke when the return value is fulfilled. - * @param callable $onRejected Callback to invoke when the return value is rejected. - * - * @return HandlerStack + * @param array|null $queue Array of responses, callables, or exceptions. + * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled. + * @param callable|null $onRejected Callback to invoke when the return value is rejected. */ - public static function createWithMiddleware( - array $queue = null, - callable $onFulfilled = null, - callable $onRejected = null - ) { + public static function createWithMiddleware(array $queue = null, callable $onFulfilled = null, callable $onRejected = null): HandlerStack + { return HandlerStack::create(new self($queue, $onFulfilled, $onRejected)); } /** * The passed in value must be an array of - * {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions, + * {@see \Psr\Http\Message\ResponseInterface} objects, Exceptions, * callables, or Promises. * - * @param array $queue - * @param callable $onFulfilled Callback to invoke when the return value is fulfilled. - * @param callable $onRejected Callback to invoke when the return value is rejected. + * @param array<int, mixed>|null $queue The parameters to be passed to the append function, as an indexed array. + * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled. + * @param callable|null $onRejected Callback to invoke when the return value is rejected. */ - public function __construct( - array $queue = null, - callable $onFulfilled = null, - callable $onRejected = null - ) { + public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null) + { $this->onFulfilled = $onFulfilled; $this->onRejected = $onRejected; if ($queue) { - call_user_func_array([$this, 'append'], $queue); + // array_values included for BC + $this->append(...array_values($queue)); } } - public function __invoke(RequestInterface $request, array $options) + public function __invoke(RequestInterface $request, array $options): PromiseInterface { if (!$this->queue) { throw new \OutOfBoundsException('Mock queue is empty'); } - if (isset($options['delay'])) { - usleep($options['delay'] * 1000); + if (isset($options['delay']) && \is_numeric($options['delay'])) { + \usleep((int) $options['delay'] * 1000); } $this->lastRequest = $request; $this->lastOptions = $options; - $response = array_shift($this->queue); + $response = \array_shift($this->queue); if (isset($options['on_headers'])) { - if (!is_callable($options['on_headers'])) { + if (!\is_callable($options['on_headers'])) { throw new \InvalidArgumentException('on_headers must be callable'); } try { @@ -86,29 +103,30 @@ public function __invoke(RequestInterface $request, array $options) } } - if (is_callable($response)) { - $response = call_user_func($response, $request, $options); + if (\is_callable($response)) { + $response = $response($request, $options); } - $response = $response instanceof \Exception - ? \GuzzleHttp\Promise\rejection_for($response) - : \GuzzleHttp\Promise\promise_for($response); + $response = $response instanceof \Throwable + ? P\Create::rejectionFor($response) + : P\Create::promiseFor($response); return $response->then( - function ($value) use ($request, $options) { + function (?ResponseInterface $value) use ($request, $options) { $this->invokeStats($request, $options, $value); if ($this->onFulfilled) { - call_user_func($this->onFulfilled, $value); + ($this->onFulfilled)($value); } - if (isset($options['sink'])) { + + if ($value !== null && isset($options['sink'])) { $contents = (string) $value->getBody(); $sink = $options['sink']; - if (is_resource($sink)) { - fwrite($sink, $contents); - } elseif (is_string($sink)) { - file_put_contents($sink, $contents); - } elseif ($sink instanceof \Psr\Http\Message\StreamInterface) { + if (\is_resource($sink)) { + \fwrite($sink, $contents); + } elseif (\is_string($sink)) { + \file_put_contents($sink, $contents); + } elseif ($sink instanceof StreamInterface) { $sink->write($contents); } } @@ -118,9 +136,10 @@ function ($value) use ($request, $options) { function ($reason) use ($request, $options) { $this->invokeStats($request, $options, null, $reason); if ($this->onRejected) { - call_user_func($this->onRejected, $reason); + ($this->onRejected)($reason); } - return \GuzzleHttp\Promise\rejection_for($reason); + + return P\Create::rejectionFor($reason); } ); } @@ -128,62 +147,66 @@ function ($reason) use ($request, $options) { /** * Adds one or more variadic requests, exceptions, callables, or promises * to the queue. + * + * @param mixed ...$values */ - public function append() + public function append(...$values): void { - foreach (func_get_args() as $value) { + foreach ($values as $value) { if ($value instanceof ResponseInterface - || $value instanceof \Exception + || $value instanceof \Throwable || $value instanceof PromiseInterface - || is_callable($value) + || \is_callable($value) ) { $this->queue[] = $value; } else { - throw new \InvalidArgumentException('Expected a response or ' - . 'exception. Found ' . \GuzzleHttp\describe_type($value)); + throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found '.Utils::describeType($value)); } } } /** * Get the last received request. - * - * @return RequestInterface */ - public function getLastRequest() + public function getLastRequest(): ?RequestInterface { return $this->lastRequest; } /** * Get the last received request options. - * - * @return array */ - public function getLastOptions() + public function getLastOptions(): array { return $this->lastOptions; } /** * Returns the number of remaining items in the queue. - * - * @return int */ - public function count() + public function count(): int { - return count($this->queue); + return \count($this->queue); } + public function reset(): void + { + $this->queue = []; + } + + /** + * @param mixed $reason Promise or reason. + */ private function invokeStats( RequestInterface $request, array $options, ResponseInterface $response = null, $reason = null - ) { + ): void { if (isset($options['on_stats'])) { - $stats = new TransferStats($request, $response, 0, $reason); - call_user_func($options['on_stats'], $stats); + $transferTime = $options['transfer_time'] ?? 0; + $stats = new TransferStats($request, $response, $transferTime, $reason); + ($options['on_stats'])($stats); } } } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php b/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php index f8b00be..f045b52 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php @@ -1,11 +1,15 @@ <?php + namespace GuzzleHttp\Handler; +use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\RequestOptions; use Psr\Http\Message\RequestInterface; /** * Provides basic proxies for handlers. + * + * @final */ class Proxy { @@ -13,19 +17,15 @@ class Proxy * Sends synchronous requests to a specific handler while sending all other * requests to another handler. * - * @param callable $default Handler used for normal responses - * @param callable $sync Handler used for synchronous responses. + * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for normal responses + * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $sync Handler used for synchronous responses. * - * @return callable Returns the composed handler. + * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler. */ - public static function wrapSync( - callable $default, - callable $sync - ) { - return function (RequestInterface $request, array $options) use ($default, $sync) { - return empty($options[RequestOptions::SYNCHRONOUS]) - ? $default($request, $options) - : $sync($request, $options); + public static function wrapSync(callable $default, callable $sync): callable + { + return static function (RequestInterface $request, array $options) use ($default, $sync): PromiseInterface { + return empty($options[RequestOptions::SYNCHRONOUS]) ? $default($request, $options) : $sync($request, $options); }; } @@ -37,19 +37,15 @@ public static function wrapSync( * performance benefits of curl while still supporting true streaming * through the StreamHandler. * - * @param callable $default Handler used for non-streaming responses - * @param callable $streaming Handler used for streaming responses + * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $default Handler used for non-streaming responses + * @param callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface $streaming Handler used for streaming responses * - * @return callable Returns the composed handler. + * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the composed handler. */ - public static function wrapStreaming( - callable $default, - callable $streaming - ) { - return function (RequestInterface $request, array $options) use ($default, $streaming) { - return empty($options['stream']) - ? $default($request, $options) - : $streaming($request, $options); + public static function wrapStreaming(callable $default, callable $streaming): callable + { + return static function (RequestInterface $request, array $options) use ($default, $streaming): PromiseInterface { + return empty($options['stream']) ? $default($request, $options) : $streaming($request, $options); }; } } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php index b686545..61632f5 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php @@ -1,21 +1,30 @@ <?php + namespace GuzzleHttp\Handler; -use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\ConnectException; +use GuzzleHttp\Exception\RequestException; +use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Psr7; use GuzzleHttp\TransferStats; +use GuzzleHttp\Utils; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; +use Psr\Http\Message\UriInterface; /** * HTTP handler that uses PHP's HTTP stream wrapper. + * + * @final */ class StreamHandler { + /** + * @var array + */ private $lastHeaders = []; /** @@ -23,17 +32,15 @@ class StreamHandler * * @param RequestInterface $request Request to send. * @param array $options Request transfer options. - * - * @return PromiseInterface */ - public function __invoke(RequestInterface $request, array $options) + public function __invoke(RequestInterface $request, array $options): PromiseInterface { // Sleep if there is a delay specified. if (isset($options['delay'])) { - usleep($options['delay'] * 1000); + \usleep($options['delay'] * 1000); } - $startTime = isset($options['on_stats']) ? microtime(true) : null; + $startTime = isset($options['on_stats']) ? Utils::currentTime() : null; try { // Does not support the expect header. @@ -42,7 +49,7 @@ public function __invoke(RequestInterface $request, array $options) // Append a content-length header if body size is zero to match // cURL's behavior. if (0 === $request->getBody()->getSize()) { - $request = $request->withHeader('Content-Length', 0); + $request = $request->withHeader('Content-Length', '0'); } return $this->createResponse( @@ -57,80 +64,80 @@ public function __invoke(RequestInterface $request, array $options) // Determine if the error was a networking error. $message = $e->getMessage(); // This list can probably get more comprehensive. - if (strpos($message, 'getaddrinfo') // DNS lookup failed - || strpos($message, 'Connection refused') - || strpos($message, "couldn't connect to host") // error on HHVM - || strpos($message, "connection attempt failed") + if (false !== \strpos($message, 'getaddrinfo') // DNS lookup failed + || false !== \strpos($message, 'Connection refused') + || false !== \strpos($message, "couldn't connect to host") // error on HHVM + || false !== \strpos($message, 'connection attempt failed') ) { $e = new ConnectException($e->getMessage(), $request, $e); + } else { + $e = RequestException::wrapException($request, $e); } - $e = RequestException::wrapException($request, $e); $this->invokeStats($options, $request, $startTime, null, $e); - return \GuzzleHttp\Promise\rejection_for($e); + return P\Create::rejectionFor($e); } } private function invokeStats( array $options, RequestInterface $request, - $startTime, + ?float $startTime, ResponseInterface $response = null, - $error = null - ) { + \Throwable $error = null + ): void { if (isset($options['on_stats'])) { - $stats = new TransferStats( - $request, - $response, - microtime(true) - $startTime, - $error, - [] - ); - call_user_func($options['on_stats'], $stats); + $stats = new TransferStats($request, $response, Utils::currentTime() - $startTime, $error, []); + ($options['on_stats'])($stats); } } - private function createResponse( - RequestInterface $request, - array $options, - $stream, - $startTime - ) { + /** + * @param resource $stream + */ + private function createResponse(RequestInterface $request, array $options, $stream, ?float $startTime): PromiseInterface + { $hdrs = $this->lastHeaders; $this->lastHeaders = []; - $parts = explode(' ', array_shift($hdrs), 3); - $ver = explode('/', $parts[0])[1]; - $status = $parts[1]; - $reason = isset($parts[2]) ? $parts[2] : null; - $headers = \GuzzleHttp\headers_from_lines($hdrs); - list($stream, $headers) = $this->checkDecode($options, $headers, $stream); - $stream = Psr7\stream_for($stream); + + try { + [$ver, $status, $reason, $headers] = HeaderProcessor::parseHeaders($hdrs); + } catch (\Exception $e) { + return P\Create::rejectionFor( + new RequestException('An error was encountered while creating the response', $request, null, $e) + ); + } + + [$stream, $headers] = $this->checkDecode($options, $headers, $stream); + $stream = Psr7\Utils::streamFor($stream); $sink = $stream; - if (strcasecmp('HEAD', $request->getMethod())) { + if (\strcasecmp('HEAD', $request->getMethod())) { $sink = $this->createSink($stream, $options); } - $response = new Psr7\Response($status, $headers, $sink, $ver, $reason); + try { + $response = new Psr7\Response($status, $headers, $sink, $ver, $reason); + } catch (\Exception $e) { + return P\Create::rejectionFor( + new RequestException('An error was encountered while creating the response', $request, null, $e) + ); + } if (isset($options['on_headers'])) { try { $options['on_headers']($response); } catch (\Exception $e) { - $msg = 'An error was encountered during the on_headers event'; - $ex = new RequestException($msg, $request, $response, $e); - return \GuzzleHttp\Promise\rejection_for($ex); + return P\Create::rejectionFor( + new RequestException('An error was encountered during the on_headers event', $request, $response, $e) + ); } } // Do not drain when the request is a HEAD request because they have // no body. if ($sink !== $stream) { - $this->drain( - $stream, - $sink, - $response->getHeaderLine('Content-Length') - ); + $this->drain($stream, $sink, $response->getHeaderLine('Content-Length')); } $this->invokeStats($options, $request, $startTime, $response, null); @@ -138,41 +145,37 @@ private function createResponse( return new FulfilledPromise($response); } - private function createSink(StreamInterface $stream, array $options) + private function createSink(StreamInterface $stream, array $options): StreamInterface { if (!empty($options['stream'])) { return $stream; } - $sink = isset($options['sink']) - ? $options['sink'] - : fopen('php://temp', 'r+'); + $sink = $options['sink'] ?? Psr7\Utils::tryFopen('php://temp', 'r+'); - return is_string($sink) - ? new Psr7\LazyOpenStream($sink, 'w+') - : Psr7\stream_for($sink); + return \is_string($sink) ? new Psr7\LazyOpenStream($sink, 'w+') : Psr7\Utils::streamFor($sink); } - private function checkDecode(array $options, array $headers, $stream) + /** + * @param resource $stream + */ + private function checkDecode(array $options, array $headers, $stream): array { // Automatically decode responses when instructed. if (!empty($options['decode_content'])) { - $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers); + $normalizedKeys = Utils::normalizeHeaderKeys($headers); if (isset($normalizedKeys['content-encoding'])) { $encoding = $headers[$normalizedKeys['content-encoding']]; if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') { - $stream = new Psr7\InflateStream( - Psr7\stream_for($stream) - ); - $headers['x-encoded-content-encoding'] - = $headers[$normalizedKeys['content-encoding']]; + $stream = new Psr7\InflateStream(Psr7\Utils::streamFor($stream)); + $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; + // Remove content-encoding header unset($headers[$normalizedKeys['content-encoding']]); + // Fix content-length header if (isset($normalizedKeys['content-length'])) { - $headers['x-encoded-content-length'] - = $headers[$normalizedKeys['content-length']]; - + $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; $length = (int) $stream->getSize(); if ($length === 0) { unset($headers[$normalizedKeys['content-length']]); @@ -190,27 +193,21 @@ private function checkDecode(array $options, array $headers, $stream) /** * Drains the source stream into the "sink" client option. * - * @param StreamInterface $source - * @param StreamInterface $sink - * @param string $contentLength Header specifying the amount of - * data to read. + * @param string $contentLength Header specifying the amount of + * data to read. * - * @return StreamInterface * @throws \RuntimeException when the sink option is invalid. */ - private function drain( - StreamInterface $source, - StreamInterface $sink, - $contentLength - ) { + private function drain(StreamInterface $source, StreamInterface $sink, string $contentLength): StreamInterface + { // If a content-length header is provided, then stop reading once // that number of bytes has been read. This can prevent infinitely // reading from a stream when dealing with servers that do not honor // Connection: Close headers. - Psr7\copy_to_stream( + Psr7\Utils::copyToStream( $source, $sink, - (strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1 + (\strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1 ); $sink->seek(0); @@ -225,41 +222,53 @@ private function drain( * @param callable $callback Callable that returns stream resource * * @return resource + * * @throws \RuntimeException on error */ private function createResource(callable $callback) { - $errors = null; - set_error_handler(function ($_, $msg, $file, $line) use (&$errors) { + $errors = []; + \set_error_handler(static function ($_, $msg, $file, $line) use (&$errors): bool { $errors[] = [ 'message' => $msg, - 'file' => $file, - 'line' => $line + 'file' => $file, + 'line' => $line, ]; + return true; }); - $resource = $callback(); - restore_error_handler(); + try { + $resource = $callback(); + } finally { + \restore_error_handler(); + } if (!$resource) { $message = 'Error creating resource: '; foreach ($errors as $err) { foreach ($err as $key => $value) { - $message .= "[$key] $value" . PHP_EOL; + $message .= "[$key] $value".\PHP_EOL; } } - throw new \RuntimeException(trim($message)); + throw new \RuntimeException(\trim($message)); } return $resource; } + /** + * @return resource + */ private function createStream(RequestInterface $request, array $options) { static $methods; if (!$methods) { - $methods = array_flip(get_class_methods(__CLASS__)); + $methods = \array_flip(\get_class_methods(__CLASS__)); + } + + if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) { + throw new RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $request); } // HTTP/1.1 streams using the PHP stream wrapper require a @@ -278,7 +287,7 @@ private function createStream(RequestInterface $request, array $options) $params = []; $context = $this->getDefaultContext($request); - if (isset($options['on_headers']) && !is_callable($options['on_headers'])) { + if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) { throw new \InvalidArgumentException('on_headers must be callable'); } @@ -292,42 +301,39 @@ private function createStream(RequestInterface $request, array $options) } if (isset($options['stream_context'])) { - if (!is_array($options['stream_context'])) { + if (!\is_array($options['stream_context'])) { throw new \InvalidArgumentException('stream_context must be an array'); } - $context = array_replace_recursive( - $context, - $options['stream_context'] - ); + $context = \array_replace_recursive($context, $options['stream_context']); } // Microsoft NTLM authentication only supported with curl handler - if (isset($options['auth']) - && is_array($options['auth']) - && isset($options['auth'][2]) - && 'ntlm' == $options['auth'][2] - ) { + if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) { throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler'); } $uri = $this->resolveHost($request, $options); - $context = $this->createResource( - function () use ($context, $params) { - return stream_context_create($context, $params); + $contextResource = $this->createResource( + static function () use ($context, $params) { + return \stream_context_create($context, $params); } ); return $this->createResource( - function () use ($uri, &$http_response_header, $context, $options) { - $resource = fopen((string) $uri, 'r', null, $context); - $this->lastHeaders = $http_response_header; + function () use ($uri, &$http_response_header, $contextResource, $context, $options, $request) { + $resource = @\fopen((string) $uri, 'r', false, $contextResource); + $this->lastHeaders = $http_response_header ?? []; + + if (false === $resource) { + throw new ConnectException(sprintf('Connection refused for URI %s', $uri), $request, null, $context); + } if (isset($options['read_timeout'])) { $readTimeout = $options['read_timeout']; $sec = (int) $readTimeout; $usec = ($readTimeout - $sec) * 100000; - stream_set_timeout($resource, $sec, $usec); + \stream_set_timeout($resource, $sec, $usec); } return $resource; @@ -335,30 +341,33 @@ function () use ($uri, &$http_response_header, $context, $options) { ); } - private function resolveHost(RequestInterface $request, array $options) + private function resolveHost(RequestInterface $request, array $options): UriInterface { $uri = $request->getUri(); - if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) { + if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) { if ('v4' === $options['force_ip_resolve']) { - $records = dns_get_record($uri->getHost(), DNS_A); - if (!isset($records[0]['ip'])) { - throw new ConnectException(sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request); + $records = \dns_get_record($uri->getHost(), \DNS_A); + if (false === $records || !isset($records[0]['ip'])) { + throw new ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request); } - $uri = $uri->withHost($records[0]['ip']); - } elseif ('v6' === $options['force_ip_resolve']) { - $records = dns_get_record($uri->getHost(), DNS_AAAA); - if (!isset($records[0]['ipv6'])) { - throw new ConnectException(sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request); + + return $uri->withHost($records[0]['ip']); + } + if ('v6' === $options['force_ip_resolve']) { + $records = \dns_get_record($uri->getHost(), \DNS_AAAA); + if (false === $records || !isset($records[0]['ipv6'])) { + throw new ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request); } - $uri = $uri->withHost('[' . $records[0]['ipv6'] . ']'); + + return $uri->withHost('['.$records[0]['ipv6'].']'); } } return $uri; } - private function getDefaultContext(RequestInterface $request) + private function getDefaultContext(RequestInterface $request): array { $headers = ''; foreach ($request->getHeaders() as $name => $value) { @@ -369,17 +378,20 @@ private function getDefaultContext(RequestInterface $request) $context = [ 'http' => [ - 'method' => $request->getMethod(), - 'header' => $headers, + 'method' => $request->getMethod(), + 'header' => $headers, 'protocol_version' => $request->getProtocolVersion(), - 'ignore_errors' => true, - 'follow_location' => 0, + 'ignore_errors' => true, + 'follow_location' => 0, + ], + 'ssl' => [ + 'peer_name' => $request->getUri()->getHost(), ], ]; $body = (string) $request->getBody(); - if (!empty($body)) { + if ('' !== $body) { $context['http']['content'] = $body; // Prevent the HTTP handler from adding a Content-Type header. if (!$request->hasHeader('Content-Type')) { @@ -387,55 +399,119 @@ private function getDefaultContext(RequestInterface $request) } } - $context['http']['header'] = rtrim($context['http']['header']); + $context['http']['header'] = \rtrim($context['http']['header']); return $context; } - private function add_proxy(RequestInterface $request, &$options, $value, &$params) + /** + * @param mixed $value as passed via Request transfer options. + */ + private function add_proxy(RequestInterface $request, array &$options, $value, array &$params): void { - if (!is_array($value)) { - $options['http']['proxy'] = $value; + $uri = null; + + if (!\is_array($value)) { + $uri = $value; } else { $scheme = $request->getUri()->getScheme(); if (isset($value[$scheme])) { - if (!isset($value['no']) - || !\GuzzleHttp\is_host_in_noproxy( - $request->getUri()->getHost(), - $value['no'] - ) - ) { - $options['http']['proxy'] = $value[$scheme]; + if (!isset($value['no']) || !Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) { + $uri = $value[$scheme]; } } } + + if (!$uri) { + return; + } + + $parsed = $this->parse_proxy($uri); + $options['http']['proxy'] = $parsed['proxy']; + + if ($parsed['auth']) { + if (!isset($options['http']['header'])) { + $options['http']['header'] = []; + } + $options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}"; + } } - private function add_timeout(RequestInterface $request, &$options, $value, &$params) + /** + * Parses the given proxy URL to make it compatible with the format PHP's stream context expects. + */ + private function parse_proxy(string $url): array + { + $parsed = \parse_url($url); + + if ($parsed !== false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') { + if (isset($parsed['host']) && isset($parsed['port'])) { + $auth = null; + if (isset($parsed['user']) && isset($parsed['pass'])) { + $auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}"); + } + + return [ + 'proxy' => "tcp://{$parsed['host']}:{$parsed['port']}", + 'auth' => $auth ? "Basic {$auth}" : null, + ]; + } + } + + // Return proxy as-is. + return [ + 'proxy' => $url, + 'auth' => null, + ]; + } + + /** + * @param mixed $value as passed via Request transfer options. + */ + private function add_timeout(RequestInterface $request, array &$options, $value, array &$params): void { if ($value > 0) { $options['http']['timeout'] = $value; } } - private function add_verify(RequestInterface $request, &$options, $value, &$params) + /** + * @param mixed $value as passed via Request transfer options. + */ + private function add_crypto_method(RequestInterface $request, array &$options, $value, array &$params): void { - if ($value === true) { - // PHP 5.6 or greater will find the system cert by default. When - // < 5.6, use the Guzzle bundled cacert. - if (PHP_VERSION_ID < 50600) { - $options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle(); - } - } elseif (is_string($value)) { - $options['ssl']['cafile'] = $value; - if (!file_exists($value)) { - throw new \RuntimeException("SSL CA bundle not found: $value"); - } - } elseif ($value === false) { + if ( + $value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT + || $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT + || $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT + || (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT) + ) { + $options['http']['crypto_method'] = $value; + + return; + } + + throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); + } + + /** + * @param mixed $value as passed via Request transfer options. + */ + private function add_verify(RequestInterface $request, array &$options, $value, array &$params): void + { + if ($value === false) { $options['ssl']['verify_peer'] = false; $options['ssl']['verify_peer_name'] = false; + return; - } else { + } + + if (\is_string($value)) { + $options['ssl']['cafile'] = $value; + if (!\file_exists($value)) { + throw new \RuntimeException("SSL CA bundle not found: $value"); + } + } elseif ($value !== true) { throw new \InvalidArgumentException('Invalid verify request option'); } @@ -444,88 +520,95 @@ private function add_verify(RequestInterface $request, &$options, $value, &$para $options['ssl']['allow_self_signed'] = false; } - private function add_cert(RequestInterface $request, &$options, $value, &$params) + /** + * @param mixed $value as passed via Request transfer options. + */ + private function add_cert(RequestInterface $request, array &$options, $value, array &$params): void { - if (is_array($value)) { + if (\is_array($value)) { $options['ssl']['passphrase'] = $value[1]; $value = $value[0]; } - if (!file_exists($value)) { + if (!\file_exists($value)) { throw new \RuntimeException("SSL certificate not found: {$value}"); } $options['ssl']['local_cert'] = $value; } - private function add_progress(RequestInterface $request, &$options, $value, &$params) + /** + * @param mixed $value as passed via Request transfer options. + */ + private function add_progress(RequestInterface $request, array &$options, $value, array &$params): void { - $this->addNotification( + self::addNotification( $params, - function ($code, $a, $b, $c, $transferred, $total) use ($value) { - if ($code == STREAM_NOTIFY_PROGRESS) { - $value($total, $transferred, null, null); + static function ($code, $a, $b, $c, $transferred, $total) use ($value) { + if ($code == \STREAM_NOTIFY_PROGRESS) { + // The upload progress cannot be determined. Use 0 for cURL compatibility: + // https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html + $value($total, $transferred, 0, 0); } } ); } - private function add_debug(RequestInterface $request, &$options, $value, &$params) + /** + * @param mixed $value as passed via Request transfer options. + */ + private function add_debug(RequestInterface $request, array &$options, $value, array &$params): void { if ($value === false) { return; } static $map = [ - STREAM_NOTIFY_CONNECT => 'CONNECT', - STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', - STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', - STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', - STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', - STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', - STREAM_NOTIFY_PROGRESS => 'PROGRESS', - STREAM_NOTIFY_FAILURE => 'FAILURE', - STREAM_NOTIFY_COMPLETED => 'COMPLETED', - STREAM_NOTIFY_RESOLVE => 'RESOLVE', + \STREAM_NOTIFY_CONNECT => 'CONNECT', + \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', + \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', + \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', + \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', + \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', + \STREAM_NOTIFY_PROGRESS => 'PROGRESS', + \STREAM_NOTIFY_FAILURE => 'FAILURE', + \STREAM_NOTIFY_COMPLETED => 'COMPLETED', + \STREAM_NOTIFY_RESOLVE => 'RESOLVE', ]; - static $args = ['severity', 'message', 'message_code', - 'bytes_transferred', 'bytes_max']; + static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max']; - $value = \GuzzleHttp\debug_resource($value); - $ident = $request->getMethod() . ' ' . $request->getUri()->withFragment(''); - $this->addNotification( + $value = Utils::debugResource($value); + $ident = $request->getMethod().' '.$request->getUri()->withFragment(''); + self::addNotification( $params, - function () use ($ident, $value, $map, $args) { - $passed = func_get_args(); - $code = array_shift($passed); - fprintf($value, '<%s> [%s] ', $ident, $map[$code]); - foreach (array_filter($passed) as $i => $v) { - fwrite($value, $args[$i] . ': "' . $v . '" '); + static function (int $code, ...$passed) use ($ident, $value, $map, $args): void { + \fprintf($value, '<%s> [%s] ', $ident, $map[$code]); + foreach (\array_filter($passed) as $i => $v) { + \fwrite($value, $args[$i].': "'.$v.'" '); } - fwrite($value, "\n"); + \fwrite($value, "\n"); } ); } - private function addNotification(array &$params, callable $notify) + private static function addNotification(array &$params, callable $notify): void { // Wrap the existing function if needed. if (!isset($params['notification'])) { $params['notification'] = $notify; } else { - $params['notification'] = $this->callArray([ + $params['notification'] = self::callArray([ $params['notification'], - $notify + $notify, ]); } } - private function callArray(array $functions) + private static function callArray(array $functions): callable { - return function () use ($functions) { - $args = func_get_args(); + return static function (...$args) use ($functions) { foreach ($functions as $fn) { - call_user_func_array($fn, $args); + $fn(...$args); } }; } diff --git a/vendor/guzzlehttp/guzzle/src/HandlerStack.php b/vendor/guzzlehttp/guzzle/src/HandlerStack.php index 24c46fd..1ce9c4b 100644 --- a/vendor/guzzlehttp/guzzle/src/HandlerStack.php +++ b/vendor/guzzlehttp/guzzle/src/HandlerStack.php @@ -1,21 +1,32 @@ <?php + namespace GuzzleHttp; +use GuzzleHttp\Promise\PromiseInterface; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; /** * Creates a composed Guzzle handler function by stacking middlewares on top of * an HTTP handler function. + * + * @final */ class HandlerStack { - /** @var callable */ + /** + * @var (callable(RequestInterface, array): PromiseInterface)|null + */ private $handler; - /** @var array */ + /** + * @var array{(callable(callable(RequestInterface, array): PromiseInterface): callable), (string|null)}[] + */ private $stack = []; - /** @var callable|null */ + /** + * @var (callable(RequestInterface, array): PromiseInterface)|null + */ private $cached; /** @@ -29,15 +40,13 @@ class HandlerStack * The returned handler stack can be passed to a client in the "handler" * option. * - * @param callable $handler HTTP handler function to use with the stack. If no - * handler is provided, the best handler for your - * system will be utilized. - * - * @return HandlerStack + * @param (callable(RequestInterface, array): PromiseInterface)|null $handler HTTP handler function to use with the stack. If no + * handler is provided, the best handler for your + * system will be utilized. */ - public static function create(callable $handler = null) + public static function create(?callable $handler = null): self { - $stack = new self($handler ?: choose_handler()); + $stack = new self($handler ?: Utils::chooseHandler()); $stack->push(Middleware::httpErrors(), 'http_errors'); $stack->push(Middleware::redirect(), 'allow_redirects'); $stack->push(Middleware::cookies(), 'cookies'); @@ -47,7 +56,7 @@ public static function create(callable $handler = null) } /** - * @param callable $handler Underlying HTTP handler. + * @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler. */ public function __construct(callable $handler = null) { @@ -57,8 +66,7 @@ public function __construct(callable $handler = null) /** * Invokes the handler stack as a composed handler * - * @param RequestInterface $request - * @param array $options + * @return ResponseInterface|PromiseInterface */ public function __invoke(RequestInterface $request, array $options) { @@ -76,20 +84,21 @@ public function __toString() { $depth = 0; $stack = []; - if ($this->handler) { - $stack[] = "0) Handler: " . $this->debugCallable($this->handler); + + if ($this->handler !== null) { + $stack[] = '0) Handler: '.$this->debugCallable($this->handler); } $result = ''; - foreach (array_reverse($this->stack) as $tuple) { - $depth++; + foreach (\array_reverse($this->stack) as $tuple) { + ++$depth; $str = "{$depth}) Name: '{$tuple[1]}', "; - $str .= "Function: " . $this->debugCallable($tuple[0]); + $str .= 'Function: '.$this->debugCallable($tuple[0]); $result = "> {$str}\n{$result}"; $stack[] = $str; } - foreach (array_keys($stack) as $k) { + foreach (\array_keys($stack) as $k) { $result .= "< {$stack[$k]}\n"; } @@ -99,10 +108,10 @@ public function __toString() /** * Set the HTTP handler that actually returns a promise. * - * @param callable $handler Accepts a request and array of options and - * returns a Promise. + * @param callable(RequestInterface, array): PromiseInterface $handler Accepts a request and array of options and + * returns a Promise. */ - public function setHandler(callable $handler) + public function setHandler(callable $handler): void { $this->handler = $handler; $this->cached = null; @@ -110,33 +119,31 @@ public function setHandler(callable $handler) /** * Returns true if the builder has a handler. - * - * @return bool */ - public function hasHandler() + public function hasHandler(): bool { - return (bool) $this->handler; + return $this->handler !== null; } /** * Unshift a middleware to the bottom of the stack. * - * @param callable $middleware Middleware function - * @param string $name Name to register for this middleware. + * @param callable(callable): callable $middleware Middleware function + * @param string $name Name to register for this middleware. */ - public function unshift(callable $middleware, $name = null) + public function unshift(callable $middleware, ?string $name = null): void { - array_unshift($this->stack, [$middleware, $name]); + \array_unshift($this->stack, [$middleware, $name]); $this->cached = null; } /** * Push a middleware to the top of the stack. * - * @param callable $middleware Middleware function - * @param string $name Name to register for this middleware. + * @param callable(callable): callable $middleware Middleware function + * @param string $name Name to register for this middleware. */ - public function push(callable $middleware, $name = '') + public function push(callable $middleware, string $name = ''): void { $this->stack[] = [$middleware, $name]; $this->cached = null; @@ -145,11 +152,11 @@ public function push(callable $middleware, $name = '') /** * Add a middleware before another middleware by name. * - * @param string $findName Middleware to find - * @param callable $middleware Middleware function - * @param string $withName Name to register for this middleware. + * @param string $findName Middleware to find + * @param callable(callable): callable $middleware Middleware function + * @param string $withName Name to register for this middleware. */ - public function before($findName, callable $middleware, $withName = '') + public function before(string $findName, callable $middleware, string $withName = ''): void { $this->splice($findName, $withName, $middleware, true); } @@ -157,11 +164,11 @@ public function before($findName, callable $middleware, $withName = '') /** * Add a middleware after another middleware by name. * - * @param string $findName Middleware to find - * @param callable $middleware Middleware function - * @param string $withName Name to register for this middleware. + * @param string $findName Middleware to find + * @param callable(callable): callable $middleware Middleware function + * @param string $withName Name to register for this middleware. */ - public function after($findName, callable $middleware, $withName = '') + public function after(string $findName, callable $middleware, string $withName = ''): void { $this->splice($findName, $withName, $middleware, false); } @@ -171,13 +178,17 @@ public function after($findName, callable $middleware, $withName = '') * * @param callable|string $remove Middleware to remove by instance or name. */ - public function remove($remove) + public function remove($remove): void { + if (!is_string($remove) && !is_callable($remove)) { + trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a callable or string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); + } + $this->cached = null; - $idx = is_callable($remove) ? 0 : 1; - $this->stack = array_values(array_filter( + $idx = \is_callable($remove) ? 0 : 1; + $this->stack = \array_values(\array_filter( $this->stack, - function ($tuple) use ($idx, $remove) { + static function ($tuple) use ($idx, $remove) { return $tuple[$idx] !== $remove; } )); @@ -186,16 +197,17 @@ function ($tuple) use ($idx, $remove) { /** * Compose the middleware and handler into a single callable function. * - * @return callable + * @return callable(RequestInterface, array): PromiseInterface */ - public function resolve() + public function resolve(): callable { - if (!$this->cached) { - if (!($prev = $this->handler)) { + if ($this->cached === null) { + if (($prev = $this->handler) === null) { throw new \LogicException('No handler has been specified'); } - foreach (array_reverse($this->stack) as $fn) { + foreach (\array_reverse($this->stack) as $fn) { + /** @var callable(RequestInterface, array): PromiseInterface $prev */ $prev = $fn[0]($prev); } @@ -205,11 +217,7 @@ public function resolve() return $this->cached; } - /** - * @param $name - * @return int - */ - private function findByName($name) + private function findByName(string $name): int { foreach ($this->stack as $k => $v) { if ($v[1] === $name) { @@ -222,13 +230,8 @@ private function findByName($name) /** * Splices a function into the middleware list at a specific position. - * - * @param $findName - * @param $withName - * @param callable $middleware - * @param $before */ - private function splice($findName, $withName, callable $middleware, $before) + private function splice(string $findName, string $withName, callable $middleware, bool $before): void { $this->cached = null; $idx = $this->findByName($findName); @@ -236,38 +239,37 @@ private function splice($findName, $withName, callable $middleware, $before) if ($before) { if ($idx === 0) { - array_unshift($this->stack, $tuple); + \array_unshift($this->stack, $tuple); } else { $replacement = [$tuple, $this->stack[$idx]]; - array_splice($this->stack, $idx, 1, $replacement); + \array_splice($this->stack, $idx, 1, $replacement); } - } elseif ($idx === count($this->stack) - 1) { + } elseif ($idx === \count($this->stack) - 1) { $this->stack[] = $tuple; } else { $replacement = [$this->stack[$idx], $tuple]; - array_splice($this->stack, $idx, 1, $replacement); + \array_splice($this->stack, $idx, 1, $replacement); } } /** * Provides a debug string for a given callable. * - * @param array|callable $fn Function to write as a string. - * - * @return string + * @param callable|string $fn Function to write as a string. */ - private function debugCallable($fn) + private function debugCallable($fn): string { - if (is_string($fn)) { + if (\is_string($fn)) { return "callable({$fn})"; } - if (is_array($fn)) { - return is_string($fn[0]) + if (\is_array($fn)) { + return \is_string($fn[0]) ? "callable({$fn[0]}::{$fn[1]})" - : "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])"; + : "callable(['".\get_class($fn[0])."', '{$fn[1]}'])"; } - return 'callable(' . spl_object_hash($fn) . ')'; + /** @var object $fn */ + return 'callable('.\spl_object_hash($fn).')'; } } diff --git a/vendor/guzzlehttp/guzzle/src/MessageFormatter.php b/vendor/guzzlehttp/guzzle/src/MessageFormatter.php index 663ac73..9b77eee 100644 --- a/vendor/guzzlehttp/guzzle/src/MessageFormatter.php +++ b/vendor/guzzlehttp/guzzle/src/MessageFormatter.php @@ -1,4 +1,5 @@ <?php + namespace GuzzleHttp; use Psr\Http\Message\MessageInterface; @@ -31,25 +32,31 @@ * - {res_headers}: Response headers * - {req_body}: Request body * - {res_body}: Response body + * + * @final */ -class MessageFormatter +class MessageFormatter implements MessageFormatterInterface { /** * Apache Common Log Format. - * @link http://httpd.apache.org/docs/2.4/logs.html#common + * + * @see https://httpd.apache.org/docs/2.4/logs.html#common + * * @var string */ - const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}"; - const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}"; - const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}'; + public const CLF = '{hostname} {req_header_User-Agent} - [{date_common_log}] "{method} {target} HTTP/{version}" {code} {res_header_Content-Length}'; + public const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}"; + public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}'; - /** @var string Template used to format log messages */ + /** + * @var string Template used to format log messages + */ private $template; /** * @param string $template Log message template */ - public function __construct($template = self::CLF) + public function __construct(?string $template = self::CLF) { $this->template = $template ?: self::CLF; } @@ -57,20 +64,16 @@ public function __construct($template = self::CLF) /** * Returns a formatted message string. * - * @param RequestInterface $request Request that was sent - * @param ResponseInterface $response Response that was received - * @param \Exception $error Exception that was received - * - * @return string + * @param RequestInterface $request Request that was sent + * @param ResponseInterface|null $response Response that was received + * @param \Throwable|null $error Exception that was received */ - public function format( - RequestInterface $request, - ResponseInterface $response = null, - \Exception $error = null - ) { + public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string + { $cache = []; - return preg_replace_callback( + /** @var string */ + return \preg_replace_callback( '/{\s*([A-Za-z_\-\.0-9]+)\s*}/', function (array $matches) use ($request, $response, $error, &$cache) { if (isset($cache[$matches[1]])) { @@ -80,39 +83,51 @@ function (array $matches) use ($request, $response, $error, &$cache) { $result = ''; switch ($matches[1]) { case 'request': - $result = Psr7\str($request); + $result = Psr7\Message::toString($request); break; case 'response': - $result = $response ? Psr7\str($response) : ''; + $result = $response ? Psr7\Message::toString($response) : ''; break; case 'req_headers': - $result = trim($request->getMethod() - . ' ' . $request->getRequestTarget()) - . ' HTTP/' . $request->getProtocolVersion() . "\r\n" - . $this->headers($request); + $result = \trim($request->getMethod() + .' '.$request->getRequestTarget()) + .' HTTP/'.$request->getProtocolVersion()."\r\n" + .$this->headers($request); break; case 'res_headers': $result = $response ? - sprintf( + \sprintf( 'HTTP/%s %d %s', $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase() - ) . "\r\n" . $this->headers($response) + )."\r\n".$this->headers($response) : 'NULL'; break; case 'req_body': - $result = $request->getBody(); + $result = $request->getBody()->__toString(); break; case 'res_body': - $result = $response ? $response->getBody() : 'NULL'; + if (!$response instanceof ResponseInterface) { + $result = 'NULL'; + break; + } + + $body = $response->getBody(); + + if (!$body->isSeekable()) { + $result = 'RESPONSE_NOT_LOGGEABLE'; + break; + } + + $result = $response->getBody()->__toString(); break; case 'ts': case 'date_iso_8601': - $result = gmdate('c'); + $result = \gmdate('c'); break; case 'date_common_log': - $result = date('d/M/Y:H:i:s O'); + $result = \date('d/M/Y:H:i:s O'); break; case 'method': $result = $request->getMethod(); @@ -122,7 +137,7 @@ function (array $matches) use ($request, $response, $error, &$cache) { break; case 'uri': case 'url': - $result = $request->getUri(); + $result = $request->getUri()->__toString(); break; case 'target': $result = $request->getRequestTarget(); @@ -139,7 +154,7 @@ function (array $matches) use ($request, $response, $error, &$cache) { $result = $request->getHeaderLine('Host'); break; case 'hostname': - $result = gethostname(); + $result = \gethostname(); break; case 'code': $result = $response ? $response->getStatusCode() : 'NULL'; @@ -152,29 +167,33 @@ function (array $matches) use ($request, $response, $error, &$cache) { break; default: // handle prefixed dynamic headers - if (strpos($matches[1], 'req_header_') === 0) { - $result = $request->getHeaderLine(substr($matches[1], 11)); - } elseif (strpos($matches[1], 'res_header_') === 0) { + if (\strpos($matches[1], 'req_header_') === 0) { + $result = $request->getHeaderLine(\substr($matches[1], 11)); + } elseif (\strpos($matches[1], 'res_header_') === 0) { $result = $response - ? $response->getHeaderLine(substr($matches[1], 11)) + ? $response->getHeaderLine(\substr($matches[1], 11)) : 'NULL'; } } $cache[$matches[1]] = $result; + return $result; }, $this->template ); } - private function headers(MessageInterface $message) + /** + * Get headers from message as string + */ + private function headers(MessageInterface $message): string { $result = ''; foreach ($message->getHeaders() as $name => $values) { - $result .= $name . ': ' . implode(', ', $values) . "\r\n"; + $result .= $name.': '.\implode(', ', $values)."\r\n"; } - return trim($result); + return \trim($result); } } diff --git a/vendor/guzzlehttp/guzzle/src/MessageFormatterInterface.php b/vendor/guzzlehttp/guzzle/src/MessageFormatterInterface.php new file mode 100644 index 0000000..a39ac24 --- /dev/null +++ b/vendor/guzzlehttp/guzzle/src/MessageFormatterInterface.php @@ -0,0 +1,18 @@ +<?php + +namespace GuzzleHttp; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +interface MessageFormatterInterface +{ + /** + * Returns a formatted message string. + * + * @param RequestInterface $request Request that was sent + * @param ResponseInterface|null $response Response that was received + * @param \Throwable|null $error Exception that was received + */ + public function format(RequestInterface $request, ?ResponseInterface $response = null, ?\Throwable $error = null): string; +} diff --git a/vendor/guzzlehttp/guzzle/src/Middleware.php b/vendor/guzzlehttp/guzzle/src/Middleware.php index d4ad75c..7e3eb6b 100644 --- a/vendor/guzzlehttp/guzzle/src/Middleware.php +++ b/vendor/guzzlehttp/guzzle/src/Middleware.php @@ -1,13 +1,14 @@ <?php + namespace GuzzleHttp; use GuzzleHttp\Cookie\CookieJarInterface; use GuzzleHttp\Exception\RequestException; -use GuzzleHttp\Promise\RejectedPromise; -use GuzzleHttp\Psr7; +use GuzzleHttp\Promise as P; +use GuzzleHttp\Promise\PromiseInterface; +use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerInterface; -use Psr\Log\LogLevel; /** * Functions used to create and wrap handlers with handler middleware. @@ -22,10 +23,10 @@ final class Middleware * * @return callable Returns a function that accepts the next handler. */ - public static function cookies() + public static function cookies(): callable { - return function (callable $handler) { - return function ($request, array $options) use ($handler) { + return static function (callable $handler): callable { + return static function ($request, array $options) use ($handler) { if (empty($options['cookies'])) { return $handler($request, $options); } elseif (!($options['cookies'] instanceof CookieJarInterface)) { @@ -33,37 +34,42 @@ public static function cookies() } $cookieJar = $options['cookies']; $request = $cookieJar->withCookieHeader($request); + return $handler($request, $options) ->then( - function ($response) use ($cookieJar, $request) { + static function (ResponseInterface $response) use ($cookieJar, $request): ResponseInterface { $cookieJar->extractCookies($request, $response); + return $response; } - ); + ); }; }; } /** * Middleware that throws exceptions for 4xx or 5xx responses when the - * "http_error" request option is set to true. + * "http_errors" request option is set to true. * - * @return callable Returns a function that accepts the next handler. + * @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages. + * + * @return callable(callable): callable Returns a function that accepts the next handler. */ - public static function httpErrors() + public static function httpErrors(BodySummarizerInterface $bodySummarizer = null): callable { - return function (callable $handler) { - return function ($request, array $options) use ($handler) { + return static function (callable $handler) use ($bodySummarizer): callable { + return static function ($request, array $options) use ($handler, $bodySummarizer) { if (empty($options['http_errors'])) { return $handler($request, $options); } + return $handler($request, $options)->then( - function (ResponseInterface $response) use ($request, $handler) { + static function (ResponseInterface $response) use ($request, $bodySummarizer) { $code = $response->getStatusCode(); if ($code < 400) { return $response; } - throw RequestException::create($request, $response); + throw RequestException::create($request, $response, null, [], $bodySummarizer); } ); }; @@ -73,37 +79,40 @@ function (ResponseInterface $response) use ($request, $handler) { /** * Middleware that pushes history data to an ArrayAccess container. * - * @param array|\ArrayAccess $container Container to hold the history (by reference). + * @param array|\ArrayAccess<int, array> $container Container to hold the history (by reference). + * + * @return callable(callable): callable Returns a function that accepts the next handler. * - * @return callable Returns a function that accepts the next handler. * @throws \InvalidArgumentException if container is not an array or ArrayAccess. */ - public static function history(&$container) + public static function history(&$container): callable { - if (!is_array($container) && !$container instanceof \ArrayAccess) { + if (!\is_array($container) && !$container instanceof \ArrayAccess) { throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess'); } - return function (callable $handler) use (&$container) { - return function ($request, array $options) use ($handler, &$container) { + return static function (callable $handler) use (&$container): callable { + return static function (RequestInterface $request, array $options) use ($handler, &$container) { return $handler($request, $options)->then( - function ($value) use ($request, &$container, $options) { + static function ($value) use ($request, &$container, $options) { $container[] = [ - 'request' => $request, + 'request' => $request, 'response' => $value, - 'error' => null, - 'options' => $options + 'error' => null, + 'options' => $options, ]; + return $value; }, - function ($reason) use ($request, &$container, $options) { + static function ($reason) use ($request, &$container, $options) { $container[] = [ - 'request' => $request, + 'request' => $request, 'response' => null, - 'error' => $reason, - 'options' => $options + 'error' => $reason, + 'options' => $options, ]; - return \GuzzleHttp\Promise\rejection_for($reason); + + return P\Create::rejectionFor($reason); } ); }; @@ -123,10 +132,10 @@ function ($reason) use ($request, &$container, $options) { * * @return callable Returns a function that accepts the next handler. */ - public static function tap(callable $before = null, callable $after = null) + public static function tap(callable $before = null, callable $after = null): callable { - return function (callable $handler) use ($before, $after) { - return function ($request, array $options) use ($handler, $before, $after) { + return static function (callable $handler) use ($before, $after): callable { + return static function (RequestInterface $request, array $options) use ($handler, $before, $after) { if ($before) { $before($request, $options); } @@ -134,6 +143,7 @@ public static function tap(callable $before = null, callable $after = null) if ($after) { $after($request, $options, $response); } + return $response; }; }; @@ -144,9 +154,9 @@ public static function tap(callable $before = null, callable $after = null) * * @return callable Returns a function that accepts the next handler. */ - public static function redirect() + public static function redirect(): callable { - return function (callable $handler) { + return static function (callable $handler): RedirectMiddleware { return new RedirectMiddleware($handler); }; } @@ -166,9 +176,9 @@ public static function redirect() * * @return callable Returns a function that accepts the next handler. */ - public static function retry(callable $decider, callable $delay = null) + public static function retry(callable $decider, callable $delay = null): callable { - return function (callable $handler) use ($decider, $delay) { + return static function (callable $handler) use ($decider, $delay): RetryMiddleware { return new RetryMiddleware($decider, $handler, $delay); }; } @@ -177,29 +187,36 @@ public static function retry(callable $decider, callable $delay = null) * Middleware that logs requests, responses, and errors using a message * formatter. * - * @param LoggerInterface $logger Logs messages. - * @param MessageFormatter $formatter Formatter used to create message strings. - * @param string $logLevel Level at which to log requests. + * @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests. + * + * @param LoggerInterface $logger Logs messages. + * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings. + * @param string $logLevel Level at which to log requests. * * @return callable Returns a function that accepts the next handler. */ - public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO) + public static function log(LoggerInterface $logger, $formatter, string $logLevel = 'info'): callable { - return function (callable $handler) use ($logger, $formatter, $logLevel) { - return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) { + // To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter + if (!$formatter instanceof MessageFormatter && !$formatter instanceof MessageFormatterInterface) { + throw new \LogicException(sprintf('Argument 2 to %s::log() must be of type %s', self::class, MessageFormatterInterface::class)); + } + + return static function (callable $handler) use ($logger, $formatter, $logLevel): callable { + return static function (RequestInterface $request, array $options = []) use ($handler, $logger, $formatter, $logLevel) { return $handler($request, $options)->then( - function ($response) use ($logger, $request, $formatter, $logLevel) { + static function ($response) use ($logger, $request, $formatter, $logLevel): ResponseInterface { $message = $formatter->format($request, $response); $logger->log($logLevel, $message); + return $response; }, - function ($reason) use ($logger, $request, $formatter) { - $response = $reason instanceof RequestException - ? $reason->getResponse() - : null; - $message = $formatter->format($request, $response, $reason); - $logger->notice($message); - return \GuzzleHttp\Promise\rejection_for($reason); + static function ($reason) use ($logger, $request, $formatter): PromiseInterface { + $response = $reason instanceof RequestException ? $reason->getResponse() : null; + $message = $formatter->format($request, $response, P\Create::exceptionFor($reason)); + $logger->error($message); + + return P\Create::rejectionFor($reason); } ); }; @@ -209,12 +226,10 @@ function ($reason) use ($logger, $request, $formatter) { /** * This middleware adds a default content-type if possible, a default * content-length or transfer-encoding header, and the expect header. - * - * @return callable */ - public static function prepareBody() + public static function prepareBody(): callable { - return function (callable $handler) { + return static function (callable $handler): PrepareBodyMiddleware { return new PrepareBodyMiddleware($handler); }; } @@ -225,12 +240,11 @@ public static function prepareBody() * * @param callable $fn Function that accepts a RequestInterface and returns * a RequestInterface. - * @return callable */ - public static function mapRequest(callable $fn) + public static function mapRequest(callable $fn): callable { - return function (callable $handler) use ($fn) { - return function ($request, array $options) use ($handler, $fn) { + return static function (callable $handler) use ($fn): callable { + return static function (RequestInterface $request, array $options) use ($handler, $fn) { return $handler($fn($request), $options); }; }; @@ -242,12 +256,11 @@ public static function mapRequest(callable $fn) * * @param callable $fn Function that accepts a ResponseInterface and * returns a ResponseInterface. - * @return callable */ - public static function mapResponse(callable $fn) + public static function mapResponse(callable $fn): callable { - return function (callable $handler) use ($fn) { - return function ($request, array $options) use ($handler, $fn) { + return static function (callable $handler) use ($fn): callable { + return static function (RequestInterface $request, array $options) use ($handler, $fn) { return $handler($request, $options)->then($fn); }; }; diff --git a/vendor/guzzlehttp/guzzle/src/Pool.php b/vendor/guzzlehttp/guzzle/src/Pool.php index 8f1be33..6277c61 100644 --- a/vendor/guzzlehttp/guzzle/src/Pool.php +++ b/vendor/guzzlehttp/guzzle/src/Pool.php @@ -1,12 +1,15 @@ <?php + namespace GuzzleHttp; +use GuzzleHttp\Promise as P; +use GuzzleHttp\Promise\EachPromise; +use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Promise\PromisorInterface; use Psr\Http\Message\RequestInterface; -use GuzzleHttp\Promise\EachPromise; /** - * Sends and iterator of requests concurrently using a capped pool size. + * Sends an iterator of requests concurrently using a capped pool size. * * The pool will read from an iterator until it is cancelled or until the * iterator is consumed. When a request is yielded, the request is sent after @@ -15,10 +18,14 @@ * When a function is yielded by the iterator, the function is provided the * "request_options" array that should be merged on top of any existing * options, and the function MUST then return a wait-able promise. + * + * @final */ class Pool implements PromisorInterface { - /** @var EachPromise */ + /** + * @var EachPromise + */ private $each; /** @@ -26,20 +33,14 @@ class Pool implements PromisorInterface * @param array|\Iterator $requests Requests or functions that return * requests to send concurrently. * @param array $config Associative array of options - * - concurrency: (int) Maximum number of requests to send concurrently - * - options: Array of request options to apply to each request. - * - fulfilled: (callable) Function to invoke when a request completes. - * - rejected: (callable) Function to invoke when a request is rejected. + * - concurrency: (int) Maximum number of requests to send concurrently + * - options: Array of request options to apply to each request. + * - fulfilled: (callable) Function to invoke when a request completes. + * - rejected: (callable) Function to invoke when a request is rejected. */ - public function __construct( - ClientInterface $client, - $requests, - array $config = [] - ) { - // Backwards compatibility. - if (isset($config['pool_size'])) { - $config['concurrency'] = $config['pool_size']; - } elseif (!isset($config['concurrency'])) { + public function __construct(ClientInterface $client, $requests, array $config = []) + { + if (!isset($config['concurrency'])) { $config['concurrency'] = 25; } @@ -50,18 +51,15 @@ public function __construct( $opts = []; } - $iterable = \GuzzleHttp\Promise\iter_for($requests); - $requests = function () use ($iterable, $client, $opts) { + $iterable = P\Create::iterFor($requests); + $requests = static function () use ($iterable, $client, $opts) { foreach ($iterable as $key => $rfn) { if ($rfn instanceof RequestInterface) { yield $key => $client->sendAsync($rfn, $opts); - } elseif (is_callable($rfn)) { + } elseif (\is_callable($rfn)) { yield $key => $rfn($opts); } else { - throw new \InvalidArgumentException('Each value yielded by ' - . 'the iterator must be a Psr7\Http\Message\RequestInterface ' - . 'or a callable that returns a promise that fulfills ' - . 'with a Psr7\Message\Http\ResponseInterface object.'); + throw new \InvalidArgumentException('Each value yielded by the iterator must be a Psr7\Http\Message\RequestInterface or a callable that returns a promise that fulfills with a Psr7\Message\Http\ResponseInterface object.'); } } }; @@ -69,7 +67,10 @@ public function __construct( $this->each = new EachPromise($requests(), $config); } - public function promise() + /** + * Get promise + */ + public function promise(): PromiseInterface { return $this->each->promise(); } @@ -85,36 +86,37 @@ public function promise() * @param ClientInterface $client Client used to send the requests * @param array|\Iterator $requests Requests to send concurrently. * @param array $options Passes through the options available in - * {@see GuzzleHttp\Pool::__construct} + * {@see \GuzzleHttp\Pool::__construct} * * @return array Returns an array containing the response or an exception * in the same order that the requests were sent. + * * @throws \InvalidArgumentException if the event format is incorrect. */ - public static function batch( - ClientInterface $client, - $requests, - array $options = [] - ) { + public static function batch(ClientInterface $client, $requests, array $options = []): array + { $res = []; self::cmpCallback($options, 'fulfilled', $res); self::cmpCallback($options, 'rejected', $res); $pool = new static($client, $requests, $options); $pool->promise()->wait(); - ksort($res); + \ksort($res); return $res; } - private static function cmpCallback(array &$options, $name, array &$results) + /** + * Execute callback(s) + */ + private static function cmpCallback(array &$options, string $name, array &$results): void { if (!isset($options[$name])) { - $options[$name] = function ($v, $k) use (&$results) { + $options[$name] = static function ($v, $k) use (&$results) { $results[$k] = $v; }; } else { $currentFn = $options[$name]; - $options[$name] = function ($v, $k) use (&$results, $currentFn) { + $options[$name] = static function ($v, $k) use (&$results, $currentFn) { $currentFn($v, $k); $results[$k] = $v; }; diff --git a/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php b/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php index 2eb95f9..0a8de81 100644 --- a/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php +++ b/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php @@ -1,34 +1,32 @@ <?php + namespace GuzzleHttp; use GuzzleHttp\Promise\PromiseInterface; -use GuzzleHttp\Psr7; use Psr\Http\Message\RequestInterface; /** * Prepares requests that contain a body, adding the Content-Length, * Content-Type, and Expect headers. + * + * @final */ class PrepareBodyMiddleware { - /** @var callable */ + /** + * @var callable(RequestInterface, array): PromiseInterface + */ private $nextHandler; /** - * @param callable $nextHandler Next handler to invoke. + * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. */ public function __construct(callable $nextHandler) { $this->nextHandler = $nextHandler; } - /** - * @param RequestInterface $request - * @param array $options - * - * @return PromiseInterface - */ - public function __invoke(RequestInterface $request, array $options) + public function __invoke(RequestInterface $request, array $options): PromiseInterface { $fn = $this->nextHandler; @@ -42,7 +40,7 @@ public function __invoke(RequestInterface $request, array $options) // Add a default content-type if possible. if (!$request->hasHeader('Content-Type')) { if ($uri = $request->getBody()->getMetadata('uri')) { - if ($type = Psr7\mimetype_from_filename($uri)) { + if (is_string($uri) && $type = Psr7\MimeType::fromFilename($uri)) { $modify['set_headers']['Content-Type'] = $type; } } @@ -63,20 +61,20 @@ public function __invoke(RequestInterface $request, array $options) // Add the expect header if needed. $this->addExpectHeader($request, $options, $modify); - return $fn(Psr7\modify_request($request, $modify), $options); + return $fn(Psr7\Utils::modifyRequest($request, $modify), $options); } - private function addExpectHeader( - RequestInterface $request, - array $options, - array &$modify - ) { + /** + * Add expect header + */ + private function addExpectHeader(RequestInterface $request, array $options, array &$modify): void + { // Determine if the Expect header should be used if ($request->hasHeader('Expect')) { return; } - $expect = isset($options['expect']) ? $options['expect'] : null; + $expect = $options['expect'] ?? null; // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0 if ($expect === false || $request->getProtocolVersion() < 1.1) { @@ -86,6 +84,7 @@ private function addExpectHeader( // The expect header is unconditionally enabled if ($expect === true) { $modify['set_headers']['Expect'] = '100-Continue'; + return; } diff --git a/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php b/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php index 131b771..f32808a 100644 --- a/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php +++ b/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php @@ -1,10 +1,10 @@ <?php + namespace GuzzleHttp; use GuzzleHttp\Exception\BadResponseException; use GuzzleHttp\Exception\TooManyRedirectsException; use GuzzleHttp\Promise\PromiseInterface; -use GuzzleHttp\Psr7; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; @@ -13,40 +13,41 @@ * Request redirect middleware. * * Apply this middleware like other middleware using - * {@see GuzzleHttp\Middleware::redirect()}. + * {@see \GuzzleHttp\Middleware::redirect()}. + * + * @final */ class RedirectMiddleware { - const HISTORY_HEADER = 'X-Guzzle-Redirect-History'; + public const HISTORY_HEADER = 'X-Guzzle-Redirect-History'; - const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History'; + public const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History'; + /** + * @var array + */ public static $defaultSettings = [ - 'max' => 5, - 'protocols' => ['http', 'https'], - 'strict' => false, - 'referer' => false, + 'max' => 5, + 'protocols' => ['http', 'https'], + 'strict' => false, + 'referer' => false, 'track_redirects' => false, ]; - /** @var callable */ + /** + * @var callable(RequestInterface, array): PromiseInterface + */ private $nextHandler; /** - * @param callable $nextHandler Next handler to invoke. + * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. */ public function __construct(callable $nextHandler) { $this->nextHandler = $nextHandler; } - /** - * @param RequestInterface $request - * @param array $options - * - * @return PromiseInterface - */ - public function __invoke(RequestInterface $request, array $options) + public function __invoke(RequestInterface $request, array $options): PromiseInterface { $fn = $this->nextHandler; @@ -56,7 +57,7 @@ public function __invoke(RequestInterface $request, array $options) if ($options['allow_redirects'] === true) { $options['allow_redirects'] = self::$defaultSettings; - } elseif (!is_array($options['allow_redirects'])) { + } elseif (!\is_array($options['allow_redirects'])) { throw new \InvalidArgumentException('allow_redirects must be true, false, or array'); } else { // Merge the default settings with the provided settings @@ -74,36 +75,35 @@ public function __invoke(RequestInterface $request, array $options) } /** - * @param RequestInterface $request - * @param array $options - * @param ResponseInterface|PromiseInterface $response - * * @return ResponseInterface|PromiseInterface */ - public function checkRedirect( - RequestInterface $request, - array $options, - ResponseInterface $response - ) { - if (substr($response->getStatusCode(), 0, 1) != '3' + public function checkRedirect(RequestInterface $request, array $options, ResponseInterface $response) + { + if (\strpos((string) $response->getStatusCode(), '3') !== 0 || !$response->hasHeader('Location') ) { return $response; } - $this->guardMax($request, $options); + $this->guardMax($request, $response, $options); $nextRequest = $this->modifyRequest($request, $options, $response); + // If authorization is handled by curl, unset it if URI is cross-origin. + if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $nextRequest->getUri()) && defined('\CURLOPT_HTTPAUTH')) { + unset( + $options['curl'][\CURLOPT_HTTPAUTH], + $options['curl'][\CURLOPT_USERPWD] + ); + } + if (isset($options['allow_redirects']['on_redirect'])) { - call_user_func( - $options['allow_redirects']['on_redirect'], + ($options['allow_redirects']['on_redirect'])( $request, $response, $nextRequest->getUri() ); } - /** @var PromiseInterface|ResponseInterface $promise */ $promise = $this($nextRequest, $options); // Add headers to be able to track history of redirects. @@ -118,51 +118,46 @@ public function checkRedirect( return $promise; } - private function withTracking(PromiseInterface $promise, $uri, $statusCode) + /** + * Enable tracking on promise. + */ + private function withTracking(PromiseInterface $promise, string $uri, int $statusCode): PromiseInterface { return $promise->then( - function (ResponseInterface $response) use ($uri, $statusCode) { + static function (ResponseInterface $response) use ($uri, $statusCode) { // Note that we are pushing to the front of the list as this // would be an earlier response than what is currently present // in the history header. $historyHeader = $response->getHeader(self::HISTORY_HEADER); $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER); - array_unshift($historyHeader, $uri); - array_unshift($statusHeader, $statusCode); + \array_unshift($historyHeader, $uri); + \array_unshift($statusHeader, (string) $statusCode); + return $response->withHeader(self::HISTORY_HEADER, $historyHeader) ->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader); } ); } - private function guardMax(RequestInterface $request, array &$options) + /** + * Check for too many redirects. + * + * @throws TooManyRedirectsException Too many redirects. + */ + private function guardMax(RequestInterface $request, ResponseInterface $response, array &$options): void { - $current = isset($options['__redirect_count']) - ? $options['__redirect_count'] - : 0; + $current = $options['__redirect_count'] + ?? 0; $options['__redirect_count'] = $current + 1; $max = $options['allow_redirects']['max']; if ($options['__redirect_count'] > $max) { - throw new TooManyRedirectsException( - "Will not follow more than {$max} redirects", - $request - ); + throw new TooManyRedirectsException("Will not follow more than {$max} redirects", $request, $response); } } - /** - * @param RequestInterface $request - * @param array $options - * @param ResponseInterface $response - * - * @return RequestInterface - */ - public function modifyRequest( - RequestInterface $request, - array $options, - ResponseInterface $response - ) { + public function modifyRequest(RequestInterface $request, array $options, ResponseInterface $response): RequestInterface + { // Request modifications to apply. $modify = []; $protocols = $options['allow_redirects']['protocols']; @@ -172,64 +167,60 @@ public function modifyRequest( // would do. $statusCode = $response->getStatusCode(); if ($statusCode == 303 || - ($statusCode <= 302 && $request->getBody() && !$options['allow_redirects']['strict']) + ($statusCode <= 302 && !$options['allow_redirects']['strict']) ) { - $modify['method'] = 'GET'; + $safeMethods = ['GET', 'HEAD', 'OPTIONS']; + $requestMethod = $request->getMethod(); + + $modify['method'] = in_array($requestMethod, $safeMethods) ? $requestMethod : 'GET'; $modify['body'] = ''; } - $modify['uri'] = $this->redirectUri($request, $response, $protocols); - Psr7\rewind_body($request); + $uri = self::redirectUri($request, $response, $protocols); + if (isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) { + $idnOptions = ($options['idn_conversion'] === true) ? \IDNA_DEFAULT : $options['idn_conversion']; + $uri = Utils::idnUriConvert($uri, $idnOptions); + } + + $modify['uri'] = $uri; + Psr7\Message::rewindBody($request); // Add the Referer header if it is told to do so and only // add the header if we are not redirecting from https to http. if ($options['allow_redirects']['referer'] && $modify['uri']->getScheme() === $request->getUri()->getScheme() ) { - $uri = $request->getUri()->withUserInfo('', ''); + $uri = $request->getUri()->withUserInfo(''); $modify['set_headers']['Referer'] = (string) $uri; } else { $modify['remove_headers'][] = 'Referer'; } - // Remove Authorization header if host is different. - if ($request->getUri()->getHost() !== $modify['uri']->getHost()) { + // Remove Authorization and Cookie headers if URI is cross-origin. + if (Psr7\UriComparator::isCrossOrigin($request->getUri(), $modify['uri'])) { $modify['remove_headers'][] = 'Authorization'; + $modify['remove_headers'][] = 'Cookie'; } - return Psr7\modify_request($request, $modify); + return Psr7\Utils::modifyRequest($request, $modify); } /** - * Set the appropriate URL on the request based on the location header - * - * @param RequestInterface $request - * @param ResponseInterface $response - * @param array $protocols - * - * @return UriInterface + * Set the appropriate URL on the request based on the location header. */ - private function redirectUri( + private static function redirectUri( RequestInterface $request, ResponseInterface $response, array $protocols - ) { + ): UriInterface { $location = Psr7\UriResolver::resolve( $request->getUri(), new Psr7\Uri($response->getHeaderLine('Location')) ); // Ensure that the redirect URI is allowed based on the protocols. - if (!in_array($location->getScheme(), $protocols)) { - throw new BadResponseException( - sprintf( - 'Redirect URI, %s, does not use one of the allowed redirect protocols: %s', - $location, - implode(', ', $protocols) - ), - $request, - $response - ); + if (!\in_array($location->getScheme(), $protocols)) { + throw new BadResponseException(\sprintf('Redirect URI, %s, does not use one of the allowed redirect protocols: %s', $location, \implode(', ', $protocols)), $request, $response); } return $location; diff --git a/vendor/guzzlehttp/guzzle/src/RequestOptions.php b/vendor/guzzlehttp/guzzle/src/RequestOptions.php index c6aacfb..bf3b02b 100644 --- a/vendor/guzzlehttp/guzzle/src/RequestOptions.php +++ b/vendor/guzzlehttp/guzzle/src/RequestOptions.php @@ -1,4 +1,5 @@ <?php + namespace GuzzleHttp; /** @@ -6,7 +7,7 @@ * * More documentation for each option can be found at http://guzzlephp.org/. * - * @link http://docs.guzzlephp.org/en/v6/request-options.html + * @see http://docs.guzzlephp.org/en/v6/request-options.html */ final class RequestOptions { @@ -22,7 +23,7 @@ final class RequestOptions * - strict: (bool, default=false) Set to true to use strict redirects * meaning redirect POST requests with POST requests vs. doing what most * browsers do which is redirect POST requests with GET requests - * - referer: (bool, default=true) Set to false to disable the Referer + * - referer: (bool, default=false) Set to true to enable the Referer * header. * - protocols: (array, default=['http', 'https']) Allowed redirect * protocols. @@ -31,7 +32,7 @@ final class RequestOptions * response that was received, and the effective URI. Any return value * from the on_redirect function is ignored. */ - const ALLOW_REDIRECTS = 'allow_redirects'; + public const ALLOW_REDIRECTS = 'allow_redirects'; /** * auth: (array) Pass an array of HTTP authentication parameters to use @@ -40,13 +41,13 @@ final class RequestOptions * authentication type in index [2]. Pass null to disable authentication * for a request. */ - const AUTH = 'auth'; + public const AUTH = 'auth'; /** * body: (resource|string|null|int|float|StreamInterface|callable|\Iterator) * Body to send in the request. */ - const BODY = 'body'; + public const BODY = 'body'; /** * cert: (string|array) Set to a string to specify the path to a file @@ -55,42 +56,54 @@ final class RequestOptions * file in the first array element followed by the certificate password * in the second array element. */ - const CERT = 'cert'; + public const CERT = 'cert'; /** * cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false) * Specifies whether or not cookies are used in a request or what cookie * jar to use or what cookies to send. This option only works if your * handler has the `cookie` middleware. Valid values are `false` and - * an instance of {@see GuzzleHttp\Cookie\CookieJarInterface}. + * an instance of {@see \GuzzleHttp\Cookie\CookieJarInterface}. */ - const COOKIES = 'cookies'; + public const COOKIES = 'cookies'; /** * connect_timeout: (float, default=0) Float describing the number of * seconds to wait while trying to connect to a server. Use 0 to wait - * indefinitely (the default behavior). + * 300 seconds (the default behavior). + */ + public const CONNECT_TIMEOUT = 'connect_timeout'; + + /** + * crypto_method: (int) A value describing the minimum TLS protocol + * version to use. + * + * This setting must be set to one of the + * ``STREAM_CRYPTO_METHOD_TLS*_CLIENT`` constants. PHP 7.4 or higher is + * required in order to use TLS 1.3, and cURL 7.34.0 or higher is required + * in order to specify a crypto method, with cURL 7.52.0 or higher being + * required to use TLS 1.3. */ - const CONNECT_TIMEOUT = 'connect_timeout'; + public const CRYPTO_METHOD = 'crypto_method'; /** * debug: (bool|resource) Set to true or set to a PHP stream returned by * fopen() enable debug output with the HTTP handler used to send a * request. */ - const DEBUG = 'debug'; + public const DEBUG = 'debug'; /** * decode_content: (bool, default=true) Specify whether or not * Content-Encoding responses (gzip, deflate, etc.) are automatically * decoded. */ - const DECODE_CONTENT = 'decode_content'; + public const DECODE_CONTENT = 'decode_content'; /** * delay: (int) The amount of time to delay before sending in milliseconds. */ - const DELAY = 'delay'; + public const DELAY = 'delay'; /** * expect: (bool|integer) Controls the behavior of the @@ -108,7 +121,7 @@ final class RequestOptions * size of the body of a request is greater than 1 MB and a request is * using HTTP/1.1. */ - const EXPECT = 'expect'; + public const EXPECT = 'expect'; /** * form_params: (array) Associative array of form field names to values @@ -116,13 +129,13 @@ final class RequestOptions * header to application/x-www-form-urlencoded when no Content-Type header * is already present. */ - const FORM_PARAMS = 'form_params'; + public const FORM_PARAMS = 'form_params'; /** * headers: (array) Associative array of HTTP headers. Each value MUST be * a string or array of strings. */ - const HEADERS = 'headers'; + public const HEADERS = 'headers'; /** * http_errors: (bool, default=true) Set to false to disable exceptions @@ -130,14 +143,22 @@ final class RequestOptions * exceptions will be thrown for 4xx and 5xx responses. This option only * works if your handler has the `httpErrors` middleware. */ - const HTTP_ERRORS = 'http_errors'; + public const HTTP_ERRORS = 'http_errors'; + + /** + * idn: (bool|int, default=true) A combination of IDNA_* constants for + * idn_to_ascii() PHP's function (see "options" parameter). Set to false to + * disable IDN support completely, or to true to use the default + * configuration (IDNA_DEFAULT constant). + */ + public const IDN_CONVERSION = 'idn_conversion'; /** * json: (mixed) Adds JSON data to a request. The provided value is JSON * encoded and a Content-Type header of application/json will be added to * the request if no Content-Type header is already present. */ - const JSON = 'json'; + public const JSON = 'json'; /** * multipart: (array) Array of associative arrays, each containing a @@ -148,14 +169,14 @@ final class RequestOptions * the part. If no "filename" key is present, then no "filename" attribute * will be added to the part. */ - const MULTIPART = 'multipart'; + public const MULTIPART = 'multipart'; /** * on_headers: (callable) A callable that is invoked when the HTTP headers * of the response have been received but the body has not yet begun to * download. */ - const ON_HEADERS = 'on_headers'; + public const ON_HEADERS = 'on_headers'; /** * on_stats: (callable) allows you to get access to transfer statistics of @@ -166,7 +187,7 @@ final class RequestOptions * the error encountered. Included in the data is the total amount of time * taken to send the request. */ - const ON_STATS = 'on_stats'; + public const ON_STATS = 'on_stats'; /** * progress: (callable) Defines a function to invoke when transfer @@ -175,14 +196,14 @@ final class RequestOptions * number of bytes downloaded so far, the number of bytes expected to be * uploaded, the number of bytes uploaded so far. */ - const PROGRESS = 'progress'; + public const PROGRESS = 'progress'; /** * proxy: (string|array) Pass a string to specify an HTTP proxy, or an * array to specify different proxies for different protocols (where the * key is the protocol and the value is a proxy string). */ - const PROXY = 'proxy'; + public const PROXY = 'proxy'; /** * query: (array|string) Associative array of query string values to add @@ -190,14 +211,14 @@ final class RequestOptions * the string representation. Pass a string value if you need more * control than what this method provides */ - const QUERY = 'query'; + public const QUERY = 'query'; /** * sink: (resource|string|StreamInterface) Where the data of the * response is written to. Defaults to a PHP temp stream. Providing a * string will write data to a file by the given name. */ - const SINK = 'sink'; + public const SINK = 'sink'; /** * synchronous: (bool) Set to true to inform HTTP handlers that you intend @@ -205,7 +226,7 @@ final class RequestOptions * that a promise is still returned if you are using one of the async * client methods. */ - const SYNCHRONOUS = 'synchronous'; + public const SYNCHRONOUS = 'synchronous'; /** * ssl_key: (array|string) Specify the path to a file containing a private @@ -213,13 +234,13 @@ final class RequestOptions * containing the path to the SSL key in the first array element followed * by the password required for the certificate in the second element. */ - const SSL_KEY = 'ssl_key'; + public const SSL_KEY = 'ssl_key'; /** * stream: Set to true to attempt to stream a response rather than * download it all up-front. */ - const STREAM = 'stream'; + public const STREAM = 'stream'; /** * verify: (bool|string, default=true) Describes the SSL certificate @@ -229,27 +250,27 @@ final class RequestOptions * is insecure!). Set to a string to provide the path to a CA bundle on * disk to enable verification using a custom certificate. */ - const VERIFY = 'verify'; + public const VERIFY = 'verify'; /** * timeout: (float, default=0) Float describing the timeout of the * request in seconds. Use 0 to wait indefinitely (the default behavior). */ - const TIMEOUT = 'timeout'; + public const TIMEOUT = 'timeout'; /** * read_timeout: (float, default=default_socket_timeout ini setting) Float describing * the body read timeout, for stream requests. */ - const READ_TIMEOUT = 'read_timeout'; + public const READ_TIMEOUT = 'read_timeout'; /** * version: (float) Specifies the HTTP protocol version to attempt to use. */ - const VERSION = 'version'; + public const VERSION = 'version'; /** * force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol */ - const FORCE_IP_RESOLVE = 'force_ip_resolve'; + public const FORCE_IP_RESOLVE = 'force_ip_resolve'; } diff --git a/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php b/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php index f27090f..8f4d93a 100644 --- a/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php +++ b/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php @@ -1,69 +1,70 @@ <?php + namespace GuzzleHttp; +use GuzzleHttp\Promise as P; use GuzzleHttp\Promise\PromiseInterface; -use GuzzleHttp\Promise\RejectedPromise; -use GuzzleHttp\Psr7; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; /** * Middleware that retries requests based on the boolean result of * invoking the provided "decider" function. + * + * @final */ class RetryMiddleware { - /** @var callable */ + /** + * @var callable(RequestInterface, array): PromiseInterface + */ private $nextHandler; - /** @var callable */ + /** + * @var callable + */ private $decider; /** - * @param callable $decider Function that accepts the number of retries, - * a request, [response], and [exception] and - * returns true if the request is to be - * retried. - * @param callable $nextHandler Next handler to invoke. - * @param callable $delay Function that accepts the number of retries - * and [response] and returns the number of - * milliseconds to delay. + * @var callable(int) */ - public function __construct( - callable $decider, - callable $nextHandler, - callable $delay = null - ) { + private $delay; + + /** + * @param callable $decider Function that accepts the number of retries, + * a request, [response], and [exception] and + * returns true if the request is to be + * retried. + * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. + * @param (callable(int): int)|null $delay Function that accepts the number of retries + * and returns the number of + * milliseconds to delay. + */ + public function __construct(callable $decider, callable $nextHandler, callable $delay = null) + { $this->decider = $decider; $this->nextHandler = $nextHandler; - $this->delay = $delay ?: __CLASS__ . '::exponentialDelay'; + $this->delay = $delay ?: __CLASS__.'::exponentialDelay'; } /** * Default exponential backoff delay function. * - * @param $retries - * - * @return int + * @return int milliseconds. */ - public static function exponentialDelay($retries) + public static function exponentialDelay(int $retries): int { - return (int) pow(2, $retries - 1); + return (int) 2 ** ($retries - 1) * 1000; } - /** - * @param RequestInterface $request - * @param array $options - * - * @return PromiseInterface - */ - public function __invoke(RequestInterface $request, array $options) + public function __invoke(RequestInterface $request, array $options): PromiseInterface { if (!isset($options['retries'])) { $options['retries'] = 0; } $fn = $this->nextHandler; + return $fn($request, $options) ->then( $this->onFulfilled($request, $options), @@ -71,41 +72,47 @@ public function __invoke(RequestInterface $request, array $options) ); } - private function onFulfilled(RequestInterface $req, array $options) + /** + * Execute fulfilled closure + */ + private function onFulfilled(RequestInterface $request, array $options): callable { - return function ($value) use ($req, $options) { - if (!call_user_func( - $this->decider, + return function ($value) use ($request, $options) { + if (!($this->decider)( $options['retries'], - $req, + $request, $value, null )) { return $value; } - return $this->doRetry($req, $options, $value); + + return $this->doRetry($request, $options, $value); }; } - private function onRejected(RequestInterface $req, array $options) + /** + * Execute rejected closure + */ + private function onRejected(RequestInterface $req, array $options): callable { return function ($reason) use ($req, $options) { - if (!call_user_func( - $this->decider, + if (!($this->decider)( $options['retries'], $req, null, $reason )) { - return \GuzzleHttp\Promise\rejection_for($reason); + return P\Create::rejectionFor($reason); } + return $this->doRetry($req, $options); }; } - private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null) + private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null): PromiseInterface { - $options['delay'] = call_user_func($this->delay, ++$options['retries'], $response); + $options['delay'] = ($this->delay)(++$options['retries'], $response, $request); return $this($request, $options); } diff --git a/vendor/guzzlehttp/guzzle/src/TransferStats.php b/vendor/guzzlehttp/guzzle/src/TransferStats.php index 15f717e..93fa334 100644 --- a/vendor/guzzlehttp/guzzle/src/TransferStats.php +++ b/vendor/guzzlehttp/guzzle/src/TransferStats.php @@ -1,4 +1,5 @@ <?php + namespace GuzzleHttp; use Psr\Http\Message\RequestInterface; @@ -11,25 +12,44 @@ */ final class TransferStats { + /** + * @var RequestInterface + */ private $request; + + /** + * @var ResponseInterface|null + */ private $response; + + /** + * @var float|null + */ private $transferTime; + + /** + * @var array + */ private $handlerStats; + + /** + * @var mixed|null + */ private $handlerErrorData; /** - * @param RequestInterface $request Request that was sent. - * @param ResponseInterface $response Response received (if any) - * @param null $transferTime Total handler transfer time. - * @param mixed $handlerErrorData Handler error data. - * @param array $handlerStats Handler specific stats. + * @param RequestInterface $request Request that was sent. + * @param ResponseInterface|null $response Response received (if any) + * @param float|null $transferTime Total handler transfer time. + * @param mixed $handlerErrorData Handler error data. + * @param array $handlerStats Handler specific stats. */ public function __construct( RequestInterface $request, - ResponseInterface $response = null, - $transferTime = null, + ?ResponseInterface $response = null, + ?float $transferTime = null, $handlerErrorData = null, - $handlerStats = [] + array $handlerStats = [] ) { $this->request = $request; $this->response = $response; @@ -38,30 +58,23 @@ public function __construct( $this->handlerStats = $handlerStats; } - /** - * @return RequestInterface - */ - public function getRequest() + public function getRequest(): RequestInterface { return $this->request; } /** * Returns the response that was received (if any). - * - * @return ResponseInterface|null */ - public function getResponse() + public function getResponse(): ?ResponseInterface { return $this->response; } /** * Returns true if a response was received. - * - * @return bool */ - public function hasResponse() + public function hasResponse(): bool { return $this->response !== null; } @@ -82,10 +95,8 @@ public function getHandlerErrorData() /** * Get the effective URI the request was sent to. - * - * @return UriInterface */ - public function getEffectiveUri() + public function getEffectiveUri(): UriInterface { return $this->request->getUri(); } @@ -93,19 +104,17 @@ public function getEffectiveUri() /** * Get the estimated time the request was being transferred by the handler. * - * @return float Time in seconds. + * @return float|null Time in seconds. */ - public function getTransferTime() + public function getTransferTime(): ?float { return $this->transferTime; } /** * Gets an array of all of the handler specific transfer data. - * - * @return array */ - public function getHandlerStats() + public function getHandlerStats(): array { return $this->handlerStats; } @@ -117,10 +126,8 @@ public function getHandlerStats() * * @return mixed|null */ - public function getHandlerStat($stat) + public function getHandlerStat(string $stat) { - return isset($this->handlerStats[$stat]) - ? $this->handlerStats[$stat] - : null; + return $this->handlerStats[$stat] ?? null; } } diff --git a/vendor/guzzlehttp/guzzle/src/UriTemplate.php b/vendor/guzzlehttp/guzzle/src/UriTemplate.php deleted file mode 100644 index 96dcfd0..0000000 --- a/vendor/guzzlehttp/guzzle/src/UriTemplate.php +++ /dev/null @@ -1,237 +0,0 @@ -<?php -namespace GuzzleHttp; - -/** - * Expands URI templates. Userland implementation of PECL uri_template. - * - * @link http://tools.ietf.org/html/rfc6570 - */ -class UriTemplate -{ - /** @var string URI template */ - private $template; - - /** @var array Variables to use in the template expansion */ - private $variables; - - /** @var array Hash for quick operator lookups */ - private static $operatorHash = [ - '' => ['prefix' => '', 'joiner' => ',', 'query' => false], - '+' => ['prefix' => '', 'joiner' => ',', 'query' => false], - '#' => ['prefix' => '#', 'joiner' => ',', 'query' => false], - '.' => ['prefix' => '.', 'joiner' => '.', 'query' => false], - '/' => ['prefix' => '/', 'joiner' => '/', 'query' => false], - ';' => ['prefix' => ';', 'joiner' => ';', 'query' => true], - '?' => ['prefix' => '?', 'joiner' => '&', 'query' => true], - '&' => ['prefix' => '&', 'joiner' => '&', 'query' => true] - ]; - - /** @var array Delimiters */ - private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$', - '&', '\'', '(', ')', '*', '+', ',', ';', '=']; - - /** @var array Percent encoded delimiters */ - private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D', - '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', - '%3B', '%3D']; - - public function expand($template, array $variables) - { - if (false === strpos($template, '{')) { - return $template; - } - - $this->template = $template; - $this->variables = $variables; - - return preg_replace_callback( - '/\{([^\}]+)\}/', - [$this, 'expandMatch'], - $this->template - ); - } - - /** - * Parse an expression into parts - * - * @param string $expression Expression to parse - * - * @return array Returns an associative array of parts - */ - private function parseExpression($expression) - { - $result = []; - - if (isset(self::$operatorHash[$expression[0]])) { - $result['operator'] = $expression[0]; - $expression = substr($expression, 1); - } else { - $result['operator'] = ''; - } - - foreach (explode(',', $expression) as $value) { - $value = trim($value); - $varspec = []; - if ($colonPos = strpos($value, ':')) { - $varspec['value'] = substr($value, 0, $colonPos); - $varspec['modifier'] = ':'; - $varspec['position'] = (int) substr($value, $colonPos + 1); - } elseif (substr($value, -1) === '*') { - $varspec['modifier'] = '*'; - $varspec['value'] = substr($value, 0, -1); - } else { - $varspec['value'] = (string) $value; - $varspec['modifier'] = ''; - } - $result['values'][] = $varspec; - } - - return $result; - } - - /** - * Process an expansion - * - * @param array $matches Matches met in the preg_replace_callback - * - * @return string Returns the replacement string - */ - private function expandMatch(array $matches) - { - static $rfc1738to3986 = ['+' => '%20', '%7e' => '~']; - - $replacements = []; - $parsed = self::parseExpression($matches[1]); - $prefix = self::$operatorHash[$parsed['operator']]['prefix']; - $joiner = self::$operatorHash[$parsed['operator']]['joiner']; - $useQuery = self::$operatorHash[$parsed['operator']]['query']; - - foreach ($parsed['values'] as $value) { - if (!isset($this->variables[$value['value']])) { - continue; - } - - $variable = $this->variables[$value['value']]; - $actuallyUseQuery = $useQuery; - $expanded = ''; - - if (is_array($variable)) { - $isAssoc = $this->isAssoc($variable); - $kvp = []; - foreach ($variable as $key => $var) { - if ($isAssoc) { - $key = rawurlencode($key); - $isNestedArray = is_array($var); - } else { - $isNestedArray = false; - } - - if (!$isNestedArray) { - $var = rawurlencode($var); - if ($parsed['operator'] === '+' || - $parsed['operator'] === '#' - ) { - $var = $this->decodeReserved($var); - } - } - - if ($value['modifier'] === '*') { - if ($isAssoc) { - if ($isNestedArray) { - // Nested arrays must allow for deeply nested - // structures. - $var = strtr( - http_build_query([$key => $var]), - $rfc1738to3986 - ); - } else { - $var = $key . '=' . $var; - } - } elseif ($key > 0 && $actuallyUseQuery) { - $var = $value['value'] . '=' . $var; - } - } - - $kvp[$key] = $var; - } - - if (empty($variable)) { - $actuallyUseQuery = false; - } elseif ($value['modifier'] === '*') { - $expanded = implode($joiner, $kvp); - if ($isAssoc) { - // Don't prepend the value name when using the explode - // modifier with an associative array. - $actuallyUseQuery = false; - } - } else { - if ($isAssoc) { - // When an associative array is encountered and the - // explode modifier is not set, then the result must be - // a comma separated list of keys followed by their - // respective values. - foreach ($kvp as $k => &$v) { - $v = $k . ',' . $v; - } - } - $expanded = implode(',', $kvp); - } - } else { - if ($value['modifier'] === ':') { - $variable = substr($variable, 0, $value['position']); - } - $expanded = rawurlencode($variable); - if ($parsed['operator'] === '+' || $parsed['operator'] === '#') { - $expanded = $this->decodeReserved($expanded); - } - } - - if ($actuallyUseQuery) { - if (!$expanded && $joiner !== '&') { - $expanded = $value['value']; - } else { - $expanded = $value['value'] . '=' . $expanded; - } - } - - $replacements[] = $expanded; - } - - $ret = implode($joiner, $replacements); - if ($ret && $prefix) { - return $prefix . $ret; - } - - return $ret; - } - - /** - * Determines if an array is associative. - * - * This makes the assumption that input arrays are sequences or hashes. - * This assumption is a tradeoff for accuracy in favor of speed, but it - * should work in almost every case where input is supplied for a URI - * template. - * - * @param array $array Array to check - * - * @return bool - */ - private function isAssoc(array $array) - { - return $array && array_keys($array)[0] !== 0; - } - - /** - * Removes percent encoding on reserved characters (used with + and # - * modifiers). - * - * @param string $string String to fix - * - * @return string - */ - private function decodeReserved($string) - { - return str_replace(self::$delimsPct, self::$delims, $string); - } -} diff --git a/vendor/guzzlehttp/guzzle/src/Utils.php b/vendor/guzzlehttp/guzzle/src/Utils.php new file mode 100644 index 0000000..fcf571d --- /dev/null +++ b/vendor/guzzlehttp/guzzle/src/Utils.php @@ -0,0 +1,385 @@ +<?php + +namespace GuzzleHttp; + +use GuzzleHttp\Exception\InvalidArgumentException; +use GuzzleHttp\Handler\CurlHandler; +use GuzzleHttp\Handler\CurlMultiHandler; +use GuzzleHttp\Handler\Proxy; +use GuzzleHttp\Handler\StreamHandler; +use Psr\Http\Message\UriInterface; + +final class Utils +{ + /** + * Debug function used to describe the provided value type and class. + * + * @param mixed $input + * + * @return string Returns a string containing the type of the variable and + * if a class is provided, the class name. + */ + public static function describeType($input): string + { + switch (\gettype($input)) { + case 'object': + return 'object('.\get_class($input).')'; + case 'array': + return 'array('.\count($input).')'; + default: + \ob_start(); + \var_dump($input); + // normalize float vs double + /** @var string $varDumpContent */ + $varDumpContent = \ob_get_clean(); + + return \str_replace('double(', 'float(', \rtrim($varDumpContent)); + } + } + + /** + * Parses an array of header lines into an associative array of headers. + * + * @param iterable $lines Header lines array of strings in the following + * format: "Name: Value" + */ + public static function headersFromLines(iterable $lines): array + { + $headers = []; + + foreach ($lines as $line) { + $parts = \explode(':', $line, 2); + $headers[\trim($parts[0])][] = isset($parts[1]) ? \trim($parts[1]) : null; + } + + return $headers; + } + + /** + * Returns a debug stream based on the provided variable. + * + * @param mixed $value Optional value + * + * @return resource + */ + public static function debugResource($value = null) + { + if (\is_resource($value)) { + return $value; + } + if (\defined('STDOUT')) { + return \STDOUT; + } + + return \GuzzleHttp\Psr7\Utils::tryFopen('php://output', 'w'); + } + + /** + * Chooses and creates a default handler to use based on the environment. + * + * The returned handler is not wrapped by any default middlewares. + * + * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system. + * + * @throws \RuntimeException if no viable Handler is available. + */ + public static function chooseHandler(): callable + { + $handler = null; + + if (\defined('CURLOPT_CUSTOMREQUEST')) { + if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) { + $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler()); + } elseif (\function_exists('curl_exec')) { + $handler = new CurlHandler(); + } elseif (\function_exists('curl_multi_exec')) { + $handler = new CurlMultiHandler(); + } + } + + if (\ini_get('allow_url_fopen')) { + $handler = $handler + ? Proxy::wrapStreaming($handler, new StreamHandler()) + : new StreamHandler(); + } elseif (!$handler) { + throw new \RuntimeException('GuzzleHttp requires cURL, the allow_url_fopen ini setting, or a custom HTTP handler.'); + } + + return $handler; + } + + /** + * Get the default User-Agent string to use with Guzzle. + */ + public static function defaultUserAgent(): string + { + return sprintf('GuzzleHttp/%d', ClientInterface::MAJOR_VERSION); + } + + /** + * Returns the default cacert bundle for the current system. + * + * First, the openssl.cafile and curl.cainfo php.ini settings are checked. + * If those settings are not configured, then the common locations for + * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X + * and Windows are checked. If any of these file locations are found on + * disk, they will be utilized. + * + * Note: the result of this function is cached for subsequent calls. + * + * @throws \RuntimeException if no bundle can be found. + * + * @deprecated Utils::defaultCaBundle will be removed in guzzlehttp/guzzle:8.0. This method is not needed in PHP 5.6+. + */ + public static function defaultCaBundle(): string + { + static $cached = null; + static $cafiles = [ + // Red Hat, CentOS, Fedora (provided by the ca-certificates package) + '/etc/pki/tls/certs/ca-bundle.crt', + // Ubuntu, Debian (provided by the ca-certificates package) + '/etc/ssl/certs/ca-certificates.crt', + // FreeBSD (provided by the ca_root_nss package) + '/usr/local/share/certs/ca-root-nss.crt', + // SLES 12 (provided by the ca-certificates package) + '/var/lib/ca-certificates/ca-bundle.pem', + // OS X provided by homebrew (using the default path) + '/usr/local/etc/openssl/cert.pem', + // Google app engine + '/etc/ca-certificates.crt', + // Windows? + 'C:\\windows\\system32\\curl-ca-bundle.crt', + 'C:\\windows\\curl-ca-bundle.crt', + ]; + + if ($cached) { + return $cached; + } + + if ($ca = \ini_get('openssl.cafile')) { + return $cached = $ca; + } + + if ($ca = \ini_get('curl.cainfo')) { + return $cached = $ca; + } + + foreach ($cafiles as $filename) { + if (\file_exists($filename)) { + return $cached = $filename; + } + } + + throw new \RuntimeException( + <<< EOT +No system CA bundle could be found in any of the the common system locations. +PHP versions earlier than 5.6 are not properly configured to use the system's +CA bundle by default. In order to verify peer certificates, you will need to +supply the path on disk to a certificate bundle to the 'verify' request +option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not +need a specific certificate bundle, then Mozilla provides a commonly used CA +bundle which can be downloaded here (provided by the maintainer of cURL): +https://curl.haxx.se/ca/cacert.pem. Once +you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP +ini setting to point to the path to the file, allowing you to omit the 'verify' +request option. See https://curl.haxx.se/docs/sslcerts.html for more +information. +EOT + ); + } + + /** + * Creates an associative array of lowercase header names to the actual + * header casing. + */ + public static function normalizeHeaderKeys(array $headers): array + { + $result = []; + foreach (\array_keys($headers) as $key) { + $result[\strtolower($key)] = $key; + } + + return $result; + } + + /** + * Returns true if the provided host matches any of the no proxy areas. + * + * This method will strip a port from the host if it is present. Each pattern + * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a + * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" == + * "baz.foo.com", but ".foo.com" != "foo.com"). + * + * Areas are matched in the following cases: + * 1. "*" (without quotes) always matches any hosts. + * 2. An exact match. + * 3. The area starts with "." and the area is the last part of the host. e.g. + * '.mit.edu' will match any host that ends with '.mit.edu'. + * + * @param string $host Host to check against the patterns. + * @param string[] $noProxyArray An array of host patterns. + * + * @throws InvalidArgumentException + */ + public static function isHostInNoProxy(string $host, array $noProxyArray): bool + { + if (\strlen($host) === 0) { + throw new InvalidArgumentException('Empty host provided'); + } + + // Strip port if present. + [$host] = \explode(':', $host, 2); + + foreach ($noProxyArray as $area) { + // Always match on wildcards. + if ($area === '*') { + return true; + } + + if (empty($area)) { + // Don't match on empty values. + continue; + } + + if ($area === $host) { + // Exact matches. + return true; + } + // Special match if the area when prefixed with ".". Remove any + // existing leading "." and add a new leading ".". + $area = '.'.\ltrim($area, '.'); + if (\substr($host, -\strlen($area)) === $area) { + return true; + } + } + + return false; + } + + /** + * Wrapper for json_decode that throws when an error occurs. + * + * @param string $json JSON data to parse + * @param bool $assoc When true, returned objects will be converted + * into associative arrays. + * @param int $depth User specified recursion depth. + * @param int $options Bitmask of JSON decode options. + * + * @return object|array|string|int|float|bool|null + * + * @throws InvalidArgumentException if the JSON cannot be decoded. + * + * @see https://www.php.net/manual/en/function.json-decode.php + */ + public static function jsonDecode(string $json, bool $assoc = false, int $depth = 512, int $options = 0) + { + $data = \json_decode($json, $assoc, $depth, $options); + if (\JSON_ERROR_NONE !== \json_last_error()) { + throw new InvalidArgumentException('json_decode error: '.\json_last_error_msg()); + } + + return $data; + } + + /** + * Wrapper for JSON encoding that throws when an error occurs. + * + * @param mixed $value The value being encoded + * @param int $options JSON encode option bitmask + * @param int $depth Set the maximum depth. Must be greater than zero. + * + * @throws InvalidArgumentException if the JSON cannot be encoded. + * + * @see https://www.php.net/manual/en/function.json-encode.php + */ + public static function jsonEncode($value, int $options = 0, int $depth = 512): string + { + $json = \json_encode($value, $options, $depth); + if (\JSON_ERROR_NONE !== \json_last_error()) { + throw new InvalidArgumentException('json_encode error: '.\json_last_error_msg()); + } + + /** @var string */ + return $json; + } + + /** + * Wrapper for the hrtime() or microtime() functions + * (depending on the PHP version, one of the two is used) + * + * @return float UNIX timestamp + * + * @internal + */ + public static function currentTime(): float + { + return (float) \function_exists('hrtime') ? \hrtime(true) / 1e9 : \microtime(true); + } + + /** + * @throws InvalidArgumentException + * + * @internal + */ + public static function idnUriConvert(UriInterface $uri, int $options = 0): UriInterface + { + if ($uri->getHost()) { + $asciiHost = self::idnToAsci($uri->getHost(), $options, $info); + if ($asciiHost === false) { + $errorBitSet = $info['errors'] ?? 0; + + $errorConstants = array_filter(array_keys(get_defined_constants()), static function (string $name): bool { + return substr($name, 0, 11) === 'IDNA_ERROR_'; + }); + + $errors = []; + foreach ($errorConstants as $errorConstant) { + if ($errorBitSet & constant($errorConstant)) { + $errors[] = $errorConstant; + } + } + + $errorMessage = 'IDN conversion failed'; + if ($errors) { + $errorMessage .= ' (errors: '.implode(', ', $errors).')'; + } + + throw new InvalidArgumentException($errorMessage); + } + if ($uri->getHost() !== $asciiHost) { + // Replace URI only if the ASCII version is different + $uri = $uri->withHost($asciiHost); + } + } + + return $uri; + } + + /** + * @internal + */ + public static function getenv(string $name): ?string + { + if (isset($_SERVER[$name])) { + return (string) $_SERVER[$name]; + } + + if (\PHP_SAPI === 'cli' && ($value = \getenv($name)) !== false && $value !== null) { + return (string) $value; + } + + return null; + } + + /** + * @return string|false + */ + private static function idnToAsci(string $domain, int $options, ?array &$info = []) + { + if (\function_exists('idn_to_ascii') && \defined('INTL_IDNA_VARIANT_UTS46')) { + return \idn_to_ascii($domain, $options, \INTL_IDNA_VARIANT_UTS46, $info); + } + + throw new \Error('ext-idn or symfony/polyfill-intl-idn not loaded or too old'); + } +} diff --git a/vendor/guzzlehttp/guzzle/src/functions.php b/vendor/guzzlehttp/guzzle/src/functions.php index a3ac450..5edc66a 100644 --- a/vendor/guzzlehttp/guzzle/src/functions.php +++ b/vendor/guzzlehttp/guzzle/src/functions.php @@ -1,77 +1,34 @@ <?php -namespace GuzzleHttp; - -use GuzzleHttp\Handler\CurlHandler; -use GuzzleHttp\Handler\CurlMultiHandler; -use GuzzleHttp\Handler\Proxy; -use GuzzleHttp\Handler\StreamHandler; - -/** - * Expands a URI template - * - * @param string $template URI template - * @param array $variables Template variables - * - * @return string - */ -function uri_template($template, array $variables) -{ - if (extension_loaded('uri_template')) { - // @codeCoverageIgnoreStart - return \uri_template($template, $variables); - // @codeCoverageIgnoreEnd - } - static $uriTemplate; - if (!$uriTemplate) { - $uriTemplate = new UriTemplate(); - } - - return $uriTemplate->expand($template, $variables); -} +namespace GuzzleHttp; /** * Debug function used to describe the provided value type and class. * - * @param mixed $input + * @param mixed $input Any type of variable to describe the type of. This + * parameter misses a typehint because of that. * * @return string Returns a string containing the type of the variable and * if a class is provided, the class name. + * + * @deprecated describe_type will be removed in guzzlehttp/guzzle:8.0. Use Utils::describeType instead. */ -function describe_type($input) +function describe_type($input): string { - switch (gettype($input)) { - case 'object': - return 'object(' . get_class($input) . ')'; - case 'array': - return 'array(' . count($input) . ')'; - default: - ob_start(); - var_dump($input); - // normalize float vs double - return str_replace('double(', 'float(', rtrim(ob_get_clean())); - } + return Utils::describeType($input); } /** * Parses an array of header lines into an associative array of headers. * - * @param array $lines Header lines array of strings in the following - * format: "Name: Value" - * @return array + * @param iterable $lines Header lines array of strings in the following + * format: "Name: Value" + * + * @deprecated headers_from_lines will be removed in guzzlehttp/guzzle:8.0. Use Utils::headersFromLines instead. */ -function headers_from_lines($lines) +function headers_from_lines(iterable $lines): array { - $headers = []; - - foreach ($lines as $line) { - $parts = explode(':', $line, 2); - $headers[trim($parts[0])][] = isset($parts[1]) - ? trim($parts[1]) - : null; - } - - return $headers; + return Utils::headersFromLines($lines); } /** @@ -80,16 +37,12 @@ function headers_from_lines($lines) * @param mixed $value Optional value * * @return resource + * + * @deprecated debug_resource will be removed in guzzlehttp/guzzle:8.0. Use Utils::debugResource instead. */ function debug_resource($value = null) { - if (is_resource($value)) { - return $value; - } elseif (defined('STDOUT')) { - return STDOUT; - } - - return fopen('php://output', 'w'); + return Utils::debugResource($value); } /** @@ -97,50 +50,25 @@ function debug_resource($value = null) * * The returned handler is not wrapped by any default middlewares. * + * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system. + * * @throws \RuntimeException if no viable Handler is available. - * @return callable Returns the best handler for the given system. + * + * @deprecated choose_handler will be removed in guzzlehttp/guzzle:8.0. Use Utils::chooseHandler instead. */ -function choose_handler() +function choose_handler(): callable { - $handler = null; - if (function_exists('curl_multi_exec') && function_exists('curl_exec')) { - $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler()); - } elseif (function_exists('curl_exec')) { - $handler = new CurlHandler(); - } elseif (function_exists('curl_multi_exec')) { - $handler = new CurlMultiHandler(); - } - - if (ini_get('allow_url_fopen')) { - $handler = $handler - ? Proxy::wrapStreaming($handler, new StreamHandler()) - : new StreamHandler(); - } elseif (!$handler) { - throw new \RuntimeException('GuzzleHttp requires cURL, the ' - . 'allow_url_fopen ini setting, or a custom HTTP handler.'); - } - - return $handler; + return Utils::chooseHandler(); } /** - * Get the default User-Agent string to use with Guzzle + * Get the default User-Agent string to use with Guzzle. * - * @return string + * @deprecated default_user_agent will be removed in guzzlehttp/guzzle:8.0. Use Utils::defaultUserAgent instead. */ -function default_user_agent() +function default_user_agent(): string { - static $defaultAgent = ''; - - if (!$defaultAgent) { - $defaultAgent = 'GuzzleHttp/' . Client::VERSION; - if (extension_loaded('curl') && function_exists('curl_version')) { - $defaultAgent .= ' curl/' . \curl_version()['version']; - } - $defaultAgent .= ' PHP/' . PHP_VERSION; - } - - return $defaultAgent; + return Utils::defaultUserAgent(); } /** @@ -154,81 +82,24 @@ function default_user_agent() * * Note: the result of this function is cached for subsequent calls. * - * @return string * @throws \RuntimeException if no bundle can be found. + * + * @deprecated default_ca_bundle will be removed in guzzlehttp/guzzle:8.0. This function is not needed in PHP 5.6+. */ -function default_ca_bundle() +function default_ca_bundle(): string { - static $cached = null; - static $cafiles = [ - // Red Hat, CentOS, Fedora (provided by the ca-certificates package) - '/etc/pki/tls/certs/ca-bundle.crt', - // Ubuntu, Debian (provided by the ca-certificates package) - '/etc/ssl/certs/ca-certificates.crt', - // FreeBSD (provided by the ca_root_nss package) - '/usr/local/share/certs/ca-root-nss.crt', - // SLES 12 (provided by the ca-certificates package) - '/var/lib/ca-certificates/ca-bundle.pem', - // OS X provided by homebrew (using the default path) - '/usr/local/etc/openssl/cert.pem', - // Google app engine - '/etc/ca-certificates.crt', - // Windows? - 'C:\\windows\\system32\\curl-ca-bundle.crt', - 'C:\\windows\\curl-ca-bundle.crt', - ]; - - if ($cached) { - return $cached; - } - - if ($ca = ini_get('openssl.cafile')) { - return $cached = $ca; - } - - if ($ca = ini_get('curl.cainfo')) { - return $cached = $ca; - } - - foreach ($cafiles as $filename) { - if (file_exists($filename)) { - return $cached = $filename; - } - } - - throw new \RuntimeException(<<< EOT -No system CA bundle could be found in any of the the common system locations. -PHP versions earlier than 5.6 are not properly configured to use the system's -CA bundle by default. In order to verify peer certificates, you will need to -supply the path on disk to a certificate bundle to the 'verify' request -option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not -need a specific certificate bundle, then Mozilla provides a commonly used CA -bundle which can be downloaded here (provided by the maintainer of cURL): -https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once -you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP -ini setting to point to the path to the file, allowing you to omit the 'verify' -request option. See http://curl.haxx.se/docs/sslcerts.html for more -information. -EOT - ); + return Utils::defaultCaBundle(); } /** * Creates an associative array of lowercase header names to the actual * header casing. * - * @param array $headers - * - * @return array + * @deprecated normalize_header_keys will be removed in guzzlehttp/guzzle:8.0. Use Utils::normalizeHeaderKeys instead. */ -function normalize_header_keys(array $headers) +function normalize_header_keys(array $headers): array { - $result = []; - foreach (array_keys($headers) as $key) { - $result[strtolower($key)] = $key; - } - - return $result; + return Utils::normalizeHeaderKeys($headers); } /** @@ -245,89 +116,52 @@ function normalize_header_keys(array $headers) * 3. The area starts with "." and the area is the last part of the host. e.g. * '.mit.edu' will match any host that ends with '.mit.edu'. * - * @param string $host Host to check against the patterns. - * @param array $noProxyArray An array of host patterns. + * @param string $host Host to check against the patterns. + * @param string[] $noProxyArray An array of host patterns. + * + * @throws Exception\InvalidArgumentException * - * @return bool + * @deprecated is_host_in_noproxy will be removed in guzzlehttp/guzzle:8.0. Use Utils::isHostInNoProxy instead. */ -function is_host_in_noproxy($host, array $noProxyArray) +function is_host_in_noproxy(string $host, array $noProxyArray): bool { - if (strlen($host) === 0) { - throw new \InvalidArgumentException('Empty host provided'); - } - - // Strip port if present. - if (strpos($host, ':')) { - $host = explode($host, ':', 2)[0]; - } - - foreach ($noProxyArray as $area) { - // Always match on wildcards. - if ($area === '*') { - return true; - } elseif (empty($area)) { - // Don't match on empty values. - continue; - } elseif ($area === $host) { - // Exact matches. - return true; - } else { - // Special match if the area when prefixed with ".". Remove any - // existing leading "." and add a new leading ".". - $area = '.' . ltrim($area, '.'); - if (substr($host, -(strlen($area))) === $area) { - return true; - } - } - } - - return false; + return Utils::isHostInNoProxy($host, $noProxyArray); } /** * Wrapper for json_decode that throws when an error occurs. * * @param string $json JSON data to parse - * @param bool $assoc When true, returned objects will be converted + * @param bool $assoc When true, returned objects will be converted * into associative arrays. * @param int $depth User specified recursion depth. * @param int $options Bitmask of JSON decode options. * - * @return mixed - * @throws \InvalidArgumentException if the JSON cannot be decoded. - * @link http://www.php.net/manual/en/function.json-decode.php + * @return object|array|string|int|float|bool|null + * + * @throws Exception\InvalidArgumentException if the JSON cannot be decoded. + * + * @see https://www.php.net/manual/en/function.json-decode.php + * @deprecated json_decode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonDecode instead. */ -function json_decode($json, $assoc = false, $depth = 512, $options = 0) +function json_decode(string $json, bool $assoc = false, int $depth = 512, int $options = 0) { - $data = \json_decode($json, $assoc, $depth, $options); - if (JSON_ERROR_NONE !== json_last_error()) { - throw new \InvalidArgumentException( - 'json_decode error: ' . json_last_error_msg() - ); - } - - return $data; + return Utils::jsonDecode($json, $assoc, $depth, $options); } /** * Wrapper for JSON encoding that throws when an error occurs. * * @param mixed $value The value being encoded - * @param int $options JSON encode option bitmask - * @param int $depth Set the maximum depth. Must be greater than zero. + * @param int $options JSON encode option bitmask + * @param int $depth Set the maximum depth. Must be greater than zero. * - * @return string - * @throws \InvalidArgumentException if the JSON cannot be encoded. - * @link http://www.php.net/manual/en/function.json-encode.php + * @throws Exception\InvalidArgumentException if the JSON cannot be encoded. + * + * @see https://www.php.net/manual/en/function.json-encode.php + * @deprecated json_encode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonEncode instead. */ -function json_encode($value, $options = 0, $depth = 512) +function json_encode($value, int $options = 0, int $depth = 512): string { - $json = \json_encode($value, $options, $depth); - if (JSON_ERROR_NONE !== json_last_error()) { - throw new \InvalidArgumentException( - 'json_encode error: ' . json_last_error_msg() - ); - } - - return $json; + return Utils::jsonEncode($value, $options, $depth); } diff --git a/vendor/guzzlehttp/guzzle/src/functions_include.php b/vendor/guzzlehttp/guzzle/src/functions_include.php index a93393a..394f953 100644 --- a/vendor/guzzlehttp/guzzle/src/functions_include.php +++ b/vendor/guzzlehttp/guzzle/src/functions_include.php @@ -1,6 +1,6 @@ <?php // Don't redefine the functions if included multiple times. -if (!function_exists('GuzzleHttp\uri_template')) { - require __DIR__ . '/functions.php'; +if (!\function_exists('GuzzleHttp\describe_type')) { + require __DIR__.'/functions.php'; } diff --git a/vendor/guzzlehttp/promises/CHANGELOG.md b/vendor/guzzlehttp/promises/CHANGELOG.md index 551929f..ab173ad 100644 --- a/vendor/guzzlehttp/promises/CHANGELOG.md +++ b/vendor/guzzlehttp/promises/CHANGELOG.md @@ -1,6 +1,79 @@ # CHANGELOG +## 2.0.0 - TBC + +### Added + +- Added PHP 7 type hints + +### Changed + +- All previously non-final non-exception classes have been marked as soft-final + +### Removed + +- Dropped PHP < 7.2 support +- All functions in the `GuzzleHttp\Promise` namespace + + +## 1.5.3 - 2023-05-21 + +### Changed + +- Removed remaining usage of deprecated functions + + +## 1.5.2 - 2022-08-07 + +### Changed + +- Officially support PHP 8.2 + + +## 1.5.1 - 2021-10-22 + +### Fixed + +- Revert "Call handler when waiting on fulfilled/rejected Promise" +- Fix pool memory leak when empty array of promises provided + + +## 1.5.0 - 2021-10-07 + +### Changed + +- Call handler when waiting on fulfilled/rejected Promise +- Officially support PHP 8.1 + +### Fixed + +- Fix manually settle promises generated with `Utils::task` + + +## 1.4.1 - 2021-02-18 + +### Fixed + +- Fixed `each_limit` skipping promises and failing + + +## 1.4.0 - 2020-09-30 + +### Added + +- Support for PHP 8 +- Optional `$recursive` flag to `all` +- Replaced functions by static methods + +### Fixed + +- Fix empty `each` processing +- Fix promise handling for Iterators of non-unique keys +- Fixed `method_exists` crashes on PHP 8 +- Memory leak on exceptions + + ## 1.3.1 - 2016-12-20 ### Fixed diff --git a/vendor/guzzlehttp/promises/LICENSE b/vendor/guzzlehttp/promises/LICENSE index 67f91a1..9f0f943 100644 --- a/vendor/guzzlehttp/promises/LICENSE +++ b/vendor/guzzlehttp/promises/LICENSE @@ -1,4 +1,9 @@ -Copyright (c) 2015-2016 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com> +The MIT License (MIT) + +Copyright (c) 2015 Michael Dowling <mtdowling@gmail.com> +Copyright (c) 2015 Graham Campbell <hello@gjcampbell.co.uk> +Copyright (c) 2017 Tobias Schultze <webmaster@tubo-world.de> +Copyright (c) 2020 Tobias Nyholm <tobias.nyholm@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/guzzlehttp/promises/Makefile b/vendor/guzzlehttp/promises/Makefile deleted file mode 100644 index 8d5b3ef..0000000 --- a/vendor/guzzlehttp/promises/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -all: clean test - -test: - vendor/bin/phpunit - -coverage: - vendor/bin/phpunit --coverage-html=artifacts/coverage - -view-coverage: - open artifacts/coverage/index.html - -clean: - rm -rf artifacts/* diff --git a/vendor/guzzlehttp/promises/README.md b/vendor/guzzlehttp/promises/README.md index 7b607e2..4dc7b6a 100644 --- a/vendor/guzzlehttp/promises/README.md +++ b/vendor/guzzlehttp/promises/README.md @@ -17,7 +17,7 @@ for a general introduction to promises. - [Implementation notes](#implementation-notes) -# Features +## Features - [Promises/A+](https://promisesaplus.com/) implementation. - Promise resolution and chaining is handled iteratively, allowing for @@ -26,18 +26,32 @@ for a general introduction to promises. - Promises can be cancelled. - Works with any object that has a `then` function. - C# style async/await coroutine promises using - `GuzzleHttp\Promise\coroutine()`. + `GuzzleHttp\Promise\Coroutine::of()`. -# Quick start +## Installation + +```shell +composer require guzzlehttp/promises +``` + + +## Version Guidance + +| Version | Status | PHP Version | +|---------|------------------------|--------------| +| 1.x | Bug and security fixes | >=5.5,<8.3 | +| 2.x | Latest | >=7.2.5,<8.3 | + + +## Quick Start A *promise* represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its `then` method, which registers callbacks to receive either a promise's eventual value or the reason why the promise cannot be fulfilled. - -## Callbacks +### Callbacks Callbacks are registered with the `then` method by providing an optional `$onFulfilled` followed by an optional `$onRejected` function. @@ -60,12 +74,11 @@ $promise->then( ``` *Resolving* a promise means that you either fulfill a promise with a *value* or -reject a promise with a *reason*. Resolving a promises triggers callbacks -registered with the promises's `then` method. These callbacks are triggered +reject a promise with a *reason*. Resolving a promise triggers callbacks +registered with the promise's `then` method. These callbacks are triggered only once and in the order in which they were added. - -## Resolving a promise +### Resolving a Promise Promises are fulfilled using the `resolve($value)` method. Resolving a promise with any value other than a `GuzzleHttp\Promise\RejectedPromise` will trigger @@ -88,12 +101,11 @@ $promise }); // Resolving the promise triggers the $onFulfilled callbacks and outputs -// "Hello, reader". +// "Hello, reader." $promise->resolve('reader.'); ``` - -## Promise forwarding +### Promise Forwarding Promises can be chained one after the other. Each then in the chain is a new promise. The return value of a promise is what's forwarded to the next @@ -123,7 +135,7 @@ $promise->resolve('A'); $nextPromise->resolve('B'); ``` -## Promise rejection +### Promise Rejection When a promise is rejected, the `$onRejected` callbacks are invoked with the rejection reason. @@ -140,7 +152,7 @@ $promise->reject('Error!'); // Outputs "Error!" ``` -## Rejection forwarding +### Rejection Forwarding If an exception is thrown in an `$onRejected` callback, subsequent `$onRejected` callbacks are invoked with the thrown exception as the reason. @@ -150,7 +162,7 @@ use GuzzleHttp\Promise\Promise; $promise = new Promise(); $promise->then(null, function ($reason) { - throw new \Exception($reason); + throw new Exception($reason); })->then(null, function ($reason) { assert($reason->getMessage() === 'Error!'); }); @@ -182,7 +194,6 @@ invoked using the value returned from the `$onRejected` callback. ```php use GuzzleHttp\Promise\Promise; -use GuzzleHttp\Promise\RejectedPromise; $promise = new Promise(); $promise @@ -196,7 +207,8 @@ $promise $promise->reject('Error!'); ``` -# Synchronous wait + +## Synchronous Wait You can synchronously force promises to complete using a promise's `wait` method. When creating a promise, you can provide a wait function that is used @@ -220,7 +232,7 @@ the promise is rejected with the exception and the exception is thrown. ```php $promise = new Promise(function () use (&$promise) { - throw new \Exception('foo'); + throw new Exception('foo'); }); $promise->wait(); // throws the exception. @@ -248,8 +260,7 @@ $promise->wait(); > PHP Fatal error: Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo' - -## Unwrapping a promise +### Unwrapping a Promise When synchronously waiting on a promise, you are joining the state of the promise into the current state of execution (i.e., return the value of the @@ -276,7 +287,7 @@ wait function will be the value delivered to promise B. **Note**: when you do not unwrap the promise, no value is returned. -# Cancellation +## Cancellation You can cancel a promise that has not yet been fulfilled using the `cancel()` method of a promise. When creating a promise you can provide an optional @@ -284,10 +295,9 @@ cancel function that when invoked cancels the action of computing a resolution of the promise. -# API - +## API -## Promise +### Promise When creating a promise object, you can provide an optional `$waitFn` and `$cancelFn`. `$waitFn` is a function that is invoked with no arguments and is @@ -350,7 +360,7 @@ A promise has the following methods: Rejects the promise with the given `$reason`. -## FulfilledPromise +### FulfilledPromise A fulfilled promise can be created to represent a promise that has been fulfilled. @@ -367,7 +377,7 @@ $promise->then(function ($value) { ``` -## RejectedPromise +### RejectedPromise A rejected promise can be created to represent a promise that has been rejected. @@ -384,7 +394,7 @@ $promise->then(null, function ($reason) { ``` -# Promise interop +## Promise Interoperability This library works with foreign promises that have a `then` method. This means you can use Guzzle promises with [React promises](https://github.com/reactphp/promise) @@ -397,7 +407,7 @@ $deferred = new React\Promise\Deferred(); $reactPromise = $deferred->promise(); // Create a Guzzle promise that is fulfilled with a React promise. -$guzzlePromise = new \GuzzleHttp\Promise\Promise(); +$guzzlePromise = new GuzzleHttp\Promise\Promise(); $guzzlePromise->then(function ($value) use ($reactPromise) { // Do something something with the value... // Return the React promise @@ -410,7 +420,7 @@ a foreign promise. You will need to wrap a third-party promise with a Guzzle promise in order to utilize wait and cancel functions with foreign promises. -## Event Loop Integration +### Event Loop Integration In order to keep the stack size constant, Guzzle promises are resolved asynchronously using a task queue. When waiting on promises synchronously, the @@ -424,7 +434,7 @@ instance. ```php // Get the global task queue -$queue = \GuzzleHttp\Promise\queue(); +$queue = GuzzleHttp\Promise\Utils::queue(); $queue->run(); ``` @@ -435,13 +445,10 @@ $loop = React\EventLoop\Factory::create(); $loop->addPeriodicTimer(0, [$queue, 'run']); ``` -*TODO*: Perhaps adding a `futureTick()` on each tick would be faster? - - -# Implementation notes +## Implementation Notes -## Promise resolution and chaining is handled iteratively +### Promise Resolution and Chaining is Handled Iteratively By shuffling pending handlers from one owner to another, promises are resolved iteratively, allowing for "infinite" then chaining. @@ -477,8 +484,7 @@ all of its pending handlers to the new promise. When the new promise is eventually resolved, all of the pending handlers are delivered the forwarded value. - -## A promise is the deferred. +### A Promise is the Deferred Some promise libraries implement promises using a deferred object to represent a computation and a promise object to represent the delivery of the result of @@ -502,3 +508,52 @@ $promise->then(function ($value) { echo $value; }); $promise->resolve('foo'); // prints "foo" ``` + + +## Upgrading from Function API + +A static API was first introduced in 1.4.0, in order to mitigate problems with +functions conflicting between global and local copies of the package. The +function API was removed in 2.0.0. A migration table has been provided here for +your convenience: + +| Original Function | Replacement Method | +|----------------|----------------| +| `queue` | `Utils::queue` | +| `task` | `Utils::task` | +| `promise_for` | `Create::promiseFor` | +| `rejection_for` | `Create::rejectionFor` | +| `exception_for` | `Create::exceptionFor` | +| `iter_for` | `Create::iterFor` | +| `inspect` | `Utils::inspect` | +| `inspect_all` | `Utils::inspectAll` | +| `unwrap` | `Utils::unwrap` | +| `all` | `Utils::all` | +| `some` | `Utils::some` | +| `any` | `Utils::any` | +| `settle` | `Utils::settle` | +| `each` | `Each::of` | +| `each_limit` | `Each::ofLimit` | +| `each_limit_all` | `Each::ofLimitAll` | +| `!is_fulfilled` | `Is::pending` | +| `is_fulfilled` | `Is::fulfilled` | +| `is_rejected` | `Is::rejected` | +| `is_settled` | `Is::settled` | +| `coroutine` | `Coroutine::of` | + + +## Security + +If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/promises/security/policy) for more information. + + +## License + +Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information. + + +## For Enterprise + +Available as part of the Tidelift Subscription + +The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-promises?utm_source=packagist-guzzlehttp-promises&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) diff --git a/vendor/guzzlehttp/promises/composer.json b/vendor/guzzlehttp/promises/composer.json index ec41a61..fc1989e 100644 --- a/vendor/guzzlehttp/promises/composer.json +++ b/vendor/guzzlehttp/promises/composer.json @@ -4,31 +4,55 @@ "keywords": ["promise"], "license": "MIT", "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], "require": { - "php": ">=5.5.0" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.0" + "bamarni/composer-bin-plugin": "^1.8.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" }, "autoload": { "psr-4": { "GuzzleHttp\\Promise\\": "src/" - }, - "files": ["src/functions_include.php"] + } }, - "scripts": { - "test": "vendor/bin/phpunit", - "test-ci": "vendor/bin/phpunit --coverage-text" + "autoload-dev": { + "psr-4": { + "GuzzleHttp\\Promise\\Tests\\": "tests/" + } }, "extra": { - "branch-alias": { - "dev-master": "1.4-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } + }, + "config": { + "allow-plugins": { + "bamarni/composer-bin-plugin": true + }, + "preferred-install": "dist", + "sort-packages": true } } diff --git a/vendor/guzzlehttp/promises/src/AggregateException.php b/vendor/guzzlehttp/promises/src/AggregateException.php index 6a5690c..40ffdbc 100644 --- a/vendor/guzzlehttp/promises/src/AggregateException.php +++ b/vendor/guzzlehttp/promises/src/AggregateException.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; /** @@ -6,7 +9,7 @@ */ class AggregateException extends RejectionException { - public function __construct($msg, array $reasons) + public function __construct(string $msg, array $reasons) { parent::__construct( $reasons, diff --git a/vendor/guzzlehttp/promises/src/CancellationException.php b/vendor/guzzlehttp/promises/src/CancellationException.php index cb360b8..ad8f51d 100644 --- a/vendor/guzzlehttp/promises/src/CancellationException.php +++ b/vendor/guzzlehttp/promises/src/CancellationException.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; /** diff --git a/vendor/guzzlehttp/promises/src/Coroutine.php b/vendor/guzzlehttp/promises/src/Coroutine.php index 6aa0958..0b5b9c0 100644 --- a/vendor/guzzlehttp/promises/src/Coroutine.php +++ b/vendor/guzzlehttp/promises/src/Coroutine.php @@ -1,7 +1,9 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; -use Exception; use Generator; use Throwable; @@ -9,7 +11,7 @@ * Creates a promise that is resolved using a generator that yields values or * promises (somewhat similar to C#'s async keyword). * - * When called, the coroutine function will start an instance of the generator + * When called, the Coroutine::of method will start an instance of the generator * and returns a promise that is fulfilled with its final yielded value. * * Control is returned back to the generator when the yielded promise settles. @@ -22,11 +24,11 @@ * return new Promise\FulfilledPromise($value); * } * - * $promise = Promise\coroutine(function () { + * $promise = Promise\Coroutine::of(function () { * $value = (yield createPromise('a')); * try { * $value = (yield createPromise($value . 'b')); - * } catch (\Exception $e) { + * } catch (\Throwable $e) { * // The promise was rejected. * } * yield $value . 'c'; @@ -38,7 +40,8 @@ * @param callable $generatorFn Generator function to wrap into a promise. * * @return Promise - * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration + * + * @see https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration */ final class Coroutine implements PromiseInterface { @@ -60,62 +63,74 @@ final class Coroutine implements PromiseInterface public function __construct(callable $generatorFn) { $this->generator = $generatorFn(); - $this->result = new Promise(function () { + $this->result = new Promise(function (): void { while (isset($this->currentPromise)) { $this->currentPromise->wait(); } }); - $this->nextCoroutine($this->generator->current()); + try { + $this->nextCoroutine($this->generator->current()); + } catch (Throwable $throwable) { + $this->result->reject($throwable); + } + } + + /** + * Create a new coroutine. + */ + public static function of(callable $generatorFn): self + { + return new self($generatorFn); } public function then( callable $onFulfilled = null, callable $onRejected = null - ) { + ): PromiseInterface { return $this->result->then($onFulfilled, $onRejected); } - public function otherwise(callable $onRejected) + public function otherwise(callable $onRejected): PromiseInterface { return $this->result->otherwise($onRejected); } - public function wait($unwrap = true) + public function wait(bool $unwrap = true) { return $this->result->wait($unwrap); } - public function getState() + public function getState(): string { return $this->result->getState(); } - public function resolve($value) + public function resolve($value): void { $this->result->resolve($value); } - public function reject($reason) + public function reject($reason): void { $this->result->reject($reason); } - public function cancel() + public function cancel(): void { $this->currentPromise->cancel(); $this->result->cancel(); } - private function nextCoroutine($yielded) + private function nextCoroutine($yielded): void { - $this->currentPromise = promise_for($yielded) + $this->currentPromise = Create::promiseFor($yielded) ->then([$this, '_handleSuccess'], [$this, '_handleFailure']); } /** * @internal */ - public function _handleSuccess($value) + public function _handleSuccess($value): void { unset($this->currentPromise); try { @@ -125,8 +140,6 @@ public function _handleSuccess($value) } else { $this->result->resolve($value); } - } catch (Exception $exception) { - $this->result->reject($exception); } catch (Throwable $throwable) { $this->result->reject($throwable); } @@ -135,15 +148,13 @@ public function _handleSuccess($value) /** * @internal */ - public function _handleFailure($reason) + public function _handleFailure($reason): void { unset($this->currentPromise); try { - $nextYield = $this->generator->throw(exception_for($reason)); + $nextYield = $this->generator->throw(Create::exceptionFor($reason)); // The throw was caught, so keep iterating on the coroutine $this->nextCoroutine($nextYield); - } catch (Exception $exception) { - $this->result->reject($exception); } catch (Throwable $throwable) { $this->result->reject($throwable); } diff --git a/vendor/guzzlehttp/promises/src/Create.php b/vendor/guzzlehttp/promises/src/Create.php new file mode 100644 index 0000000..9d3fc4a --- /dev/null +++ b/vendor/guzzlehttp/promises/src/Create.php @@ -0,0 +1,79 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Promise; + +final class Create +{ + /** + * Creates a promise for a value if the value is not a promise. + * + * @param mixed $value Promise or value. + */ + public static function promiseFor($value): PromiseInterface + { + if ($value instanceof PromiseInterface) { + return $value; + } + + // Return a Guzzle promise that shadows the given promise. + if (is_object($value) && method_exists($value, 'then')) { + $wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null; + $cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null; + $promise = new Promise($wfn, $cfn); + $value->then([$promise, 'resolve'], [$promise, 'reject']); + + return $promise; + } + + return new FulfilledPromise($value); + } + + /** + * Creates a rejected promise for a reason if the reason is not a promise. + * If the provided reason is a promise, then it is returned as-is. + * + * @param mixed $reason Promise or reason. + */ + public static function rejectionFor($reason): PromiseInterface + { + if ($reason instanceof PromiseInterface) { + return $reason; + } + + return new RejectedPromise($reason); + } + + /** + * Create an exception for a rejected promise value. + * + * @param mixed $reason + */ + public static function exceptionFor($reason): \Throwable + { + if ($reason instanceof \Throwable) { + return $reason; + } + + return new RejectionException($reason); + } + + /** + * Returns an iterator for the given value. + * + * @param mixed $value + */ + public static function iterFor($value): \Iterator + { + if ($value instanceof \Iterator) { + return $value; + } + + if (is_array($value)) { + return new \ArrayIterator($value); + } + + return new \ArrayIterator([$value]); + } +} diff --git a/vendor/guzzlehttp/promises/src/Each.php b/vendor/guzzlehttp/promises/src/Each.php new file mode 100644 index 0000000..1a7aa0f --- /dev/null +++ b/vendor/guzzlehttp/promises/src/Each.php @@ -0,0 +1,86 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Promise; + +final class Each +{ + /** + * Given an iterator that yields promises or values, returns a promise that + * is fulfilled with a null value when the iterator has been consumed or + * the aggregate promise has been fulfilled or rejected. + * + * $onFulfilled is a function that accepts the fulfilled value, iterator + * index, and the aggregate promise. The callback can invoke any necessary + * side effects and choose to resolve or reject the aggregate if needed. + * + * $onRejected is a function that accepts the rejection reason, iterator + * index, and the aggregate promise. The callback can invoke any necessary + * side effects and choose to resolve or reject the aggregate if needed. + * + * @param mixed $iterable Iterator or array to iterate over. + * @param callable $onFulfilled + * @param callable $onRejected + */ + public static function of( + $iterable, + callable $onFulfilled = null, + callable $onRejected = null + ): PromiseInterface { + return (new EachPromise($iterable, [ + 'fulfilled' => $onFulfilled, + 'rejected' => $onRejected, + ]))->promise(); + } + + /** + * Like of, but only allows a certain number of outstanding promises at any + * given time. + * + * $concurrency may be an integer or a function that accepts the number of + * pending promises and returns a numeric concurrency limit value to allow + * for dynamic a concurrency size. + * + * @param mixed $iterable + * @param int|callable $concurrency + * @param callable $onFulfilled + * @param callable $onRejected + */ + public static function ofLimit( + $iterable, + $concurrency, + callable $onFulfilled = null, + callable $onRejected = null + ): PromiseInterface { + return (new EachPromise($iterable, [ + 'fulfilled' => $onFulfilled, + 'rejected' => $onRejected, + 'concurrency' => $concurrency, + ]))->promise(); + } + + /** + * Like limit, but ensures that no promise in the given $iterable argument + * is rejected. If any promise is rejected, then the aggregate promise is + * rejected with the encountered rejection. + * + * @param mixed $iterable + * @param int|callable $concurrency + * @param callable $onFulfilled + */ + public static function ofLimitAll( + $iterable, + $concurrency, + callable $onFulfilled = null + ): PromiseInterface { + return self::ofLimit( + $iterable, + $concurrency, + $onFulfilled, + function ($reason, $idx, PromiseInterface $aggregate): void { + $aggregate->reject($reason); + } + ); + } +} diff --git a/vendor/guzzlehttp/promises/src/EachPromise.php b/vendor/guzzlehttp/promises/src/EachPromise.php index d0ddf60..28dd979 100644 --- a/vendor/guzzlehttp/promises/src/EachPromise.php +++ b/vendor/guzzlehttp/promises/src/EachPromise.php @@ -1,30 +1,37 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; /** * Represents a promise that iterates over many promises and invokes * side-effect functions in the process. + * + * @final */ class EachPromise implements PromisorInterface { private $pending = []; - /** @var \Iterator */ + private $nextPendingIndex = 0; + + /** @var \Iterator|null */ private $iterable; - /** @var callable|int */ + /** @var callable|int|null */ private $concurrency; - /** @var callable */ + /** @var callable|null */ private $onFulfilled; - /** @var callable */ + /** @var callable|null */ private $onRejected; - /** @var Promise */ + /** @var Promise|null */ private $aggregate; - /** @var bool */ + /** @var bool|null */ private $mutex; /** @@ -45,12 +52,12 @@ class EachPromise implements PromisorInterface * allowed number of outstanding concurrently executing promises, * creating a capped pool of promises. There is no limit by default. * - * @param mixed $iterable Promises or values to iterate. - * @param array $config Configuration options + * @param mixed $iterable Promises or values to iterate. + * @param array $config Configuration options */ public function __construct($iterable, array $config = []) { - $this->iterable = iter_for($iterable); + $this->iterable = Create::iterFor($iterable); if (isset($config['concurrency'])) { $this->concurrency = $config['concurrency']; @@ -65,7 +72,8 @@ public function __construct($iterable, array $config = []) } } - public function promise() + /** @psalm-suppress InvalidNullableReturnType */ + public function promise(): PromiseInterface { if ($this->aggregate) { return $this->aggregate; @@ -73,52 +81,55 @@ public function promise() try { $this->createPromise(); + /** @psalm-assert Promise $this->aggregate */ $this->iterable->rewind(); $this->refillPending(); } catch (\Throwable $e) { $this->aggregate->reject($e); - } catch (\Exception $e) { - $this->aggregate->reject($e); } + /** + * @psalm-suppress NullableReturnStatement + */ return $this->aggregate; } - private function createPromise() + private function createPromise(): void { $this->mutex = false; - $this->aggregate = new Promise(function () { - reset($this->pending); - if (empty($this->pending) && !$this->iterable->valid()) { - $this->aggregate->resolve(null); + $this->aggregate = new Promise(function (): void { + if ($this->checkIfFinished()) { return; } - + reset($this->pending); // Consume a potentially fluctuating list of promises while // ensuring that indexes are maintained (precluding array_shift). while ($promise = current($this->pending)) { next($this->pending); $promise->wait(); - if ($this->aggregate->getState() !== PromiseInterface::PENDING) { + if (Is::settled($this->aggregate)) { return; } } }); // Clear the references when the promise is resolved. - $clearFn = function () { + $clearFn = function (): void { $this->iterable = $this->concurrency = $this->pending = null; $this->onFulfilled = $this->onRejected = null; + $this->nextPendingIndex = 0; }; $this->aggregate->then($clearFn, $clearFn); } - private function refillPending() + private function refillPending(): void { if (!$this->concurrency) { // Add all pending promises. - while ($this->addPending() && $this->advanceIterator()); + while ($this->addPending() && $this->advanceIterator()) { + } + return; } @@ -139,31 +150,42 @@ private function refillPending() // next value to yield until promise callbacks are called. while (--$concurrency && $this->advanceIterator() - && $this->addPending()); + && $this->addPending()) { + } } - private function addPending() + private function addPending(): bool { if (!$this->iterable || !$this->iterable->valid()) { return false; } - $promise = promise_for($this->iterable->current()); - $idx = $this->iterable->key(); + $promise = Create::promiseFor($this->iterable->current()); + $key = $this->iterable->key(); + + // Iterable keys may not be unique, so we use a counter to + // guarantee uniqueness + $idx = $this->nextPendingIndex++; $this->pending[$idx] = $promise->then( - function ($value) use ($idx) { + function ($value) use ($idx, $key): void { if ($this->onFulfilled) { call_user_func( - $this->onFulfilled, $value, $idx, $this->aggregate + $this->onFulfilled, + $value, + $key, + $this->aggregate ); } $this->step($idx); }, - function ($reason) use ($idx) { + function ($reason) use ($idx, $key): void { if ($this->onRejected) { call_user_func( - $this->onRejected, $reason, $idx, $this->aggregate + $this->onRejected, + $reason, + $key, + $this->aggregate ); } $this->step($idx); @@ -173,7 +195,7 @@ function ($reason) use ($idx) { return true; } - private function advanceIterator() + private function advanceIterator(): bool { // Place a lock on the iterator so that we ensure to not recurse, // preventing fatal generator errors. @@ -186,22 +208,20 @@ private function advanceIterator() try { $this->iterable->next(); $this->mutex = false; + return true; } catch (\Throwable $e) { $this->aggregate->reject($e); $this->mutex = false; - return false; - } catch (\Exception $e) { - $this->aggregate->reject($e); - $this->mutex = false; + return false; } } - private function step($idx) + private function step(int $idx): void { // If the promise was already resolved, then ignore this step. - if ($this->aggregate->getState() !== PromiseInterface::PENDING) { + if (Is::settled($this->aggregate)) { return; } @@ -216,11 +236,12 @@ private function step($idx) } } - private function checkIfFinished() + private function checkIfFinished(): bool { if (!$this->pending && !$this->iterable->valid()) { // Resolve the promise if there's nothing left to do. $this->aggregate->resolve(null); + return true; } diff --git a/vendor/guzzlehttp/promises/src/FulfilledPromise.php b/vendor/guzzlehttp/promises/src/FulfilledPromise.php index dbbeeb9..ab71296 100644 --- a/vendor/guzzlehttp/promises/src/FulfilledPromise.php +++ b/vendor/guzzlehttp/promises/src/FulfilledPromise.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; /** @@ -6,16 +9,22 @@ * * Thenning off of this promise will invoke the onFulfilled callback * immediately and ignore other callbacks. + * + * @final */ class FulfilledPromise implements PromiseInterface { private $value; + /** + * @param mixed $value + */ public function __construct($value) { - if (method_exists($value, 'then')) { + if (is_object($value) && method_exists($value, 'then')) { throw new \InvalidArgumentException( - 'You cannot create a FulfilledPromise with a promise.'); + 'You cannot create a FulfilledPromise with a promise.' + ); } $this->value = $value; @@ -24,23 +33,21 @@ public function __construct($value) public function then( callable $onFulfilled = null, callable $onRejected = null - ) { + ): PromiseInterface { // Return itself if there is no onFulfilled function. if (!$onFulfilled) { return $this; } - $queue = queue(); + $queue = Utils::queue(); $p = new Promise([$queue, 'run']); $value = $this->value; - $queue->add(static function () use ($p, $value, $onFulfilled) { - if ($p->getState() === self::PENDING) { + $queue->add(static function () use ($p, $value, $onFulfilled): void { + if (Is::pending($p)) { try { $p->resolve($onFulfilled($value)); } catch (\Throwable $e) { $p->reject($e); - } catch (\Exception $e) { - $p->reject($e); } } }); @@ -48,34 +55,34 @@ public function then( return $p; } - public function otherwise(callable $onRejected) + public function otherwise(callable $onRejected): PromiseInterface { return $this->then(null, $onRejected); } - public function wait($unwrap = true, $defaultDelivery = null) + public function wait(bool $unwrap = true) { return $unwrap ? $this->value : null; } - public function getState() + public function getState(): string { return self::FULFILLED; } - public function resolve($value) + public function resolve($value): void { if ($value !== $this->value) { - throw new \LogicException("Cannot resolve a fulfilled promise"); + throw new \LogicException('Cannot resolve a fulfilled promise'); } } - public function reject($reason) + public function reject($reason): void { - throw new \LogicException("Cannot reject a fulfilled promise"); + throw new \LogicException('Cannot reject a fulfilled promise'); } - public function cancel() + public function cancel(): void { // pass } diff --git a/vendor/guzzlehttp/promises/src/Is.php b/vendor/guzzlehttp/promises/src/Is.php new file mode 100644 index 0000000..f3f0503 --- /dev/null +++ b/vendor/guzzlehttp/promises/src/Is.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Promise; + +final class Is +{ + /** + * Returns true if a promise is pending. + */ + public static function pending(PromiseInterface $promise): bool + { + return $promise->getState() === PromiseInterface::PENDING; + } + + /** + * Returns true if a promise is fulfilled or rejected. + */ + public static function settled(PromiseInterface $promise): bool + { + return $promise->getState() !== PromiseInterface::PENDING; + } + + /** + * Returns true if a promise is fulfilled. + */ + public static function fulfilled(PromiseInterface $promise): bool + { + return $promise->getState() === PromiseInterface::FULFILLED; + } + + /** + * Returns true if a promise is rejected. + */ + public static function rejected(PromiseInterface $promise): bool + { + return $promise->getState() === PromiseInterface::REJECTED; + } +} diff --git a/vendor/guzzlehttp/promises/src/Promise.php b/vendor/guzzlehttp/promises/src/Promise.php index 844ada0..1b07bdc 100644 --- a/vendor/guzzlehttp/promises/src/Promise.php +++ b/vendor/guzzlehttp/promises/src/Promise.php @@ -1,10 +1,15 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; /** * Promises/A+ implementation that avoids recursion when possible. * - * @link https://promisesaplus.com/ + * @see https://promisesaplus.com/ + * + * @final */ class Promise implements PromiseInterface { @@ -30,59 +35,57 @@ public function __construct( public function then( callable $onFulfilled = null, callable $onRejected = null - ) { + ): PromiseInterface { if ($this->state === self::PENDING) { $p = new Promise(null, [$this, 'cancel']); $this->handlers[] = [$p, $onFulfilled, $onRejected]; $p->waitList = $this->waitList; $p->waitList[] = $this; + return $p; } // Return a fulfilled promise and immediately invoke any callbacks. if ($this->state === self::FULFILLED) { - return $onFulfilled - ? promise_for($this->result)->then($onFulfilled) - : promise_for($this->result); + $promise = Create::promiseFor($this->result); + + return $onFulfilled ? $promise->then($onFulfilled) : $promise; } // It's either cancelled or rejected, so return a rejected promise // and immediately invoke any callbacks. - $rejection = rejection_for($this->result); + $rejection = Create::rejectionFor($this->result); + return $onRejected ? $rejection->then(null, $onRejected) : $rejection; } - public function otherwise(callable $onRejected) + public function otherwise(callable $onRejected): PromiseInterface { return $this->then(null, $onRejected); } - public function wait($unwrap = true) + public function wait(bool $unwrap = true) { $this->waitIfPending(); - $inner = $this->result instanceof PromiseInterface - ? $this->result->wait($unwrap) - : $this->result; - + if ($this->result instanceof PromiseInterface) { + return $this->result->wait($unwrap); + } if ($unwrap) { - if ($this->result instanceof PromiseInterface - || $this->state === self::FULFILLED - ) { - return $inner; - } else { - // It's rejected so "unwrap" and throw an exception. - throw exception_for($inner); + if ($this->state === self::FULFILLED) { + return $this->result; } + // It's rejected so "unwrap" and throw an exception. + throw Create::exceptionFor($this->result); } } - public function getState() + public function getState(): string { return $this->state; } - public function cancel() + public function cancel(): void { if ($this->state !== self::PENDING) { return; @@ -97,28 +100,27 @@ public function cancel() $fn(); } catch (\Throwable $e) { $this->reject($e); - } catch (\Exception $e) { - $this->reject($e); } } // Reject the promise only if it wasn't rejected in a then callback. + /** @psalm-suppress RedundantCondition */ if ($this->state === self::PENDING) { $this->reject(new CancellationException('Promise has been cancelled')); } } - public function resolve($value) + public function resolve($value): void { $this->settle(self::FULFILLED, $value); } - public function reject($reason) + public function reject($reason): void { $this->settle(self::REJECTED, $reason); } - private function settle($state, $value) + private function settle(string $state, $value): void { if ($this->state !== self::PENDING) { // Ignore calls with the same resolution. @@ -148,28 +150,26 @@ private function settle($state, $value) // If the value was not a settled promise or a thenable, then resolve // it in the task queue using the correct ID. - if (!method_exists($value, 'then')) { + if (!is_object($value) || !method_exists($value, 'then')) { $id = $state === self::FULFILLED ? 1 : 2; // It's a success, so resolve the handlers in the queue. - queue()->add(static function () use ($id, $value, $handlers) { + Utils::queue()->add(static function () use ($id, $value, $handlers): void { foreach ($handlers as $handler) { self::callHandler($id, $value, $handler); } }); - } elseif ($value instanceof Promise - && $value->getState() === self::PENDING - ) { + } elseif ($value instanceof Promise && Is::pending($value)) { // We can just merge our handlers onto the next promise. $value->handlers = array_merge($value->handlers, $handlers); } else { // Resolve the handlers when the forwarded promise is resolved. $value->then( - static function ($value) use ($handlers) { + static function ($value) use ($handlers): void { foreach ($handlers as $handler) { self::callHandler(1, $value, $handler); } }, - static function ($reason) use ($handlers) { + static function ($reason) use ($handlers): void { foreach ($handlers as $handler) { self::callHandler(2, $reason, $handler); } @@ -184,23 +184,29 @@ static function ($reason) use ($handlers) { * @param int $index 1 (resolve) or 2 (reject). * @param mixed $value Value to pass to the callback. * @param array $handler Array of handler data (promise and callbacks). - * - * @return array Returns the next group to resolve. */ - private static function callHandler($index, $value, array $handler) + private static function callHandler(int $index, $value, array $handler): void { /** @var PromiseInterface $promise */ $promise = $handler[0]; // The promise may have been cancelled or resolved before placing // this thunk in the queue. - if ($promise->getState() !== self::PENDING) { + if (Is::settled($promise)) { return; } try { if (isset($handler[$index])) { - $promise->resolve($handler[$index]($value)); + /* + * If $f throws an exception, then $handler will be in the exception + * stack trace. Since $handler contains a reference to the callable + * itself we get a circular reference. We clear the $handler + * here to avoid that memory leak. + */ + $f = $handler[$index]; + unset($handler); + $promise->resolve($f($value)); } elseif ($index === 1) { // Forward resolution values as-is. $promise->resolve($value); @@ -210,12 +216,10 @@ private static function callHandler($index, $value, array $handler) } } catch (\Throwable $reason) { $promise->reject($reason); - } catch (\Exception $reason) { - $promise->reject($reason); } } - private function waitIfPending() + private function waitIfPending(): void { if ($this->state !== self::PENDING) { return; @@ -224,27 +228,28 @@ private function waitIfPending() } elseif ($this->waitList) { $this->invokeWaitList(); } else { - // If there's not wait function, then reject the promise. + // If there's no wait function, then reject the promise. $this->reject('Cannot wait on a promise that has ' - . 'no internal wait function. You must provide a wait ' - . 'function when constructing the promise to be able to ' - . 'wait on a promise.'); + .'no internal wait function. You must provide a wait ' + .'function when constructing the promise to be able to ' + .'wait on a promise.'); } - queue()->run(); + Utils::queue()->run(); + /** @psalm-suppress RedundantCondition */ if ($this->state === self::PENDING) { $this->reject('Invoking the wait callback did not resolve the promise'); } } - private function invokeWaitFn() + private function invokeWaitFn(): void { try { $wfn = $this->waitFn; $this->waitFn = null; $wfn(true); - } catch (\Exception $reason) { + } catch (\Throwable $reason) { if ($this->state === self::PENDING) { // The promise has not been resolved yet, so reject the promise // with the exception. @@ -257,23 +262,19 @@ private function invokeWaitFn() } } - private function invokeWaitList() + private function invokeWaitList(): void { $waitList = $this->waitList; $this->waitList = null; foreach ($waitList as $result) { - while (true) { + do { $result->waitIfPending(); + $result = $result->result; + } while ($result instanceof Promise); - if ($result->result instanceof Promise) { - $result = $result->result; - } else { - if ($result->result instanceof PromiseInterface) { - $result->result->wait(false); - } - break; - } + if ($result instanceof PromiseInterface) { + $result->wait(false); } } } diff --git a/vendor/guzzlehttp/promises/src/PromiseInterface.php b/vendor/guzzlehttp/promises/src/PromiseInterface.php index 8f5f4b9..2824802 100644 --- a/vendor/guzzlehttp/promises/src/PromiseInterface.php +++ b/vendor/guzzlehttp/promises/src/PromiseInterface.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; /** @@ -8,13 +11,13 @@ * which registers callbacks to receive either a promise’s eventual value or * the reason why the promise cannot be fulfilled. * - * @link https://promisesaplus.com/ + * @see https://promisesaplus.com/ */ interface PromiseInterface { - const PENDING = 'pending'; - const FULFILLED = 'fulfilled'; - const REJECTED = 'rejected'; + public const PENDING = 'pending'; + public const FULFILLED = 'fulfilled'; + public const REJECTED = 'rejected'; /** * Appends fulfillment and rejection handlers to the promise, and returns @@ -22,13 +25,11 @@ interface PromiseInterface * * @param callable $onFulfilled Invoked when the promise fulfills. * @param callable $onRejected Invoked when the promise is rejected. - * - * @return PromiseInterface */ public function then( callable $onFulfilled = null, callable $onRejected = null - ); + ): PromiseInterface; /** * Appends a rejection handler callback to the promise, and returns a new @@ -37,43 +38,41 @@ public function then( * fulfilled. * * @param callable $onRejected Invoked when the promise is rejected. - * - * @return PromiseInterface */ - public function otherwise(callable $onRejected); + public function otherwise(callable $onRejected): PromiseInterface; /** * Get the state of the promise ("pending", "rejected", or "fulfilled"). * * The three states can be checked against the constants defined on * PromiseInterface: PENDING, FULFILLED, and REJECTED. - * - * @return string */ - public function getState(); + public function getState(): string; /** * Resolve the promise with the given value. * * @param mixed $value + * * @throws \RuntimeException if the promise is already resolved. */ - public function resolve($value); + public function resolve($value): void; /** * Reject the promise with the given reason. * * @param mixed $reason + * * @throws \RuntimeException if the promise is already resolved. */ - public function reject($reason); + public function reject($reason): void; /** * Cancels the promise if possible. * - * @link https://github.com/promises-aplus/cancellation-spec/issues/7 + * @see https://github.com/promises-aplus/cancellation-spec/issues/7 */ - public function cancel(); + public function cancel(): void; /** * Waits until the promise completes if possible. @@ -83,11 +82,10 @@ public function cancel(); * * If the promise cannot be waited on, then the promise will be rejected. * - * @param bool $unwrap - * * @return mixed + * * @throws \LogicException if the promise has no wait function or if the * promise does not settle after waiting. */ - public function wait($unwrap = true); + public function wait(bool $unwrap = true); } diff --git a/vendor/guzzlehttp/promises/src/PromisorInterface.php b/vendor/guzzlehttp/promises/src/PromisorInterface.php index b07fe32..5e8c512 100644 --- a/vendor/guzzlehttp/promises/src/PromisorInterface.php +++ b/vendor/guzzlehttp/promises/src/PromisorInterface.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; /** @@ -8,8 +11,6 @@ interface PromisorInterface { /** * Returns a promise. - * - * @return PromiseInterface */ - public function promise(); + public function promise(): PromiseInterface; } diff --git a/vendor/guzzlehttp/promises/src/RejectedPromise.php b/vendor/guzzlehttp/promises/src/RejectedPromise.php index 2bc6508..d947da1 100644 --- a/vendor/guzzlehttp/promises/src/RejectedPromise.php +++ b/vendor/guzzlehttp/promises/src/RejectedPromise.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; /** @@ -6,16 +9,22 @@ * * Thenning off of this promise will invoke the onRejected callback * immediately and ignore other callbacks. + * + * @final */ class RejectedPromise implements PromiseInterface { private $reason; + /** + * @param mixed $reason + */ public function __construct($reason) { - if (method_exists($reason, 'then')) { + if (is_object($reason) && method_exists($reason, 'then')) { throw new \InvalidArgumentException( - 'You cannot create a RejectedPromise with a promise.'); + 'You cannot create a RejectedPromise with a promise.' + ); } $this->reason = $reason; @@ -24,26 +33,23 @@ public function __construct($reason) public function then( callable $onFulfilled = null, callable $onRejected = null - ) { + ): PromiseInterface { // If there's no onRejected callback then just return self. if (!$onRejected) { return $this; } - $queue = queue(); + $queue = Utils::queue(); $reason = $this->reason; $p = new Promise([$queue, 'run']); - $queue->add(static function () use ($p, $reason, $onRejected) { - if ($p->getState() === self::PENDING) { + $queue->add(static function () use ($p, $reason, $onRejected): void { + if (Is::pending($p)) { try { // Return a resolved promise if onRejected does not throw. $p->resolve($onRejected($reason)); } catch (\Throwable $e) { // onRejected threw, so return a rejected promise. $p->reject($e); - } catch (\Exception $e) { - // onRejected threw, so return a rejected promise. - $p->reject($e); } } }); @@ -51,36 +57,38 @@ public function then( return $p; } - public function otherwise(callable $onRejected) + public function otherwise(callable $onRejected): PromiseInterface { return $this->then(null, $onRejected); } - public function wait($unwrap = true, $defaultDelivery = null) + public function wait(bool $unwrap = true) { if ($unwrap) { - throw exception_for($this->reason); + throw Create::exceptionFor($this->reason); } + + return null; } - public function getState() + public function getState(): string { return self::REJECTED; } - public function resolve($value) + public function resolve($value): void { - throw new \LogicException("Cannot resolve a rejected promise"); + throw new \LogicException('Cannot resolve a rejected promise'); } - public function reject($reason) + public function reject($reason): void { if ($reason !== $this->reason) { - throw new \LogicException("Cannot reject a rejected promise"); + throw new \LogicException('Cannot reject a rejected promise'); } } - public function cancel() + public function cancel(): void { // pass } diff --git a/vendor/guzzlehttp/promises/src/RejectionException.php b/vendor/guzzlehttp/promises/src/RejectionException.php index 07c1136..0db98ff 100644 --- a/vendor/guzzlehttp/promises/src/RejectionException.php +++ b/vendor/guzzlehttp/promises/src/RejectionException.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; /** @@ -12,8 +15,8 @@ class RejectionException extends \RuntimeException private $reason; /** - * @param mixed $reason Rejection reason. - * @param string $description Optional description + * @param mixed $reason Rejection reason. + * @param string|null $description Optional description. */ public function __construct($reason, $description = null) { @@ -22,14 +25,13 @@ public function __construct($reason, $description = null) $message = 'The promise was rejected'; if ($description) { - $message .= ' with reason: ' . $description; + $message .= ' with reason: '.$description; } elseif (is_string($reason) || (is_object($reason) && method_exists($reason, '__toString')) ) { - $message .= ' with reason: ' . $this->reason; + $message .= ' with reason: '.$this->reason; } elseif ($reason instanceof \JsonSerializable) { - $message .= ' with reason: ' - . json_encode($this->reason, JSON_PRETTY_PRINT); + $message .= ' with reason: '.json_encode($this->reason, JSON_PRETTY_PRINT); } parent::__construct($message); diff --git a/vendor/guzzlehttp/promises/src/TaskQueue.php b/vendor/guzzlehttp/promises/src/TaskQueue.php index 6e8a2a0..503e0b2 100644 --- a/vendor/guzzlehttp/promises/src/TaskQueue.php +++ b/vendor/guzzlehttp/promises/src/TaskQueue.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; /** @@ -8,17 +11,19 @@ * maintains a constant stack size. You can use the task queue asynchronously * by calling the `run()` function of the global task queue in an event loop. * - * GuzzleHttp\Promise\queue()->run(); + * GuzzleHttp\Promise\Utils::queue()->run(); + * + * @final */ class TaskQueue implements TaskQueueInterface { private $enableShutdown = true; private $queue = []; - public function __construct($withShutdown = true) + public function __construct(bool $withShutdown = true) { if ($withShutdown) { - register_shutdown_function(function () { + register_shutdown_function(function (): void { if ($this->enableShutdown) { // Only run the tasks if an E_ERROR didn't occur. $err = error_get_last(); @@ -30,20 +35,20 @@ public function __construct($withShutdown = true) } } - public function isEmpty() + public function isEmpty(): bool { return !$this->queue; } - public function add(callable $task) + public function add(callable $task): void { $this->queue[] = $task; } - public function run() + public function run(): void { - /** @var callable $task */ while ($task = array_shift($this->queue)) { + /** @var callable $task */ $task(); } } @@ -59,7 +64,7 @@ public function run() * * Note: This shutdown will occur before any destructors are triggered. */ - public function disableShutdown() + public function disableShutdown(): void { $this->enableShutdown = false; } diff --git a/vendor/guzzlehttp/promises/src/TaskQueueInterface.php b/vendor/guzzlehttp/promises/src/TaskQueueInterface.php index ac8306e..34c561a 100644 --- a/vendor/guzzlehttp/promises/src/TaskQueueInterface.php +++ b/vendor/guzzlehttp/promises/src/TaskQueueInterface.php @@ -1,25 +1,24 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Promise; interface TaskQueueInterface { /** * Returns true if the queue is empty. - * - * @return bool */ - public function isEmpty(); + public function isEmpty(): bool; /** * Adds a task to the queue that will be executed the next time run is * called. - * - * @param callable $task */ - public function add(callable $task); + public function add(callable $task): void; /** * Execute all of the pending task in the queue. */ - public function run(); + public function run(): void; } diff --git a/vendor/guzzlehttp/promises/src/Utils.php b/vendor/guzzlehttp/promises/src/Utils.php new file mode 100644 index 0000000..e1570d7 --- /dev/null +++ b/vendor/guzzlehttp/promises/src/Utils.php @@ -0,0 +1,259 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Promise; + +final class Utils +{ + /** + * Get the global task queue used for promise resolution. + * + * This task queue MUST be run in an event loop in order for promises to be + * settled asynchronously. It will be automatically run when synchronously + * waiting on a promise. + * + * <code> + * while ($eventLoop->isRunning()) { + * GuzzleHttp\Promise\Utils::queue()->run(); + * } + * </code> + * + * @param TaskQueueInterface|null $assign Optionally specify a new queue instance. + */ + public static function queue(TaskQueueInterface $assign = null): TaskQueueInterface + { + static $queue; + + if ($assign) { + $queue = $assign; + } elseif (!$queue) { + $queue = new TaskQueue(); + } + + return $queue; + } + + /** + * Adds a function to run in the task queue when it is next `run()` and + * returns a promise that is fulfilled or rejected with the result. + * + * @param callable $task Task function to run. + */ + public static function task(callable $task): PromiseInterface + { + $queue = self::queue(); + $promise = new Promise([$queue, 'run']); + $queue->add(function () use ($task, $promise): void { + try { + if (Is::pending($promise)) { + $promise->resolve($task()); + } + } catch (\Throwable $e) { + $promise->reject($e); + } + }); + + return $promise; + } + + /** + * Synchronously waits on a promise to resolve and returns an inspection + * state array. + * + * Returns a state associative array containing a "state" key mapping to a + * valid promise state. If the state of the promise is "fulfilled", the + * array will contain a "value" key mapping to the fulfilled value of the + * promise. If the promise is rejected, the array will contain a "reason" + * key mapping to the rejection reason of the promise. + * + * @param PromiseInterface $promise Promise or value. + */ + public static function inspect(PromiseInterface $promise): array + { + try { + return [ + 'state' => PromiseInterface::FULFILLED, + 'value' => $promise->wait(), + ]; + } catch (RejectionException $e) { + return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()]; + } catch (\Throwable $e) { + return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; + } + } + + /** + * Waits on all of the provided promises, but does not unwrap rejected + * promises as thrown exception. + * + * Returns an array of inspection state arrays. + * + * @see inspect for the inspection state array format. + * + * @param PromiseInterface[] $promises Traversable of promises to wait upon. + */ + public static function inspectAll($promises): array + { + $results = []; + foreach ($promises as $key => $promise) { + $results[$key] = self::inspect($promise); + } + + return $results; + } + + /** + * Waits on all of the provided promises and returns the fulfilled values. + * + * Returns an array that contains the value of each promise (in the same + * order the promises were provided). An exception is thrown if any of the + * promises are rejected. + * + * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on. + * + * @throws \Throwable on error + */ + public static function unwrap($promises): array + { + $results = []; + foreach ($promises as $key => $promise) { + $results[$key] = $promise->wait(); + } + + return $results; + } + + /** + * Given an array of promises, return a promise that is fulfilled when all + * the items in the array are fulfilled. + * + * The promise's fulfillment value is an array with fulfillment values at + * respective positions to the original array. If any promise in the array + * rejects, the returned promise is rejected with the rejection reason. + * + * @param mixed $promises Promises or values. + * @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution. + */ + public static function all($promises, bool $recursive = false): PromiseInterface + { + $results = []; + $promise = Each::of( + $promises, + function ($value, $idx) use (&$results): void { + $results[$idx] = $value; + }, + function ($reason, $idx, Promise $aggregate): void { + $aggregate->reject($reason); + } + )->then(function () use (&$results) { + ksort($results); + + return $results; + }); + + if (true === $recursive) { + $promise = $promise->then(function ($results) use ($recursive, &$promises) { + foreach ($promises as $promise) { + if (Is::pending($promise)) { + return self::all($promises, $recursive); + } + } + + return $results; + }); + } + + return $promise; + } + + /** + * Initiate a competitive race between multiple promises or values (values + * will become immediately fulfilled promises). + * + * When count amount of promises have been fulfilled, the returned promise + * is fulfilled with an array that contains the fulfillment values of the + * winners in order of resolution. + * + * This promise is rejected with a {@see AggregateException} if the number + * of fulfilled promises is less than the desired $count. + * + * @param int $count Total number of promises. + * @param mixed $promises Promises or values. + */ + public static function some(int $count, $promises): PromiseInterface + { + $results = []; + $rejections = []; + + return Each::of( + $promises, + function ($value, $idx, PromiseInterface $p) use (&$results, $count): void { + if (Is::settled($p)) { + return; + } + $results[$idx] = $value; + if (count($results) >= $count) { + $p->resolve(null); + } + }, + function ($reason) use (&$rejections): void { + $rejections[] = $reason; + } + )->then( + function () use (&$results, &$rejections, $count) { + if (count($results) !== $count) { + throw new AggregateException( + 'Not enough promises to fulfill count', + $rejections + ); + } + ksort($results); + + return array_values($results); + } + ); + } + + /** + * Like some(), with 1 as count. However, if the promise fulfills, the + * fulfillment value is not an array of 1 but the value directly. + * + * @param mixed $promises Promises or values. + */ + public static function any($promises): PromiseInterface + { + return self::some(1, $promises)->then(function ($values) { + return $values[0]; + }); + } + + /** + * Returns a promise that is fulfilled when all of the provided promises have + * been fulfilled or rejected. + * + * The returned promise is fulfilled with an array of inspection state arrays. + * + * @see inspect for the inspection state array format. + * + * @param mixed $promises Promises or values. + */ + public static function settle($promises): PromiseInterface + { + $results = []; + + return Each::of( + $promises, + function ($value, $idx) use (&$results): void { + $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value]; + }, + function ($reason, $idx) use (&$results): void { + $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason]; + } + )->then(function () use (&$results) { + ksort($results); + + return $results; + }); + } +} diff --git a/vendor/guzzlehttp/promises/src/functions.php b/vendor/guzzlehttp/promises/src/functions.php deleted file mode 100644 index 4e27709..0000000 --- a/vendor/guzzlehttp/promises/src/functions.php +++ /dev/null @@ -1,457 +0,0 @@ -<?php -namespace GuzzleHttp\Promise; - -/** - * Get the global task queue used for promise resolution. - * - * This task queue MUST be run in an event loop in order for promises to be - * settled asynchronously. It will be automatically run when synchronously - * waiting on a promise. - * - * <code> - * while ($eventLoop->isRunning()) { - * GuzzleHttp\Promise\queue()->run(); - * } - * </code> - * - * @param TaskQueueInterface $assign Optionally specify a new queue instance. - * - * @return TaskQueueInterface - */ -function queue(TaskQueueInterface $assign = null) -{ - static $queue; - - if ($assign) { - $queue = $assign; - } elseif (!$queue) { - $queue = new TaskQueue(); - } - - return $queue; -} - -/** - * Adds a function to run in the task queue when it is next `run()` and returns - * a promise that is fulfilled or rejected with the result. - * - * @param callable $task Task function to run. - * - * @return PromiseInterface - */ -function task(callable $task) -{ - $queue = queue(); - $promise = new Promise([$queue, 'run']); - $queue->add(function () use ($task, $promise) { - try { - $promise->resolve($task()); - } catch (\Throwable $e) { - $promise->reject($e); - } catch (\Exception $e) { - $promise->reject($e); - } - }); - - return $promise; -} - -/** - * Creates a promise for a value if the value is not a promise. - * - * @param mixed $value Promise or value. - * - * @return PromiseInterface - */ -function promise_for($value) -{ - if ($value instanceof PromiseInterface) { - return $value; - } - - // Return a Guzzle promise that shadows the given promise. - if (method_exists($value, 'then')) { - $wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null; - $cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null; - $promise = new Promise($wfn, $cfn); - $value->then([$promise, 'resolve'], [$promise, 'reject']); - return $promise; - } - - return new FulfilledPromise($value); -} - -/** - * Creates a rejected promise for a reason if the reason is not a promise. If - * the provided reason is a promise, then it is returned as-is. - * - * @param mixed $reason Promise or reason. - * - * @return PromiseInterface - */ -function rejection_for($reason) -{ - if ($reason instanceof PromiseInterface) { - return $reason; - } - - return new RejectedPromise($reason); -} - -/** - * Create an exception for a rejected promise value. - * - * @param mixed $reason - * - * @return \Exception|\Throwable - */ -function exception_for($reason) -{ - return $reason instanceof \Exception || $reason instanceof \Throwable - ? $reason - : new RejectionException($reason); -} - -/** - * Returns an iterator for the given value. - * - * @param mixed $value - * - * @return \Iterator - */ -function iter_for($value) -{ - if ($value instanceof \Iterator) { - return $value; - } elseif (is_array($value)) { - return new \ArrayIterator($value); - } else { - return new \ArrayIterator([$value]); - } -} - -/** - * Synchronously waits on a promise to resolve and returns an inspection state - * array. - * - * Returns a state associative array containing a "state" key mapping to a - * valid promise state. If the state of the promise is "fulfilled", the array - * will contain a "value" key mapping to the fulfilled value of the promise. If - * the promise is rejected, the array will contain a "reason" key mapping to - * the rejection reason of the promise. - * - * @param PromiseInterface $promise Promise or value. - * - * @return array - */ -function inspect(PromiseInterface $promise) -{ - try { - return [ - 'state' => PromiseInterface::FULFILLED, - 'value' => $promise->wait() - ]; - } catch (RejectionException $e) { - return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()]; - } catch (\Throwable $e) { - return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; - } catch (\Exception $e) { - return ['state' => PromiseInterface::REJECTED, 'reason' => $e]; - } -} - -/** - * Waits on all of the provided promises, but does not unwrap rejected promises - * as thrown exception. - * - * Returns an array of inspection state arrays. - * - * @param PromiseInterface[] $promises Traversable of promises to wait upon. - * - * @return array - * @see GuzzleHttp\Promise\inspect for the inspection state array format. - */ -function inspect_all($promises) -{ - $results = []; - foreach ($promises as $key => $promise) { - $results[$key] = inspect($promise); - } - - return $results; -} - -/** - * Waits on all of the provided promises and returns the fulfilled values. - * - * Returns an array that contains the value of each promise (in the same order - * the promises were provided). An exception is thrown if any of the promises - * are rejected. - * - * @param mixed $promises Iterable of PromiseInterface objects to wait on. - * - * @return array - * @throws \Exception on error - * @throws \Throwable on error in PHP >=7 - */ -function unwrap($promises) -{ - $results = []; - foreach ($promises as $key => $promise) { - $results[$key] = $promise->wait(); - } - - return $results; -} - -/** - * Given an array of promises, return a promise that is fulfilled when all the - * items in the array are fulfilled. - * - * The promise's fulfillment value is an array with fulfillment values at - * respective positions to the original array. If any promise in the array - * rejects, the returned promise is rejected with the rejection reason. - * - * @param mixed $promises Promises or values. - * - * @return PromiseInterface - */ -function all($promises) -{ - $results = []; - return each( - $promises, - function ($value, $idx) use (&$results) { - $results[$idx] = $value; - }, - function ($reason, $idx, Promise $aggregate) { - $aggregate->reject($reason); - } - )->then(function () use (&$results) { - ksort($results); - return $results; - }); -} - -/** - * Initiate a competitive race between multiple promises or values (values will - * become immediately fulfilled promises). - * - * When count amount of promises have been fulfilled, the returned promise is - * fulfilled with an array that contains the fulfillment values of the winners - * in order of resolution. - * - * This prommise is rejected with a {@see GuzzleHttp\Promise\AggregateException} - * if the number of fulfilled promises is less than the desired $count. - * - * @param int $count Total number of promises. - * @param mixed $promises Promises or values. - * - * @return PromiseInterface - */ -function some($count, $promises) -{ - $results = []; - $rejections = []; - - return each( - $promises, - function ($value, $idx, PromiseInterface $p) use (&$results, $count) { - if ($p->getState() !== PromiseInterface::PENDING) { - return; - } - $results[$idx] = $value; - if (count($results) >= $count) { - $p->resolve(null); - } - }, - function ($reason) use (&$rejections) { - $rejections[] = $reason; - } - )->then( - function () use (&$results, &$rejections, $count) { - if (count($results) !== $count) { - throw new AggregateException( - 'Not enough promises to fulfill count', - $rejections - ); - } - ksort($results); - return array_values($results); - } - ); -} - -/** - * Like some(), with 1 as count. However, if the promise fulfills, the - * fulfillment value is not an array of 1 but the value directly. - * - * @param mixed $promises Promises or values. - * - * @return PromiseInterface - */ -function any($promises) -{ - return some(1, $promises)->then(function ($values) { return $values[0]; }); -} - -/** - * Returns a promise that is fulfilled when all of the provided promises have - * been fulfilled or rejected. - * - * The returned promise is fulfilled with an array of inspection state arrays. - * - * @param mixed $promises Promises or values. - * - * @return PromiseInterface - * @see GuzzleHttp\Promise\inspect for the inspection state array format. - */ -function settle($promises) -{ - $results = []; - - return each( - $promises, - function ($value, $idx) use (&$results) { - $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value]; - }, - function ($reason, $idx) use (&$results) { - $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason]; - } - )->then(function () use (&$results) { - ksort($results); - return $results; - }); -} - -/** - * Given an iterator that yields promises or values, returns a promise that is - * fulfilled with a null value when the iterator has been consumed or the - * aggregate promise has been fulfilled or rejected. - * - * $onFulfilled is a function that accepts the fulfilled value, iterator - * index, and the aggregate promise. The callback can invoke any necessary side - * effects and choose to resolve or reject the aggregate promise if needed. - * - * $onRejected is a function that accepts the rejection reason, iterator - * index, and the aggregate promise. The callback can invoke any necessary side - * effects and choose to resolve or reject the aggregate promise if needed. - * - * @param mixed $iterable Iterator or array to iterate over. - * @param callable $onFulfilled - * @param callable $onRejected - * - * @return PromiseInterface - */ -function each( - $iterable, - callable $onFulfilled = null, - callable $onRejected = null -) { - return (new EachPromise($iterable, [ - 'fulfilled' => $onFulfilled, - 'rejected' => $onRejected - ]))->promise(); -} - -/** - * Like each, but only allows a certain number of outstanding promises at any - * given time. - * - * $concurrency may be an integer or a function that accepts the number of - * pending promises and returns a numeric concurrency limit value to allow for - * dynamic a concurrency size. - * - * @param mixed $iterable - * @param int|callable $concurrency - * @param callable $onFulfilled - * @param callable $onRejected - * - * @return PromiseInterface - */ -function each_limit( - $iterable, - $concurrency, - callable $onFulfilled = null, - callable $onRejected = null -) { - return (new EachPromise($iterable, [ - 'fulfilled' => $onFulfilled, - 'rejected' => $onRejected, - 'concurrency' => $concurrency - ]))->promise(); -} - -/** - * Like each_limit, but ensures that no promise in the given $iterable argument - * is rejected. If any promise is rejected, then the aggregate promise is - * rejected with the encountered rejection. - * - * @param mixed $iterable - * @param int|callable $concurrency - * @param callable $onFulfilled - * - * @return PromiseInterface - */ -function each_limit_all( - $iterable, - $concurrency, - callable $onFulfilled = null -) { - return each_limit( - $iterable, - $concurrency, - $onFulfilled, - function ($reason, $idx, PromiseInterface $aggregate) { - $aggregate->reject($reason); - } - ); -} - -/** - * Returns true if a promise is fulfilled. - * - * @param PromiseInterface $promise - * - * @return bool - */ -function is_fulfilled(PromiseInterface $promise) -{ - return $promise->getState() === PromiseInterface::FULFILLED; -} - -/** - * Returns true if a promise is rejected. - * - * @param PromiseInterface $promise - * - * @return bool - */ -function is_rejected(PromiseInterface $promise) -{ - return $promise->getState() === PromiseInterface::REJECTED; -} - -/** - * Returns true if a promise is fulfilled or rejected. - * - * @param PromiseInterface $promise - * - * @return bool - */ -function is_settled(PromiseInterface $promise) -{ - return $promise->getState() !== PromiseInterface::PENDING; -} - -/** - * @see Coroutine - * - * @param callable $generatorFn - * - * @return PromiseInterface - */ -function coroutine(callable $generatorFn) -{ - return new Coroutine($generatorFn); -} diff --git a/vendor/guzzlehttp/promises/src/functions_include.php b/vendor/guzzlehttp/promises/src/functions_include.php deleted file mode 100644 index 34cd171..0000000 --- a/vendor/guzzlehttp/promises/src/functions_include.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php - -// Don't redefine the functions if included multiple times. -if (!function_exists('GuzzleHttp\Promise\promise_for')) { - require __DIR__ . '/functions.php'; -} diff --git a/vendor/guzzlehttp/promises/vendor-bin/php-cs-fixer/composer.json b/vendor/guzzlehttp/promises/vendor-bin/php-cs-fixer/composer.json new file mode 100644 index 0000000..c9dd5ee --- /dev/null +++ b/vendor/guzzlehttp/promises/vendor-bin/php-cs-fixer/composer.json @@ -0,0 +1,9 @@ +{ + "require": { + "php": "^7.4 || ^8.0", + "friendsofphp/php-cs-fixer": "3.16.0" + }, + "config": { + "preferred-install": "dist" + } +} diff --git a/vendor/guzzlehttp/promises/vendor-bin/phpstan/composer.json b/vendor/guzzlehttp/promises/vendor-bin/phpstan/composer.json new file mode 100644 index 0000000..711507c --- /dev/null +++ b/vendor/guzzlehttp/promises/vendor-bin/phpstan/composer.json @@ -0,0 +1,10 @@ +{ + "require": { + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "1.10.11", + "phpstan/phpstan-deprecation-rules": "1.1.3" + }, + "config": { + "preferred-install": "dist" + } +} diff --git a/vendor/guzzlehttp/promises/vendor-bin/psalm/composer.json b/vendor/guzzlehttp/promises/vendor-bin/psalm/composer.json new file mode 100644 index 0000000..ab96f2c --- /dev/null +++ b/vendor/guzzlehttp/promises/vendor-bin/psalm/composer.json @@ -0,0 +1,9 @@ +{ + "require": { + "php": "^7.4 || ^8.0", + "psalm/phar": "5.9.0" + }, + "config": { + "preferred-install": "dist" + } +} diff --git a/vendor/guzzlehttp/psr7/CHANGELOG.md b/vendor/guzzlehttp/psr7/CHANGELOG.md index 5c252b3..fa716c0 100644 --- a/vendor/guzzlehttp/psr7/CHANGELOG.md +++ b/vendor/guzzlehttp/psr7/CHANGELOG.md @@ -1,32 +1,273 @@ -# CHANGELOG +# Change Log -## 1.4.2 - 2017-03-20 +All notable changes to this project will be documented in this file. -* Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Unreleased + +## 2.5.0 - 2023-04-17 + +### Changed + +- Adjusted `psr/http-message` version constraint to `^1.1 || ^2.0` + +## 2.4.5 - 2023-04-17 + +### Fixed + +- Prevent possible warnings on unset variables in `ServerRequest::normalizeNestedFileSpec` +- Fixed `Message::bodySummary` when `preg_match` fails +- Fixed header validation issue + +## 2.4.4 - 2023-03-09 + +### Changed + +- Removed the need for `AllowDynamicProperties` in `LazyOpenStream` + +## 2.4.3 - 2022-10-26 + +### Changed + +- Replaced `sha1(uniqid())` by `bin2hex(random_bytes(20))` + +## 2.4.2 - 2022-10-25 + +### Fixed + +- Fixed erroneous behaviour when combining host and relative path + +## 2.4.1 - 2022-08-28 + +### Fixed + +- Rewind body before reading in `Message::bodySummary` + +## 2.4.0 - 2022-06-20 + +### Added + +- Added provisional PHP 8.2 support +- Added `UriComparator::isCrossOrigin` method + +## 2.3.0 - 2022-06-09 + +### Fixed + +- Added `Header::splitList` method +- Added `Utils::tryGetContents` method +- Improved `Stream::getContents` method +- Updated mimetype mappings + +## 2.2.2 - 2022-06-08 + +### Fixed + +- Fix `Message::parseRequestUri` for numeric headers +- Re-wrap exceptions thrown in `fread` into runtime exceptions +- Throw an exception when multipart options is misformatted + +## 2.2.1 - 2022-03-20 + +### Fixed + +- Correct header value validation + +## 2.2.0 - 2022-03-20 + +### Added + +- A more compressive list of mime types +- Add JsonSerializable to Uri +- Missing return types + +### Fixed + +- Bug MultipartStream no `uri` metadata +- Bug MultipartStream with filename for `data://` streams +- Fixed new line handling in MultipartStream +- Reduced RAM usage when copying streams +- Updated parsing in `Header::normalize()` + +## 2.1.1 - 2022-03-20 + +### Fixed + +- Validate header values properly + +## 2.1.0 - 2021-10-06 + +### Changed + +- Attempting to create a `Uri` object from a malformed URI will no longer throw a generic + `InvalidArgumentException`, but rather a `MalformedUriException`, which inherits from the former + for backwards compatibility. Callers relying on the exception being thrown to detect invalid + URIs should catch the new exception. + +### Fixed + +- Return `null` in caching stream size if remote size is `null` + +## 2.0.0 - 2021-06-30 + +Identical to the RC release. + +## 2.0.0@RC-1 - 2021-04-29 + +### Fixed + +- Handle possibly unset `url` in `stream_get_meta_data` + +## 2.0.0@beta-1 - 2021-03-21 + +### Added + +- PSR-17 factories +- Made classes final +- PHP7 type hints + +### Changed + +- When building a query string, booleans are represented as 1 and 0. + +### Removed + +- PHP < 7.2 support +- All functions in the `GuzzleHttp\Psr7` namespace + +## 1.8.1 - 2021-03-21 + +### Fixed + +- Issue parsing IPv6 URLs +- Issue modifying ServerRequest lost all its attributes + +## 1.8.0 - 2021-03-21 + +### Added + +- Locale independent URL parsing +- Most classes got a `@final` annotation to prepare for 2.0 + +### Fixed + +- Issue when creating stream from `php://input` and curl-ext is not installed +- Broken `Utils::tryFopen()` on PHP 8 + +## 1.7.0 - 2020-09-30 + +### Added + +- Replaced functions by static methods + +### Fixed + +- Converting a non-seekable stream to a string +- Handle multiple Set-Cookie correctly +- Ignore array keys in header values when merging +- Allow multibyte characters to be parsed in `Message:bodySummary()` + +### Changed + +- Restored partial HHVM 3 support + + +## [1.6.1] - 2019-07-02 + +### Fixed + +- Accept null and bool header values again + + +## [1.6.0] - 2019-06-30 + +### Added + +- Allowed version `^3.0` of `ralouphie/getallheaders` dependency (#244) +- Added MIME type for WEBP image format (#246) +- Added more validation of values according to PSR-7 and RFC standards, e.g. status code range (#250, #272) + +### Changed + +- Tests don't pass with HHVM 4.0, so HHVM support got dropped. Other libraries like composer have done the same. (#262) +- Accept port number 0 to be valid (#270) + +### Fixed + +- Fixed subsequent reads from `php://input` in ServerRequest (#247) +- Fixed readable/writable detection for certain stream modes (#248) +- Fixed encoding of special characters in the `userInfo` component of an URI (#253) + + +## [1.5.2] - 2018-12-04 + +### Fixed + +- Check body size when getting the message summary + + +## [1.5.1] - 2018-12-04 + +### Fixed + +- Get the summary of a body only if it is readable + + +## [1.5.0] - 2018-12-03 + +### Added + +- Response first-line to response string exception (fixes #145) +- A test for #129 behavior +- `get_message_body_summary` function in order to get the message summary +- `3gp` and `mkv` mime types + +### Changed + +- Clarify exception message when stream is detached + +### Deprecated + +- Deprecated parsing folded header lines as per RFC 7230 + +### Fixed + +- Fix `AppendStream::detach` to not close streams +- `InflateStream` preserves `isSeekable` attribute of the underlying stream +- `ServerRequest::getUriFromGlobals` to support URLs in query parameters + + +Several other fixes and improvements. + + +## [1.4.2] - 2017-03-20 + +### Fixed + +- Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing calls to `trigger_error` when deprecated methods are invoked. -## 1.4.1 - 2017-02-27 -* Reverted BC break by reintroducing behavior to automagically fix a URI with a +## [1.4.1] - 2017-02-27 + +### Added + +- Rriggering of silenced deprecation warnings. + +### Fixed + +- Reverted BC break by reintroducing behavior to automagically fix a URI with a relative path and an authority by adding a leading slash to the path. It's only deprecated now. -* Added triggering of silenced deprecation warnings. -## 1.4.0 - 2017-02-21 -* Fix `Stream::read` when length parameter <= 0. -* `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory. -* Fix `ServerRequest::getUriFromGlobals` when `Host` header contains port. -* Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form. -* Allow `parse_response` to parse a response without delimiting space and reason. -* Ensure each URI modification results in a valid URI according to PSR-7 discussions. - Invalid modifications will throw an exception instead of returning a wrong URI or - doing some magic. - - `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception - because the path of a URI with an authority must start with a slash "/" or be empty - - `(new Uri())->withScheme('http')` will return `'http://localhost'` -* Fix compatibility of URIs with `file` scheme and empty host. -* Added common URI utility methods based on RFC 3986 (see documentation in the readme): +## [1.4.0] - 2017-02-21 + +### Added + +- Added common URI utility methods based on RFC 3986 (see documentation in the readme): - `Uri::isDefaultPort` - `Uri::isAbsolute` - `Uri::isNetworkPathReference` @@ -37,69 +278,117 @@ - `UriNormalizer::normalize` - `UriNormalizer::isEquivalent` - `UriResolver::relativize` -* Deprecated `Uri::resolve` in favor of `UriResolver::resolve` -* Deprecated `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments` -## 1.3.1 - 2016-06-25 +### Changed -* Fix `Uri::__toString` for network path references, e.g. `//example.org`. -* Fix missing lowercase normalization for host. -* Fix handling of URI components in case they are `'0'` in a lot of places, +- Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form. +- Allow `parse_response` to parse a response without delimiting space and reason. +- Ensure each URI modification results in a valid URI according to PSR-7 discussions. + Invalid modifications will throw an exception instead of returning a wrong URI or + doing some magic. + - `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception + because the path of a URI with an authority must start with a slash "/" or be empty + - `(new Uri())->withScheme('http')` will return `'http://localhost'` + +### Deprecated + +- `Uri::resolve` in favor of `UriResolver::resolve` +- `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments` + +### Fixed + +- `Stream::read` when length parameter <= 0. +- `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory. +- `ServerRequest::getUriFromGlobals` when `Host` header contains port. +- Compatibility of URIs with `file` scheme and empty host. + + +## [1.3.1] - 2016-06-25 + +### Fixed + +- `Uri::__toString` for network path references, e.g. `//example.org`. +- Missing lowercase normalization for host. +- Handling of URI components in case they are `'0'` in a lot of places, e.g. as a user info password. -* Fix `Uri::withAddedHeader` to correctly merge headers with different case. -* Fix trimming of header values in `Uri::withAddedHeader`. Header values may +- `Uri::withAddedHeader` to correctly merge headers with different case. +- Trimming of header values in `Uri::withAddedHeader`. Header values may be surrounded by whitespace which should be ignored according to RFC 7230 Section 3.2.4. This does not apply to header names. -* Fix `Uri::withAddedHeader` with an array of header values. -* Fix `Uri::resolve` when base path has no slash and handling of fragment. -* Fix handling of encoding in `Uri::with(out)QueryValue` so one can pass the +- `Uri::withAddedHeader` with an array of header values. +- `Uri::resolve` when base path has no slash and handling of fragment. +- Handling of encoding in `Uri::with(out)QueryValue` so one can pass the key/value both in encoded as well as decoded form to those methods. This is consistent with withPath, withQuery etc. -* Fix `ServerRequest::withoutAttribute` when attribute value is null. +- `ServerRequest::withoutAttribute` when attribute value is null. + -## 1.3.0 - 2016-04-13 +## [1.3.0] - 2016-04-13 -* Added remaining interfaces needed for full PSR7 compatibility +### Added + +- Remaining interfaces needed for full PSR7 compatibility (ServerRequestInterface, UploadedFileInterface, etc.). -* Added support for stream_for from scalars. -* Can now extend Uri. -* Fixed a bug in validating request methods by making it more permissive. +- Support for stream_for from scalars. + +### Changed + +- Can now extend Uri. + +### Fixed +- A bug in validating request methods by making it more permissive. + -## 1.2.3 - 2016-02-18 +## [1.2.3] - 2016-02-18 -* Fixed support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote +### Fixed + +- Support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote streams, which can sometimes return fewer bytes than requested with `fread`. -* Fixed handling of gzipped responses with FNAME headers. +- Handling of gzipped responses with FNAME headers. + + +## [1.2.2] - 2016-01-22 + +### Added -## 1.2.2 - 2016-01-22 +- Support for URIs without any authority. +- Support for HTTP 451 'Unavailable For Legal Reasons.' +- Support for using '0' as a filename. +- Support for including non-standard ports in Host headers. -* Added support for URIs without any authority. -* Added support for HTTP 451 'Unavailable For Legal Reasons.' -* Added support for using '0' as a filename. -* Added support for including non-standard ports in Host headers. -## 1.2.1 - 2015-11-02 +## [1.2.1] - 2015-11-02 -* Now supporting negative offsets when seeking to SEEK_END. +### Changes -## 1.2.0 - 2015-08-15 +- Now supporting negative offsets when seeking to SEEK_END. -* 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 + +## [1.2.0] - 2015-08-15 + +### Changed + +- 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. +- functions.php is now conditionally required. +- user-info is no longer dropped when resolving URIs. + + +## [1.1.0] - 2015-06-24 -## 1.1.0 - 2015-06-24 +### Changed -* 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 +- 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 +- 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. @@ -108,3 +397,20 @@ Currently unsupported: - `Psr\Http\Message\ServerRequestInterface` - `Psr\Http\Message\UploadedFileInterface` + + + +[1.6.0]: https://github.com/guzzle/psr7/compare/1.5.2...1.6.0 +[1.5.2]: https://github.com/guzzle/psr7/compare/1.5.1...1.5.2 +[1.5.1]: https://github.com/guzzle/psr7/compare/1.5.0...1.5.1 +[1.5.0]: https://github.com/guzzle/psr7/compare/1.4.2...1.5.0 +[1.4.2]: https://github.com/guzzle/psr7/compare/1.4.1...1.4.2 +[1.4.1]: https://github.com/guzzle/psr7/compare/1.4.0...1.4.1 +[1.4.0]: https://github.com/guzzle/psr7/compare/1.3.1...1.4.0 +[1.3.1]: https://github.com/guzzle/psr7/compare/1.3.0...1.3.1 +[1.3.0]: https://github.com/guzzle/psr7/compare/1.2.3...1.3.0 +[1.2.3]: https://github.com/guzzle/psr7/compare/1.2.2...1.2.3 +[1.2.2]: https://github.com/guzzle/psr7/compare/1.2.1...1.2.2 +[1.2.1]: https://github.com/guzzle/psr7/compare/1.2.0...1.2.1 +[1.2.0]: https://github.com/guzzle/psr7/compare/1.1.0...1.2.0 +[1.1.0]: https://github.com/guzzle/psr7/compare/1.0.0...1.1.0 diff --git a/vendor/guzzlehttp/psr7/LICENSE b/vendor/guzzlehttp/psr7/LICENSE index 581d95f..51c7ec8 100644 --- a/vendor/guzzlehttp/psr7/LICENSE +++ b/vendor/guzzlehttp/psr7/LICENSE @@ -1,4 +1,11 @@ -Copyright (c) 2015 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com> +The MIT License (MIT) + +Copyright (c) 2015 Michael Dowling <mtdowling@gmail.com> +Copyright (c) 2015 Márk Sági-Kazár <mark.sagikazar@gmail.com> +Copyright (c) 2015 Graham Campbell <hello@gjcampbell.co.uk> +Copyright (c) 2016 Tobias Schultze <webmaster@tubo-world.de> +Copyright (c) 2016 George Mponos <gmponos@gmail.com> +Copyright (c) 2018 Tobias Nyholm <tobias.nyholm@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/guzzlehttp/psr7/README.md b/vendor/guzzlehttp/psr7/README.md index 1649935..9566a7d 100644 --- a/vendor/guzzlehttp/psr7/README.md +++ b/vendor/guzzlehttp/psr7/README.md @@ -1,12 +1,18 @@ # PSR-7 Message Implementation -This repository contains a full [PSR-7](http://www.php-fig.org/psr/psr-7/) +This repository contains a full [PSR-7](https://www.php-fig.org/psr/psr-7/) message implementation, several stream decorators, and some helpful functionality like query string parsing. +![CI](https://github.com/guzzle/psr7/workflows/CI/badge.svg) +![Static analysis](https://github.com/guzzle/psr7/workflows/Static%20analysis/badge.svg) -[![Build Status](https://travis-ci.org/guzzle/psr7.svg?branch=master)](https://travis-ci.org/guzzle/psr7) +# Installation + +```shell +composer require guzzlehttp/psr7 +``` # Stream implementation @@ -23,11 +29,11 @@ Reads from multiple streams, one after the other. ```php use GuzzleHttp\Psr7; -$a = Psr7\stream_for('abc, '); -$b = Psr7\stream_for('123.'); +$a = Psr7\Utils::streamFor('abc, '); +$b = Psr7\Utils::streamFor('123.'); $composed = new Psr7\AppendStream([$a, $b]); -$composed->addStream(Psr7\stream_for(' Above all listen to me')); +$composed->addStream(Psr7\Utils::streamFor(' Above all listen to me')); echo $composed; // abc, 123. Above all listen to me. ``` @@ -65,7 +71,7 @@ then on disk. ```php use GuzzleHttp\Psr7; -$original = Psr7\stream_for(fopen('http://www.google.com', 'r')); +$original = Psr7\Utils::streamFor(fopen('http://www.google.com', 'r')); $stream = new Psr7\CachingStream($original); $stream->read(1024); @@ -89,7 +95,7 @@ stream becomes too full. use GuzzleHttp\Psr7; // Create an empty stream -$stream = Psr7\stream_for(); +$stream = Psr7\Utils::streamFor(); // Start dropping data when the stream has more than 10 bytes $dropping = new Psr7\DroppingStream($stream, 10); @@ -112,7 +118,7 @@ to create a concrete class for a simple extension point. use GuzzleHttp\Psr7; -$stream = Psr7\stream_for('hi'); +$stream = Psr7\Utils::streamFor('hi'); $fnStream = Psr7\FnStream::decorate($stream, [ 'rewind' => function () use ($stream) { echo 'About to rewind - '; @@ -130,10 +136,9 @@ $fnStream->rewind(); `GuzzleHttp\Psr7\InflateStream` -Uses PHP's zlib.inflate filter to inflate deflate or gzipped content. +Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) 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, +This stream decorator 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. @@ -167,7 +172,7 @@ chunks (e.g. Amazon S3's multipart upload API). ```php use GuzzleHttp\Psr7; -$original = Psr7\stream_for(fopen('/tmp/test.txt', 'r+')); +$original = Psr7\Utils::streamFor(fopen('/tmp/test.txt', 'r+')); echo $original->getSize(); // >>> 1048576 @@ -197,7 +202,7 @@ NoSeekStream wraps a stream and does not allow seeking. ```php use GuzzleHttp\Psr7; -$original = Psr7\stream_for('foo'); +$original = Psr7\Utils::streamFor('foo'); $noSeek = new Psr7\NoSeekStream($original); echo $noSeek->read(3); @@ -246,6 +251,8 @@ class EofCallbackStream implements StreamInterface private $callback; + private $stream; + public function __construct(StreamInterface $stream, callable $cb) { $this->stream = $stream; @@ -271,7 +278,7 @@ This decorator could be added to any existing stream and used like so: ```php use GuzzleHttp\Psr7; -$original = Psr7\stream_for('foo'); +$original = Psr7\Utils::streamFor('foo'); $eofStream = new EofCallbackStream($original, function () { echo 'EOF!'; @@ -297,228 +304,321 @@ stream from a PSR-7 stream. ```php use GuzzleHttp\Psr7\StreamWrapper; -$stream = GuzzleHttp\Psr7\stream_for('hello!'); +$stream = GuzzleHttp\Psr7\Utils::streamFor('hello!'); $resource = StreamWrapper::getResource($stream); echo fread($resource, 6); // outputs hello! ``` -# Function API +# Static API -There are various functions available under the `GuzzleHttp\Psr7` namespace. +There are various static methods available under the `GuzzleHttp\Psr7` namespace. -## `function str` +## `GuzzleHttp\Psr7\Message::toString` -`function str(MessageInterface $message)` +`public static function toString(MessageInterface $message): string` Returns the string representation of an HTTP message. ```php $request = new GuzzleHttp\Psr7\Request('GET', 'http://example.com'); -echo GuzzleHttp\Psr7\str($request); +echo GuzzleHttp\Psr7\Message::toString($request); ``` -## `function uri_for` +## `GuzzleHttp\Psr7\Message::bodySummary` -`function uri_for($uri)` +`public static function bodySummary(MessageInterface $message, int $truncateAt = 120): string|null` -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. +Get a short summary of the message body. -```php -$uri = GuzzleHttp\Psr7\uri_for('http://example.com'); -assert($uri === GuzzleHttp\Psr7\uri_for($uri)); -``` +Will return `null` if the response is not printable. -## `function stream_for` +## `GuzzleHttp\Psr7\Message::rewindBody` -`function stream_for($resource = '', array $options = [])` +`public static function rewindBody(MessageInterface $message): void` -Create a new stream based on the input type. +Attempts to rewind a message body and throws an exception on failure. -Options is an associative array that can contain the following keys: +The body of the message will only be rewound if a call to `tell()` +returns a value other than `0`. -* - metadata: Array of custom metadata. -* - size: Size of the stream. -This method accepts the following `$resource` types: +## `GuzzleHttp\Psr7\Message::parseMessage` -- `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. +`public static function parseMessage(string $message): array` -```php -$stream = GuzzleHttp\Psr7\stream_for('foo'); -$stream = GuzzleHttp\Psr7\stream_for(fopen('/path/to/file', 'r')); +Parses an HTTP message into an associative array. -$generator function ($bytes) { - for ($i = 0; $i < $bytes; $i++) { - yield ' '; - } -} +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. -$stream = GuzzleHttp\Psr7\stream_for($generator(100)); -``` +## `GuzzleHttp\Psr7\Message::parseRequestUri` + +`public static function parseRequestUri(string $path, array $headers): string` + +Constructs a URI for an HTTP request message. -## `function parse_header` -`function parse_header($header)` +## `GuzzleHttp\Psr7\Message::parseRequest` -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. +`public static function parseRequest(string $message): Request` +Parses a request message string into a request object. -## `function normalize_header` -`function normalize_header($header)` +## `GuzzleHttp\Psr7\Message::parseResponse` -Converts an array of header values that may contain comma separated headers -into an array of headers with no comma separated values. +`public static function parseResponse(string $message): Response` +Parses a response message string into a response object. -## `function modify_request` -`function modify_request(RequestInterface $request, array $changes)` +## `GuzzleHttp\Psr7\Header::parse` -Clone and modify a request with the given changes. This method is useful for -reducing the number of clones needed to mutate a message. +`public static function parse(string|array $header): array` -The changes can be one of: +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. -- 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. +## `GuzzleHttp\Psr7\Header::splitList` -## `function rewind_body` +`public static function splitList(string|string[] $header): string[]` -`function rewind_body(MessageInterface $message)` +Splits a HTTP header defined to contain a comma-separated list into +each individual value: -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`. +``` +$knownEtags = Header::splitList($request->getHeader('if-none-match')); +``` +Example headers include `accept`, `cache-control` and `if-none-match`. -## `function try_fopen` -`function try_fopen($filename, $mode)` +## `GuzzleHttp\Psr7\Header::normalize` (deprecated) + +`public static function normalize(string|array $header): array` + +`Header::normalize()` is deprecated in favor of [`Header::splitList()`](README.md#guzzlehttppsr7headersplitlist) +which performs the same operation with a cleaned up API and improved +documentation. + +Converts an array of header values that may contain comma separated +headers into an array of headers with no comma separated values. + + +## `GuzzleHttp\Psr7\Query::parse` + +`public static function parse(string $str, int|bool $urlEncoding = true): array` + +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'])`. + + +## `GuzzleHttp\Psr7\Query::build` + +`public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986): string` + +Build a query string from an array of key value pairs. + +This function can use the return value of `parse()` to build a query +string. This function does not modify the provided keys when an array is +encountered (like `http_build_query()` would). -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. +## `GuzzleHttp\Psr7\Utils::caselessRemove` +`public static function caselessRemove(iterable<string> $keys, $keys, array $data): array` -## `function copy_to_string` +Remove the items given by the keys, case insensitively from the data. -`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. +## `GuzzleHttp\Psr7\Utils::copyToStream` +`public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void` -## `function copy_to_stream` +Copy the contents of a stream into another stream until the given number +of bytes have been read. -`function copy_to_stream(StreamInterface $source, StreamInterface $dest, $maxLen = -1)` -Copy the contents of a stream into another stream until the given number of +## `GuzzleHttp\Psr7\Utils::copyToString` + +`public static function copyToString(StreamInterface $stream, int $maxLen = -1): string` + +Copy the contents of a stream into a string until the given number of bytes have been read. -## `function hash` +## `GuzzleHttp\Psr7\Utils::hash` + +`public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string` + +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 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). +## `GuzzleHttp\Psr7\Utils::modifyRequest` +`public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface` -## `function readline` +Clone and modify a request with the given changes. -`function readline(StreamInterface $stream, $maxLength = null)` +This method is useful for reducing the number of clones needed to mutate +a message. + +- 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. + + +## `GuzzleHttp\Psr7\Utils::readLine` + +`public static function readLine(StreamInterface $stream, int $maxLength = null): string` Read a line from the stream up to the maximum allowed buffer length. -## `function parse_request` +## `GuzzleHttp\Psr7\Utils::streamFor` -`function parse_request($message)` +`public static function streamFor(resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource = '', array $options = []): StreamInterface` -Parses a request message string into a request object. +Create a new stream based on the input type. +Options is an associative array that can contain the following keys: -## `function parse_response` +- metadata: Array of custom metadata. +- size: Size of the stream. -`function parse_response($message)` +This method accepts the following `$resource` types: -Parses a response message string into a response object. +- `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 = GuzzleHttp\Psr7\Utils::streamFor('foo'); +$stream = GuzzleHttp\Psr7\Utils::streamFor(fopen('/path/to/file', 'r')); -## `function parse_query` +$generator = function ($bytes) { + for ($i = 0; $i < $bytes; $i++) { + yield ' '; + } +} -`function parse_query($str, $urlEncoding = true)` +$stream = GuzzleHttp\Psr7\Utils::streamFor($generator(100)); +``` -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']`). +## `GuzzleHttp\Psr7\Utils::tryFopen` +`public static function tryFopen(string $filename, string $mode): resource` -## `function build_query` +Safely opens a PHP stream resource using a filename. -`function build_query(array $params, $encoding = PHP_QUERY_RFC3986)` +When fopen fails, PHP normally raises a warning. This function adds an +error handler that checks for errors and throws an exception instead. -Build a query string from an array of key value pairs. -This function can use the return value of parse_query() to build a query string. -This function does not modify the provided keys when an array is encountered -(like http_build_query would). +## `GuzzleHttp\Psr7\Utils::tryGetContents` + +`public static function tryGetContents(resource $stream): string` + +Safely gets the contents of a given stream. + +When stream_get_contents fails, PHP normally raises a warning. This +function adds an error handler that checks for errors and throws an +exception instead. + +## `GuzzleHttp\Psr7\Utils::uriFor` -## `function mimetype_from_filename` +`public static function uriFor(string|UriInterface $uri): UriInterface` -`function mimetype_from_filename($filename)` +Returns a UriInterface for the given value. + +This function accepts a string or UriInterface and returns a +UriInterface for the given value. If the value is already a +UriInterface, it is returned as-is. + + +## `GuzzleHttp\Psr7\MimeType::fromFilename` + +`public static function fromFilename(string $filename): string|null` Determines the mimetype of a file by looking at its extension. -## `function mimetype_from_extension` +## `GuzzleHttp\Psr7\MimeType::fromExtension` -`function mimetype_from_extension($extension)` +`public static function fromExtension(string $extension): string|null` Maps a file extensions to a mimetype. +## Upgrading from Function API + +The static API was first introduced in 1.7.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The function API was removed in 2.0.0. A migration table has been provided here for your convenience: + +| Original Function | Replacement Method | +|----------------|----------------| +| `str` | `Message::toString` | +| `uri_for` | `Utils::uriFor` | +| `stream_for` | `Utils::streamFor` | +| `parse_header` | `Header::parse` | +| `normalize_header` | `Header::normalize` | +| `modify_request` | `Utils::modifyRequest` | +| `rewind_body` | `Message::rewindBody` | +| `try_fopen` | `Utils::tryFopen` | +| `copy_to_string` | `Utils::copyToString` | +| `copy_to_stream` | `Utils::copyToStream` | +| `hash` | `Utils::hash` | +| `readline` | `Utils::readLine` | +| `parse_request` | `Message::parseRequest` | +| `parse_response` | `Message::parseResponse` | +| `parse_query` | `Query::parse` | +| `build_query` | `Query::build` | +| `mimetype_from_filename` | `MimeType::fromFilename` | +| `mimetype_from_extension` | `MimeType::fromExtension` | +| `_parse_message` | `Message::parseMessage` | +| `_parse_request_uri` | `Message::parseRequestUri` | +| `get_message_body_summary` | `Message::bodySummary` | +| `_caseless_remove` | `Utils::caselessRemove` | + + # Additional URI Methods Aside from the standard `Psr\Http\Message\UriInterface` implementation in form of the `GuzzleHttp\Psr7\Uri` class, @@ -595,7 +695,7 @@ manually but instead is used indirectly via `Psr\Http\Message\UriInterface::__to `public static function fromParts(array $parts): UriInterface` -Creates a URI from a hash of [`parse_url`](http://php.net/manual/en/function.parse-url.php) components. +Creates a URI from a hash of [`parse_url`](https://www.php.net/manual/en/function.parse-url.php) components. ### `GuzzleHttp\Psr7\Uri::withQueryValue` @@ -606,6 +706,12 @@ Creates a new URI with a specific query string value. Any existing query string provided key are removed and replaced with the given key value pair. A value of null will set the query string key without a value, e.g. "key" instead of "key=value". +### `GuzzleHttp\Psr7\Uri::withQueryValues` + +`public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface` + +Creates a new URI with multiple query string values. It has the same behavior as `withQueryValue()` but for an +associative array of key => value. ### `GuzzleHttp\Psr7\Uri::withoutQueryValue` @@ -614,6 +720,16 @@ key without a value, e.g. "key" instead of "key=value". Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the provided key are removed. +## Cross-Origin Detection + +`GuzzleHttp\Psr7\UriComparator` provides methods to determine if a modified URL should be considered cross-origin. + +### `GuzzleHttp\Psr7\UriComparator::isCrossOrigin` + +`public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool` + +Determines if a modified URL should be considered cross-origin with respect to an original URL. + ## Reference Resolution `GuzzleHttp\Psr7\UriResolver` provides methods to resolve a URI reference in the context of a base URI according @@ -737,3 +853,28 @@ Whether two URIs can be considered equivalent. Both URIs are normalized automati `$normalizations` bitmask. The method also accepts relative URI references and returns true when they are equivalent. This of course assumes they will be resolved against the same base URI. If this is not the case, determination of equivalence or difference of relative references does not mean anything. + + +## Version Guidance + +| Version | Status | PHP Version | +|---------|----------------|------------------| +| 1.x | Security fixes | >=5.4,<8.1 | +| 2.x | Latest | ^7.2.5 \|\| ^8.0 | + + +## Security + +If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/psr7/security/policy) for more information. + + +## License + +Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information. + + +## For Enterprise + +Available as part of the Tidelift Subscription + +The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-psr7?utm_source=packagist-guzzlehttp-psr7&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) diff --git a/vendor/guzzlehttp/psr7/composer.json b/vendor/guzzlehttp/psr7/composer.json index b1c5a90..d51dd62 100644 --- a/vendor/guzzlehttp/psr7/composer.json +++ b/vendor/guzzlehttp/psr7/composer.json @@ -1,39 +1,93 @@ { "name": "guzzlehttp/psr7", - "type": "library", "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": ["request", "response", "message", "stream", "http", "uri", "url"], + "keywords": [ + "request", + "response", + "message", + "stream", + "http", + "uri", + "url", + "psr-7" + ], "license": "MIT", "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, { "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" }, "provide": { + "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, "autoload": { "psr-4": { "GuzzleHttp\\Psr7\\": "src/" - }, - "files": ["src/functions_include.php"] + } + }, + "autoload-dev": { + "psr-4": { + "GuzzleHttp\\Tests\\Psr7\\": "tests/" + } }, "extra": { - "branch-alias": { - "dev-master": "1.4-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } + }, + "config": { + "allow-plugins": { + "bamarni/composer-bin-plugin": true + }, + "preferred-install": "dist", + "sort-packages": true } } diff --git a/vendor/guzzlehttp/psr7/src/AppendStream.php b/vendor/guzzlehttp/psr7/src/AppendStream.php index 23039fd..cbcfaee 100644 --- a/vendor/guzzlehttp/psr7/src/AppendStream.php +++ b/vendor/guzzlehttp/psr7/src/AppendStream.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; @@ -8,15 +11,19 @@ * * This is a read-only stream decorator. */ -class AppendStream implements StreamInterface +final class AppendStream implements StreamInterface { /** @var StreamInterface[] Streams being decorated */ private $streams = []; + /** @var bool */ private $seekable = true; + + /** @var int */ private $current = 0; + + /** @var int */ private $pos = 0; - private $detached = false; /** * @param StreamInterface[] $streams Streams to decorate. Each stream must @@ -29,12 +36,16 @@ public function __construct(array $streams = []) } } - public function __toString() + public function __toString(): string { try { $this->rewind(); return $this->getContents(); - } catch (\Exception $e) { + } catch (\Throwable $e) { + if (\PHP_VERSION_ID >= 70400) { + throw $e; + } + trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } @@ -46,7 +57,7 @@ public function __toString() * * @throws \InvalidArgumentException if the stream is not readable */ - public function addStream(StreamInterface $stream) + public function addStream(StreamInterface $stream): void { if (!$stream->isReadable()) { throw new \InvalidArgumentException('Each stream must be readable'); @@ -60,19 +71,18 @@ public function addStream(StreamInterface $stream) $this->streams[] = $stream; } - public function getContents() + public function getContents(): string { - return copy_to_string($this); + return Utils::copyToString($this); } /** * Closes each attached stream. - * - * {@inheritdoc} */ - public function close() + public function close(): void { $this->pos = $this->current = 0; + $this->seekable = true; foreach ($this->streams as $stream) { $stream->close(); @@ -82,17 +92,25 @@ public function close() } /** - * Detaches each attached stream + * Detaches each attached stream. * - * {@inheritdoc} + * Returns null as it's not clear which underlying stream resource to return. */ public function detach() { - $this->close(); - $this->detached = true; + $this->pos = $this->current = 0; + $this->seekable = true; + + foreach ($this->streams as $stream) { + $stream->detach(); + } + + $this->streams = []; + + return null; } - public function tell() + public function tell(): int { return $this->pos; } @@ -102,10 +120,8 @@ public function tell() * * 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() + public function getSize(): ?int { $size = 0; @@ -120,24 +136,22 @@ public function getSize() return $size; } - public function eof() + public function eof(): bool { return !$this->streams || ($this->current >= count($this->streams) - 1 && $this->streams[$this->current]->eof()); } - public function rewind() + public function rewind(): void { $this->seek(0); } /** * Attempts to seek to the given position. Only supports SEEK_SET. - * - * {@inheritdoc} */ - public function seek($offset, $whence = SEEK_SET) + public function seek($offset, $whence = SEEK_SET): void { if (!$this->seekable) { throw new \RuntimeException('This AppendStream is not seekable'); @@ -168,10 +182,8 @@ public function seek($offset, $whence = SEEK_SET) /** * Reads from all of the appended streams until the length is met or EOF. - * - * {@inheritdoc} */ - public function read($length) + public function read($length): string { $buffer = ''; $total = count($this->streams) - 1; @@ -179,7 +191,6 @@ public function read($length) $progressToNext = false; while ($remaining > 0) { - // Progress to the next stream if needed. if ($progressToNext || $this->streams[$this->current]->eof()) { $progressToNext = false; @@ -191,8 +202,7 @@ public function read($length) $result = $this->streams[$this->current]->read($remaining); - // Using a loose comparison here to match on '', false, and null - if ($result == null) { + if ($result === '') { $progressToNext = true; continue; } @@ -206,26 +216,31 @@ public function read($length) return $buffer; } - public function isReadable() + public function isReadable(): bool { return true; } - public function isWritable() + public function isWritable(): bool { return false; } - public function isSeekable() + public function isSeekable(): bool { return $this->seekable; } - public function write($string) + public function write($string): int { throw new \RuntimeException('Cannot write to an AppendStream'); } + /** + * {@inheritdoc} + * + * @return mixed + */ public function getMetadata($key = null) { return $key ? null : []; diff --git a/vendor/guzzlehttp/psr7/src/BufferStream.php b/vendor/guzzlehttp/psr7/src/BufferStream.php index af4d4c2..21be8c0 100644 --- a/vendor/guzzlehttp/psr7/src/BufferStream.php +++ b/vendor/guzzlehttp/psr7/src/BufferStream.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; @@ -11,29 +14,32 @@ * what the configured high water mark of the stream is, or the maximum * preferred size of the buffer. */ -class BufferStream implements StreamInterface +final class BufferStream implements StreamInterface { + /** @var int */ private $hwm; + + /** @var string */ private $buffer = ''; /** * @param int $hwm High water mark, representing the preferred maximum * buffer size. If the size of the buffer exceeds the high * water mark, then calls to write will continue to succeed - * but will return false to inform writers to slow down + * but will return 0 to inform writers to slow down * until the buffer has been drained by reading from it. */ - public function __construct($hwm = 16384) + public function __construct(int $hwm = 16384) { $this->hwm = $hwm; } - public function __toString() + public function __toString(): string { return $this->getContents(); } - public function getContents() + public function getContents(): string { $buffer = $this->buffer; $this->buffer = ''; @@ -41,7 +47,7 @@ public function getContents() return $buffer; } - public function close() + public function close(): void { $this->buffer = ''; } @@ -49,44 +55,46 @@ public function close() public function detach() { $this->close(); + + return null; } - public function getSize() + public function getSize(): ?int { return strlen($this->buffer); } - public function isReadable() + public function isReadable(): bool { return true; } - public function isWritable() + public function isWritable(): bool { return true; } - public function isSeekable() + public function isSeekable(): bool { return false; } - public function rewind() + public function rewind(): void { $this->seek(0); } - public function seek($offset, $whence = SEEK_SET) + public function seek($offset, $whence = SEEK_SET): void { throw new \RuntimeException('Cannot seek a BufferStream'); } - public function eof() + public function eof(): bool { return strlen($this->buffer) === 0; } - public function tell() + public function tell(): int { throw new \RuntimeException('Cannot determine the position of a BufferStream'); } @@ -94,7 +102,7 @@ public function tell() /** * Reads data from the buffer. */ - public function read($length) + public function read($length): string { $currentLength = strlen($this->buffer); @@ -114,21 +122,25 @@ public function read($length) /** * Writes data to the buffer. */ - public function write($string) + public function write($string): int { $this->buffer .= $string; - // TODO: What should happen here? if (strlen($this->buffer) >= $this->hwm) { - return false; + return 0; } return strlen($string); } + /** + * {@inheritdoc} + * + * @return mixed + */ public function getMetadata($key = null) { - if ($key == 'hwm') { + if ($key === 'hwm') { return $this->hwm; } diff --git a/vendor/guzzlehttp/psr7/src/CachingStream.php b/vendor/guzzlehttp/psr7/src/CachingStream.php index ed68f08..f34722c 100644 --- a/vendor/guzzlehttp/psr7/src/CachingStream.php +++ b/vendor/guzzlehttp/psr7/src/CachingStream.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; @@ -7,7 +10,7 @@ * Stream decorator that can cache previously read bytes from a sequentially * read stream. */ -class CachingStream implements StreamInterface +final class CachingStream implements StreamInterface { use StreamDecoratorTrait; @@ -17,10 +20,15 @@ class CachingStream implements StreamInterface /** @var int Number of bytes to skip reading due to a write on the buffer */ private $skipReadBytes = 0; + /** + * @var StreamInterface + */ + private $stream; + /** * We will treat the buffer object as the body of the stream * - * @param StreamInterface $stream Stream to cache + * @param StreamInterface $stream Stream to cache. The cursor is assumed to be at the beginning of the stream. * @param StreamInterface $target Optionally specify where data is cached */ public function __construct( @@ -28,26 +36,32 @@ public function __construct( StreamInterface $target = null ) { $this->remoteStream = $stream; - $this->stream = $target ?: new Stream(fopen('php://temp', 'r+')); + $this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+')); } - public function getSize() + public function getSize(): ?int { - return max($this->stream->getSize(), $this->remoteStream->getSize()); + $remoteSize = $this->remoteStream->getSize(); + + if (null === $remoteSize) { + return null; + } + + return max($this->stream->getSize(), $remoteSize); } - public function rewind() + public function rewind(): void { $this->seek(0); } - public function seek($offset, $whence = SEEK_SET) + public function seek($offset, $whence = SEEK_SET): void { - if ($whence == SEEK_SET) { + if ($whence === SEEK_SET) { $byte = $offset; - } elseif ($whence == SEEK_CUR) { + } elseif ($whence === SEEK_CUR) { $byte = $offset + $this->tell(); - } elseif ($whence == SEEK_END) { + } elseif ($whence === SEEK_END) { $size = $this->remoteStream->getSize(); if ($size === null) { $size = $this->cacheEntireStream(); @@ -72,7 +86,7 @@ public function seek($offset, $whence = SEEK_SET) } } - public function read($length) + public function read($length): string { // Perform a regular read on any previously read data from the buffer $data = $this->stream->read($length); @@ -101,7 +115,7 @@ public function read($length) return $data; } - public function write($string) + public function write($string): int { // 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 @@ -115,7 +129,7 @@ public function write($string) return $this->stream->write($string); } - public function eof() + public function eof(): bool { return $this->stream->eof() && $this->remoteStream->eof(); } @@ -123,15 +137,16 @@ public function eof() /** * Close both the remote stream and buffer stream */ - public function close() + public function close(): void { - $this->remoteStream->close() && $this->stream->close(); + $this->remoteStream->close(); + $this->stream->close(); } - private function cacheEntireStream() + private function cacheEntireStream(): int { $target = new FnStream(['write' => 'strlen']); - copy_to_stream($this, $target); + Utils::copyToStream($this, $target); return $this->tell(); } diff --git a/vendor/guzzlehttp/psr7/src/DroppingStream.php b/vendor/guzzlehttp/psr7/src/DroppingStream.php index 8935c80..6e3d209 100644 --- a/vendor/guzzlehttp/psr7/src/DroppingStream.php +++ b/vendor/guzzlehttp/psr7/src/DroppingStream.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; @@ -7,23 +10,27 @@ * Stream decorator that begins dropping data once the size of the underlying * stream becomes too full. */ -class DroppingStream implements StreamInterface +final class DroppingStream implements StreamInterface { use StreamDecoratorTrait; + /** @var int */ private $maxLength; + /** @var StreamInterface */ + private $stream; + /** * @param StreamInterface $stream Underlying stream to decorate. * @param int $maxLength Maximum size before dropping data. */ - public function __construct(StreamInterface $stream, $maxLength) + public function __construct(StreamInterface $stream, int $maxLength) { $this->stream = $stream; $this->maxLength = $maxLength; } - public function write($string) + public function write($string): int { $diff = $this->maxLength - $this->stream->getSize(); diff --git a/vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php b/vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php new file mode 100644 index 0000000..3a08477 --- /dev/null +++ b/vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php @@ -0,0 +1,14 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Psr7\Exception; + +use InvalidArgumentException; + +/** + * Exception thrown if a URI cannot be parsed because it's malformed. + */ +class MalformedUriException extends InvalidArgumentException +{ +} diff --git a/vendor/guzzlehttp/psr7/src/FnStream.php b/vendor/guzzlehttp/psr7/src/FnStream.php index cc9b445..3a1a951 100644 --- a/vendor/guzzlehttp/psr7/src/FnStream.php +++ b/vendor/guzzlehttp/psr7/src/FnStream.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; @@ -9,18 +12,20 @@ * Allows for easy testing and extension of a provided stream without needing * to create a concrete class for a simple extension point. */ -class FnStream implements StreamInterface +#[\AllowDynamicProperties] +final class FnStream implements StreamInterface { - /** @var array */ - private $methods; - - /** @var array Methods that must be implemented in the given array */ - private static $slots = ['__toString', 'close', 'detach', 'rewind', + private const SLOTS = [ + '__toString', 'close', 'detach', 'rewind', 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write', - 'isReadable', 'read', 'getContents', 'getMetadata']; + 'isReadable', 'read', 'getContents', 'getMetadata' + ]; + + /** @var array<string, callable> */ + private $methods; /** - * @param array $methods Hash of method name to a callable. + * @param array<string, callable> $methods Hash of method name to a callable. */ public function __construct(array $methods) { @@ -34,9 +39,10 @@ public function __construct(array $methods) /** * Lazily determine which methods are not implemented. + * * @throws \BadMethodCallException */ - public function __get($name) + public function __get(string $name): void { throw new \BadMethodCallException(str_replace('_fn_', '', $name) . '() is not implemented in the FnStream'); @@ -52,12 +58,22 @@ public function __destruct() } } + /** + * An unserialize would allow the __destruct to run when the unserialized value goes out of scope. + * + * @throws \LogicException + */ + public function __wakeup(): void + { + throw new \LogicException('FnStream should never be unserialized'); + } + /** * 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 + * @param StreamInterface $stream Stream to decorate + * @param array<string, callable> $methods Hash of method name to a closure * * @return FnStream */ @@ -65,21 +81,31 @@ 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] = [$stream, $diff]; + foreach (array_diff(self::SLOTS, array_keys($methods)) as $diff) { + /** @var callable $callable */ + $callable = [$stream, $diff]; + $methods[$diff] = $callable; } return new self($methods); } - public function __toString() + public function __toString(): string { - return call_user_func($this->_fn___toString); + try { + return call_user_func($this->_fn___toString); + } catch (\Throwable $e) { + if (\PHP_VERSION_ID >= 70400) { + throw $e; + } + trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); + return ''; + } } - public function close() + public function close(): void { - return call_user_func($this->_fn_close); + call_user_func($this->_fn_close); } public function detach() @@ -87,61 +113,66 @@ public function detach() return call_user_func($this->_fn_detach); } - public function getSize() + public function getSize(): ?int { return call_user_func($this->_fn_getSize); } - public function tell() + public function tell(): int { return call_user_func($this->_fn_tell); } - public function eof() + public function eof(): bool { return call_user_func($this->_fn_eof); } - public function isSeekable() + public function isSeekable(): bool { return call_user_func($this->_fn_isSeekable); } - public function rewind() + public function rewind(): void { call_user_func($this->_fn_rewind); } - public function seek($offset, $whence = SEEK_SET) + public function seek($offset, $whence = SEEK_SET): void { call_user_func($this->_fn_seek, $offset, $whence); } - public function isWritable() + public function isWritable(): bool { return call_user_func($this->_fn_isWritable); } - public function write($string) + public function write($string): int { return call_user_func($this->_fn_write, $string); } - public function isReadable() + public function isReadable(): bool { return call_user_func($this->_fn_isReadable); } - public function read($length) + public function read($length): string { return call_user_func($this->_fn_read, $length); } - public function getContents() + public function getContents(): string { return call_user_func($this->_fn_getContents); } + /** + * {@inheritdoc} + * + * @return mixed + */ public function getMetadata($key = null) { return call_user_func($this->_fn_getMetadata, $key); diff --git a/vendor/guzzlehttp/psr7/src/Header.php b/vendor/guzzlehttp/psr7/src/Header.php new file mode 100644 index 0000000..4d7005b --- /dev/null +++ b/vendor/guzzlehttp/psr7/src/Header.php @@ -0,0 +1,134 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Psr7; + +final class 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. + * + * @param string|array $header Header to parse into components. + */ + public static function parse($header): array + { + static $trimmed = "\"' \n\t\r"; + $params = $matches = []; + + foreach ((array) $header as $value) { + foreach (self::splitList($value) as $val) { + $part = []; + 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. + * + * @deprecated Use self::splitList() instead. + */ + public static function normalize($header): array + { + $result = []; + foreach ((array) $header as $value) { + foreach (self::splitList($value) as $parsed) { + $result[] = $parsed; + } + } + + return $result; + } + + /** + * Splits a HTTP header defined to contain a comma-separated list into + * each individual value. Empty values will be removed. + * + * Example headers include 'accept', 'cache-control' and 'if-none-match'. + * + * This method must not be used to parse headers that are not defined as + * a list, such as 'user-agent' or 'set-cookie'. + * + * @param string|string[] $values Header value as returned by MessageInterface::getHeader() + * + * @return string[] + */ + public static function splitList($values): array + { + if (!\is_array($values)) { + $values = [$values]; + } + + $result = []; + foreach ($values as $value) { + if (!\is_string($value)) { + throw new \TypeError('$header must either be a string or an array containing strings.'); + } + + $v = ''; + $isQuoted = false; + $isEscaped = false; + for ($i = 0, $max = \strlen($value); $i < $max; $i++) { + if ($isEscaped) { + $v .= $value[$i]; + $isEscaped = false; + + continue; + } + + if (!$isQuoted && $value[$i] === ',') { + $v = \trim($v); + if ($v !== '') { + $result[] = $v; + } + + $v = ''; + continue; + } + + if ($isQuoted && $value[$i] === '\\') { + $isEscaped = true; + $v .= $value[$i]; + + continue; + } + if ($value[$i] === '"') { + $isQuoted = !$isQuoted; + $v .= $value[$i]; + + continue; + } + + $v .= $value[$i]; + } + + $v = \trim($v); + if ($v !== '') { + $result[] = $v; + } + } + + return $result; + } +} diff --git a/vendor/guzzlehttp/psr7/src/HttpFactory.php b/vendor/guzzlehttp/psr7/src/HttpFactory.php new file mode 100644 index 0000000..30be222 --- /dev/null +++ b/vendor/guzzlehttp/psr7/src/HttpFactory.php @@ -0,0 +1,100 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Psr7; + +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseFactoryInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestFactoryInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\StreamFactoryInterface; +use Psr\Http\Message\StreamInterface; +use Psr\Http\Message\UploadedFileFactoryInterface; +use Psr\Http\Message\UploadedFileInterface; +use Psr\Http\Message\UriFactoryInterface; +use Psr\Http\Message\UriInterface; + +/** + * Implements all of the PSR-17 interfaces. + * + * Note: in consuming code it is recommended to require the implemented interfaces + * and inject the instance of this class multiple times. + */ +final class HttpFactory implements + RequestFactoryInterface, + ResponseFactoryInterface, + ServerRequestFactoryInterface, + StreamFactoryInterface, + UploadedFileFactoryInterface, + UriFactoryInterface +{ + public function createUploadedFile( + StreamInterface $stream, + int $size = null, + int $error = \UPLOAD_ERR_OK, + string $clientFilename = null, + string $clientMediaType = null + ): UploadedFileInterface { + if ($size === null) { + $size = $stream->getSize(); + } + + return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType); + } + + public function createStream(string $content = ''): StreamInterface + { + return Utils::streamFor($content); + } + + public function createStreamFromFile(string $file, string $mode = 'r'): StreamInterface + { + try { + $resource = Utils::tryFopen($file, $mode); + } catch (\RuntimeException $e) { + if ('' === $mode || false === \in_array($mode[0], ['r', 'w', 'a', 'x', 'c'], true)) { + throw new \InvalidArgumentException(sprintf('Invalid file opening mode "%s"', $mode), 0, $e); + } + + throw $e; + } + + return Utils::streamFor($resource); + } + + public function createStreamFromResource($resource): StreamInterface + { + return Utils::streamFor($resource); + } + + public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface + { + if (empty($method)) { + if (!empty($serverParams['REQUEST_METHOD'])) { + $method = $serverParams['REQUEST_METHOD']; + } else { + throw new \InvalidArgumentException('Cannot determine HTTP method'); + } + } + + return new ServerRequest($method, $uri, [], null, '1.1', $serverParams); + } + + public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface + { + return new Response($code, [], null, '1.1', $reasonPhrase); + } + + public function createRequest(string $method, $uri): RequestInterface + { + return new Request($method, $uri); + } + + public function createUri(string $uri = ''): UriInterface + { + return new Uri($uri); + } +} diff --git a/vendor/guzzlehttp/psr7/src/InflateStream.php b/vendor/guzzlehttp/psr7/src/InflateStream.php index 0051d3f..8e00f1c 100644 --- a/vendor/guzzlehttp/psr7/src/InflateStream.php +++ b/vendor/guzzlehttp/psr7/src/InflateStream.php @@ -1,52 +1,37 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** - * Uses PHP's zlib.inflate filter to inflate deflate or gzipped content. + * Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) 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, + * This stream decorator 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. * + * @link http://tools.ietf.org/html/rfc1950 * @link http://tools.ietf.org/html/rfc1952 * @link http://php.net/manual/en/filters.compression.php */ -class InflateStream implements StreamInterface +final class InflateStream implements StreamInterface { use StreamDecoratorTrait; + /** @var StreamInterface */ + private $stream; + public function __construct(StreamInterface $stream) { - // read the first 10 bytes, ie. gzip header - $header = $stream->read(10); - $filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header); - // Skip the header, that is 10 + length of filename + 1 (nil) bytes - $stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength); $resource = StreamWrapper::getResource($stream); - stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ); - $this->stream = new Stream($resource); - } - - /** - * @param StreamInterface $stream - * @param $header - * @return int - */ - private function getLengthOfPossibleFilenameHeader(StreamInterface $stream, $header) - { - $filename_header_length = 0; - - if (substr(bin2hex($header), 6, 2) === '08') { - // we have a filename, read until nil - $filename_header_length = 1; - while ($stream->read(1) !== chr(0)) { - $filename_header_length++; - } - } - - return $filename_header_length; + // Specify window=15+32, so zlib will use header detection to both gzip (with header) and zlib data + // See http://www.zlib.net/manual.html#Advanced definition of inflateInit2 + // "Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection" + // Default window size is 15. + stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 15 + 32]); + $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource)); } } diff --git a/vendor/guzzlehttp/psr7/src/LazyOpenStream.php b/vendor/guzzlehttp/psr7/src/LazyOpenStream.php index 02cec3a..f6c8490 100644 --- a/vendor/guzzlehttp/psr7/src/LazyOpenStream.php +++ b/vendor/guzzlehttp/psr7/src/LazyOpenStream.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; @@ -7,33 +10,40 @@ * Lazily reads or writes to a file that is opened only after an IO operation * take place on the stream. */ -class LazyOpenStream implements StreamInterface +final class LazyOpenStream implements StreamInterface { use StreamDecoratorTrait; - /** @var string File to open */ + /** @var string */ private $filename; - /** @var string $mode */ + /** @var string */ private $mode; + /** + * @var StreamInterface + */ + private $stream; + /** * @param string $filename File to lazily open * @param string $mode fopen mode to use when opening the stream */ - public function __construct($filename, $mode) + public function __construct(string $filename, string $mode) { $this->filename = $filename; $this->mode = $mode; + + // unsetting the property forces the first access to go through + // __get(). + unset($this->stream); } /** * Creates the underlying stream lazily when required. - * - * @return StreamInterface */ - protected function createStream() + protected function createStream(): StreamInterface { - return stream_for(try_fopen($this->filename, $this->mode)); + return Utils::streamFor(Utils::tryFopen($this->filename, $this->mode)); } } diff --git a/vendor/guzzlehttp/psr7/src/LimitStream.php b/vendor/guzzlehttp/psr7/src/LimitStream.php index 3c13d4f..fb22325 100644 --- a/vendor/guzzlehttp/psr7/src/LimitStream.php +++ b/vendor/guzzlehttp/psr7/src/LimitStream.php @@ -1,13 +1,15 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; - /** - * Decorator used to return only a subset of a stream + * Decorator used to return only a subset of a stream. */ -class LimitStream implements StreamInterface +final class LimitStream implements StreamInterface { use StreamDecoratorTrait; @@ -17,6 +19,9 @@ class LimitStream implements StreamInterface /** @var int Limit the number of bytes that can be read */ private $limit; + /** @var StreamInterface */ + private $stream; + /** * @param StreamInterface $stream Stream to wrap * @param int $limit Total number of bytes to allow to be read @@ -26,15 +31,15 @@ class LimitStream implements StreamInterface */ public function __construct( StreamInterface $stream, - $limit = -1, - $offset = 0 + int $limit = -1, + int $offset = 0 ) { $this->stream = $stream; $this->setLimit($limit); $this->setOffset($offset); } - public function eof() + public function eof(): bool { // Always return true if the underlying stream is EOF if ($this->stream->eof()) { @@ -42,7 +47,7 @@ public function eof() } // No limit and the underlying stream is not at EOF - if ($this->limit == -1) { + if ($this->limit === -1) { return false; } @@ -51,13 +56,12 @@ public function eof() /** * Returns the size of the limited subset of data - * {@inheritdoc} */ - public function getSize() + public function getSize(): ?int { if (null === ($length = $this->stream->getSize())) { return null; - } elseif ($this->limit == -1) { + } elseif ($this->limit === -1) { return $length - $this->offset; } else { return min($this->limit, $length - $this->offset); @@ -66,13 +70,12 @@ public function getSize() /** * Allow for a bounded seek on the read limited stream - * {@inheritdoc} */ - public function seek($offset, $whence = SEEK_SET) + public function seek($offset, $whence = SEEK_SET): void { if ($whence !== SEEK_SET || $offset < 0) { throw new \RuntimeException(sprintf( - 'Cannot seek to offset % with whence %s', + 'Cannot seek to offset %s with whence %s', $offset, $whence )); @@ -91,9 +94,8 @@ public function seek($offset, $whence = SEEK_SET) /** * Give a relative tell() - * {@inheritdoc} */ - public function tell() + public function tell(): int { return $this->stream->tell() - $this->offset; } @@ -105,7 +107,7 @@ public function tell() * * @throws \RuntimeException if the stream cannot be seeked. */ - public function setOffset($offset) + public function setOffset(int $offset): void { $current = $this->stream->tell(); @@ -130,14 +132,14 @@ public function setOffset($offset) * @param int $limit Number of bytes to allow to be read from the stream. * Use -1 for no limit. */ - public function setLimit($limit) + public function setLimit(int $limit): void { $this->limit = $limit; } - public function read($length) + public function read($length): string { - if ($this->limit == -1) { + if ($this->limit === -1) { return $this->stream->read($length); } diff --git a/vendor/guzzlehttp/psr7/src/Message.php b/vendor/guzzlehttp/psr7/src/Message.php new file mode 100644 index 0000000..c1e15f8 --- /dev/null +++ b/vendor/guzzlehttp/psr7/src/Message.php @@ -0,0 +1,246 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Psr7; + +use Psr\Http\Message\MessageInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +final class Message +{ + /** + * Returns the string representation of an HTTP message. + * + * @param MessageInterface $message Message to convert to a string. + */ + public static function toString(MessageInterface $message): string + { + if ($message instanceof RequestInterface) { + $msg = trim($message->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) { + if (strtolower($name) === 'set-cookie') { + foreach ($values as $value) { + $msg .= "\r\n{$name}: " . $value; + } + } else { + $msg .= "\r\n{$name}: " . implode(', ', $values); + } + } + + return "{$msg}\r\n\r\n" . $message->getBody(); + } + + /** + * Get a short summary of the message body. + * + * Will return `null` if the response is not printable. + * + * @param MessageInterface $message The message to get the body summary + * @param int $truncateAt The maximum allowed size of the summary + */ + public static function bodySummary(MessageInterface $message, int $truncateAt = 120): ?string + { + $body = $message->getBody(); + + if (!$body->isSeekable() || !$body->isReadable()) { + return null; + } + + $size = $body->getSize(); + + if ($size === 0) { + return null; + } + + $body->rewind(); + $summary = $body->read($truncateAt); + $body->rewind(); + + if ($size > $truncateAt) { + $summary .= ' (truncated...)'; + } + + // Matches any printable character, including unicode characters: + // letters, marks, numbers, punctuation, spacing, and separators. + if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/u', $summary) !== 0) { + return null; + } + + return $summary; + } + + /** + * 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 + */ + public static function rewindBody(MessageInterface $message): void + { + $body = $message->getBody(); + + if ($body->tell()) { + $body->rewind(); + } + } + + /** + * 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. + */ + public static function parseMessage(string $message): array + { + if (!$message) { + throw new \InvalidArgumentException('Invalid message'); + } + + $message = ltrim($message, "\r\n"); + + $messageParts = preg_split("/\r?\n\r?\n/", $message, 2); + + if ($messageParts === false || count($messageParts) !== 2) { + throw new \InvalidArgumentException('Invalid message: Missing header delimiter'); + } + + [$rawHeaders, $body] = $messageParts; + $rawHeaders .= "\r\n"; // Put back the delimiter we split previously + $headerParts = preg_split("/\r?\n/", $rawHeaders, 2); + + if ($headerParts === false || count($headerParts) !== 2) { + throw new \InvalidArgumentException('Invalid message: Missing status line'); + } + + [$startLine, $rawHeaders] = $headerParts; + + if (preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') { + // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0 + $rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders); + } + + /** @var array[] $headerLines */ + $count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER); + + // If these aren't the same, then one line didn't match and there's an invalid header. + if ($count !== substr_count($rawHeaders, "\n")) { + // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4 + if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) { + throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding'); + } + + throw new \InvalidArgumentException('Invalid header syntax'); + } + + $headers = []; + + foreach ($headerLines as $headerLine) { + $headers[$headerLine[1]][] = $headerLine[2]; + } + + return [ + 'start-line' => $startLine, + 'headers' => $headers, + 'body' => $body, + ]; + } + + /** + * 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). + */ + public static function parseRequestUri(string $path, array $headers): string + { + $hostKey = array_filter(array_keys($headers), function ($k) { + // Numeric array keys are converted to int by PHP. + $k = (string) $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, '/'); + } + + /** + * Parses a request message string into a request object. + * + * @param string $message Request message string. + */ + public static function parseRequest(string $message): RequestInterface + { + $data = self::parseMessage($message); + $matches = []; + if (!preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) { + throw new \InvalidArgumentException('Invalid request string'); + } + $parts = explode(' ', $data['start-line'], 3); + $version = isset($parts[2]) ? explode('/', $parts[2])[1] : '1.1'; + + $request = new Request( + $parts[0], + $matches[1] === '/' ? self::parseRequestUri($parts[1], $data['headers']) : $parts[1], + $data['headers'], + $data['body'], + $version + ); + + return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]); + } + + /** + * Parses a response message string into a response object. + * + * @param string $message Response message string. + */ + public static function parseResponse(string $message): ResponseInterface + { + $data = self::parseMessage($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: ' . $data['start-line']); + } + $parts = explode(' ', $data['start-line'], 3); + + return new Response( + (int) $parts[1], + $data['headers'], + $data['body'], + explode('/', $parts[0])[1], + $parts[2] ?? null + ); + } +} diff --git a/vendor/guzzlehttp/psr7/src/MessageTrait.php b/vendor/guzzlehttp/psr7/src/MessageTrait.php index 1e4da64..464bdfa 100644 --- a/vendor/guzzlehttp/psr7/src/MessageTrait.php +++ b/vendor/guzzlehttp/psr7/src/MessageTrait.php @@ -1,6 +1,10 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; +use Psr\Http\Message\MessageInterface; use Psr\Http\Message\StreamInterface; /** @@ -8,24 +12,24 @@ */ trait MessageTrait { - /** @var array Map of all registered headers, as original name => array of values */ + /** @var array<string, string[]> Map of all registered headers, as original name => array of values */ private $headers = []; - /** @var array Map of lowercase header name => original name at registration */ + /** @var array<string, string> Map of lowercase header name => original name at registration */ private $headerNames = []; /** @var string */ private $protocol = '1.1'; - /** @var StreamInterface */ + /** @var StreamInterface|null */ private $stream; - public function getProtocolVersion() + public function getProtocolVersion(): string { return $this->protocol; } - public function withProtocolVersion($version) + public function withProtocolVersion($version): MessageInterface { if ($this->protocol === $version) { return $this; @@ -36,17 +40,17 @@ public function withProtocolVersion($version) return $new; } - public function getHeaders() + public function getHeaders(): array { return $this->headers; } - public function hasHeader($header) + public function hasHeader($header): bool { return isset($this->headerNames[strtolower($header)]); } - public function getHeader($header) + public function getHeader($header): array { $header = strtolower($header); @@ -59,18 +63,15 @@ public function getHeader($header) return $this->headers[$header]; } - public function getHeaderLine($header) + public function getHeaderLine($header): string { return implode(', ', $this->getHeader($header)); } - public function withHeader($header, $value) + public function withHeader($header, $value): MessageInterface { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); + $this->assertHeader($header); + $value = $this->normalizeHeaderValue($value); $normalized = strtolower($header); $new = clone $this; @@ -83,13 +84,10 @@ public function withHeader($header, $value) return $new; } - public function withAddedHeader($header, $value) + public function withAddedHeader($header, $value): MessageInterface { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); + $this->assertHeader($header); + $value = $this->normalizeHeaderValue($value); $normalized = strtolower($header); $new = clone $this; @@ -104,7 +102,7 @@ public function withAddedHeader($header, $value) return $new; } - public function withoutHeader($header) + public function withoutHeader($header): MessageInterface { $normalized = strtolower($header); @@ -120,16 +118,16 @@ public function withoutHeader($header) return $new; } - public function getBody() + public function getBody(): StreamInterface { if (!$this->stream) { - $this->stream = stream_for(''); + $this->stream = Utils::streamFor(''); } return $this->stream; } - public function withBody(StreamInterface $body) + public function withBody(StreamInterface $body): MessageInterface { if ($body === $this->stream) { return $this; @@ -140,15 +138,18 @@ public function withBody(StreamInterface $body) return $new; } - private function setHeaders(array $headers) + /** + * @param array<string|int, string|string[]> $headers + */ + private function setHeaders(array $headers): void { $this->headerNames = $this->headers = []; foreach ($headers as $header => $value) { - if (!is_array($value)) { - $value = [$value]; - } + // Numeric array keys are converted to int by PHP. + $header = (string) $header; - $value = $this->trimHeaderValues($value); + $this->assertHeader($header); + $value = $this->normalizeHeaderValue($value); $normalized = strtolower($header); if (isset($this->headerNames[$normalized])) { $header = $this->headerNames[$normalized]; @@ -160,6 +161,24 @@ private function setHeaders(array $headers) } } + /** + * @param mixed $value + * + * @return string[] + */ + private function normalizeHeaderValue($value): array + { + if (!is_array($value)) { + return $this->trimAndValidateHeaderValues([$value]); + } + + if (count($value) === 0) { + throw new \InvalidArgumentException('Header value can not be an empty array.'); + } + + return $this->trimAndValidateHeaderValues($value); + } + /** * Trims whitespace from the header values. * @@ -168,16 +187,77 @@ private function setHeaders(array $headers) * header-field = field-name ":" OWS field-value OWS * OWS = *( SP / HTAB ) * - * @param string[] $values Header values + * @param mixed[] $values Header values * * @return string[] Trimmed header values * * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 */ - private function trimHeaderValues(array $values) + private function trimAndValidateHeaderValues(array $values): array { return array_map(function ($value) { - return trim($value, " \t"); - }, $values); + if (!is_scalar($value) && null !== $value) { + throw new \InvalidArgumentException(sprintf( + 'Header value must be scalar or null but %s provided.', + is_object($value) ? get_class($value) : gettype($value) + )); + } + + $trimmed = trim((string) $value, " \t"); + $this->assertValue($trimmed); + + return $trimmed; + }, array_values($values)); + } + + /** + * @see https://tools.ietf.org/html/rfc7230#section-3.2 + * + * @param mixed $header + */ + private function assertHeader($header): void + { + if (!is_string($header)) { + throw new \InvalidArgumentException(sprintf( + 'Header name must be a string but %s provided.', + is_object($header) ? get_class($header) : gettype($header) + )); + } + + if (! preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) { + throw new \InvalidArgumentException( + sprintf('"%s" is not valid header name.', $header) + ); + } + } + + /** + * @see https://tools.ietf.org/html/rfc7230#section-3.2 + * + * field-value = *( field-content / obs-fold ) + * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] + * field-vchar = VCHAR / obs-text + * VCHAR = %x21-7E + * obs-text = %x80-FF + * obs-fold = CRLF 1*( SP / HTAB ) + */ + private function assertValue(string $value): void + { + // The regular expression intentionally does not support the obs-fold production, because as + // per RFC 7230#3.2.4: + // + // A sender MUST NOT generate a message that includes + // line folding (i.e., that has any field-value that contains a match to + // the obs-fold rule) unless the message is intended for packaging + // within the message/http media type. + // + // Clients must not send a request with line folding and a server sending folded headers is + // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting + // folding is not likely to break any legitimate use case. + if (! preg_match('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/D', $value)) { + throw new \InvalidArgumentException( + sprintf('"%s" is not valid header value.', $value) + ); + } } } diff --git a/vendor/guzzlehttp/psr7/src/MimeType.php b/vendor/guzzlehttp/psr7/src/MimeType.php new file mode 100644 index 0000000..0debbd1 --- /dev/null +++ b/vendor/guzzlehttp/psr7/src/MimeType.php @@ -0,0 +1,1237 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Psr7; + +final class MimeType +{ + private const MIME_TYPES = [ + '1km' => 'application/vnd.1000minds.decision-model+xml', + '3dml' => 'text/vnd.in3d.3dml', + '3ds' => 'image/x-3ds', + '3g2' => 'video/3gpp2', + '3gp' => 'video/3gp', + '3gpp' => 'video/3gpp', + '3mf' => 'model/3mf', + '7z' => 'application/x-7z-compressed', + '7zip' => 'application/x-7z-compressed', + '123' => 'application/vnd.lotus-1-2-3', + 'aab' => 'application/x-authorware-bin', + 'aac' => 'audio/x-acc', + 'aam' => 'application/x-authorware-map', + 'aas' => 'application/x-authorware-seg', + 'abw' => 'application/x-abiword', + 'ac' => 'application/vnd.nokia.n-gage.ac+xml', + 'ac3' => 'audio/ac3', + 'acc' => 'application/vnd.americandynamics.acc', + 'ace' => 'application/x-ace-compressed', + 'acu' => 'application/vnd.acucobol', + 'acutc' => 'application/vnd.acucorp', + 'adp' => 'audio/adpcm', + 'aep' => 'application/vnd.audiograph', + 'afm' => 'application/x-font-type1', + 'afp' => 'application/vnd.ibm.modcap', + 'age' => 'application/vnd.age', + 'ahead' => 'application/vnd.ahead.space', + 'ai' => 'application/pdf', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'air' => 'application/vnd.adobe.air-application-installer-package+zip', + 'ait' => 'application/vnd.dvb.ait', + 'ami' => 'application/vnd.amiga.ami', + 'amr' => 'audio/amr', + 'apk' => 'application/vnd.android.package-archive', + 'apng' => 'image/apng', + 'appcache' => 'text/cache-manifest', + 'application' => 'application/x-ms-application', + 'apr' => 'application/vnd.lotus-approach', + 'arc' => 'application/x-freearc', + 'arj' => 'application/x-arj', + 'asc' => 'application/pgp-signature', + 'asf' => 'video/x-ms-asf', + 'asm' => 'text/x-asm', + 'aso' => 'application/vnd.accpac.simply.aso', + 'asx' => 'video/x-ms-asf', + 'atc' => 'application/vnd.acucorp', + 'atom' => 'application/atom+xml', + 'atomcat' => 'application/atomcat+xml', + 'atomdeleted' => 'application/atomdeleted+xml', + 'atomsvc' => 'application/atomsvc+xml', + 'atx' => 'application/vnd.antix.game-component', + 'au' => 'audio/x-au', + 'avci' => 'image/avci', + 'avcs' => 'image/avcs', + 'avi' => 'video/x-msvideo', + 'avif' => 'image/avif', + 'aw' => 'application/applixware', + 'azf' => 'application/vnd.airzip.filesecure.azf', + 'azs' => 'application/vnd.airzip.filesecure.azs', + 'azv' => 'image/vnd.airzip.accelerator.azv', + 'azw' => 'application/vnd.amazon.ebook', + 'b16' => 'image/vnd.pco.b16', + 'bat' => 'application/x-msdownload', + 'bcpio' => 'application/x-bcpio', + 'bdf' => 'application/x-font-bdf', + 'bdm' => 'application/vnd.syncml.dm+wbxml', + 'bdoc' => 'application/x-bdoc', + 'bed' => 'application/vnd.realvnc.bed', + 'bh2' => 'application/vnd.fujitsu.oasysprs', + 'bin' => 'application/octet-stream', + 'blb' => 'application/x-blorb', + 'blorb' => 'application/x-blorb', + 'bmi' => 'application/vnd.bmi', + 'bmml' => 'application/vnd.balsamiq.bmml+xml', + 'bmp' => 'image/bmp', + 'book' => 'application/vnd.framemaker', + 'box' => 'application/vnd.previewsystems.box', + 'boz' => 'application/x-bzip2', + 'bpk' => 'application/octet-stream', + 'bpmn' => 'application/octet-stream', + 'bsp' => 'model/vnd.valve.source.compiled-map', + 'btif' => 'image/prs.btif', + 'buffer' => 'application/octet-stream', + 'bz' => 'application/x-bzip', + 'bz2' => 'application/x-bzip2', + 'c' => 'text/x-c', + 'c4d' => 'application/vnd.clonk.c4group', + 'c4f' => 'application/vnd.clonk.c4group', + 'c4g' => 'application/vnd.clonk.c4group', + 'c4p' => 'application/vnd.clonk.c4group', + 'c4u' => 'application/vnd.clonk.c4group', + 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', + 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', + 'cab' => 'application/vnd.ms-cab-compressed', + 'caf' => 'audio/x-caf', + 'cap' => 'application/vnd.tcpdump.pcap', + 'car' => 'application/vnd.curl.car', + 'cat' => 'application/vnd.ms-pki.seccat', + 'cb7' => 'application/x-cbr', + 'cba' => 'application/x-cbr', + 'cbr' => 'application/x-cbr', + 'cbt' => 'application/x-cbr', + 'cbz' => 'application/x-cbr', + 'cc' => 'text/x-c', + 'cco' => 'application/x-cocoa', + 'cct' => 'application/x-director', + 'ccxml' => 'application/ccxml+xml', + 'cdbcmsg' => 'application/vnd.contact.cmsg', + 'cdf' => 'application/x-netcdf', + 'cdfx' => 'application/cdfx+xml', + 'cdkey' => 'application/vnd.mediastation.cdkey', + 'cdmia' => 'application/cdmi-capability', + 'cdmic' => 'application/cdmi-container', + 'cdmid' => 'application/cdmi-domain', + 'cdmio' => 'application/cdmi-object', + 'cdmiq' => 'application/cdmi-queue', + 'cdr' => 'application/cdr', + 'cdx' => 'chemical/x-cdx', + 'cdxml' => 'application/vnd.chemdraw+xml', + 'cdy' => 'application/vnd.cinderella', + 'cer' => 'application/pkix-cert', + 'cfs' => 'application/x-cfs-compressed', + 'cgm' => 'image/cgm', + 'chat' => 'application/x-chat', + 'chm' => 'application/vnd.ms-htmlhelp', + 'chrt' => 'application/vnd.kde.kchart', + 'cif' => 'chemical/x-cif', + 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', + 'cil' => 'application/vnd.ms-artgalry', + 'cjs' => 'application/node', + 'cla' => 'application/vnd.claymore', + 'class' => 'application/octet-stream', + 'clkk' => 'application/vnd.crick.clicker.keyboard', + 'clkp' => 'application/vnd.crick.clicker.palette', + 'clkt' => 'application/vnd.crick.clicker.template', + 'clkw' => 'application/vnd.crick.clicker.wordbank', + 'clkx' => 'application/vnd.crick.clicker', + 'clp' => 'application/x-msclip', + 'cmc' => 'application/vnd.cosmocaller', + 'cmdf' => 'chemical/x-cmdf', + 'cml' => 'chemical/x-cml', + 'cmp' => 'application/vnd.yellowriver-custom-menu', + 'cmx' => 'image/x-cmx', + 'cod' => 'application/vnd.rim.cod', + 'coffee' => 'text/coffeescript', + 'com' => 'application/x-msdownload', + 'conf' => 'text/plain', + 'cpio' => 'application/x-cpio', + 'cpl' => 'application/cpl+xml', + 'cpp' => 'text/x-c', + 'cpt' => 'application/mac-compactpro', + 'crd' => 'application/x-mscardfile', + 'crl' => 'application/pkix-crl', + 'crt' => 'application/x-x509-ca-cert', + 'crx' => 'application/x-chrome-extension', + 'cryptonote' => 'application/vnd.rig.cryptonote', + 'csh' => 'application/x-csh', + 'csl' => 'application/vnd.citationstyles.style+xml', + 'csml' => 'chemical/x-csml', + 'csp' => 'application/vnd.commonspace', + 'csr' => 'application/octet-stream', + 'css' => 'text/css', + 'cst' => 'application/x-director', + 'csv' => 'text/csv', + 'cu' => 'application/cu-seeme', + 'curl' => 'text/vnd.curl', + 'cww' => 'application/prs.cww', + 'cxt' => 'application/x-director', + 'cxx' => 'text/x-c', + 'dae' => 'model/vnd.collada+xml', + 'daf' => 'application/vnd.mobius.daf', + 'dart' => 'application/vnd.dart', + 'dataless' => 'application/vnd.fdsn.seed', + 'davmount' => 'application/davmount+xml', + 'dbf' => 'application/vnd.dbf', + 'dbk' => 'application/docbook+xml', + 'dcr' => 'application/x-director', + 'dcurl' => 'text/vnd.curl.dcurl', + 'dd2' => 'application/vnd.oma.dd2+xml', + 'ddd' => 'application/vnd.fujixerox.ddd', + 'ddf' => 'application/vnd.syncml.dmddf+xml', + 'dds' => 'image/vnd.ms-dds', + 'deb' => 'application/x-debian-package', + 'def' => 'text/plain', + 'deploy' => 'application/octet-stream', + 'der' => 'application/x-x509-ca-cert', + 'dfac' => 'application/vnd.dreamfactory', + 'dgc' => 'application/x-dgc-compressed', + 'dic' => 'text/x-c', + 'dir' => 'application/x-director', + 'dis' => 'application/vnd.mobius.dis', + 'disposition-notification' => 'message/disposition-notification', + 'dist' => 'application/octet-stream', + 'distz' => 'application/octet-stream', + 'djv' => 'image/vnd.djvu', + 'djvu' => 'image/vnd.djvu', + 'dll' => 'application/octet-stream', + 'dmg' => 'application/x-apple-diskimage', + 'dmn' => 'application/octet-stream', + 'dmp' => 'application/vnd.tcpdump.pcap', + 'dms' => 'application/octet-stream', + 'dna' => 'application/vnd.dna', + 'doc' => 'application/msword', + 'docm' => 'application/vnd.ms-word.template.macroEnabled.12', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dot' => 'application/msword', + 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dp' => 'application/vnd.osgi.dp', + 'dpg' => 'application/vnd.dpgraph', + 'dra' => 'audio/vnd.dra', + 'drle' => 'image/dicom-rle', + 'dsc' => 'text/prs.lines.tag', + 'dssc' => 'application/dssc+der', + 'dtb' => 'application/x-dtbook+xml', + 'dtd' => 'application/xml-dtd', + 'dts' => 'audio/vnd.dts', + 'dtshd' => 'audio/vnd.dts.hd', + 'dump' => 'application/octet-stream', + 'dvb' => 'video/vnd.dvb.file', + 'dvi' => 'application/x-dvi', + 'dwd' => 'application/atsc-dwd+xml', + 'dwf' => 'model/vnd.dwf', + 'dwg' => 'image/vnd.dwg', + 'dxf' => 'image/vnd.dxf', + 'dxp' => 'application/vnd.spotfire.dxp', + 'dxr' => 'application/x-director', + 'ear' => 'application/java-archive', + 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', + 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', + 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', + 'ecma' => 'application/ecmascript', + 'edm' => 'application/vnd.novadigm.edm', + 'edx' => 'application/vnd.novadigm.edx', + 'efif' => 'application/vnd.picsel', + 'ei6' => 'application/vnd.pg.osasli', + 'elc' => 'application/octet-stream', + 'emf' => 'image/emf', + 'eml' => 'message/rfc822', + 'emma' => 'application/emma+xml', + 'emotionml' => 'application/emotionml+xml', + 'emz' => 'application/x-msmetafile', + 'eol' => 'audio/vnd.digital-winds', + 'eot' => 'application/vnd.ms-fontobject', + 'eps' => 'application/postscript', + 'epub' => 'application/epub+zip', + 'es' => 'application/ecmascript', + 'es3' => 'application/vnd.eszigno3+xml', + 'esa' => 'application/vnd.osgi.subsystem', + 'esf' => 'application/vnd.epson.esf', + 'et3' => 'application/vnd.eszigno3+xml', + 'etx' => 'text/x-setext', + 'eva' => 'application/x-eva', + 'evy' => 'application/x-envoy', + 'exe' => 'application/octet-stream', + 'exi' => 'application/exi', + 'exp' => 'application/express', + 'exr' => 'image/aces', + 'ext' => 'application/vnd.novadigm.ext', + 'ez' => 'application/andrew-inset', + 'ez2' => 'application/vnd.ezpix-album', + 'ez3' => 'application/vnd.ezpix-package', + 'f' => 'text/x-fortran', + 'f4v' => 'video/mp4', + 'f77' => 'text/x-fortran', + 'f90' => 'text/x-fortran', + 'fbs' => 'image/vnd.fastbidsheet', + 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', + 'fcs' => 'application/vnd.isac.fcs', + 'fdf' => 'application/vnd.fdf', + 'fdt' => 'application/fdt+xml', + 'fe_launch' => 'application/vnd.denovo.fcselayout-link', + 'fg5' => 'application/vnd.fujitsu.oasysgp', + 'fgd' => 'application/x-director', + 'fh' => 'image/x-freehand', + 'fh4' => 'image/x-freehand', + 'fh5' => 'image/x-freehand', + 'fh7' => 'image/x-freehand', + 'fhc' => 'image/x-freehand', + 'fig' => 'application/x-xfig', + 'fits' => 'image/fits', + 'flac' => 'audio/x-flac', + 'fli' => 'video/x-fli', + 'flo' => 'application/vnd.micrografx.flo', + 'flv' => 'video/x-flv', + 'flw' => 'application/vnd.kde.kivio', + 'flx' => 'text/vnd.fmi.flexstor', + 'fly' => 'text/vnd.fly', + 'fm' => 'application/vnd.framemaker', + 'fnc' => 'application/vnd.frogans.fnc', + 'fo' => 'application/vnd.software602.filler.form+xml', + 'for' => 'text/x-fortran', + 'fpx' => 'image/vnd.fpx', + 'frame' => 'application/vnd.framemaker', + 'fsc' => 'application/vnd.fsc.weblaunch', + 'fst' => 'image/vnd.fst', + 'ftc' => 'application/vnd.fluxtime.clip', + 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', + 'fvt' => 'video/vnd.fvt', + 'fxp' => 'application/vnd.adobe.fxp', + 'fxpl' => 'application/vnd.adobe.fxp', + 'fzs' => 'application/vnd.fuzzysheet', + 'g2w' => 'application/vnd.geoplan', + 'g3' => 'image/g3fax', + 'g3w' => 'application/vnd.geospace', + 'gac' => 'application/vnd.groove-account', + 'gam' => 'application/x-tads', + 'gbr' => 'application/rpki-ghostbusters', + 'gca' => 'application/x-gca-compressed', + 'gdl' => 'model/vnd.gdl', + 'gdoc' => 'application/vnd.google-apps.document', + 'ged' => 'text/vnd.familysearch.gedcom', + 'geo' => 'application/vnd.dynageo', + 'geojson' => 'application/geo+json', + 'gex' => 'application/vnd.geometry-explorer', + 'ggb' => 'application/vnd.geogebra.file', + 'ggt' => 'application/vnd.geogebra.tool', + 'ghf' => 'application/vnd.groove-help', + 'gif' => 'image/gif', + 'gim' => 'application/vnd.groove-identity-message', + 'glb' => 'model/gltf-binary', + 'gltf' => 'model/gltf+json', + 'gml' => 'application/gml+xml', + 'gmx' => 'application/vnd.gmx', + 'gnumeric' => 'application/x-gnumeric', + 'gpg' => 'application/gpg-keys', + 'gph' => 'application/vnd.flographit', + 'gpx' => 'application/gpx+xml', + 'gqf' => 'application/vnd.grafeq', + 'gqs' => 'application/vnd.grafeq', + 'gram' => 'application/srgs', + 'gramps' => 'application/x-gramps-xml', + 'gre' => 'application/vnd.geometry-explorer', + 'grv' => 'application/vnd.groove-injector', + 'grxml' => 'application/srgs+xml', + 'gsf' => 'application/x-font-ghostscript', + 'gsheet' => 'application/vnd.google-apps.spreadsheet', + 'gslides' => 'application/vnd.google-apps.presentation', + 'gtar' => 'application/x-gtar', + 'gtm' => 'application/vnd.groove-tool-message', + 'gtw' => 'model/vnd.gtw', + 'gv' => 'text/vnd.graphviz', + 'gxf' => 'application/gxf', + 'gxt' => 'application/vnd.geonext', + 'gz' => 'application/gzip', + 'gzip' => 'application/gzip', + 'h' => 'text/x-c', + 'h261' => 'video/h261', + 'h263' => 'video/h263', + 'h264' => 'video/h264', + 'hal' => 'application/vnd.hal+xml', + 'hbci' => 'application/vnd.hbci', + 'hbs' => 'text/x-handlebars-template', + 'hdd' => 'application/x-virtualbox-hdd', + 'hdf' => 'application/x-hdf', + 'heic' => 'image/heic', + 'heics' => 'image/heic-sequence', + 'heif' => 'image/heif', + 'heifs' => 'image/heif-sequence', + 'hej2' => 'image/hej2k', + 'held' => 'application/atsc-held+xml', + 'hh' => 'text/x-c', + 'hjson' => 'application/hjson', + 'hlp' => 'application/winhlp', + 'hpgl' => 'application/vnd.hp-hpgl', + 'hpid' => 'application/vnd.hp-hpid', + 'hps' => 'application/vnd.hp-hps', + 'hqx' => 'application/mac-binhex40', + 'hsj2' => 'image/hsj2', + 'htc' => 'text/x-component', + 'htke' => 'application/vnd.kenameaapp', + 'htm' => 'text/html', + 'html' => 'text/html', + 'hvd' => 'application/vnd.yamaha.hv-dic', + 'hvp' => 'application/vnd.yamaha.hv-voice', + 'hvs' => 'application/vnd.yamaha.hv-script', + 'i2g' => 'application/vnd.intergeo', + 'icc' => 'application/vnd.iccprofile', + 'ice' => 'x-conference/x-cooltalk', + 'icm' => 'application/vnd.iccprofile', + 'ico' => 'image/x-icon', + 'ics' => 'text/calendar', + 'ief' => 'image/ief', + 'ifb' => 'text/calendar', + 'ifm' => 'application/vnd.shana.informed.formdata', + 'iges' => 'model/iges', + 'igl' => 'application/vnd.igloader', + 'igm' => 'application/vnd.insors.igm', + 'igs' => 'model/iges', + 'igx' => 'application/vnd.micrografx.igx', + 'iif' => 'application/vnd.shana.informed.interchange', + 'img' => 'application/octet-stream', + 'imp' => 'application/vnd.accpac.simply.imp', + 'ims' => 'application/vnd.ms-ims', + 'in' => 'text/plain', + 'ini' => 'text/plain', + 'ink' => 'application/inkml+xml', + 'inkml' => 'application/inkml+xml', + 'install' => 'application/x-install-instructions', + 'iota' => 'application/vnd.astraea-software.iota', + 'ipfix' => 'application/ipfix', + 'ipk' => 'application/vnd.shana.informed.package', + 'irm' => 'application/vnd.ibm.rights-management', + 'irp' => 'application/vnd.irepository.package+xml', + 'iso' => 'application/x-iso9660-image', + 'itp' => 'application/vnd.shana.informed.formtemplate', + 'its' => 'application/its+xml', + 'ivp' => 'application/vnd.immervision-ivp', + 'ivu' => 'application/vnd.immervision-ivu', + 'jad' => 'text/vnd.sun.j2me.app-descriptor', + 'jade' => 'text/jade', + 'jam' => 'application/vnd.jam', + 'jar' => 'application/java-archive', + 'jardiff' => 'application/x-java-archive-diff', + 'java' => 'text/x-java-source', + 'jhc' => 'image/jphc', + 'jisp' => 'application/vnd.jisp', + 'jls' => 'image/jls', + 'jlt' => 'application/vnd.hp-jlyt', + 'jng' => 'image/x-jng', + 'jnlp' => 'application/x-java-jnlp-file', + 'joda' => 'application/vnd.joost.joda-archive', + 'jp2' => 'image/jp2', + 'jpe' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpf' => 'image/jpx', + 'jpg' => 'image/jpeg', + 'jpg2' => 'image/jp2', + 'jpgm' => 'video/jpm', + 'jpgv' => 'video/jpeg', + 'jph' => 'image/jph', + 'jpm' => 'video/jpm', + 'jpx' => 'image/jpx', + 'js' => 'application/javascript', + 'json' => 'application/json', + 'json5' => 'application/json5', + 'jsonld' => 'application/ld+json', + 'jsonml' => 'application/jsonml+json', + 'jsx' => 'text/jsx', + 'jxr' => 'image/jxr', + 'jxra' => 'image/jxra', + 'jxrs' => 'image/jxrs', + 'jxs' => 'image/jxs', + 'jxsc' => 'image/jxsc', + 'jxsi' => 'image/jxsi', + 'jxss' => 'image/jxss', + 'kar' => 'audio/midi', + 'karbon' => 'application/vnd.kde.karbon', + 'kdb' => 'application/octet-stream', + 'kdbx' => 'application/x-keepass2', + 'key' => 'application/x-iwork-keynote-sffkey', + 'kfo' => 'application/vnd.kde.kformula', + 'kia' => 'application/vnd.kidspiration', + 'kml' => 'application/vnd.google-earth.kml+xml', + 'kmz' => 'application/vnd.google-earth.kmz', + 'kne' => 'application/vnd.kinar', + 'knp' => 'application/vnd.kinar', + 'kon' => 'application/vnd.kde.kontour', + 'kpr' => 'application/vnd.kde.kpresenter', + 'kpt' => 'application/vnd.kde.kpresenter', + 'kpxx' => 'application/vnd.ds-keypoint', + 'ksp' => 'application/vnd.kde.kspread', + 'ktr' => 'application/vnd.kahootz', + 'ktx' => 'image/ktx', + 'ktx2' => 'image/ktx2', + 'ktz' => 'application/vnd.kahootz', + 'kwd' => 'application/vnd.kde.kword', + 'kwt' => 'application/vnd.kde.kword', + 'lasxml' => 'application/vnd.las.las+xml', + 'latex' => 'application/x-latex', + 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', + 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', + 'les' => 'application/vnd.hhe.lesson-player', + 'less' => 'text/less', + 'lgr' => 'application/lgr+xml', + 'lha' => 'application/octet-stream', + 'link66' => 'application/vnd.route66.link66+xml', + 'list' => 'text/plain', + 'list3820' => 'application/vnd.ibm.modcap', + 'listafp' => 'application/vnd.ibm.modcap', + 'litcoffee' => 'text/coffeescript', + 'lnk' => 'application/x-ms-shortcut', + 'log' => 'text/plain', + 'lostxml' => 'application/lost+xml', + 'lrf' => 'application/octet-stream', + 'lrm' => 'application/vnd.ms-lrm', + 'ltf' => 'application/vnd.frogans.ltf', + 'lua' => 'text/x-lua', + 'luac' => 'application/x-lua-bytecode', + 'lvp' => 'audio/vnd.lucent.voice', + 'lwp' => 'application/vnd.lotus-wordpro', + 'lzh' => 'application/octet-stream', + 'm1v' => 'video/mpeg', + 'm2a' => 'audio/mpeg', + 'm2v' => 'video/mpeg', + 'm3a' => 'audio/mpeg', + 'm3u' => 'text/plain', + 'm3u8' => 'application/vnd.apple.mpegurl', + 'm4a' => 'audio/x-m4a', + 'm4p' => 'application/mp4', + 'm4s' => 'video/iso.segment', + 'm4u' => 'application/vnd.mpegurl', + 'm4v' => 'video/x-m4v', + 'm13' => 'application/x-msmediaview', + 'm14' => 'application/x-msmediaview', + 'm21' => 'application/mp21', + 'ma' => 'application/mathematica', + 'mads' => 'application/mads+xml', + 'maei' => 'application/mmt-aei+xml', + 'mag' => 'application/vnd.ecowin.chart', + 'maker' => 'application/vnd.framemaker', + 'man' => 'text/troff', + 'manifest' => 'text/cache-manifest', + 'map' => 'application/json', + 'mar' => 'application/octet-stream', + 'markdown' => 'text/markdown', + 'mathml' => 'application/mathml+xml', + 'mb' => 'application/mathematica', + 'mbk' => 'application/vnd.mobius.mbk', + 'mbox' => 'application/mbox', + 'mc1' => 'application/vnd.medcalcdata', + 'mcd' => 'application/vnd.mcd', + 'mcurl' => 'text/vnd.curl.mcurl', + 'md' => 'text/markdown', + 'mdb' => 'application/x-msaccess', + 'mdi' => 'image/vnd.ms-modi', + 'mdx' => 'text/mdx', + 'me' => 'text/troff', + 'mesh' => 'model/mesh', + 'meta4' => 'application/metalink4+xml', + 'metalink' => 'application/metalink+xml', + 'mets' => 'application/mets+xml', + 'mfm' => 'application/vnd.mfmp', + 'mft' => 'application/rpki-manifest', + 'mgp' => 'application/vnd.osgeo.mapguide.package', + 'mgz' => 'application/vnd.proteus.magazine', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mie' => 'application/x-mie', + 'mif' => 'application/vnd.mif', + 'mime' => 'message/rfc822', + 'mj2' => 'video/mj2', + 'mjp2' => 'video/mj2', + 'mjs' => 'application/javascript', + 'mk3d' => 'video/x-matroska', + 'mka' => 'audio/x-matroska', + 'mkd' => 'text/x-markdown', + 'mks' => 'video/x-matroska', + 'mkv' => 'video/x-matroska', + 'mlp' => 'application/vnd.dolby.mlp', + 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', + 'mmf' => 'application/vnd.smaf', + 'mml' => 'text/mathml', + 'mmr' => 'image/vnd.fujixerox.edmics-mmr', + 'mng' => 'video/x-mng', + 'mny' => 'application/x-msmoney', + 'mobi' => 'application/x-mobipocket-ebook', + 'mods' => 'application/mods+xml', + 'mov' => 'video/quicktime', + 'movie' => 'video/x-sgi-movie', + 'mp2' => 'audio/mpeg', + 'mp2a' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'mp4a' => 'audio/mp4', + 'mp4s' => 'application/mp4', + 'mp4v' => 'video/mp4', + 'mp21' => 'application/mp21', + 'mpc' => 'application/vnd.mophun.certificate', + 'mpd' => 'application/dash+xml', + 'mpe' => 'video/mpeg', + 'mpeg' => 'video/mpeg', + 'mpf' => 'application/media-policy-dataset+xml', + 'mpg' => 'video/mpeg', + 'mpg4' => 'video/mp4', + 'mpga' => 'audio/mpeg', + 'mpkg' => 'application/vnd.apple.installer+xml', + 'mpm' => 'application/vnd.blueice.multipass', + 'mpn' => 'application/vnd.mophun.application', + 'mpp' => 'application/vnd.ms-project', + 'mpt' => 'application/vnd.ms-project', + 'mpy' => 'application/vnd.ibm.minipay', + 'mqy' => 'application/vnd.mobius.mqy', + 'mrc' => 'application/marc', + 'mrcx' => 'application/marcxml+xml', + 'ms' => 'text/troff', + 'mscml' => 'application/mediaservercontrol+xml', + 'mseed' => 'application/vnd.fdsn.mseed', + 'mseq' => 'application/vnd.mseq', + 'msf' => 'application/vnd.epson.msf', + 'msg' => 'application/vnd.ms-outlook', + 'msh' => 'model/mesh', + 'msi' => 'application/x-msdownload', + 'msl' => 'application/vnd.mobius.msl', + 'msm' => 'application/octet-stream', + 'msp' => 'application/octet-stream', + 'msty' => 'application/vnd.muvee.style', + 'mtl' => 'model/mtl', + 'mts' => 'model/vnd.mts', + 'mus' => 'application/vnd.musician', + 'musd' => 'application/mmt-usd+xml', + 'musicxml' => 'application/vnd.recordare.musicxml+xml', + 'mvb' => 'application/x-msmediaview', + 'mvt' => 'application/vnd.mapbox-vector-tile', + 'mwf' => 'application/vnd.mfer', + 'mxf' => 'application/mxf', + 'mxl' => 'application/vnd.recordare.musicxml', + 'mxmf' => 'audio/mobile-xmf', + 'mxml' => 'application/xv+xml', + 'mxs' => 'application/vnd.triscape.mxs', + 'mxu' => 'video/vnd.mpegurl', + 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', + 'n3' => 'text/n3', + 'nb' => 'application/mathematica', + 'nbp' => 'application/vnd.wolfram.player', + 'nc' => 'application/x-netcdf', + 'ncx' => 'application/x-dtbncx+xml', + 'nfo' => 'text/x-nfo', + 'ngdat' => 'application/vnd.nokia.n-gage.data', + 'nitf' => 'application/vnd.nitf', + 'nlu' => 'application/vnd.neurolanguage.nlu', + 'nml' => 'application/vnd.enliven', + 'nnd' => 'application/vnd.noblenet-directory', + 'nns' => 'application/vnd.noblenet-sealer', + 'nnw' => 'application/vnd.noblenet-web', + 'npx' => 'image/vnd.net-fpx', + 'nq' => 'application/n-quads', + 'nsc' => 'application/x-conference', + 'nsf' => 'application/vnd.lotus-notes', + 'nt' => 'application/n-triples', + 'ntf' => 'application/vnd.nitf', + 'numbers' => 'application/x-iwork-numbers-sffnumbers', + 'nzb' => 'application/x-nzb', + 'oa2' => 'application/vnd.fujitsu.oasys2', + 'oa3' => 'application/vnd.fujitsu.oasys3', + 'oas' => 'application/vnd.fujitsu.oasys', + 'obd' => 'application/x-msbinder', + 'obgx' => 'application/vnd.openblox.game+xml', + 'obj' => 'model/obj', + 'oda' => 'application/oda', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'odf' => 'application/vnd.oasis.opendocument.formula', + 'odft' => 'application/vnd.oasis.opendocument.formula-template', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'odi' => 'application/vnd.oasis.opendocument.image', + 'odm' => 'application/vnd.oasis.opendocument.text-master', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'oga' => 'audio/ogg', + 'ogex' => 'model/vnd.opengex', + 'ogg' => 'audio/ogg', + 'ogv' => 'video/ogg', + 'ogx' => 'application/ogg', + 'omdoc' => 'application/omdoc+xml', + 'onepkg' => 'application/onenote', + 'onetmp' => 'application/onenote', + 'onetoc' => 'application/onenote', + 'onetoc2' => 'application/onenote', + 'opf' => 'application/oebps-package+xml', + 'opml' => 'text/x-opml', + 'oprc' => 'application/vnd.palm', + 'opus' => 'audio/ogg', + 'org' => 'text/x-org', + 'osf' => 'application/vnd.yamaha.openscoreformat', + 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', + 'osm' => 'application/vnd.openstreetmap.data+xml', + 'otc' => 'application/vnd.oasis.opendocument.chart-template', + 'otf' => 'font/otf', + 'otg' => 'application/vnd.oasis.opendocument.graphics-template', + 'oth' => 'application/vnd.oasis.opendocument.text-web', + 'oti' => 'application/vnd.oasis.opendocument.image-template', + 'otp' => 'application/vnd.oasis.opendocument.presentation-template', + 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', + 'ott' => 'application/vnd.oasis.opendocument.text-template', + 'ova' => 'application/x-virtualbox-ova', + 'ovf' => 'application/x-virtualbox-ovf', + 'owl' => 'application/rdf+xml', + 'oxps' => 'application/oxps', + 'oxt' => 'application/vnd.openofficeorg.extension', + 'p' => 'text/x-pascal', + 'p7a' => 'application/x-pkcs7-signature', + 'p7b' => 'application/x-pkcs7-certificates', + 'p7c' => 'application/pkcs7-mime', + 'p7m' => 'application/pkcs7-mime', + 'p7r' => 'application/x-pkcs7-certreqresp', + 'p7s' => 'application/pkcs7-signature', + 'p8' => 'application/pkcs8', + 'p10' => 'application/x-pkcs10', + 'p12' => 'application/x-pkcs12', + 'pac' => 'application/x-ns-proxy-autoconfig', + 'pages' => 'application/x-iwork-pages-sffpages', + 'pas' => 'text/x-pascal', + 'paw' => 'application/vnd.pawaafile', + 'pbd' => 'application/vnd.powerbuilder6', + 'pbm' => 'image/x-portable-bitmap', + 'pcap' => 'application/vnd.tcpdump.pcap', + 'pcf' => 'application/x-font-pcf', + 'pcl' => 'application/vnd.hp-pcl', + 'pclxl' => 'application/vnd.hp-pclxl', + 'pct' => 'image/x-pict', + 'pcurl' => 'application/vnd.curl.pcurl', + 'pcx' => 'image/x-pcx', + 'pdb' => 'application/x-pilot', + 'pde' => 'text/x-processing', + 'pdf' => 'application/pdf', + 'pem' => 'application/x-x509-user-cert', + 'pfa' => 'application/x-font-type1', + 'pfb' => 'application/x-font-type1', + 'pfm' => 'application/x-font-type1', + 'pfr' => 'application/font-tdpfr', + 'pfx' => 'application/x-pkcs12', + 'pgm' => 'image/x-portable-graymap', + 'pgn' => 'application/x-chess-pgn', + 'pgp' => 'application/pgp', + 'phar' => 'application/octet-stream', + 'php' => 'application/x-httpd-php', + 'php3' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'phps' => 'application/x-httpd-php-source', + 'phtml' => 'application/x-httpd-php', + 'pic' => 'image/x-pict', + 'pkg' => 'application/octet-stream', + 'pki' => 'application/pkixcmp', + 'pkipath' => 'application/pkix-pkipath', + 'pkpass' => 'application/vnd.apple.pkpass', + 'pl' => 'application/x-perl', + 'plb' => 'application/vnd.3gpp.pic-bw-large', + 'plc' => 'application/vnd.mobius.plc', + 'plf' => 'application/vnd.pocketlearn', + 'pls' => 'application/pls+xml', + 'pm' => 'application/x-perl', + 'pml' => 'application/vnd.ctc-posml', + 'png' => 'image/png', + 'pnm' => 'image/x-portable-anymap', + 'portpkg' => 'application/vnd.macports.portpkg', + 'pot' => 'application/vnd.ms-powerpoint', + 'potm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppa' => 'application/vnd.ms-powerpoint', + 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', + 'ppd' => 'application/vnd.cups-ppd', + 'ppm' => 'image/x-portable-pixmap', + 'pps' => 'application/vnd.ms-powerpoint', + 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'ppt' => 'application/powerpoint', + 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'pqa' => 'application/vnd.palm', + 'prc' => 'model/prc', + 'pre' => 'application/vnd.lotus-freelance', + 'prf' => 'application/pics-rules', + 'provx' => 'application/provenance+xml', + 'ps' => 'application/postscript', + 'psb' => 'application/vnd.3gpp.pic-bw-small', + 'psd' => 'application/x-photoshop', + 'psf' => 'application/x-font-linux-psf', + 'pskcxml' => 'application/pskc+xml', + 'pti' => 'image/prs.pti', + 'ptid' => 'application/vnd.pvi.ptid1', + 'pub' => 'application/x-mspublisher', + 'pvb' => 'application/vnd.3gpp.pic-bw-var', + 'pwn' => 'application/vnd.3m.post-it-notes', + 'pya' => 'audio/vnd.ms-playready.media.pya', + 'pyv' => 'video/vnd.ms-playready.media.pyv', + 'qam' => 'application/vnd.epson.quickanime', + 'qbo' => 'application/vnd.intu.qbo', + 'qfx' => 'application/vnd.intu.qfx', + 'qps' => 'application/vnd.publishare-delta-tree', + 'qt' => 'video/quicktime', + 'qwd' => 'application/vnd.quark.quarkxpress', + 'qwt' => 'application/vnd.quark.quarkxpress', + 'qxb' => 'application/vnd.quark.quarkxpress', + 'qxd' => 'application/vnd.quark.quarkxpress', + 'qxl' => 'application/vnd.quark.quarkxpress', + 'qxt' => 'application/vnd.quark.quarkxpress', + 'ra' => 'audio/x-realaudio', + 'ram' => 'audio/x-pn-realaudio', + 'raml' => 'application/raml+yaml', + 'rapd' => 'application/route-apd+xml', + 'rar' => 'application/x-rar', + 'ras' => 'image/x-cmu-raster', + 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', + 'rdf' => 'application/rdf+xml', + 'rdz' => 'application/vnd.data-vision.rdz', + 'relo' => 'application/p2p-overlay+xml', + 'rep' => 'application/vnd.businessobjects', + 'res' => 'application/x-dtbresource+xml', + 'rgb' => 'image/x-rgb', + 'rif' => 'application/reginfo+xml', + 'rip' => 'audio/vnd.rip', + 'ris' => 'application/x-research-info-systems', + 'rl' => 'application/resource-lists+xml', + 'rlc' => 'image/vnd.fujixerox.edmics-rlc', + 'rld' => 'application/resource-lists-diff+xml', + 'rm' => 'audio/x-pn-realaudio', + 'rmi' => 'audio/midi', + 'rmp' => 'audio/x-pn-realaudio-plugin', + 'rms' => 'application/vnd.jcp.javame.midlet-rms', + 'rmvb' => 'application/vnd.rn-realmedia-vbr', + 'rnc' => 'application/relax-ng-compact-syntax', + 'rng' => 'application/xml', + 'roa' => 'application/rpki-roa', + 'roff' => 'text/troff', + 'rp9' => 'application/vnd.cloanto.rp9', + 'rpm' => 'audio/x-pn-realaudio-plugin', + 'rpss' => 'application/vnd.nokia.radio-presets', + 'rpst' => 'application/vnd.nokia.radio-preset', + 'rq' => 'application/sparql-query', + 'rs' => 'application/rls-services+xml', + 'rsa' => 'application/x-pkcs7', + 'rsat' => 'application/atsc-rsat+xml', + 'rsd' => 'application/rsd+xml', + 'rsheet' => 'application/urc-ressheet+xml', + 'rss' => 'application/rss+xml', + 'rtf' => 'text/rtf', + 'rtx' => 'text/richtext', + 'run' => 'application/x-makeself', + 'rusd' => 'application/route-usd+xml', + 'rv' => 'video/vnd.rn-realvideo', + 's' => 'text/x-asm', + 's3m' => 'audio/s3m', + 'saf' => 'application/vnd.yamaha.smaf-audio', + 'sass' => 'text/x-sass', + 'sbml' => 'application/sbml+xml', + 'sc' => 'application/vnd.ibm.secure-container', + 'scd' => 'application/x-msschedule', + 'scm' => 'application/vnd.lotus-screencam', + 'scq' => 'application/scvp-cv-request', + 'scs' => 'application/scvp-cv-response', + 'scss' => 'text/x-scss', + 'scurl' => 'text/vnd.curl.scurl', + 'sda' => 'application/vnd.stardivision.draw', + 'sdc' => 'application/vnd.stardivision.calc', + 'sdd' => 'application/vnd.stardivision.impress', + 'sdkd' => 'application/vnd.solent.sdkm+xml', + 'sdkm' => 'application/vnd.solent.sdkm+xml', + 'sdp' => 'application/sdp', + 'sdw' => 'application/vnd.stardivision.writer', + 'sea' => 'application/octet-stream', + 'see' => 'application/vnd.seemail', + 'seed' => 'application/vnd.fdsn.seed', + 'sema' => 'application/vnd.sema', + 'semd' => 'application/vnd.semd', + 'semf' => 'application/vnd.semf', + 'senmlx' => 'application/senml+xml', + 'sensmlx' => 'application/sensml+xml', + 'ser' => 'application/java-serialized-object', + 'setpay' => 'application/set-payment-initiation', + 'setreg' => 'application/set-registration-initiation', + 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', + 'sfs' => 'application/vnd.spotfire.sfs', + 'sfv' => 'text/x-sfv', + 'sgi' => 'image/sgi', + 'sgl' => 'application/vnd.stardivision.writer-global', + 'sgm' => 'text/sgml', + 'sgml' => 'text/sgml', + 'sh' => 'application/x-sh', + 'shar' => 'application/x-shar', + 'shex' => 'text/shex', + 'shf' => 'application/shf+xml', + 'shtml' => 'text/html', + 'sid' => 'image/x-mrsid-image', + 'sieve' => 'application/sieve', + 'sig' => 'application/pgp-signature', + 'sil' => 'audio/silk', + 'silo' => 'model/mesh', + 'sis' => 'application/vnd.symbian.install', + 'sisx' => 'application/vnd.symbian.install', + 'sit' => 'application/x-stuffit', + 'sitx' => 'application/x-stuffitx', + 'siv' => 'application/sieve', + 'skd' => 'application/vnd.koan', + 'skm' => 'application/vnd.koan', + 'skp' => 'application/vnd.koan', + 'skt' => 'application/vnd.koan', + 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', + 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'slim' => 'text/slim', + 'slm' => 'text/slim', + 'sls' => 'application/route-s-tsid+xml', + 'slt' => 'application/vnd.epson.salt', + 'sm' => 'application/vnd.stepmania.stepchart', + 'smf' => 'application/vnd.stardivision.math', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'smv' => 'video/x-smv', + 'smzip' => 'application/vnd.stepmania.package', + 'snd' => 'audio/basic', + 'snf' => 'application/x-font-snf', + 'so' => 'application/octet-stream', + 'spc' => 'application/x-pkcs7-certificates', + 'spdx' => 'text/spdx', + 'spf' => 'application/vnd.yamaha.smaf-phrase', + 'spl' => 'application/x-futuresplash', + 'spot' => 'text/vnd.in3d.spot', + 'spp' => 'application/scvp-vp-response', + 'spq' => 'application/scvp-vp-request', + 'spx' => 'audio/ogg', + 'sql' => 'application/x-sql', + 'src' => 'application/x-wais-source', + 'srt' => 'application/x-subrip', + 'sru' => 'application/sru+xml', + 'srx' => 'application/sparql-results+xml', + 'ssdl' => 'application/ssdl+xml', + 'sse' => 'application/vnd.kodak-descriptor', + 'ssf' => 'application/vnd.epson.ssf', + 'ssml' => 'application/ssml+xml', + 'sst' => 'application/octet-stream', + 'st' => 'application/vnd.sailingtracker.track', + 'stc' => 'application/vnd.sun.xml.calc.template', + 'std' => 'application/vnd.sun.xml.draw.template', + 'stf' => 'application/vnd.wt.stf', + 'sti' => 'application/vnd.sun.xml.impress.template', + 'stk' => 'application/hyperstudio', + 'stl' => 'model/stl', + 'stpx' => 'model/step+xml', + 'stpxz' => 'model/step-xml+zip', + 'stpz' => 'model/step+zip', + 'str' => 'application/vnd.pg.format', + 'stw' => 'application/vnd.sun.xml.writer.template', + 'styl' => 'text/stylus', + 'stylus' => 'text/stylus', + 'sub' => 'text/vnd.dvb.subtitle', + 'sus' => 'application/vnd.sus-calendar', + 'susp' => 'application/vnd.sus-calendar', + 'sv4cpio' => 'application/x-sv4cpio', + 'sv4crc' => 'application/x-sv4crc', + 'svc' => 'application/vnd.dvb.service', + 'svd' => 'application/vnd.svd', + 'svg' => 'image/svg+xml', + 'svgz' => 'image/svg+xml', + 'swa' => 'application/x-director', + 'swf' => 'application/x-shockwave-flash', + 'swi' => 'application/vnd.aristanetworks.swi', + 'swidtag' => 'application/swid+xml', + 'sxc' => 'application/vnd.sun.xml.calc', + 'sxd' => 'application/vnd.sun.xml.draw', + 'sxg' => 'application/vnd.sun.xml.writer.global', + 'sxi' => 'application/vnd.sun.xml.impress', + 'sxm' => 'application/vnd.sun.xml.math', + 'sxw' => 'application/vnd.sun.xml.writer', + 't' => 'text/troff', + 't3' => 'application/x-t3vm-image', + 't38' => 'image/t38', + 'taglet' => 'application/vnd.mynfc', + 'tao' => 'application/vnd.tao.intent-module-archive', + 'tap' => 'image/vnd.tencent.tap', + 'tar' => 'application/x-tar', + 'tcap' => 'application/vnd.3gpp2.tcap', + 'tcl' => 'application/x-tcl', + 'td' => 'application/urc-targetdesc+xml', + 'teacher' => 'application/vnd.smart.teacher', + 'tei' => 'application/tei+xml', + 'teicorpus' => 'application/tei+xml', + 'tex' => 'application/x-tex', + 'texi' => 'application/x-texinfo', + 'texinfo' => 'application/x-texinfo', + 'text' => 'text/plain', + 'tfi' => 'application/thraud+xml', + 'tfm' => 'application/x-tex-tfm', + 'tfx' => 'image/tiff-fx', + 'tga' => 'image/x-tga', + 'tgz' => 'application/x-tar', + 'thmx' => 'application/vnd.ms-officetheme', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'tk' => 'application/x-tcl', + 'tmo' => 'application/vnd.tmobile-livetv', + 'toml' => 'application/toml', + 'torrent' => 'application/x-bittorrent', + 'tpl' => 'application/vnd.groove-tool-template', + 'tpt' => 'application/vnd.trid.tpt', + 'tr' => 'text/troff', + 'tra' => 'application/vnd.trueapp', + 'trig' => 'application/trig', + 'trm' => 'application/x-msterminal', + 'ts' => 'video/mp2t', + 'tsd' => 'application/timestamped-data', + 'tsv' => 'text/tab-separated-values', + 'ttc' => 'font/collection', + 'ttf' => 'font/ttf', + 'ttl' => 'text/turtle', + 'ttml' => 'application/ttml+xml', + 'twd' => 'application/vnd.simtech-mindmapper', + 'twds' => 'application/vnd.simtech-mindmapper', + 'txd' => 'application/vnd.genomatix.tuxedo', + 'txf' => 'application/vnd.mobius.txf', + 'txt' => 'text/plain', + 'u3d' => 'model/u3d', + 'u8dsn' => 'message/global-delivery-status', + 'u8hdr' => 'message/global-headers', + 'u8mdn' => 'message/global-disposition-notification', + 'u8msg' => 'message/global', + 'u32' => 'application/x-authorware-bin', + 'ubj' => 'application/ubjson', + 'udeb' => 'application/x-debian-package', + 'ufd' => 'application/vnd.ufdl', + 'ufdl' => 'application/vnd.ufdl', + 'ulx' => 'application/x-glulx', + 'umj' => 'application/vnd.umajin', + 'unityweb' => 'application/vnd.unity', + 'uoml' => 'application/vnd.uoml+xml', + 'uri' => 'text/uri-list', + 'uris' => 'text/uri-list', + 'urls' => 'text/uri-list', + 'usdz' => 'model/vnd.usdz+zip', + 'ustar' => 'application/x-ustar', + 'utz' => 'application/vnd.uiq.theme', + 'uu' => 'text/x-uuencode', + 'uva' => 'audio/vnd.dece.audio', + 'uvd' => 'application/vnd.dece.data', + 'uvf' => 'application/vnd.dece.data', + 'uvg' => 'image/vnd.dece.graphic', + 'uvh' => 'video/vnd.dece.hd', + 'uvi' => 'image/vnd.dece.graphic', + 'uvm' => 'video/vnd.dece.mobile', + 'uvp' => 'video/vnd.dece.pd', + 'uvs' => 'video/vnd.dece.sd', + 'uvt' => 'application/vnd.dece.ttml+xml', + 'uvu' => 'video/vnd.uvvu.mp4', + 'uvv' => 'video/vnd.dece.video', + 'uvva' => 'audio/vnd.dece.audio', + 'uvvd' => 'application/vnd.dece.data', + 'uvvf' => 'application/vnd.dece.data', + 'uvvg' => 'image/vnd.dece.graphic', + 'uvvh' => 'video/vnd.dece.hd', + 'uvvi' => 'image/vnd.dece.graphic', + 'uvvm' => 'video/vnd.dece.mobile', + 'uvvp' => 'video/vnd.dece.pd', + 'uvvs' => 'video/vnd.dece.sd', + 'uvvt' => 'application/vnd.dece.ttml+xml', + 'uvvu' => 'video/vnd.uvvu.mp4', + 'uvvv' => 'video/vnd.dece.video', + 'uvvx' => 'application/vnd.dece.unspecified', + 'uvvz' => 'application/vnd.dece.zip', + 'uvx' => 'application/vnd.dece.unspecified', + 'uvz' => 'application/vnd.dece.zip', + 'vbox' => 'application/x-virtualbox-vbox', + 'vbox-extpack' => 'application/x-virtualbox-vbox-extpack', + 'vcard' => 'text/vcard', + 'vcd' => 'application/x-cdlink', + 'vcf' => 'text/x-vcard', + 'vcg' => 'application/vnd.groove-vcard', + 'vcs' => 'text/x-vcalendar', + 'vcx' => 'application/vnd.vcx', + 'vdi' => 'application/x-virtualbox-vdi', + 'vds' => 'model/vnd.sap.vds', + 'vhd' => 'application/x-virtualbox-vhd', + 'vis' => 'application/vnd.visionary', + 'viv' => 'video/vnd.vivo', + 'vlc' => 'application/videolan', + 'vmdk' => 'application/x-virtualbox-vmdk', + 'vob' => 'video/x-ms-vob', + 'vor' => 'application/vnd.stardivision.writer', + 'vox' => 'application/x-authorware-bin', + 'vrml' => 'model/vrml', + 'vsd' => 'application/vnd.visio', + 'vsf' => 'application/vnd.vsf', + 'vss' => 'application/vnd.visio', + 'vst' => 'application/vnd.visio', + 'vsw' => 'application/vnd.visio', + 'vtf' => 'image/vnd.valve.source.texture', + 'vtt' => 'text/vtt', + 'vtu' => 'model/vnd.vtu', + 'vxml' => 'application/voicexml+xml', + 'w3d' => 'application/x-director', + 'wad' => 'application/x-doom', + 'wadl' => 'application/vnd.sun.wadl+xml', + 'war' => 'application/java-archive', + 'wasm' => 'application/wasm', + 'wav' => 'audio/x-wav', + 'wax' => 'audio/x-ms-wax', + 'wbmp' => 'image/vnd.wap.wbmp', + 'wbs' => 'application/vnd.criticaltools.wbs+xml', + 'wbxml' => 'application/wbxml', + 'wcm' => 'application/vnd.ms-works', + 'wdb' => 'application/vnd.ms-works', + 'wdp' => 'image/vnd.ms-photo', + 'weba' => 'audio/webm', + 'webapp' => 'application/x-web-app-manifest+json', + 'webm' => 'video/webm', + 'webmanifest' => 'application/manifest+json', + 'webp' => 'image/webp', + 'wg' => 'application/vnd.pmi.widget', + 'wgt' => 'application/widget', + 'wif' => 'application/watcherinfo+xml', + 'wks' => 'application/vnd.ms-works', + 'wm' => 'video/x-ms-wm', + 'wma' => 'audio/x-ms-wma', + 'wmd' => 'application/x-ms-wmd', + 'wmf' => 'image/wmf', + 'wml' => 'text/vnd.wap.wml', + 'wmlc' => 'application/wmlc', + 'wmls' => 'text/vnd.wap.wmlscript', + 'wmlsc' => 'application/vnd.wap.wmlscriptc', + 'wmv' => 'video/x-ms-wmv', + 'wmx' => 'video/x-ms-wmx', + 'wmz' => 'application/x-msmetafile', + 'woff' => 'font/woff', + 'woff2' => 'font/woff2', + 'word' => 'application/msword', + 'wpd' => 'application/vnd.wordperfect', + 'wpl' => 'application/vnd.ms-wpl', + 'wps' => 'application/vnd.ms-works', + 'wqd' => 'application/vnd.wqd', + 'wri' => 'application/x-mswrite', + 'wrl' => 'model/vrml', + 'wsc' => 'message/vnd.wfa.wsc', + 'wsdl' => 'application/wsdl+xml', + 'wspolicy' => 'application/wspolicy+xml', + 'wtb' => 'application/vnd.webturbo', + 'wvx' => 'video/x-ms-wvx', + 'x3d' => 'model/x3d+xml', + 'x3db' => 'model/x3d+fastinfoset', + 'x3dbz' => 'model/x3d+binary', + 'x3dv' => 'model/x3d-vrml', + 'x3dvz' => 'model/x3d+vrml', + 'x3dz' => 'model/x3d+xml', + 'x32' => 'application/x-authorware-bin', + 'x_b' => 'model/vnd.parasolid.transmit.binary', + 'x_t' => 'model/vnd.parasolid.transmit.text', + 'xaml' => 'application/xaml+xml', + 'xap' => 'application/x-silverlight-app', + 'xar' => 'application/vnd.xara', + 'xav' => 'application/xcap-att+xml', + 'xbap' => 'application/x-ms-xbap', + 'xbd' => 'application/vnd.fujixerox.docuworks.binder', + 'xbm' => 'image/x-xbitmap', + 'xca' => 'application/xcap-caps+xml', + 'xcs' => 'application/calendar+xml', + 'xdf' => 'application/xcap-diff+xml', + 'xdm' => 'application/vnd.syncml.dm+xml', + 'xdp' => 'application/vnd.adobe.xdp+xml', + 'xdssc' => 'application/dssc+xml', + 'xdw' => 'application/vnd.fujixerox.docuworks', + 'xel' => 'application/xcap-el+xml', + 'xenc' => 'application/xenc+xml', + 'xer' => 'application/patch-ops-error+xml', + 'xfdf' => 'application/vnd.adobe.xfdf', + 'xfdl' => 'application/vnd.xfdl', + 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', + 'xhvml' => 'application/xv+xml', + 'xif' => 'image/vnd.xiff', + 'xl' => 'application/excel', + 'xla' => 'application/vnd.ms-excel', + 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'xlc' => 'application/vnd.ms-excel', + 'xlf' => 'application/xliff+xml', + 'xlm' => 'application/vnd.ms-excel', + 'xls' => 'application/vnd.ms-excel', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xlt' => 'application/vnd.ms-excel', + 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'xlw' => 'application/vnd.ms-excel', + 'xm' => 'audio/xm', + 'xml' => 'application/xml', + 'xns' => 'application/xcap-ns+xml', + 'xo' => 'application/vnd.olpc-sugar', + 'xop' => 'application/xop+xml', + 'xpi' => 'application/x-xpinstall', + 'xpl' => 'application/xproc+xml', + 'xpm' => 'image/x-xpixmap', + 'xpr' => 'application/vnd.is-xpr', + 'xps' => 'application/vnd.ms-xpsdocument', + 'xpw' => 'application/vnd.intercon.formnet', + 'xpx' => 'application/vnd.intercon.formnet', + 'xsd' => 'application/xml', + 'xsl' => 'application/xml', + 'xslt' => 'application/xslt+xml', + 'xsm' => 'application/vnd.syncml+xml', + 'xspf' => 'application/xspf+xml', + 'xul' => 'application/vnd.mozilla.xul+xml', + 'xvm' => 'application/xv+xml', + 'xvml' => 'application/xv+xml', + 'xwd' => 'image/x-xwindowdump', + 'xyz' => 'chemical/x-xyz', + 'xz' => 'application/x-xz', + 'yaml' => 'text/yaml', + 'yang' => 'application/yang', + 'yin' => 'application/yin+xml', + 'yml' => 'text/yaml', + 'ymp' => 'text/x-suse-ymp', + 'z' => 'application/x-compress', + 'z1' => 'application/x-zmachine', + 'z2' => 'application/x-zmachine', + 'z3' => 'application/x-zmachine', + 'z4' => 'application/x-zmachine', + 'z5' => 'application/x-zmachine', + 'z6' => 'application/x-zmachine', + 'z7' => 'application/x-zmachine', + 'z8' => 'application/x-zmachine', + 'zaz' => 'application/vnd.zzazz.deck+xml', + 'zip' => 'application/zip', + 'zir' => 'application/vnd.zul', + 'zirz' => 'application/vnd.zul', + 'zmm' => 'application/vnd.handheld-entertainment+xml', + 'zsh' => 'text/x-scriptzsh', + ]; + + /** + * Determines the mimetype of a file by looking at its extension. + * + * @link https://raw.githubusercontent.com/jshttp/mime-db/master/db.json + */ + public static function fromFilename(string $filename): ?string + { + return self::fromExtension(pathinfo($filename, PATHINFO_EXTENSION)); + } + + /** + * Maps a file extensions to a mimetype. + * + * @link https://raw.githubusercontent.com/jshttp/mime-db/master/db.json + */ + public static function fromExtension(string $extension): ?string + { + return self::MIME_TYPES[strtolower($extension)] ?? null; + } +} diff --git a/vendor/guzzlehttp/psr7/src/MultipartStream.php b/vendor/guzzlehttp/psr7/src/MultipartStream.php index c0fd584..3e12b74 100644 --- a/vendor/guzzlehttp/psr7/src/MultipartStream.php +++ b/vendor/guzzlehttp/psr7/src/MultipartStream.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; @@ -7,12 +10,16 @@ * Stream that when read returns bytes for a streaming multipart or * multipart/form-data stream. */ -class MultipartStream implements StreamInterface +final class MultipartStream implements StreamInterface { use StreamDecoratorTrait; + /** @var string */ private $boundary; + /** @var StreamInterface */ + private $stream; + /** * @param array $elements Array of associative arrays, each containing a * required "name" key mapping to the form field, @@ -25,31 +32,28 @@ class MultipartStream implements StreamInterface * * @throws \InvalidArgumentException */ - public function __construct(array $elements = [], $boundary = null) + public function __construct(array $elements = [], string $boundary = null) { - $this->boundary = $boundary ?: sha1(uniqid('', true)); + $this->boundary = $boundary ?: bin2hex(random_bytes(20)); $this->stream = $this->createStream($elements); } - /** - * Get the boundary - * - * @return string - */ - public function getBoundary() + public function getBoundary(): string { return $this->boundary; } - public function isWritable() + public function isWritable(): bool { return false; } /** * Get the headers needed before transferring the content of a POST file + * + * @param array<string, string> $headers */ - private function getHeaders(array $headers) + private function getHeaders(array $headers): string { $str = ''; foreach ($headers as $key => $value) { @@ -62,21 +66,24 @@ private function getHeaders(array $headers) /** * Create the aggregate stream that will be used to upload the POST data */ - protected function createStream(array $elements) + protected function createStream(array $elements = []): StreamInterface { $stream = new AppendStream(); foreach ($elements as $element) { + if (!is_array($element)) { + throw new \UnexpectedValueException("An array is expected"); + } $this->addElement($stream, $element); } // Add the trailing boundary with CRLF - $stream->addStream(stream_for("--{$this->boundary}--\r\n")); + $stream->addStream(Utils::streamFor("--{$this->boundary}--\r\n")); return $stream; } - private function addElement(AppendStream $stream, array $element) + private function addElement(AppendStream $stream, array $element): void { foreach (['contents', 'name'] as $key) { if (!array_key_exists($key, $element)) { @@ -84,39 +91,38 @@ private function addElement(AppendStream $stream, array $element) } } - $element['contents'] = stream_for($element['contents']); + $element['contents'] = Utils::streamFor($element['contents']); if (empty($element['filename'])) { $uri = $element['contents']->getMetadata('uri'); - if (substr($uri, 0, 6) !== 'php://') { + if ($uri && \is_string($uri) && \substr($uri, 0, 6) !== 'php://' && \substr($uri, 0, 7) !== 'data://') { $element['filename'] = $uri; } } - list($body, $headers) = $this->createElement( + [$body, $headers] = $this->createElement( $element['name'], $element['contents'], - isset($element['filename']) ? $element['filename'] : null, - isset($element['headers']) ? $element['headers'] : [] + $element['filename'] ?? null, + $element['headers'] ?? [] ); - $stream->addStream(stream_for($this->getHeaders($headers))); + $stream->addStream(Utils::streamFor($this->getHeaders($headers))); $stream->addStream($body); - $stream->addStream(stream_for("\r\n")); + $stream->addStream(Utils::streamFor("\r\n")); } - /** - * @return array - */ - private function createElement($name, StreamInterface $stream, $filename, array $headers) + private function createElement(string $name, StreamInterface $stream, ?string $filename, array $headers): array { // Set a default content-disposition header if one was no provided $disposition = $this->getHeader($headers, 'content-disposition'); if (!$disposition) { $headers['Content-Disposition'] = ($filename === '0' || $filename) - ? sprintf('form-data; name="%s"; filename="%s"', + ? sprintf( + 'form-data; name="%s"; filename="%s"', $name, - basename($filename)) + basename($filename) + ) : "form-data; name=\"{$name}\""; } @@ -131,7 +137,7 @@ private function createElement($name, StreamInterface $stream, $filename, array // Set a default Content-Type if one was not supplied $type = $this->getHeader($headers, 'content-type'); if (!$type && ($filename === '0' || $filename)) { - if ($type = mimetype_from_filename($filename)) { + if ($type = MimeType::fromFilename($filename)) { $headers['Content-Type'] = $type; } } @@ -139,7 +145,7 @@ private function createElement($name, StreamInterface $stream, $filename, array return [$stream, $headers]; } - private function getHeader(array $headers, $key) + private function getHeader(array $headers, string $key) { $lowercaseHeader = strtolower($key); foreach ($headers as $k => $v) { diff --git a/vendor/guzzlehttp/psr7/src/NoSeekStream.php b/vendor/guzzlehttp/psr7/src/NoSeekStream.php index 2332218..161a224 100644 --- a/vendor/guzzlehttp/psr7/src/NoSeekStream.php +++ b/vendor/guzzlehttp/psr7/src/NoSeekStream.php @@ -1,21 +1,27 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** - * Stream decorator that prevents a stream from being seeked + * Stream decorator that prevents a stream from being seeked. */ -class NoSeekStream implements StreamInterface +final class NoSeekStream implements StreamInterface { use StreamDecoratorTrait; - public function seek($offset, $whence = SEEK_SET) + /** @var StreamInterface */ + private $stream; + + public function seek($offset, $whence = SEEK_SET): void { throw new \RuntimeException('Cannot seek a NoSeekStream'); } - public function isSeekable() + public function isSeekable(): bool { return false; } diff --git a/vendor/guzzlehttp/psr7/src/PumpStream.php b/vendor/guzzlehttp/psr7/src/PumpStream.php index ffb5440..e90389c 100644 --- a/vendor/guzzlehttp/psr7/src/PumpStream.php +++ b/vendor/guzzlehttp/psr7/src/PumpStream.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; @@ -13,12 +16,12 @@ * the read() function of the PumpStream. The provided callable MUST return * false when there is no more data to read. */ -class PumpStream implements StreamInterface +final class PumpStream implements StreamInterface { - /** @var callable */ + /** @var callable|null */ private $source; - /** @var int */ + /** @var int|null */ private $size; /** @var int */ @@ -31,89 +34,95 @@ class PumpStream implements StreamInterface private $buffer; /** - * @param callable $source Source of the stream data. The callable MAY - * accept an integer argument used to control the - * amount of data to return. The callable MUST - * return a string when called, or false on error - * or EOF. - * @param array $options Stream options: - * - metadata: Hash of metadata to use with stream. - * - size: Size of the stream, if known. + * @param callable(int): (string|null|false) $source Source of the stream data. The callable MAY + * accept an integer argument used to control the + * amount of data to return. The callable MUST + * return a string when called, or false|null on error + * or EOF. + * @param array{size?: int, metadata?: array} $options Stream options: + * - metadata: Hash of metadata to use with stream. + * - size: Size of the stream, if known. */ public function __construct(callable $source, array $options = []) { $this->source = $source; - $this->size = isset($options['size']) ? $options['size'] : null; - $this->metadata = isset($options['metadata']) ? $options['metadata'] : []; + $this->size = $options['size'] ?? null; + $this->metadata = $options['metadata'] ?? []; $this->buffer = new BufferStream(); } - public function __toString() + public function __toString(): string { try { - return copy_to_string($this); - } catch (\Exception $e) { + return Utils::copyToString($this); + } catch (\Throwable $e) { + if (\PHP_VERSION_ID >= 70400) { + throw $e; + } + trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } - public function close() + public function close(): void { $this->detach(); } public function detach() { - $this->tellPos = false; + $this->tellPos = 0; $this->source = null; + + return null; } - public function getSize() + public function getSize(): ?int { return $this->size; } - public function tell() + public function tell(): int { return $this->tellPos; } - public function eof() + public function eof(): bool { - return !$this->source; + return $this->source === null; } - public function isSeekable() + public function isSeekable(): bool { return false; } - public function rewind() + public function rewind(): void { $this->seek(0); } - public function seek($offset, $whence = SEEK_SET) + public function seek($offset, $whence = SEEK_SET): void { throw new \RuntimeException('Cannot seek a PumpStream'); } - public function isWritable() + public function isWritable(): bool { return false; } - public function write($string) + public function write($string): int { throw new \RuntimeException('Cannot write to a PumpStream'); } - public function isReadable() + public function isReadable(): bool { return true; } - public function read($length) + public function read($length): string { $data = $this->buffer->read($length); $readLen = strlen($data); @@ -129,7 +138,7 @@ public function read($length) return $data; } - public function getContents() + public function getContents(): string { $result = ''; while (!$this->eof()) { @@ -139,16 +148,21 @@ public function getContents() return $result; } + /** + * {@inheritdoc} + * + * @return mixed + */ public function getMetadata($key = null) { if (!$key) { return $this->metadata; } - return isset($this->metadata[$key]) ? $this->metadata[$key] : null; + return $this->metadata[$key] ?? null; } - private function pump($length) + private function pump(int $length): void { if ($this->source) { do { diff --git a/vendor/guzzlehttp/psr7/src/Query.php b/vendor/guzzlehttp/psr7/src/Query.php new file mode 100644 index 0000000..2faab3a --- /dev/null +++ b/vendor/guzzlehttp/psr7/src/Query.php @@ -0,0 +1,113 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Psr7; + +final class Query +{ + /** + * 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 int|bool $urlEncoding How the query string is encoded + */ + public static function parse(string $str, $urlEncoding = true): array + { + $result = []; + + if ($str === '') { + return $result; + } + + if ($urlEncoding === true) { + $decoder = function ($value) { + return rawurldecode(str_replace('+', ' ', (string) $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 (!array_key_exists($key, $result)) { + $result[$key] = $value; + } else { + if (!is_array($result[$key])) { + $result[$key] = [$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 `parse()` 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. + */ + public static function build(array $params, $encoding = PHP_QUERY_RFC3986): string + { + if (!$params) { + return ''; + } + + if ($encoding === false) { + $encoder = function (string $str): string { + 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((string) $k); + if (!is_array($v)) { + $qs .= $k; + $v = is_bool($v) ? (int) $v : $v; + if ($v !== null) { + $qs .= '=' . $encoder((string) $v); + } + $qs .= '&'; + } else { + foreach ($v as $vv) { + $qs .= $k; + $vv = is_bool($vv) ? (int) $vv : $vv; + if ($vv !== null) { + $qs .= '=' . $encoder((string) $vv); + } + $qs .= '&'; + } + } + } + + return $qs ? (string) substr($qs, 0, -1) : ''; + } +} diff --git a/vendor/guzzlehttp/psr7/src/Request.php b/vendor/guzzlehttp/psr7/src/Request.php index 0828548..b17af66 100644 --- a/vendor/guzzlehttp/psr7/src/Request.php +++ b/vendor/guzzlehttp/psr7/src/Request.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use InvalidArgumentException; @@ -16,7 +19,7 @@ class Request implements RequestInterface /** @var string */ private $method; - /** @var null|string */ + /** @var string|null */ private $requestTarget; /** @var UriInterface */ @@ -25,17 +28,18 @@ class Request implements RequestInterface /** * @param string $method HTTP method * @param string|UriInterface $uri URI - * @param array $headers Request headers - * @param string|null|resource|StreamInterface $body Request body + * @param array<string, string|string[]> $headers Request headers + * @param string|resource|StreamInterface|null $body Request body * @param string $version Protocol version */ public function __construct( - $method, + string $method, $uri, array $headers = [], $body = null, - $version = '1.1' + string $version = '1.1' ) { + $this->assertMethod($method); if (!($uri instanceof UriInterface)) { $uri = new Uri($uri); } @@ -45,23 +49,23 @@ public function __construct( $this->setHeaders($headers); $this->protocol = $version; - if (!$this->hasHeader('Host')) { + if (!isset($this->headerNames['host'])) { $this->updateHostFromUri(); } if ($body !== '' && $body !== null) { - $this->stream = stream_for($body); + $this->stream = Utils::streamFor($body); } } - public function getRequestTarget() + public function getRequestTarget(): string { if ($this->requestTarget !== null) { return $this->requestTarget; } $target = $this->uri->getPath(); - if ($target == '') { + if ($target === '') { $target = '/'; } if ($this->uri->getQuery() != '') { @@ -71,7 +75,7 @@ public function getRequestTarget() return $target; } - public function withRequestTarget($requestTarget) + public function withRequestTarget($requestTarget): RequestInterface { if (preg_match('#\s#', $requestTarget)) { throw new InvalidArgumentException( @@ -84,24 +88,25 @@ public function withRequestTarget($requestTarget) return $new; } - public function getMethod() + public function getMethod(): string { return $this->method; } - public function withMethod($method) + public function withMethod($method): RequestInterface { + $this->assertMethod($method); $new = clone $this; $new->method = strtoupper($method); return $new; } - public function getUri() + public function getUri(): UriInterface { return $this->uri; } - public function withUri(UriInterface $uri, $preserveHost = false) + public function withUri(UriInterface $uri, $preserveHost = false): RequestInterface { if ($uri === $this->uri) { return $this; @@ -110,14 +115,14 @@ public function withUri(UriInterface $uri, $preserveHost = false) $new = clone $this; $new->uri = $uri; - if (!$preserveHost) { + if (!$preserveHost || !isset($this->headerNames['host'])) { $new->updateHostFromUri(); } return $new; } - private function updateHostFromUri() + private function updateHostFromUri(): void { $host = $this->uri->getHost(); @@ -139,4 +144,14 @@ private function updateHostFromUri() // See: http://tools.ietf.org/html/rfc7230#section-5.4 $this->headers = [$header => [$host]] + $this->headers; } + + /** + * @param mixed $method + */ + private function assertMethod($method): void + { + if (!is_string($method) || $method === '') { + throw new InvalidArgumentException('Method must be a non-empty string.'); + } + } } diff --git a/vendor/guzzlehttp/psr7/src/Response.php b/vendor/guzzlehttp/psr7/src/Response.php index 2830c6c..4c6ee6f 100644 --- a/vendor/guzzlehttp/psr7/src/Response.php +++ b/vendor/guzzlehttp/psr7/src/Response.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\ResponseInterface; @@ -11,8 +14,8 @@ class Response implements ResponseInterface { use MessageTrait; - /** @var array Map of standard HTTP status code/reason phrases */ - private static $phrases = [ + /** Map of standard HTTP status code/reason phrases */ + private const PHRASES = [ 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', @@ -33,6 +36,7 @@ class Response implements ResponseInterface 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', + 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', @@ -70,38 +74,41 @@ class Response implements ResponseInterface 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', + 510 => 'Not Extended', 511 => 'Network Authentication Required', ]; /** @var string */ - private $reasonPhrase = ''; + private $reasonPhrase; /** @var int */ - private $statusCode = 200; + private $statusCode; /** * @param int $status Status code - * @param array $headers Response headers - * @param string|null|resource|StreamInterface $body Response body + * @param array<string, string|string[]> $headers Response headers + * @param string|resource|StreamInterface|null $body Response body * @param string $version Protocol version * @param string|null $reason Reason phrase (when empty a default will be used based on the status code) */ public function __construct( - $status = 200, + int $status = 200, array $headers = [], $body = null, - $version = '1.1', - $reason = null + string $version = '1.1', + string $reason = null ) { - $this->statusCode = (int) $status; + $this->assertStatusCodeRange($status); + + $this->statusCode = $status; if ($body !== '' && $body !== null) { - $this->stream = stream_for($body); + $this->stream = Utils::streamFor($body); } $this->setHeaders($headers); - if ($reason == '' && isset(self::$phrases[$this->statusCode])) { - $this->reasonPhrase = self::$phrases[$this->statusCode]; + if ($reason == '' && isset(self::PHRASES[$this->statusCode])) { + $this->reasonPhrase = self::PHRASES[$this->statusCode]; } else { $this->reasonPhrase = (string) $reason; } @@ -109,24 +116,45 @@ public function __construct( $this->protocol = $version; } - public function getStatusCode() + public function getStatusCode(): int { return $this->statusCode; } - public function getReasonPhrase() + public function getReasonPhrase(): string { return $this->reasonPhrase; } - public function withStatus($code, $reasonPhrase = '') + public function withStatus($code, $reasonPhrase = ''): ResponseInterface { + $this->assertStatusCodeIsInteger($code); + $code = (int) $code; + $this->assertStatusCodeRange($code); + $new = clone $this; - $new->statusCode = (int) $code; - if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) { - $reasonPhrase = self::$phrases[$new->statusCode]; + $new->statusCode = $code; + if ($reasonPhrase == '' && isset(self::PHRASES[$new->statusCode])) { + $reasonPhrase = self::PHRASES[$new->statusCode]; } - $new->reasonPhrase = $reasonPhrase; + $new->reasonPhrase = (string) $reasonPhrase; return $new; } + + /** + * @param mixed $statusCode + */ + private function assertStatusCodeIsInteger($statusCode): void + { + if (filter_var($statusCode, FILTER_VALIDATE_INT) === false) { + throw new \InvalidArgumentException('Status code must be an integer value.'); + } + } + + private function assertStatusCodeRange(int $statusCode): void + { + if ($statusCode < 100 || $statusCode >= 600) { + throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.'); + } + } } diff --git a/vendor/guzzlehttp/psr7/src/Rfc7230.php b/vendor/guzzlehttp/psr7/src/Rfc7230.php new file mode 100644 index 0000000..3022401 --- /dev/null +++ b/vendor/guzzlehttp/psr7/src/Rfc7230.php @@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Psr7; + +/** + * @internal + */ +final class Rfc7230 +{ + /** + * Header related regular expressions (based on amphp/http package) + * + * Note: header delimiter (\r\n) is modified to \r?\n to accept line feed only delimiters for BC reasons. + * + * @link https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15 + * + * @license https://github.com/amphp/http/blob/v1.0.1/LICENSE + */ + public const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\]?={}\x01-\x20\x7F]++):[ \t]*+((?:[ \t]*+[\x21-\x7E\x80-\xFF]++)*+)[ \t]*+\r?\n)m"; + public const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; +} diff --git a/vendor/guzzlehttp/psr7/src/ServerRequest.php b/vendor/guzzlehttp/psr7/src/ServerRequest.php index 575aab8..b2aa382 100644 --- a/vendor/guzzlehttp/psr7/src/ServerRequest.php +++ b/vendor/guzzlehttp/psr7/src/ServerRequest.php @@ -1,12 +1,14 @@ <?php +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use InvalidArgumentException; use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Message\UriInterface; use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UploadedFileInterface; +use Psr\Http\Message\UriInterface; /** * Server-side HTTP request @@ -35,7 +37,7 @@ class ServerRequest extends Request implements ServerRequestInterface private $cookieParams = []; /** - * @var null|array|object + * @var array|object|null */ private $parsedBody; @@ -57,17 +59,17 @@ class ServerRequest extends Request implements ServerRequestInterface /** * @param string $method HTTP method * @param string|UriInterface $uri URI - * @param array $headers Request headers - * @param string|null|resource|StreamInterface $body Request body + * @param array<string, string|string[]> $headers Request headers + * @param string|resource|StreamInterface|null $body Request body * @param string $version Protocol version * @param array $serverParams Typically the $_SERVER superglobal */ public function __construct( - $method, + string $method, $uri, array $headers = [], $body = null, - $version = '1.1', + string $version = '1.1', array $serverParams = [] ) { $this->serverParams = $serverParams; @@ -78,11 +80,11 @@ public function __construct( /** * Return an UploadedFile instance array. * - * @param array $files A array which respect $_FILES structure + * @param array $files An array which respect $_FILES structure + * * @throws InvalidArgumentException for unrecognized values - * @return array */ - public static function normalizeFiles(array $files) + public static function normalizeFiles(array $files): array { $normalized = []; @@ -109,7 +111,8 @@ public static function normalizeFiles(array $files) * delegate to normalizeNestedFileSpec() and return that return value. * * @param array $value $_FILES struct - * @return array|UploadedFileInterface + * + * @return UploadedFileInterface|UploadedFileInterface[] */ private static function createUploadedFileFromSpec(array $value) { @@ -132,20 +135,19 @@ private static function createUploadedFileFromSpec(array $value) * Loops through all nested files and returns a normalized array of * UploadedFileInterface instances. * - * @param array $files * @return UploadedFileInterface[] */ - private static function normalizeNestedFileSpec(array $files = []) + private static function normalizeNestedFileSpec(array $files = []): array { $normalizedFiles = []; foreach (array_keys($files['tmp_name']) as $key) { $spec = [ 'tmp_name' => $files['tmp_name'][$key], - 'size' => $files['size'][$key], - 'error' => $files['error'][$key], - 'name' => $files['name'][$key], - 'type' => $files['type'][$key], + 'size' => $files['size'][$key] ?? null, + 'error' => $files['error'][$key] ?? null, + 'name' => $files['name'][$key] ?? null, + 'type' => $files['type'][$key] ?? null, ]; $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec); } @@ -160,15 +162,13 @@ private static function normalizeNestedFileSpec(array $files = []) * $_COOKIE * $_FILES * $_SERVER - * - * @return ServerRequestInterface */ - public static function fromGlobals() + public static function fromGlobals(): ServerRequestInterface { - $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET'; - $headers = function_exists('getallheaders') ? getallheaders() : []; + $method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; + $headers = getallheaders(); $uri = self::getUriFromGlobals(); - $body = new LazyOpenStream('php://input', 'r+'); + $body = new CachingStream(new LazyOpenStream('php://input', 'r+')); $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1'; $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER); @@ -180,23 +180,39 @@ public static function fromGlobals() ->withUploadedFiles(self::normalizeFiles($_FILES)); } + private static function extractHostAndPortFromAuthority(string $authority): array + { + $uri = 'http://' . $authority; + $parts = parse_url($uri); + if (false === $parts) { + return [null, null]; + } + + $host = $parts['host'] ?? null; + $port = $parts['port'] ?? null; + + return [$host, $port]; + } + /** * Get a Uri populated with values from $_SERVER. - * - * @return UriInterface */ - public static function getUriFromGlobals() { + public static function getUriFromGlobals(): UriInterface + { $uri = new Uri(''); $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); $hasPort = false; if (isset($_SERVER['HTTP_HOST'])) { - $hostHeaderParts = explode(':', $_SERVER['HTTP_HOST']); - $uri = $uri->withHost($hostHeaderParts[0]); - if (isset($hostHeaderParts[1])) { + [$host, $port] = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']); + if ($host !== null) { + $uri = $uri->withHost($host); + } + + if ($port !== null) { $hasPort = true; - $uri = $uri->withPort($hostHeaderParts[1]); + $uri = $uri->withPort($port); } } elseif (isset($_SERVER['SERVER_NAME'])) { $uri = $uri->withHost($_SERVER['SERVER_NAME']); @@ -210,7 +226,7 @@ public static function getUriFromGlobals() { $hasQuery = false; if (isset($_SERVER['REQUEST_URI'])) { - $requestUriParts = explode('?', $_SERVER['REQUEST_URI']); + $requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2); $uri = $uri->withPath($requestUriParts[0]); if (isset($requestUriParts[1])) { $hasQuery = true; @@ -225,27 +241,17 @@ public static function getUriFromGlobals() { return $uri; } - - /** - * {@inheritdoc} - */ - public function getServerParams() + public function getServerParams(): array { return $this->serverParams; } - /** - * {@inheritdoc} - */ - public function getUploadedFiles() + public function getUploadedFiles(): array { return $this->uploadedFiles; } - /** - * {@inheritdoc} - */ - public function withUploadedFiles(array $uploadedFiles) + public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface { $new = clone $this; $new->uploadedFiles = $uploadedFiles; @@ -253,18 +259,12 @@ public function withUploadedFiles(array $uploadedFiles) return $new; } - /** - * {@inheritdoc} - */ - public function getCookieParams() + public function getCookieParams(): array { return $this->cookieParams; } - /** - * {@inheritdoc} - */ - public function withCookieParams(array $cookies) + public function withCookieParams(array $cookies): ServerRequestInterface { $new = clone $this; $new->cookieParams = $cookies; @@ -272,18 +272,12 @@ public function withCookieParams(array $cookies) return $new; } - /** - * {@inheritdoc} - */ - public function getQueryParams() + public function getQueryParams(): array { return $this->queryParams; } - /** - * {@inheritdoc} - */ - public function withQueryParams(array $query) + public function withQueryParams(array $query): ServerRequestInterface { $new = clone $this; $new->queryParams = $query; @@ -293,16 +287,15 @@ public function withQueryParams(array $query) /** * {@inheritdoc} + * + * @return array|object|null */ public function getParsedBody() { return $this->parsedBody; } - /** - * {@inheritdoc} - */ - public function withParsedBody($data) + public function withParsedBody($data): ServerRequestInterface { $new = clone $this; $new->parsedBody = $data; @@ -310,16 +303,15 @@ public function withParsedBody($data) return $new; } - /** - * {@inheritdoc} - */ - public function getAttributes() + public function getAttributes(): array { return $this->attributes; } /** * {@inheritdoc} + * + * @return mixed */ public function getAttribute($attribute, $default = null) { @@ -330,10 +322,7 @@ public function getAttribute($attribute, $default = null) return $this->attributes[$attribute]; } - /** - * {@inheritdoc} - */ - public function withAttribute($attribute, $value) + public function withAttribute($attribute, $value): ServerRequestInterface { $new = clone $this; $new->attributes[$attribute] = $value; @@ -341,10 +330,7 @@ public function withAttribute($attribute, $value) return $new; } - /** - * {@inheritdoc} - */ - public function withoutAttribute($attribute) + public function withoutAttribute($attribute): ServerRequestInterface { if (false === array_key_exists($attribute, $this->attributes)) { return $this; diff --git a/vendor/guzzlehttp/psr7/src/Stream.php b/vendor/guzzlehttp/psr7/src/Stream.php index e336628..ecd3186 100644 --- a/vendor/guzzlehttp/psr7/src/Stream.php +++ b/vendor/guzzlehttp/psr7/src/Stream.php @@ -1,39 +1,38 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * PHP stream implementation. - * - * @var $stream */ class Stream implements StreamInterface { + /** + * @see http://php.net/manual/function.fopen.php + * @see http://php.net/manual/en/function.gzopen.php + */ + private const READABLE_MODES = '/r|a\+|ab\+|w\+|wb\+|x\+|xb\+|c\+|cb\+/'; + private const WRITABLE_MODES = '/a|w|r\+|rb\+|rw|x|c/'; + + /** @var resource */ private $stream; + /** @var int|null */ private $size; + /** @var bool */ private $seekable; + /** @var bool */ private $readable; + /** @var bool */ private $writable; + /** @var string|null */ private $uri; + /** @var mixed[] */ private $customMetadata; - /** @var array Hash of readable and writable stream types */ - private static $readWriteHash = [ - 'read' => [ - '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' => [ - '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. * @@ -43,12 +42,12 @@ class Stream implements StreamInterface * - 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. + * @param resource $stream Stream resource to wrap. + * @param array{size?: int, metadata?: array} $options Associative array of options. * * @throws \InvalidArgumentException if the stream is not a stream resource */ - public function __construct($stream, $options = []) + public function __construct($stream, array $options = []) { if (!is_resource($stream)) { throw new \InvalidArgumentException('Stream must be a resource'); @@ -58,27 +57,15 @@ public function __construct($stream, $options = []) $this->size = $options['size']; } - $this->customMetadata = isset($options['metadata']) - ? $options['metadata'] - : []; - + $this->customMetadata = $options['metadata'] ?? []; $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->readable = (bool)preg_match(self::READABLE_MODES, $meta['mode']); + $this->writable = (bool)preg_match(self::WRITABLE_MODES, $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 */ @@ -87,28 +74,36 @@ public function __destruct() $this->close(); } - public function __toString() + public function __toString(): string { try { - $this->seek(0); - return (string) stream_get_contents($this->stream); - } catch (\Exception $e) { + if ($this->isSeekable()) { + $this->seek(0); + } + return $this->getContents(); + } catch (\Throwable $e) { + if (\PHP_VERSION_ID >= 70400) { + throw $e; + } + trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } - public function getContents() + public function getContents(): string { - $contents = stream_get_contents($this->stream); + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } - if ($contents === false) { - throw new \RuntimeException('Unable to read stream contents'); + if (!$this->readable) { + throw new \RuntimeException('Cannot read from non-readable stream'); } - return $contents; + return Utils::tryGetContents($this->stream); } - public function close() + public function close(): void { if (isset($this->stream)) { if (is_resource($this->stream)) { @@ -132,7 +127,7 @@ public function detach() return $result; } - public function getSize() + public function getSize(): ?int { if ($this->size !== null) { return $this->size; @@ -148,7 +143,7 @@ public function getSize() } $stats = fstat($this->stream); - if (isset($stats['size'])) { + if (is_array($stats) && isset($stats['size'])) { $this->size = $stats['size']; return $this->size; } @@ -156,28 +151,36 @@ public function getSize() return null; } - public function isReadable() + public function isReadable(): bool { return $this->readable; } - public function isWritable() + public function isWritable(): bool { return $this->writable; } - public function isSeekable() + public function isSeekable(): bool { return $this->seekable; } - public function eof() + public function eof(): bool { - return !$this->stream || feof($this->stream); + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + + return feof($this->stream); } - public function tell() + public function tell(): int { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + $result = ftell($this->stream); if ($result === false) { @@ -187,23 +190,32 @@ public function tell() return $result; } - public function rewind() + public function rewind(): void { $this->seek(0); } - public function seek($offset, $whence = SEEK_SET) + public function seek($offset, $whence = SEEK_SET): void { + $whence = (int) $whence; + + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } if (!$this->seekable) { throw new \RuntimeException('Stream is not seekable'); - } elseif (fseek($this->stream, $offset, $whence) === -1) { + } + if (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) + public function read($length): string { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } if (!$this->readable) { throw new \RuntimeException('Cannot read from non-readable stream'); } @@ -215,7 +227,12 @@ public function read($length) return ''; } - $string = fread($this->stream, $length); + try { + $string = fread($this->stream, $length); + } catch (\Exception $e) { + throw new \RuntimeException('Unable to read from stream', 0, $e); + } + if (false === $string) { throw new \RuntimeException('Unable to read from stream'); } @@ -223,8 +240,11 @@ public function read($length) return $string; } - public function write($string) + public function write($string): int { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } if (!$this->writable) { throw new \RuntimeException('Cannot write to a non-writable stream'); } @@ -240,6 +260,11 @@ public function write($string) return $result; } + /** + * {@inheritdoc} + * + * @return mixed + */ public function getMetadata($key = null) { if (!isset($this->stream)) { @@ -252,6 +277,6 @@ public function getMetadata($key = null) $meta = stream_get_meta_data($this->stream); - return isset($meta[$key]) ? $meta[$key] : null; + return $meta[$key] ?? null; } } diff --git a/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php b/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php index daec6f5..56d4104 100644 --- a/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php +++ b/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php @@ -1,11 +1,15 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Stream decorator trait - * @property StreamInterface stream + * + * @property StreamInterface $stream */ trait StreamDecoratorTrait { @@ -21,13 +25,11 @@ public function __construct(StreamInterface $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) + public function __get(string $name) { - if ($name == 'stream') { + if ($name === 'stream') { $this->stream = $this->createStream(); return $this->stream; } @@ -35,47 +37,52 @@ public function __get($name) throw new \UnexpectedValueException("$name not found on class"); } - public function __toString() + public function __toString(): string { 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); + } catch (\Throwable $e) { + if (\PHP_VERSION_ID >= 70400) { + throw $e; + } + trigger_error(sprintf('%s::__toString exception: %s', self::class, (string) $e), E_USER_ERROR); return ''; } } - public function getContents() + public function getContents(): string { - return copy_to_string($this); + return Utils::copyToString($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) + public function __call(string $method, array $args) { - $result = call_user_func_array([$this->stream, $method], $args); + /** @var callable $callable */ + $callable = [$this->stream, $method]; + $result = call_user_func_array($callable, $args); // Always return the wrapped object if the result is a return $this return $result === $this->stream ? $this : $result; } - public function close() + public function close(): void { $this->stream->close(); } + /** + * {@inheritdoc} + * + * @return mixed + */ public function getMetadata($key = null) { return $this->stream->getMetadata($key); @@ -86,52 +93,52 @@ public function detach() return $this->stream->detach(); } - public function getSize() + public function getSize(): ?int { return $this->stream->getSize(); } - public function eof() + public function eof(): bool { return $this->stream->eof(); } - public function tell() + public function tell(): int { return $this->stream->tell(); } - public function isReadable() + public function isReadable(): bool { return $this->stream->isReadable(); } - public function isWritable() + public function isWritable(): bool { return $this->stream->isWritable(); } - public function isSeekable() + public function isSeekable(): bool { return $this->stream->isSeekable(); } - public function rewind() + public function rewind(): void { $this->seek(0); } - public function seek($offset, $whence = SEEK_SET) + public function seek($offset, $whence = SEEK_SET): void { $this->stream->seek($offset, $whence); } - public function read($length) + public function read($length): string { return $this->stream->read($length); } - public function write($string) + public function write($string): int { return $this->stream->write($string); } @@ -139,10 +146,9 @@ public function write($string) /** * Implement in subclasses to dynamically create streams when requested. * - * @return StreamInterface * @throws \BadMethodCallException */ - protected function createStream() + protected function createStream(): StreamInterface { throw new \BadMethodCallException('Not implemented'); } diff --git a/vendor/guzzlehttp/psr7/src/StreamWrapper.php b/vendor/guzzlehttp/psr7/src/StreamWrapper.php index cf7b223..2a93464 100644 --- a/vendor/guzzlehttp/psr7/src/StreamWrapper.php +++ b/vendor/guzzlehttp/psr7/src/StreamWrapper.php @@ -1,12 +1,17 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; /** * Converts Guzzle streams into PHP stream resources. + * + * @see https://www.php.net/streamwrapper */ -class StreamWrapper +final class StreamWrapper { /** @var resource */ public $context; @@ -23,6 +28,7 @@ class StreamWrapper * @param StreamInterface $stream The stream to get a resource for * * @return resource + * * @throws \InvalidArgumentException if stream is not readable or writable */ public static function getResource(StreamInterface $stream) @@ -38,22 +44,32 @@ public static function getResource(StreamInterface $stream) . 'writable, or both.'); } - return fopen('guzzle://stream', $mode, null, stream_context_create([ + return fopen('guzzle://stream', $mode, false, self::createStreamContext($stream)); + } + + /** + * Creates a stream context that can be used to open a stream as a php stream resource. + * + * @return resource + */ + public static function createStreamContext(StreamInterface $stream) + { + return stream_context_create([ 'guzzle' => ['stream' => $stream] - ])); + ]); } /** * Registers the stream wrapper if needed */ - public static function register() + public static function register(): void { if (!in_array('guzzle', stream_get_wrappers())) { stream_wrapper_register('guzzle', __CLASS__); } } - public function stream_open($path, $mode, $options, &$opened_path) + public function stream_open(string $path, string $mode, int $options, string &$opened_path = null): bool { $options = stream_context_get_options($this->context); @@ -67,39 +83,55 @@ public function stream_open($path, $mode, $options, &$opened_path) return true; } - public function stream_read($count) + public function stream_read(int $count): string { return $this->stream->read($count); } - public function stream_write($data) + public function stream_write(string $data): int { - return (int) $this->stream->write($data); + return $this->stream->write($data); } - public function stream_tell() + public function stream_tell(): int { return $this->stream->tell(); } - public function stream_eof() + public function stream_eof(): bool { return $this->stream->eof(); } - public function stream_seek($offset, $whence) + public function stream_seek(int $offset, int $whence): bool { $this->stream->seek($offset, $whence); return true; } - public function stream_stat() + /** + * @return resource|false + */ + public function stream_cast(int $cast_as) + { + $stream = clone($this->stream); + $resource = $stream->detach(); + + return $resource ?? false; + } + + /** + * @return array<int|string, int> + */ + public function stream_stat(): array { static $modeMap = [ 'r' => 33060, + 'rb' => 33060, 'r+' => 33206, - 'w' => 33188 + 'w' => 33188, + 'wb' => 33188 ]; return [ @@ -118,4 +150,26 @@ public function stream_stat() 'blocks' => 0 ]; } + + /** + * @return array<int|string, int> + */ + public function url_stat(string $path, int $flags): array + { + return [ + 'dev' => 0, + 'ino' => 0, + 'mode' => 0, + 'nlink' => 0, + 'uid' => 0, + 'gid' => 0, + 'rdev' => 0, + 'size' => 0, + 'atime' => 0, + 'mtime' => 0, + 'ctime' => 0, + 'blksize' => 0, + 'blocks' => 0 + ]; + } } diff --git a/vendor/guzzlehttp/psr7/src/UploadedFile.php b/vendor/guzzlehttp/psr7/src/UploadedFile.php index e62bd5c..b1521bc 100644 --- a/vendor/guzzlehttp/psr7/src/UploadedFile.php +++ b/vendor/guzzlehttp/psr7/src/UploadedFile.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use InvalidArgumentException; @@ -8,10 +11,7 @@ class UploadedFile implements UploadedFileInterface { - /** - * @var int[] - */ - private static $errors = [ + private const ERRORS = [ UPLOAD_ERR_OK, UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, @@ -23,12 +23,12 @@ class UploadedFile implements UploadedFileInterface ]; /** - * @var string + * @var string|null */ private $clientFilename; /** - * @var string + * @var string|null */ private $clientMediaType; @@ -38,7 +38,7 @@ class UploadedFile implements UploadedFileInterface private $error; /** - * @var null|string + * @var string|null */ private $file; @@ -48,7 +48,7 @@ class UploadedFile implements UploadedFileInterface private $moved = false; /** - * @var int + * @var int|null */ private $size; @@ -59,22 +59,18 @@ class UploadedFile implements UploadedFileInterface /** * @param StreamInterface|string|resource $streamOrFile - * @param int $size - * @param int $errorStatus - * @param string|null $clientFilename - * @param string|null $clientMediaType */ public function __construct( $streamOrFile, - $size, - $errorStatus, - $clientFilename = null, - $clientMediaType = null + ?int $size, + int $errorStatus, + string $clientFilename = null, + string $clientMediaType = null ) { $this->setError($errorStatus); - $this->setSize($size); - $this->setClientFilename($clientFilename); - $this->setClientMediaType($clientMediaType); + $this->size = $size; + $this->clientFilename = $clientFilename; + $this->clientMediaType = $clientMediaType; if ($this->isOk()) { $this->setStreamOrFile($streamOrFile); @@ -84,10 +80,11 @@ public function __construct( /** * Depending on the value set file or stream variable * - * @param mixed $streamOrFile + * @param StreamInterface|string|resource $streamOrFile + * * @throws InvalidArgumentException */ - private function setStreamOrFile($streamOrFile) + private function setStreamOrFile($streamOrFile): void { if (is_string($streamOrFile)) { $this->file = $streamOrFile; @@ -103,18 +100,11 @@ private function setStreamOrFile($streamOrFile) } /** - * @param int $error * @throws InvalidArgumentException */ - private function setError($error) + private function setError(int $error): void { - if (false === is_int($error)) { - throw new InvalidArgumentException( - 'Upload file error status must be an integer' - ); - } - - if (false === in_array($error, UploadedFile::$errors)) { + if (false === in_array($error, UploadedFile::ERRORS, true)) { throw new InvalidArgumentException( 'Invalid error status for UploadedFile' ); @@ -123,83 +113,20 @@ private function setError($error) $this->error = $error; } - /** - * @param int $size - * @throws InvalidArgumentException - */ - private function setSize($size) - { - if (false === is_int($size)) { - throw new InvalidArgumentException( - 'Upload file size must be an integer' - ); - } - - $this->size = $size; - } - - /** - * @param mixed $param - * @return boolean - */ - private function isStringOrNull($param) - { - return in_array(gettype($param), ['string', 'NULL']); - } - - /** - * @param mixed $param - * @return boolean - */ - private function isStringNotEmpty($param) + private function isStringNotEmpty($param): bool { return is_string($param) && false === empty($param); } - /** - * @param string|null $clientFilename - * @throws InvalidArgumentException - */ - private function setClientFilename($clientFilename) - { - if (false === $this->isStringOrNull($clientFilename)) { - throw new InvalidArgumentException( - 'Upload file client filename must be a string or null' - ); - } - - $this->clientFilename = $clientFilename; - } - - /** - * @param string|null $clientMediaType - * @throws InvalidArgumentException - */ - private function setClientMediaType($clientMediaType) - { - if (false === $this->isStringOrNull($clientMediaType)) { - throw new InvalidArgumentException( - 'Upload file client media type must be a string or null' - ); - } - - $this->clientMediaType = $clientMediaType; - } - /** * Return true if there is no upload error - * - * @return boolean */ - private function isOk() + private function isOk(): bool { return $this->error === UPLOAD_ERR_OK; } - /** - * @return boolean - */ - public function isMoved() + public function isMoved(): bool { return $this->moved; } @@ -207,7 +134,7 @@ public function isMoved() /** * @throws RuntimeException if is moved or not ok */ - private function validateActive() + private function validateActive(): void { if (false === $this->isOk()) { throw new RuntimeException('Cannot retrieve stream due to upload error'); @@ -218,11 +145,7 @@ private function validateActive() } } - /** - * {@inheritdoc} - * @throws RuntimeException if the upload was not successful. - */ - public function getStream() + public function getStream(): StreamInterface { $this->validateActive(); @@ -230,21 +153,13 @@ public function getStream() return $this->stream; } - return new LazyOpenStream($this->file, 'r+'); + /** @var string $file */ + $file = $this->file; + + return new LazyOpenStream($file, 'r+'); } - /** - * {@inheritdoc} - * - * @see http://php.net/is_uploaded_file - * @see http://php.net/move_uploaded_file - * @param string $targetPath Path to which to move the uploaded file. - * @throws RuntimeException if the upload was not successful. - * @throws InvalidArgumentException if the $path specified is invalid. - * @throws RuntimeException on any error during the move operation, or on - * the second or subsequent call to the method. - */ - public function moveTo($targetPath) + public function moveTo($targetPath): void { $this->validateActive(); @@ -255,11 +170,11 @@ public function moveTo($targetPath) } if ($this->file) { - $this->moved = php_sapi_name() == 'cli' + $this->moved = PHP_SAPI === 'cli' ? rename($this->file, $targetPath) : move_uploaded_file($this->file, $targetPath); } else { - copy_to_stream( + Utils::copyToStream( $this->getStream(), new LazyOpenStream($targetPath, 'w') ); @@ -274,42 +189,22 @@ public function moveTo($targetPath) } } - /** - * {@inheritdoc} - * - * @return int|null The file size in bytes or null if unknown. - */ - public function getSize() + public function getSize(): ?int { return $this->size; } - /** - * {@inheritdoc} - * - * @see http://php.net/manual/en/features.file-upload.errors.php - * @return int One of PHP's UPLOAD_ERR_XXX constants. - */ - public function getError() + public function getError(): int { return $this->error; } - /** - * {@inheritdoc} - * - * @return string|null The filename sent by the client or null if none - * was provided. - */ - public function getClientFilename() + public function getClientFilename(): ?string { return $this->clientFilename; } - /** - * {@inheritdoc} - */ - public function getClientMediaType() + public function getClientMediaType(): ?string { return $this->clientMediaType; } diff --git a/vendor/guzzlehttp/psr7/src/Uri.php b/vendor/guzzlehttp/psr7/src/Uri.php index f46c1db..09e878d 100644 --- a/vendor/guzzlehttp/psr7/src/Uri.php +++ b/vendor/guzzlehttp/psr7/src/Uri.php @@ -1,6 +1,10 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; +use GuzzleHttp\Psr7\Exception\MalformedUriException; use Psr\Http\Message\UriInterface; /** @@ -10,7 +14,7 @@ * @author Tobias Schultze * @author Matthew Weier O'Phinney */ -class Uri implements UriInterface +class Uri implements UriInterface, \JsonSerializable { /** * Absolute http and https URIs require a host per RFC 7230 Section 2.7 @@ -18,9 +22,9 @@ class Uri implements UriInterface * we apply this default host when no host is given yet to form a * valid URI. */ - const HTTP_DEFAULT_HOST = 'localhost'; + private const HTTP_DEFAULT_HOST = 'localhost'; - private static $defaultPorts = [ + private const DEFAULT_PORTS = [ 'http' => 80, 'https' => 443, 'ftp' => 21, @@ -34,9 +38,20 @@ class Uri implements UriInterface 'ldap' => 389, ]; - private static $charUnreserved = 'a-zA-Z0-9_\-\.~'; - private static $charSubDelims = '!\$&\'\(\)\*\+,;='; - private static $replaceQuery = ['=' => '%3D', '&' => '%26']; + /** + * Unreserved characters for use in a regex. + * + * @link https://tools.ietf.org/html/rfc3986#section-2.3 + */ + private const CHAR_UNRESERVED = 'a-zA-Z0-9_\-\.~'; + + /** + * Sub-delims for use in a regex. + * + * @link https://tools.ietf.org/html/rfc3986#section-2.2 + */ + private const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; + private const QUERY_SEPARATORS_REPLACEMENT = ['=' => '%3D', '&' => '%26']; /** @var string Uri scheme. */ private $scheme = ''; @@ -59,30 +74,75 @@ class Uri implements UriInterface /** @var string Uri fragment. */ private $fragment = ''; - /** - * @param string $uri URI to parse - */ - public function __construct($uri = '') + /** @var string|null String representation */ + private $composedComponents; + + public function __construct(string $uri = '') { - // weak type check to also accept null until we can add scalar type hints - if ($uri != '') { - $parts = parse_url($uri); + if ($uri !== '') { + $parts = self::parse($uri); if ($parts === false) { - throw new \InvalidArgumentException("Unable to parse URI: $uri"); + throw new MalformedUriException("Unable to parse URI: $uri"); } $this->applyParts($parts); } } + /** + * UTF-8 aware \parse_url() replacement. + * + * The internal function produces broken output for non ASCII domain names + * (IDN) when used with locales other than "C". + * + * On the other hand, cURL understands IDN correctly only when UTF-8 locale + * is configured ("C.UTF-8", "en_US.UTF-8", etc.). + * + * @see https://bugs.php.net/bug.php?id=52923 + * @see https://www.php.net/manual/en/function.parse-url.php#114817 + * @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING + * + * @return array|false + */ + private static function parse(string $url) + { + // If IPv6 + $prefix = ''; + if (preg_match('%^(.*://\[[0-9:a-f]+\])(.*?)$%', $url, $matches)) { + /** @var array{0:string, 1:string, 2:string} $matches */ + $prefix = $matches[1]; + $url = $matches[2]; + } - public function __toString() - { - return self::composeComponents( - $this->scheme, - $this->getAuthority(), - $this->path, - $this->query, - $this->fragment + /** @var string */ + $encodedUrl = preg_replace_callback( + '%[^:/@?&=#]+%usD', + static function ($matches) { + return urlencode($matches[0]); + }, + $url ); + + $result = parse_url($prefix . $encodedUrl); + + if ($result === false) { + return false; + } + + return array_map('urldecode', $result); + } + + public function __toString(): string + { + if ($this->composedComponents === null) { + $this->composedComponents = self::composeComponents( + $this->scheme, + $this->getAuthority(), + $this->path, + $this->query, + $this->fragment + ); + } + + return $this->composedComponents; } /** @@ -101,17 +161,9 @@ public function __toString() * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to * that format). * - * @param string $scheme - * @param string $authority - * @param string $path - * @param string $query - * @param string $fragment - * - * @return string - * * @link https://tools.ietf.org/html/rfc3986#section-5.3 */ - public static function composeComponents($scheme, $authority, $path, $query, $fragment) + public static function composeComponents(?string $scheme, ?string $authority, string $path, ?string $query, ?string $fragment): string { $uri = ''; @@ -120,10 +172,14 @@ public static function composeComponents($scheme, $authority, $path, $query, $fr $uri .= $scheme . ':'; } - if ($authority != ''|| $scheme === 'file') { + if ($authority != '' || $scheme === 'file') { $uri .= '//' . $authority; } + if ($authority != '' && $path != '' && $path[0] != '/') { + $path = '/' . $path; + } + $uri .= $path; if ($query != '') { @@ -142,15 +198,11 @@ public static function composeComponents($scheme, $authority, $path, $query, $fr * * `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used * independently of the implementation. - * - * @param UriInterface $uri - * - * @return bool */ - public static function isDefaultPort(UriInterface $uri) + public static function isDefaultPort(UriInterface $uri): bool { return $uri->getPort() === null - || (isset(self::$defaultPorts[$uri->getScheme()]) && $uri->getPort() === self::$defaultPorts[$uri->getScheme()]); + || (isset(self::DEFAULT_PORTS[$uri->getScheme()]) && $uri->getPort() === self::DEFAULT_PORTS[$uri->getScheme()]); } /** @@ -163,15 +215,12 @@ public static function isDefaultPort(UriInterface $uri) * - absolute-path references, e.g. '/path' * - relative-path references, e.g. 'subpath' * - * @param UriInterface $uri - * - * @return bool * @see Uri::isNetworkPathReference * @see Uri::isAbsolutePathReference * @see Uri::isRelativePathReference * @link https://tools.ietf.org/html/rfc3986#section-4 */ - public static function isAbsolute(UriInterface $uri) + public static function isAbsolute(UriInterface $uri): bool { return $uri->getScheme() !== ''; } @@ -181,12 +230,9 @@ public static function isAbsolute(UriInterface $uri) * * A relative reference that begins with two slash characters is termed an network-path reference. * - * @param UriInterface $uri - * - * @return bool * @link https://tools.ietf.org/html/rfc3986#section-4.2 */ - public static function isNetworkPathReference(UriInterface $uri) + public static function isNetworkPathReference(UriInterface $uri): bool { return $uri->getScheme() === '' && $uri->getAuthority() !== ''; } @@ -196,12 +242,9 @@ public static function isNetworkPathReference(UriInterface $uri) * * A relative reference that begins with a single slash character is termed an absolute-path reference. * - * @param UriInterface $uri - * - * @return bool * @link https://tools.ietf.org/html/rfc3986#section-4.2 */ - public static function isAbsolutePathReference(UriInterface $uri) + public static function isAbsolutePathReference(UriInterface $uri): bool { return $uri->getScheme() === '' && $uri->getAuthority() === '' @@ -214,12 +257,9 @@ public static function isAbsolutePathReference(UriInterface $uri) * * A relative reference that does not begin with a slash character is termed a relative-path reference. * - * @param UriInterface $uri - * - * @return bool * @link https://tools.ietf.org/html/rfc3986#section-4.2 */ - public static function isRelativePathReference(UriInterface $uri) + public static function isRelativePathReference(UriInterface $uri): bool { return $uri->getScheme() === '' && $uri->getAuthority() === '' @@ -236,10 +276,9 @@ public static function isRelativePathReference(UriInterface $uri) * @param UriInterface $uri The URI to check * @param UriInterface|null $base An optional base URI to compare against * - * @return bool * @link https://tools.ietf.org/html/rfc3986#section-4.4 */ - public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null) + public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool { if ($base !== null) { $uri = UriResolver::resolve($base, $uri); @@ -253,41 +292,6 @@ public static function isSameDocumentReference(UriInterface $uri, UriInterface $ return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === ''; } - /** - * Removes dot segments from a path and returns the new path. - * - * @param string $path - * - * @return string - * - * @deprecated since version 1.4. Use UriResolver::removeDotSegments instead. - * @see UriResolver::removeDotSegments - */ - public static function removeDotSegments($path) - { - return UriResolver::removeDotSegments($path); - } - - /** - * Converts the relative URI into a new URI that is resolved against the base URI. - * - * @param UriInterface $base Base URI - * @param string|UriInterface $rel Relative URI - * - * @return UriInterface - * - * @deprecated since version 1.4. Use UriResolver::resolve instead. - * @see UriResolver::resolve - */ - public static function resolve(UriInterface $base, $rel) - { - if (!($rel instanceof UriInterface)) { - $rel = new self($rel); - } - - return UriResolver::resolve($base, $rel); - } - /** * Creates a new URI with a specific query string value removed. * @@ -296,20 +300,10 @@ public static function resolve(UriInterface $base, $rel) * * @param UriInterface $uri URI to use as a base. * @param string $key Query string key to remove. - * - * @return UriInterface */ - public static function withoutQueryValue(UriInterface $uri, $key) + public static function withoutQueryValue(UriInterface $uri, string $key): UriInterface { - $current = $uri->getQuery(); - if ($current === '') { - return $uri; - } - - $decodedKey = rawurldecode($key); - $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) { - return rawurldecode(explode('=', $part)[0]) !== $decodedKey; - }); + $result = self::getFilteredQueryString($uri, [$key]); return $uri->withQuery(implode('&', $result)); } @@ -326,31 +320,30 @@ public static function withoutQueryValue(UriInterface $uri, $key) * @param UriInterface $uri URI to use as a base. * @param string $key Key to set. * @param string|null $value Value to set - * - * @return UriInterface */ - public static function withQueryValue(UriInterface $uri, $key, $value) + public static function withQueryValue(UriInterface $uri, string $key, ?string $value): UriInterface { - $current = $uri->getQuery(); + $result = self::getFilteredQueryString($uri, [$key]); - if ($current === '') { - $result = []; - } else { - $decodedKey = rawurldecode($key); - $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) { - return rawurldecode(explode('=', $part)[0]) !== $decodedKey; - }); - } + $result[] = self::generateQueryString($key, $value); - // Query string separators ("=", "&") within the key or value need to be encoded - // (while preventing double-encoding) before setting the query string. All other - // chars that need percent-encoding will be encoded by withQuery(). - $key = strtr($key, self::$replaceQuery); + return $uri->withQuery(implode('&', $result)); + } - if ($value !== null) { - $result[] = $key . '=' . strtr($value, self::$replaceQuery); - } else { - $result[] = $key; + /** + * Creates a new URI with multiple specific query string values. + * + * It has the same behavior as withQueryValue() but for an associative array of key => value. + * + * @param UriInterface $uri URI to use as a base. + * @param array<string, string|null> $keyValueArray Associative array of key and values + */ + public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface + { + $result = self::getFilteredQueryString($uri, array_keys($keyValueArray)); + + foreach ($keyValueArray as $key => $value) { + $result[] = self::generateQueryString((string) $key, $value !== null ? (string) $value : null); } return $uri->withQuery(implode('&', $result)); @@ -359,14 +352,11 @@ public static function withQueryValue(UriInterface $uri, $key, $value) /** * Creates a URI from a hash of `parse_url` components. * - * @param array $parts - * - * @return UriInterface * @link http://php.net/manual/en/function.parse-url.php * - * @throws \InvalidArgumentException If the components do not form a valid URI. + * @throws MalformedUriException If the components do not form a valid URI. */ - public static function fromParts(array $parts) + public static function fromParts(array $parts): UriInterface { $uri = new self(); $uri->applyParts($parts); @@ -375,12 +365,12 @@ public static function fromParts(array $parts) return $uri; } - public function getScheme() + public function getScheme(): string { return $this->scheme; } - public function getAuthority() + public function getAuthority(): string { $authority = $this->host; if ($this->userInfo !== '') { @@ -394,37 +384,37 @@ public function getAuthority() return $authority; } - public function getUserInfo() + public function getUserInfo(): string { return $this->userInfo; } - public function getHost() + public function getHost(): string { return $this->host; } - public function getPort() + public function getPort(): ?int { return $this->port; } - public function getPath() + public function getPath(): string { return $this->path; } - public function getQuery() + public function getQuery(): string { return $this->query; } - public function getFragment() + public function getFragment(): string { return $this->fragment; } - public function withScheme($scheme) + public function withScheme($scheme): UriInterface { $scheme = $this->filterScheme($scheme); @@ -434,17 +424,18 @@ public function withScheme($scheme) $new = clone $this; $new->scheme = $scheme; + $new->composedComponents = null; $new->removeDefaultPort(); $new->validateState(); return $new; } - public function withUserInfo($user, $password = null) + public function withUserInfo($user, $password = null): UriInterface { - $info = $user; - if ($password != '') { - $info .= ':' . $password; + $info = $this->filterUserInfoComponent($user); + if ($password !== null) { + $info .= ':' . $this->filterUserInfoComponent($password); } if ($this->userInfo === $info) { @@ -453,12 +444,13 @@ public function withUserInfo($user, $password = null) $new = clone $this; $new->userInfo = $info; + $new->composedComponents = null; $new->validateState(); return $new; } - public function withHost($host) + public function withHost($host): UriInterface { $host = $this->filterHost($host); @@ -468,12 +460,13 @@ public function withHost($host) $new = clone $this; $new->host = $host; + $new->composedComponents = null; $new->validateState(); return $new; } - public function withPort($port) + public function withPort($port): UriInterface { $port = $this->filterPort($port); @@ -483,13 +476,14 @@ public function withPort($port) $new = clone $this; $new->port = $port; + $new->composedComponents = null; $new->removeDefaultPort(); $new->validateState(); return $new; } - public function withPath($path) + public function withPath($path): UriInterface { $path = $this->filterPath($path); @@ -499,12 +493,13 @@ public function withPath($path) $new = clone $this; $new->path = $path; + $new->composedComponents = null; $new->validateState(); return $new; } - public function withQuery($query) + public function withQuery($query): UriInterface { $query = $this->filterQueryAndFragment($query); @@ -514,11 +509,12 @@ public function withQuery($query) $new = clone $this; $new->query = $query; + $new->composedComponents = null; return $new; } - public function withFragment($fragment) + public function withFragment($fragment): UriInterface { $fragment = $this->filterQueryAndFragment($fragment); @@ -528,21 +524,29 @@ public function withFragment($fragment) $new = clone $this; $new->fragment = $fragment; + $new->composedComponents = null; return $new; } + public function jsonSerialize(): string + { + return $this->__toString(); + } + /** * Apply parse_url parts to a URI. * * @param array $parts Array of parse_url parts to apply. */ - private function applyParts(array $parts) + private function applyParts(array $parts): void { $this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : ''; - $this->userInfo = isset($parts['user']) ? $parts['user'] : ''; + $this->userInfo = isset($parts['user']) + ? $this->filterUserInfoComponent($parts['user']) + : ''; $this->host = isset($parts['host']) ? $this->filterHost($parts['host']) : ''; @@ -559,68 +563,114 @@ private function applyParts(array $parts) ? $this->filterQueryAndFragment($parts['fragment']) : ''; if (isset($parts['pass'])) { - $this->userInfo .= ':' . $parts['pass']; + $this->userInfo .= ':' . $this->filterUserInfoComponent($parts['pass']); } $this->removeDefaultPort(); } /** - * @param string $scheme - * - * @return string + * @param mixed $scheme * * @throws \InvalidArgumentException If the scheme is invalid. */ - private function filterScheme($scheme) + private function filterScheme($scheme): string { if (!is_string($scheme)) { throw new \InvalidArgumentException('Scheme must be a string'); } - return strtolower($scheme); + return \strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); } /** - * @param string $host + * @param mixed $component * - * @return string + * @throws \InvalidArgumentException If the user info is invalid. + */ + private function filterUserInfoComponent($component): string + { + if (!is_string($component)) { + throw new \InvalidArgumentException('User info must be a string'); + } + + return preg_replace_callback( + '/(?:[^%' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ']+|%(?![A-Fa-f0-9]{2}))/', + [$this, 'rawurlencodeMatchZero'], + $component + ); + } + + /** + * @param mixed $host * * @throws \InvalidArgumentException If the host is invalid. */ - private function filterHost($host) + private function filterHost($host): string { if (!is_string($host)) { throw new \InvalidArgumentException('Host must be a string'); } - return strtolower($host); + return \strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); } /** - * @param int|null $port - * - * @return int|null + * @param mixed $port * * @throws \InvalidArgumentException If the port is invalid. */ - private function filterPort($port) + private function filterPort($port): ?int { if ($port === null) { return null; } $port = (int) $port; - if (1 > $port || 0xffff < $port) { + if (0 > $port || 0xffff < $port) { throw new \InvalidArgumentException( - sprintf('Invalid port: %d. Must be between 1 and 65535', $port) + sprintf('Invalid port: %d. Must be between 0 and 65535', $port) ); } return $port; } - private function removeDefaultPort() + /** + * @param string[] $keys + * + * @return string[] + */ + private static function getFilteredQueryString(UriInterface $uri, array $keys): array + { + $current = $uri->getQuery(); + + if ($current === '') { + return []; + } + + $decodedKeys = array_map('rawurldecode', $keys); + + return array_filter(explode('&', $current), function ($part) use ($decodedKeys) { + return !in_array(rawurldecode(explode('=', $part)[0]), $decodedKeys, true); + }); + } + + private static function generateQueryString(string $key, ?string $value): string + { + // Query string separators ("=", "&") within the key or value need to be encoded + // (while preventing double-encoding) before setting the query string. All other + // chars that need percent-encoding will be encoded by withQuery(). + $queryString = strtr($key, self::QUERY_SEPARATORS_REPLACEMENT); + + if ($value !== null) { + $queryString .= '=' . strtr($value, self::QUERY_SEPARATORS_REPLACEMENT); + } + + return $queryString; + } + + private function removeDefaultPort(): void { if ($this->port !== null && self::isDefaultPort($this)) { $this->port = null; @@ -630,20 +680,18 @@ private function removeDefaultPort() /** * Filters the path of a URI * - * @param string $path - * - * @return string + * @param mixed $path * * @throws \InvalidArgumentException If the path is invalid. */ - private function filterPath($path) + private function filterPath($path): string { if (!is_string($path)) { throw new \InvalidArgumentException('Path must be a string'); } return preg_replace_callback( - '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/', + '/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $path ); @@ -652,31 +700,29 @@ private function filterPath($path) /** * Filters the query string or fragment of a URI. * - * @param string $str - * - * @return string + * @param mixed $str * * @throws \InvalidArgumentException If the query or fragment is invalid. */ - private function filterQueryAndFragment($str) + private function filterQueryAndFragment($str): string { if (!is_string($str)) { throw new \InvalidArgumentException('Query and fragment must be a string'); } return preg_replace_callback( - '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/', + '/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $str ); } - private function rawurlencodeMatchZero(array $match) + private function rawurlencodeMatchZero(array $match): string { return rawurlencode($match[0]); } - private function validateState() + private function validateState(): void { if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) { $this->host = self::HTTP_DEFAULT_HOST; @@ -684,19 +730,11 @@ private function validateState() if ($this->getAuthority() === '') { if (0 === strpos($this->path, '//')) { - throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"'); + throw new MalformedUriException('The path of a URI without an authority must not start with two slashes "//"'); } if ($this->scheme === '' && false !== strpos(explode('/', $this->path, 2)[0], ':')) { - throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon'); + throw new MalformedUriException('A relative URI must not have a path beginning with a segment containing a colon'); } - } elseif (isset($this->path[0]) && $this->path[0] !== '/') { - @trigger_error( - 'The path of a URI with an authority must start with a slash "/" or be empty. Automagically fixing the URI ' . - 'by adding a leading slash to the path is deprecated since version 1.4 and will throw an exception instead.', - E_USER_DEPRECATED - ); - $this->path = '/'. $this->path; - //throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty'); } } } diff --git a/vendor/guzzlehttp/psr7/src/UriComparator.php b/vendor/guzzlehttp/psr7/src/UriComparator.php new file mode 100644 index 0000000..70c582a --- /dev/null +++ b/vendor/guzzlehttp/psr7/src/UriComparator.php @@ -0,0 +1,52 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Psr7; + +use Psr\Http\Message\UriInterface; + +/** + * Provides methods to determine if a modified URL should be considered cross-origin. + * + * @author Graham Campbell + */ +final class UriComparator +{ + /** + * Determines if a modified URL should be considered cross-origin with + * respect to an original URL. + */ + public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool + { + if (\strcasecmp($original->getHost(), $modified->getHost()) !== 0) { + return true; + } + + if ($original->getScheme() !== $modified->getScheme()) { + return true; + } + + if (self::computePort($original) !== self::computePort($modified)) { + return true; + } + + return false; + } + + private static function computePort(UriInterface $uri): int + { + $port = $uri->getPort(); + + if (null !== $port) { + return $port; + } + + return 'https' === $uri->getScheme() ? 443 : 80; + } + + private function __construct() + { + // cannot be instantiated + } +} diff --git a/vendor/guzzlehttp/psr7/src/UriNormalizer.php b/vendor/guzzlehttp/psr7/src/UriNormalizer.php index 384c29e..e12971e 100644 --- a/vendor/guzzlehttp/psr7/src/UriNormalizer.php +++ b/vendor/guzzlehttp/psr7/src/UriNormalizer.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\UriInterface; @@ -14,18 +17,21 @@ final class UriNormalizer { /** * Default normalizations which only include the ones that preserve semantics. - * - * self::CAPITALIZE_PERCENT_ENCODING | self::DECODE_UNRESERVED_CHARACTERS | self::CONVERT_EMPTY_PATH | - * self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS */ - const PRESERVING_NORMALIZATIONS = 63; + public const PRESERVING_NORMALIZATIONS = + self::CAPITALIZE_PERCENT_ENCODING | + self::DECODE_UNRESERVED_CHARACTERS | + self::CONVERT_EMPTY_PATH | + self::REMOVE_DEFAULT_HOST | + self::REMOVE_DEFAULT_PORT | + self::REMOVE_DOT_SEGMENTS; /** * All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized. * * Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b */ - const CAPITALIZE_PERCENT_ENCODING = 1; + public const CAPITALIZE_PERCENT_ENCODING = 1; /** * Decodes percent-encoded octets of unreserved characters. @@ -36,14 +42,14 @@ final class UriNormalizer * * Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/ */ - const DECODE_UNRESERVED_CHARACTERS = 2; + public const DECODE_UNRESERVED_CHARACTERS = 2; /** * Converts the empty path to "/" for http and https URIs. * * Example: http://example.org → http://example.org/ */ - const CONVERT_EMPTY_PATH = 4; + public const CONVERT_EMPTY_PATH = 4; /** * Removes the default host of the given URI scheme from the URI. @@ -56,14 +62,14 @@ final class UriNormalizer * * Example: file://localhost/myfile → file:///myfile */ - const REMOVE_DEFAULT_HOST = 8; + public const REMOVE_DEFAULT_HOST = 8; /** * Removes the default port of the given URI scheme from the URI. * * Example: http://example.org:80/ → http://example.org/ */ - const REMOVE_DEFAULT_PORT = 16; + public const REMOVE_DEFAULT_PORT = 16; /** * Removes unnecessary dot-segments. @@ -73,7 +79,7 @@ final class UriNormalizer * * Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html */ - const REMOVE_DOT_SEGMENTS = 32; + public const REMOVE_DOT_SEGMENTS = 32; /** * Paths which include two or more adjacent slashes are converted to one. @@ -84,7 +90,7 @@ final class UriNormalizer * * Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html */ - const REMOVE_DUPLICATE_SLASHES = 64; + public const REMOVE_DUPLICATE_SLASHES = 64; /** * Sort query parameters with their values in alphabetical order. @@ -97,7 +103,7 @@ final class UriNormalizer * Note: The sorting is neither locale nor Unicode aware (the URI query does not get decoded at all) as the * purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly. */ - const SORT_QUERY_PARAMETERS = 128; + public const SORT_QUERY_PARAMETERS = 128; /** * Returns a normalized URI. @@ -113,10 +119,9 @@ final class UriNormalizer * @param UriInterface $uri The URI to normalize * @param int $flags A bitmask of normalizations to apply, see constants * - * @return UriInterface The normalized URI * @link https://tools.ietf.org/html/rfc3986#section-6.2 */ - public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS) + public static function normalize(UriInterface $uri, int $flags = self::PRESERVING_NORMALIZATIONS): UriInterface { if ($flags & self::CAPITALIZE_PERCENT_ENCODING) { $uri = self::capitalizePercentEncoding($uri); @@ -169,15 +174,14 @@ public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NO * @param UriInterface $uri2 An URI to compare * @param int $normalizations A bitmask of normalizations to apply, see constants * - * @return bool * @link https://tools.ietf.org/html/rfc3986#section-6.1 */ - public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS) + public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, int $normalizations = self::PRESERVING_NORMALIZATIONS): bool { return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations); } - private static function capitalizePercentEncoding(UriInterface $uri) + private static function capitalizePercentEncoding(UriInterface $uri): UriInterface { $regex = '/(?:%[A-Fa-f0-9]{2})++/'; @@ -193,7 +197,7 @@ private static function capitalizePercentEncoding(UriInterface $uri) ); } - private static function decodeUnreservedCharacters(UriInterface $uri) + private static function decodeUnreservedCharacters(UriInterface $uri): UriInterface { $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i'; diff --git a/vendor/guzzlehttp/psr7/src/UriResolver.php b/vendor/guzzlehttp/psr7/src/UriResolver.php index c1cb8a2..426e5c9 100644 --- a/vendor/guzzlehttp/psr7/src/UriResolver.php +++ b/vendor/guzzlehttp/psr7/src/UriResolver.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + namespace GuzzleHttp\Psr7; use Psr\Http\Message\UriInterface; @@ -15,12 +18,9 @@ final class UriResolver /** * 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) + public static function removeDotSegments(string $path): string { if ($path === '' || $path === '/') { return $path; @@ -53,13 +53,9 @@ public static function removeDotSegments($path) /** * Converts the relative URI into a new URI that is resolved against the base URI. * - * @param UriInterface $base Base URI - * @param UriInterface $rel Relative URI - * - * @return UriInterface * @link http://tools.ietf.org/html/rfc3986#section-5.2 */ - public static function resolve(UriInterface $base, UriInterface $rel) + public static function resolve(UriInterface $base, UriInterface $rel): UriInterface { if ((string) $rel === '') { // we can simply return the same base URI instance for this same-document reference @@ -128,13 +124,8 @@ public static function resolve(UriInterface $base, UriInterface $rel) * relative-path reference will be returned as-is. * * echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well - * - * @param UriInterface $base Base URI - * @param UriInterface $target Target URI - * - * @return UriInterface The relative URI reference */ - public static function relativize(UriInterface $base, UriInterface $target) + public static function relativize(UriInterface $base, UriInterface $target): UriInterface { if ($target->getScheme() !== '' && ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '') @@ -171,6 +162,7 @@ public static function relativize(UriInterface $base, UriInterface $target) // inherit the base query component when resolving. if ($target->getQuery() === '') { $segments = explode('/', $target->getPath()); + /** @var string $lastSegment */ $lastSegment = end($segments); return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment); @@ -179,7 +171,7 @@ public static function relativize(UriInterface $base, UriInterface $target) return $emptyPathUri; } - private static function getRelativePath(UriInterface $base, UriInterface $target) + private static function getRelativePath(UriInterface $base, UriInterface $target): string { $sourceSegments = explode('/', $base->getPath()); $targetSegments = explode('/', $target->getPath()); diff --git a/vendor/guzzlehttp/psr7/src/Utils.php b/vendor/guzzlehttp/psr7/src/Utils.php new file mode 100644 index 0000000..3a4cf39 --- /dev/null +++ b/vendor/guzzlehttp/psr7/src/Utils.php @@ -0,0 +1,459 @@ +<?php + +declare(strict_types=1); + +namespace GuzzleHttp\Psr7; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\StreamInterface; +use Psr\Http\Message\UriInterface; + +final class Utils +{ + /** + * Remove the items given by the keys, case insensitively from the data. + * + * @param string[] $keys + */ + public static function caselessRemove(array $keys, array $data): array + { + $result = []; + + foreach ($keys as &$key) { + $key = strtolower($key); + } + + foreach ($data as $k => $v) { + if (!is_string($k) || !in_array(strtolower($k), $keys)) { + $result[$k] = $v; + } + } + + return $result; + } + + /** + * 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. + */ + public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void + { + $bufferSize = 8192; + + if ($maxLen === -1) { + while (!$source->eof()) { + if (!$dest->write($source->read($bufferSize))) { + break; + } + } + } else { + $remaining = $maxLen; + while ($remaining > 0 && !$source->eof()) { + $buf = $source->read(min($bufferSize, $remaining)); + $len = strlen($buf); + if (!$len) { + break; + } + $remaining -= $len; + $dest->write($buf); + } + } + } + + /** + * 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. + * + * @throws \RuntimeException on error. + */ + public static function copyToString(StreamInterface $stream, int $maxLen = -1): string + { + $buffer = ''; + + if ($maxLen === -1) { + while (!$stream->eof()) { + $buf = $stream->read(1048576); + if ($buf === '') { + break; + } + $buffer .= $buf; + } + return $buffer; + } + + $len = 0; + while (!$stream->eof() && $len < $maxLen) { + $buf = $stream->read($maxLen - $len); + if ($buf === '') { + break; + } + $buffer .= $buf; + $len = strlen($buffer); + } + + return $buffer; + } + + /** + * Calculate a hash of a stream. + * + * This method reads the entire stream to calculate a rolling hash, based + * on PHP's `hash_init` functions. + * + * @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 + * + * @throws \RuntimeException on error. + */ + public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string + { + $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, $rawOutput); + $stream->seek($pos); + + return $out; + } + + /** + * 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. + * + * @param RequestInterface $request Request to clone and modify. + * @param array $changes Changes to apply. + */ + public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface + { + 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; + + if ($port = $changes['uri']->getPort()) { + $standardPorts = ['http' => 80, 'https' => 443]; + $scheme = $changes['uri']->getScheme(); + if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) { + $changes['set_headers']['Host'] .= ':' . $port; + } + } + } + $uri = $changes['uri']; + } + + if (!empty($changes['remove_headers'])) { + $headers = self::caselessRemove($changes['remove_headers'], $headers); + } + + if (!empty($changes['set_headers'])) { + $headers = self::caselessRemove(array_keys($changes['set_headers']), $headers); + $headers = $changes['set_headers'] + $headers; + } + + if (isset($changes['query'])) { + $uri = $uri->withQuery($changes['query']); + } + + if ($request instanceof ServerRequestInterface) { + $new = (new ServerRequest( + $changes['method'] ?? $request->getMethod(), + $uri, + $headers, + $changes['body'] ?? $request->getBody(), + $changes['version'] ?? $request->getProtocolVersion(), + $request->getServerParams() + )) + ->withParsedBody($request->getParsedBody()) + ->withQueryParams($request->getQueryParams()) + ->withCookieParams($request->getCookieParams()) + ->withUploadedFiles($request->getUploadedFiles()); + + foreach ($request->getAttributes() as $key => $value) { + $new = $new->withAttribute($key, $value); + } + + return $new; + } + + return new Request( + $changes['method'] ?? $request->getMethod(), + $uri, + $headers, + $changes['body'] ?? $request->getBody(), + $changes['version'] ?? $request->getProtocolVersion() + ); + } + + /** + * Read a line from the stream up to the maximum allowed buffer length. + * + * @param StreamInterface $stream Stream to read from + * @param int|null $maxLength Maximum buffer length + */ + public static function readLine(StreamInterface $stream, ?int $maxLength = null): string + { + $buffer = ''; + $size = 0; + + while (!$stream->eof()) { + if ('' === ($byte = $stream->read(1))) { + return $buffer; + } + $buffer .= $byte; + // Break when a new line is found or the max length - 1 is reached + if ($byte === "\n" || ++$size === $maxLength - 1) { + break; + } + } + + return $buffer; + } + + /** + * 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. + * + * @param resource|string|int|float|bool|StreamInterface|callable|\Iterator|null $resource Entity body data + * @param array{size?: int, metadata?: array} $options Additional options + * + * @throws \InvalidArgumentException if the $resource arg is not valid. + */ + public static function streamFor($resource = '', array $options = []): StreamInterface + { + if (is_scalar($resource)) { + $stream = self::tryFopen('php://temp', 'r+'); + if ($resource !== '') { + fwrite($stream, (string) $resource); + fseek($stream, 0); + } + return new Stream($stream, $options); + } + + switch (gettype($resource)) { + case 'resource': + /* + * The 'php://input' is a special stream with quirks and inconsistencies. + * We avoid using that stream by reading it into php://temp + */ + + /** @var resource $resource */ + if ((\stream_get_meta_data($resource)['uri'] ?? '') === 'php://input') { + $stream = self::tryFopen('php://temp', 'w+'); + stream_copy_to_stream($resource, $stream); + fseek($stream, 0); + $resource = $stream; + } + return new Stream($resource, $options); + case 'object': + /** @var object $resource */ + 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 self::streamFor((string) $resource, $options); + } + break; + case 'NULL': + return new Stream(self::tryFopen('php://temp', 'r+'), $options); + } + + if (is_callable($resource)) { + return new PumpStream($resource, $options); + } + + throw new \InvalidArgumentException('Invalid resource type: ' . gettype($resource)); + } + + /** + * 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 + */ + public static function tryFopen(string $filename, string $mode) + { + $ex = null; + set_error_handler(static function (int $errno, string $errstr) use ($filename, $mode, &$ex): bool { + $ex = new \RuntimeException(sprintf( + 'Unable to open "%s" using mode "%s": %s', + $filename, + $mode, + $errstr + )); + + return true; + }); + + try { + /** @var resource $handle */ + $handle = fopen($filename, $mode); + } catch (\Throwable $e) { + $ex = new \RuntimeException(sprintf( + 'Unable to open "%s" using mode "%s": %s', + $filename, + $mode, + $e->getMessage() + ), 0, $e); + } + + restore_error_handler(); + + if ($ex) { + /** @var $ex \RuntimeException */ + throw $ex; + } + + return $handle; + } + + /** + * Safely gets the contents of a given stream. + * + * When stream_get_contents fails, PHP normally raises a warning. This + * function adds an error handler that checks for errors and throws an + * exception instead. + * + * @param resource $stream + * + * @throws \RuntimeException if the stream cannot be read + */ + public static function tryGetContents($stream): string + { + $ex = null; + set_error_handler(static function (int $errno, string $errstr) use (&$ex): bool { + $ex = new \RuntimeException(sprintf( + 'Unable to read stream contents: %s', + $errstr + )); + + return true; + }); + + try { + /** @var string|false $contents */ + $contents = stream_get_contents($stream); + + if ($contents === false) { + $ex = new \RuntimeException('Unable to read stream contents'); + } + } catch (\Throwable $e) { + $ex = new \RuntimeException(sprintf( + 'Unable to read stream contents: %s', + $e->getMessage() + ), 0, $e); + } + + restore_error_handler(); + + if ($ex) { + /** @var $ex \RuntimeException */ + throw $ex; + } + + return $contents; + } + + /** + * Returns a UriInterface for the given value. + * + * This function accepts a string or 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 + * + * @throws \InvalidArgumentException + */ + public static function uriFor($uri): UriInterface + { + if ($uri instanceof UriInterface) { + return $uri; + } + + if (is_string($uri)) { + return new Uri($uri); + } + + throw new \InvalidArgumentException('URI must be a string or UriInterface'); + } +} diff --git a/vendor/guzzlehttp/psr7/src/functions.php b/vendor/guzzlehttp/psr7/src/functions.php deleted file mode 100644 index e40348d..0000000 --- a/vendor/guzzlehttp/psr7/src/functions.php +++ /dev/null @@ -1,828 +0,0 @@ -<?php -namespace GuzzleHttp\Psr7; - -use Psr\Http\Message\MessageInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Message\StreamInterface; -use Psr\Http\Message\UriInterface; - -/** - * Returns the string representation of an HTTP message. - * - * @param MessageInterface $message Message to convert to a string. - * - * @return string - */ -function str(MessageInterface $message) -{ - if ($message instanceof RequestInterface) { - $msg = trim($message->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|null|int|float|bool|StreamInterface|callable $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 = []) -{ - if (is_scalar($resource)) { - $stream = fopen('php://temp', 'r+'); - if ($resource !== '') { - fwrite($stream, $resource); - fseek($stream, 0); - } - return new Stream($stream, $options); - } - - switch (gettype($resource)) { - 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 = []; - - foreach (normalize_header($header) as $val) { - $part = []; - 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 = []; - 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; - - if ($port = $changes['uri']->getPort()) { - $standardPorts = ['http' => 80, 'https' => 443]; - $scheme = $changes['uri']->getScheme(); - if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) { - $changes['set_headers']['Host'] .= ':'.$port; - } - } - } - $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']); - } - - if ($request instanceof ServerRequestInterface) { - return new ServerRequest( - isset($changes['method']) ? $changes['method'] : $request->getMethod(), - $uri, - $headers, - isset($changes['body']) ? $changes['body'] : $request->getBody(), - isset($changes['version']) - ? $changes['version'] - : $request->getProtocolVersion(), - $request->getServerParams() - ); - } - - 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; - set_error_handler(function () use ($filename, $mode, &$ex) { - $ex = new \RuntimeException(sprintf( - 'Unable to open %s using mode %s: %s', - $filename, - $mode, - func_get_args()[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 -) { - $bufferSize = 8192; - - if ($maxLen === -1) { - while (!$source->eof()) { - if (!$dest->write($source->read($bufferSize))) { - break; - } - } - } else { - $remaining = $maxLen; - while ($remaining > 0 && !$source->eof()) { - $buf = $source->read(min($bufferSize, $remaining)); - $len = strlen($buf); - if (!$len) { - break; - } - $remaining -= $len; - $dest->write($buf); - } - } -} - -/** - * 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 === "\n" || ++$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 = []; - if (!preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) { - throw new \InvalidArgumentException('Invalid request string'); - } - $parts = explode(' ', $data['start-line'], 3); - $version = isset($parts[2]) ? explode('/', $parts[2])[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 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); - - return new Response( - $parts[1], - $data['headers'], - $data['body'], - explode('/', $parts[0])[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 = []; - - 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] = [$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 parse_query() 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 = [ - '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 = ['start-line' => array_shift($lines), 'headers' => [], '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 = []; - - 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/vendor/guzzlehttp/psr7/src/functions_include.php b/vendor/guzzlehttp/psr7/src/functions_include.php deleted file mode 100644 index 96a4a83..0000000 --- a/vendor/guzzlehttp/psr7/src/functions_include.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php - -// Don't redefine the functions if included multiple times. -if (!function_exists('GuzzleHttp\Psr7\str')) { - require __DIR__ . '/functions.php'; -} diff --git a/vendor/php-cs-fixer/diff/ChangeLog.md b/vendor/php-cs-fixer/diff/ChangeLog.md new file mode 100644 index 0000000..b876708 --- /dev/null +++ b/vendor/php-cs-fixer/diff/ChangeLog.md @@ -0,0 +1,7 @@ +# ChangeLog + +Changelog for v1.0 + +First stable release, based on: +https://github.com/sebastianbergmann/diff/releases +1.4.3 and 2.0.1 diff --git a/vendor/php-cs-fixer/diff/LICENSE b/vendor/php-cs-fixer/diff/LICENSE new file mode 100644 index 0000000..19a2d69 --- /dev/null +++ b/vendor/php-cs-fixer/diff/LICENSE @@ -0,0 +1,5 @@ +Code from `sebastian/diff` has been forked and republished by permission of Sebastian Bergmann. +Licenced with BSD-3-Clause @ see LICENSE_DIFF, copyright (c) Sebastian Bergmann <sebastian@phpunit.de> + +Code from `GeckoPackages/GeckoDiffOutputBuilder` has been copied and republished by permission of GeckoPackages. +Licenced with MIT @ see LICENSE_GECKO, copyright (c) GeckoPackages https://github.com/GeckoPackages diff --git a/vendor/php-cs-fixer/diff/LICENSE_DIFF b/vendor/php-cs-fixer/diff/LICENSE_DIFF new file mode 100644 index 0000000..93cf008 --- /dev/null +++ b/vendor/php-cs-fixer/diff/LICENSE_DIFF @@ -0,0 +1,31 @@ +Copyright (c) 2002-2017, Sebastian Bergmann <sebastian@phpunit.de>. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Sebastian Bergmann nor the names of his + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/php-cs-fixer/diff/LICENSE_GECKO b/vendor/php-cs-fixer/diff/LICENSE_GECKO new file mode 100644 index 0000000..066294d --- /dev/null +++ b/vendor/php-cs-fixer/diff/LICENSE_GECKO @@ -0,0 +1,19 @@ +Copyright (c) https://github.com/GeckoPackages + +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. \ No newline at end of file diff --git a/vendor/php-cs-fixer/diff/README.md b/vendor/php-cs-fixer/diff/README.md new file mode 100644 index 0000000..d410625 --- /dev/null +++ b/vendor/php-cs-fixer/diff/README.md @@ -0,0 +1,13 @@ +# PHP-CS-Fixer/diff + +This version is for PHP CS Fixer only! Do not use it! + +Code from `sebastian/diff` has been forked a republished by permission of Sebastian Bergmann. +Licenced with BSD-3-Clause @ see LICENSE_DIFF, copyright (c) Sebastian Bergmann <sebastian@phpunit.de> +https://github.com/sebastianbergmann/diff + +Code from `GeckoPackages/GeckoDiffOutputBuilder` has been copied and republished by permission of GeckoPackages. +Licenced with MIT @ see LICENSE_GECKO, copyright (c) GeckoPackages https://github.com/GeckoPackages +https://github.com/GeckoPackages/GeckoDiffOutputBuilder/ + +For questions visit us @ https://gitter.im/PHP-CS-Fixer/Lobby diff --git a/vendor/php-cs-fixer/diff/composer.json b/vendor/php-cs-fixer/diff/composer.json new file mode 100644 index 0000000..2c4b3ad --- /dev/null +++ b/vendor/php-cs-fixer/diff/composer.json @@ -0,0 +1,41 @@ +{ + "name": "php-cs-fixer/diff", + "description": "sebastian/diff v2 backport support for PHP5.6", + "keywords": ["diff"], + "homepage": "https://github.com/PHP-CS-Fixer", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "SpacePossum" + } + ], + "require": { + "php": "^5.6 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", + "symfony/process": "^3.3" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "psr-4": { + "PhpCsFixer\\Diff\\v1_4\\Tests\\": "tests/v1_4", + "PhpCsFixer\\Diff\\v2_0\\Tests\\": "tests/v2_0", + "PhpCsFixer\\Diff\\v3_0\\": "tests/v3_0", + "PhpCsFixer\\Diff\\GeckoPackages\\DiffOutputBuilder\\Tests\\": "tests/GeckoPackages/DiffOutputBuilder/Tests", + "PhpCsFixer\\Diff\\GeckoPackages\\DiffOutputBuilder\\Utils\\": "tests/GeckoPackages/DiffOutputBuilder/Utils" + } + } +} diff --git a/vendor/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/ConfigurationException.php b/vendor/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/ConfigurationException.php new file mode 100644 index 0000000..315ac07 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/ConfigurationException.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of the GeckoPackages. + * + * (c) GeckoPackages https://github.com/GeckoPackages + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Diff\GeckoPackages\DiffOutputBuilder; + +use Exception; + +final class ConfigurationException extends \InvalidArgumentException +{ + public function __construct( + $option, + $expected, + $value, + $code = 0, + Exception $previous = null + ) { + parent::__construct( + \sprintf( + 'Option "%s" must be %s, got "%s".', + $option, + $expected, + \is_object($value) ? \get_class($value) : (null === $value ? '<null>' : \gettype($value).'#'.$value) + ), + $code, + $previous + ); + } +} diff --git a/vendor/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/UnifiedDiffOutputBuilder.php b/vendor/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/UnifiedDiffOutputBuilder.php new file mode 100644 index 0000000..8a70372 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/GeckoPackages/DiffOutputBuilder/UnifiedDiffOutputBuilder.php @@ -0,0 +1,295 @@ +<?php + +/* + * This file is part of the GeckoPackages. + * + * (c) GeckoPackages https://github.com/GeckoPackages + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Diff\GeckoPackages\DiffOutputBuilder; + +use PhpCsFixer\Diff\v2_0\Output\DiffOutputBuilderInterface; + +/** + * Strict Unified diff output builder. + * + * @name Unified diff output builder + * + * @description Generates (strict) Unified diff's (unidiffs) with hunks. + * + * @author SpacePossum + * + * @api + */ +final class UnifiedDiffOutputBuilder implements DiffOutputBuilderInterface +{ + /** + * @var int + */ + private static $noNewlineAtOEFid = 998877; + + /** + * @var bool + */ + private $changed; + + /** + * @var bool + */ + private $collapseRanges; + + /** + * @var int >= 0 + */ + private $commonLineThreshold; + + /** + * @var string + */ + private $header; + + /** + * @var int >= 0 + */ + private $contextLines; + + private static $default = [ + 'contextLines' => 3, // like `diff: -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3 + 'collapseRanges' => true, // ranges of length one are rendered with the trailing `,1` + 'fromFile' => null, + 'fromFileDate' => null, + 'toFile' => null, + 'toFileDate' => null, + 'commonLineThreshold' => 6, // number of same lines before ending a new hunk and creating a new one (if needed) + ]; + + public function __construct(array $options = []) + { + $options = \array_merge(self::$default, $options); + + if (!\is_bool($options['collapseRanges'])) { + throw new ConfigurationException('collapseRanges', 'a bool', $options['collapseRanges']); + } + + if (!\is_int($options['contextLines']) || $options['contextLines'] < 0) { + throw new ConfigurationException('contextLines', 'an int >= 0', $options['contextLines']); + } + + if (!\is_int($options['commonLineThreshold']) || $options['commonLineThreshold'] < 1) { + throw new ConfigurationException('commonLineThreshold', 'an int > 0', $options['commonLineThreshold']); + } + + foreach (['fromFile', 'toFile'] as $option) { + if (!\is_string($options[$option])) { + throw new ConfigurationException($option, 'a string', $options[$option]); + } + } + + foreach (['fromFileDate', 'toFileDate'] as $option) { + if (null !== $options[$option] && !\is_string($options[$option])) { + throw new ConfigurationException($option, 'a string or <null>', $options[$option]); + } + } + + $this->header = \sprintf( + "--- %s%s\n+++ %s%s\n", + $options['fromFile'], + null === $options['fromFileDate'] ? '' : "\t".$options['fromFileDate'], + $options['toFile'], + null === $options['toFileDate'] ? '' : "\t".$options['toFileDate'] + ); + + $this->collapseRanges = $options['collapseRanges']; + $this->commonLineThreshold = $options['commonLineThreshold']; + $this->contextLines = $options['contextLines']; + } + + public function getDiff(array $diff) + { + if (0 === \count($diff)) { + return ''; + } + + $this->changed = false; + + $buffer = \fopen('php://memory', 'r+b'); + \fwrite($buffer, $this->header); + + $this->writeDiffHunks($buffer, $diff); + + $diff = \stream_get_contents($buffer, -1, 0); + + \fclose($buffer); + + if (!$this->changed) { + return ''; + } + + return $diff; + } + + private function writeDiffHunks($output, array $diff) + { + // detect "No newline at end of file" and insert into `$diff` if needed + + $upperLimit = \count($diff); + + // append "\ No newline at end of file" if needed + if (0 === $diff[$upperLimit - 1][1]) { + $lc = \substr($diff[$upperLimit - 1][0], -1); + if ("\n" !== $lc) { + \array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", self::$noNewlineAtOEFid]]); + } + } else { + // search back for the last `+` and `-` line, + // check if has trailing linebreak, else add under it warning under it + $toFind = [1 => true, 2 => true]; + for ($i = $upperLimit - 1; $i >= 0; --$i) { + if (isset($toFind[$diff[$i][1]])) { + unset($toFind[$diff[$i][1]]); + $lc = \substr($diff[$i][0], -1); + if ("\n" !== $lc) { + \array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", self::$noNewlineAtOEFid]]); + } + + if (!\count($toFind)) { + break; + } + } + } + } + + // write hunks to output buffer + + $cutOff = \max($this->commonLineThreshold, $this->contextLines); + $hunkCapture = false; + $sameCount = $toRange = $fromRange = 0; + $toStart = $fromStart = 1; + + foreach ($diff as $i => $entry) { + if (0 === $entry[1]) { // same + if (false === $hunkCapture) { + ++$fromStart; + ++$toStart; + + continue; + } + + ++$sameCount; + ++$toRange; + ++$fromRange; + + if ($sameCount === $cutOff) { + $contextStartOffset = $hunkCapture - $this->contextLines < 0 + ? $hunkCapture + : $this->contextLines + ; + + $contextEndOffset = $i + $this->contextLines >= \count($diff) + ? \count($diff) - $i + : $this->contextLines + ; + + $this->writeHunk( + $diff, + $hunkCapture - $contextStartOffset, + $i - $cutOff + $contextEndOffset + 1, + $fromStart - $contextStartOffset, + $fromRange - $cutOff + $contextStartOffset + $contextEndOffset, + $toStart - $contextStartOffset, + $toRange - $cutOff + $contextStartOffset + $contextEndOffset, + $output + ); + + $fromStart += $fromRange; + $toStart += $toRange; + + $hunkCapture = false; + $sameCount = $toRange = $fromRange = 0; + } + + continue; + } + + $sameCount = 0; + + if ($entry[1] === self::$noNewlineAtOEFid) { + continue; + } + + $this->changed = true; + + if (false === $hunkCapture) { + $hunkCapture = $i; + } + + if (1 === $entry[1]) { // added + ++$toRange; + } + + if (2 === $entry[1]) { // removed + ++$fromRange; + } + } + + if (false !== $hunkCapture) { + $contextStartOffset = $hunkCapture - $this->contextLines < 0 + ? $hunkCapture + : $this->contextLines + ; + + $this->writeHunk( + $diff, + $hunkCapture - $contextStartOffset, + \count($diff), + $fromStart - $contextStartOffset, + $fromRange + $contextStartOffset, + $toStart - $contextStartOffset, + $toRange + $contextStartOffset, + $output + ); + } + } + + private function writeHunk( + array $diff, + $diffStartIndex, + $diffEndIndex, + $fromStart, + $fromRange, + $toStart, + $toRange, + $output + ) { + \fwrite($output, '@@ -'.$fromStart); + + if (!$this->collapseRanges || 1 !== $fromRange) { + \fwrite($output, ','.$fromRange); + } + + \fwrite($output, ' +'.$toStart); + if (!$this->collapseRanges || 1 !== $toRange) { + \fwrite($output, ','.$toRange); + } + + \fwrite($output, " @@\n"); + + for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { + if ($diff[$i][1] === 1) { // added + $this->changed = true; + \fwrite($output, '+'.$diff[$i][0]); + } elseif ($diff[$i][1] === 2) { // removed + $this->changed = true; + \fwrite($output, '-'.$diff[$i][0]); + } elseif ($diff[$i][1] === 0) { // same + \fwrite($output, ' '.$diff[$i][0]); + } elseif ($diff[$i][1] === self::$noNewlineAtOEFid) { + $this->changed = true; + \fwrite($output, $diff[$i][0]); + } + } + } +} diff --git a/vendor/php-cs-fixer/diff/src/v1_4/Chunk.php b/vendor/php-cs-fixer/diff/src/v1_4/Chunk.php new file mode 100644 index 0000000..b247e03 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v1_4/Chunk.php @@ -0,0 +1,103 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v1_4; + +class Chunk +{ + /** + * @var int + */ + private $start; + + /** + * @var int + */ + private $startRange; + + /** + * @var int + */ + private $end; + + /** + * @var int + */ + private $endRange; + + /** + * @var array + */ + private $lines; + + /** + * @param int $start + * @param int $startRange + * @param int $end + * @param int $endRange + * @param array $lines + */ + public function __construct($start = 0, $startRange = 1, $end = 0, $endRange = 1, array $lines = array()) + { + $this->start = (int) $start; + $this->startRange = (int) $startRange; + $this->end = (int) $end; + $this->endRange = (int) $endRange; + $this->lines = $lines; + } + + /** + * @return int + */ + public function getStart() + { + return $this->start; + } + + /** + * @return int + */ + public function getStartRange() + { + return $this->startRange; + } + + /** + * @return int + */ + public function getEnd() + { + return $this->end; + } + + /** + * @return int + */ + public function getEndRange() + { + return $this->endRange; + } + + /** + * @return array + */ + public function getLines() + { + return $this->lines; + } + + /** + * @param array $lines + */ + public function setLines(array $lines) + { + $this->lines = $lines; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v1_4/Diff.php b/vendor/php-cs-fixer/diff/src/v1_4/Diff.php new file mode 100644 index 0000000..695a519 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v1_4/Diff.php @@ -0,0 +1,73 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v1_4; + +class Diff +{ + /** + * @var string + */ + private $from; + + /** + * @var string + */ + private $to; + + /** + * @var Chunk[] + */ + private $chunks; + + /** + * @param string $from + * @param string $to + * @param Chunk[] $chunks + */ + public function __construct($from, $to, array $chunks = array()) + { + $this->from = $from; + $this->to = $to; + $this->chunks = $chunks; + } + + /** + * @return string + */ + public function getFrom() + { + return $this->from; + } + + /** + * @return string + */ + public function getTo() + { + return $this->to; + } + + /** + * @return Chunk[] + */ + public function getChunks() + { + return $this->chunks; + } + + /** + * @param Chunk[] $chunks + */ + public function setChunks(array $chunks) + { + $this->chunks = $chunks; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v1_4/Differ.php b/vendor/php-cs-fixer/diff/src/v1_4/Differ.php new file mode 100644 index 0000000..b2015ab --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v1_4/Differ.php @@ -0,0 +1,399 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v1_4; + +use PhpCsFixer\Diff\v1_4\LCS\LongestCommonSubsequence; +use PhpCsFixer\Diff\v1_4\LCS\TimeEfficientImplementation; +use PhpCsFixer\Diff\v1_4\LCS\MemoryEfficientImplementation; + +/** + * Diff implementation. + */ +class Differ +{ + /** + * @var string + */ + private $header; + + /** + * @var bool + */ + private $showNonDiffLines; + + /** + * @param string $header + * @param bool $showNonDiffLines + */ + public function __construct($header = "--- Original\n+++ New\n", $showNonDiffLines = true) + { + $this->header = $header; + $this->showNonDiffLines = $showNonDiffLines; + } + + /** + * Returns the diff between two arrays or strings as string. + * + * @param array|string $from + * @param array|string $to + * @param LongestCommonSubsequence $lcs + * + * @return string + */ + public function diff($from, $to, LongestCommonSubsequence $lcs = null) + { + $from = $this->validateDiffInput($from); + $to = $this->validateDiffInput($to); + $diff = $this->diffToArray($from, $to, $lcs); + $old = $this->checkIfDiffInOld($diff); + $start = isset($old[0]) ? $old[0] : 0; + $end = \count($diff); + + if ($tmp = \array_search($end, $old)) { + $end = $tmp; + } + + return $this->getBuffer($diff, $old, $start, $end); + } + + /** + * Casts variable to string if it is not a string or array. + * + * @param mixed $input + * + * @return string + */ + private function validateDiffInput($input) + { + if (!\is_array($input) && !\is_string($input)) { + return (string) $input; + } + + return $input; + } + + /** + * Takes input of the diff array and returns the old array. + * Iterates through diff line by line, + * + * @param array $diff + * + * @return array + */ + private function checkIfDiffInOld(array $diff) + { + $inOld = false; + $i = 0; + $old = array(); + + foreach ($diff as $line) { + if ($line[1] === 0 /* OLD */) { + if ($inOld === false) { + $inOld = $i; + } + } elseif ($inOld !== false) { + if (($i - $inOld) > 5) { + $old[$inOld] = $i - 1; + } + + $inOld = false; + } + + ++$i; + } + + return $old; + } + + /** + * Generates buffer in string format, returning the patch. + * + * @param array $diff + * @param array $old + * @param int $start + * @param int $end + * + * @return string + */ + private function getBuffer(array $diff, array $old, $start, $end) + { + $buffer = $this->header; + + if (!isset($old[$start])) { + $buffer = $this->getDiffBufferElementNew($diff, $buffer, $start); + ++$start; + } + + for ($i = $start; $i < $end; $i++) { + if (isset($old[$i])) { + $i = $old[$i]; + $buffer = $this->getDiffBufferElementNew($diff, $buffer, $i); + } else { + $buffer = $this->getDiffBufferElement($diff, $buffer, $i); + } + } + + return $buffer; + } + + /** + * Gets individual buffer element. + * + * @param array $diff + * @param string $buffer + * @param int $diffIndex + * + * @return string + */ + private function getDiffBufferElement(array $diff, $buffer, $diffIndex) + { + if ($diff[$diffIndex][1] === 1 /* ADDED */) { + $buffer .= '+' . $diff[$diffIndex][0] . "\n"; + } elseif ($diff[$diffIndex][1] === 2 /* REMOVED */) { + $buffer .= '-' . $diff[$diffIndex][0] . "\n"; + } elseif ($this->showNonDiffLines === true) { + $buffer .= ' ' . $diff[$diffIndex][0] . "\n"; + } + + return $buffer; + } + + /** + * Gets individual buffer element with opening. + * + * @param array $diff + * @param string $buffer + * @param int $diffIndex + * + * @return string + */ + private function getDiffBufferElementNew(array $diff, $buffer, $diffIndex) + { + if ($this->showNonDiffLines === true) { + $buffer .= "@@ @@\n"; + } + + return $this->getDiffBufferElement($diff, $buffer, $diffIndex); + } + + /** + * Returns the diff between two arrays or strings as array. + * + * Each array element contains two elements: + * - [0] => mixed $token + * - [1] => 2|1|0 + * + * - 2: REMOVED: $token was removed from $from + * - 1: ADDED: $token was added to $from + * - 0: OLD: $token is not changed in $to + * + * @param array|string $from + * @param array|string $to + * @param LongestCommonSubsequence $lcs + * + * @return array + */ + public function diffToArray($from, $to, LongestCommonSubsequence $lcs = null) + { + if (\is_string($from)) { + $fromMatches = $this->getNewLineMatches($from); + $from = $this->splitStringByLines($from); + } elseif (\is_array($from)) { + $fromMatches = array(); + } else { + throw new \InvalidArgumentException('"from" must be an array or string.'); + } + + if (\is_string($to)) { + $toMatches = $this->getNewLineMatches($to); + $to = $this->splitStringByLines($to); + } elseif (\is_array($to)) { + $toMatches = array(); + } else { + throw new \InvalidArgumentException('"to" must be an array or string.'); + } + + list($from, $to, $start, $end) = self::getArrayDiffParted($from, $to); + + if ($lcs === null) { + $lcs = $this->selectLcsImplementation($from, $to); + } + + $common = $lcs->calculate(\array_values($from), \array_values($to)); + $diff = array(); + + if ($this->detectUnmatchedLineEndings($fromMatches, $toMatches)) { + $diff[] = array( + '#Warnings contain different line endings!', + 0 + ); + } + + foreach ($start as $token) { + $diff[] = array($token, 0 /* OLD */); + } + + \reset($from); + \reset($to); + + foreach ($common as $token) { + while (($fromToken = \reset($from)) !== $token) { + $diff[] = array(\array_shift($from), 2 /* REMOVED */); + } + + while (($toToken = \reset($to)) !== $token) { + $diff[] = array(\array_shift($to), 1 /* ADDED */); + } + + $diff[] = array($token, 0 /* OLD */); + + \array_shift($from); + \array_shift($to); + } + + while (($token = \array_shift($from)) !== null) { + $diff[] = array($token, 2 /* REMOVED */); + } + + while (($token = \array_shift($to)) !== null) { + $diff[] = array($token, 1 /* ADDED */); + } + + foreach ($end as $token) { + $diff[] = array($token, 0 /* OLD */); + } + + return $diff; + } + + /** + * Get new strings denoting new lines from a given string. + * + * @param string $string + * + * @return array + */ + private function getNewLineMatches($string) + { + \preg_match_all('(\r\n|\r|\n)', $string, $stringMatches); + + return $stringMatches; + } + + /** + * Checks if input is string, if so it will split it line-by-line. + * + * @param string $input + * + * @return array + */ + private function splitStringByLines($input) + { + return \preg_split('(\r\n|\r|\n)', $input); + } + + /** + * @param array $from + * @param array $to + * + * @return LongestCommonSubsequence + */ + private function selectLcsImplementation(array $from, array $to) + { + // We do not want to use the time-efficient implementation if its memory + // footprint will probably exceed this value. Note that the footprint + // calculation is only an estimation for the matrix and the LCS method + // will typically allocate a bit more memory than this. + $memoryLimit = 100 * 1024 * 1024; + + if ($this->calculateEstimatedFootprint($from, $to) > $memoryLimit) { + return new MemoryEfficientImplementation; + } + + return new TimeEfficientImplementation; + } + + /** + * Calculates the estimated memory footprint for the DP-based method. + * + * @param array $from + * @param array $to + * + * @return int|float + */ + private function calculateEstimatedFootprint(array $from, array $to) + { + $itemSize = PHP_INT_SIZE === 4 ? 76 : 144; + + return $itemSize * \pow(\min(\count($from), \count($to)), 2); + } + + /** + * Returns true if line ends don't match on fromMatches and toMatches. + * + * @param array $fromMatches + * @param array $toMatches + * + * @return bool + */ + private function detectUnmatchedLineEndings(array $fromMatches, array $toMatches) + { + return isset($fromMatches[0], $toMatches[0]) && + \count($fromMatches[0]) === \count($toMatches[0]) && + $fromMatches[0] !== $toMatches[0]; + } + + /** + * @param array $from + * @param array $to + * + * @return array + */ + private static function getArrayDiffParted(array &$from, array &$to) + { + $start = array(); + $end = array(); + + \reset($to); + + foreach ($from as $k => $v) { + $toK = \key($to); + + if ($toK === $k && $v === $to[$k]) { + $start[$k] = $v; + + unset($from[$k], $to[$k]); + } else { + break; + } + } + + \end($from); + \end($to); + + do { + $fromK = \key($from); + $toK = \key($to); + + if (null === $fromK || null === $toK || \current($from) !== \current($to)) { + break; + } + + \prev($from); + \prev($to); + + $end = array($fromK => $from[$fromK]) + $end; + unset($from[$fromK], $to[$toK]); + } while (true); + + return array($from, $to, $start, $end); + } +} diff --git a/vendor/php-cs-fixer/diff/src/v1_4/LCS/LongestCommonSubsequence.php b/vendor/php-cs-fixer/diff/src/v1_4/LCS/LongestCommonSubsequence.php new file mode 100644 index 0000000..dad5a0c --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v1_4/LCS/LongestCommonSubsequence.php @@ -0,0 +1,27 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v1_4\LCS; + +/** + * Interface for implementations of longest common subsequence calculation. + */ +interface LongestCommonSubsequence +{ + /** + * Calculates the longest common subsequence of two arrays. + * + * @param array $from + * @param array $to + * + * @return array + */ + public function calculate(array $from, array $to); +} diff --git a/vendor/php-cs-fixer/diff/src/v1_4/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php b/vendor/php-cs-fixer/diff/src/v1_4/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php new file mode 100644 index 0000000..6685252 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v1_4/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php @@ -0,0 +1,95 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v1_4\LCS; + +/** + * Memory-efficient implementation of longest common subsequence calculation. + */ +class MemoryEfficientImplementation implements LongestCommonSubsequence +{ + /** + * Calculates the longest common subsequence of two arrays. + * + * @param array $from + * @param array $to + * + * @return array + */ + public function calculate(array $from, array $to) + { + $cFrom = \count($from); + $cTo = \count($to); + + if ($cFrom === 0) { + return array(); + } + + if ($cFrom === 1) { + if (\in_array($from[0], $to, true)) { + return array($from[0]); + } + + return array(); + } + + $i = (int) ($cFrom / 2); + $fromStart = \array_slice($from, 0, $i); + $fromEnd = \array_slice($from, $i); + $llB = $this->length($fromStart, $to); + $llE = $this->length(\array_reverse($fromEnd), \array_reverse($to)); + $jMax = 0; + $max = 0; + + for ($j = 0; $j <= $cTo; $j++) { + $m = $llB[$j] + $llE[$cTo - $j]; + + if ($m >= $max) { + $max = $m; + $jMax = $j; + } + } + + $toStart = \array_slice($to, 0, $jMax); + $toEnd = \array_slice($to, $jMax); + + return \array_merge( + $this->calculate($fromStart, $toStart), + $this->calculate($fromEnd, $toEnd) + ); + } + + /** + * @param array $from + * @param array $to + * + * @return array + */ + private function length(array $from, array $to) + { + $current = \array_fill(0, \count($to) + 1, 0); + $cFrom = \count($from); + $cTo = \count($to); + + for ($i = 0; $i < $cFrom; $i++) { + $prev = $current; + + for ($j = 0; $j < $cTo; $j++) { + if ($from[$i] === $to[$j]) { + $current[$j + 1] = $prev[$j] + 1; + } else { + $current[$j + 1] = \max($current[$j], $prev[$j + 1]); + } + } + } + + return $current; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v1_4/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php b/vendor/php-cs-fixer/diff/src/v1_4/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php new file mode 100644 index 0000000..4acd68e --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v1_4/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php @@ -0,0 +1,74 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v1_4\LCS; + +/** + * Time-efficient implementation of longest common subsequence calculation. + */ +class TimeEfficientImplementation implements LongestCommonSubsequence +{ + /** + * Calculates the longest common subsequence of two arrays. + * + * @param array $from + * @param array $to + * + * @return array + */ + public function calculate(array $from, array $to) + { + $common = array(); + $fromLength = \count($from); + $toLength = \count($to); + $width = $fromLength + 1; + $matrix = new \SplFixedArray($width * ($toLength + 1)); + + for ($i = 0; $i <= $fromLength; ++$i) { + $matrix[$i] = 0; + } + + for ($j = 0; $j <= $toLength; ++$j) { + $matrix[$j * $width] = 0; + } + + for ($i = 1; $i <= $fromLength; ++$i) { + for ($j = 1; $j <= $toLength; ++$j) { + $o = ($j * $width) + $i; + $matrix[$o] = \max( + $matrix[$o - 1], + $matrix[$o - $width], + $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0 + ); + } + } + + $i = $fromLength; + $j = $toLength; + + while ($i > 0 && $j > 0) { + if ($from[$i - 1] === $to[$j - 1]) { + $common[] = $from[$i - 1]; + --$i; + --$j; + } else { + $o = ($j * $width) + $i; + + if ($matrix[$o - $width] > $matrix[$o - 1]) { + --$j; + } else { + --$i; + } + } + } + + return \array_reverse($common); + } +} diff --git a/vendor/php-cs-fixer/diff/src/v1_4/Line.php b/vendor/php-cs-fixer/diff/src/v1_4/Line.php new file mode 100644 index 0000000..1187bcd --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v1_4/Line.php @@ -0,0 +1,54 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v1_4; + +class Line +{ + const ADDED = 1; + const REMOVED = 2; + const UNCHANGED = 3; + + /** + * @var int + */ + private $type; + + /** + * @var string + */ + private $content; + + /** + * @param int $type + * @param string $content + */ + public function __construct($type = self::UNCHANGED, $content = '') + { + $this->type = $type; + $this->content = $content; + } + + /** + * @return string + */ + public function getContent() + { + return $this->content; + } + + /** + * @return int + */ + public function getType() + { + return $this->type; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v1_4/Parser.php b/vendor/php-cs-fixer/diff/src/v1_4/Parser.php new file mode 100644 index 0000000..6f8e75b --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v1_4/Parser.php @@ -0,0 +1,110 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v1_4; + +/** + * Unified diff parser. + */ +class Parser +{ + /** + * @param string $string + * + * @return Diff[] + */ + public function parse($string) + { + $lines = \preg_split('(\r\n|\r|\n)', $string); + + if (!empty($lines) && $lines[\count($lines) - 1] == '') { + \array_pop($lines); + } + + $lineCount = \count($lines); + $diffs = array(); + $diff = null; + $collected = array(); + + for ($i = 0; $i < $lineCount; ++$i) { + if (\preg_match('(^---\\s+(?P<file>\\S+))', $lines[$i], $fromMatch) && + \preg_match('(^\\+\\+\\+\\s+(?P<file>\\S+))', $lines[$i + 1], $toMatch)) { + if ($diff !== null) { + $this->parseFileDiff($diff, $collected); + + $diffs[] = $diff; + $collected = array(); + } + + $diff = new Diff($fromMatch['file'], $toMatch['file']); + + ++$i; + } else { + if (\preg_match('/^(?:diff --git |index [\da-f\.]+|[+-]{3} [ab])/', $lines[$i])) { + continue; + } + + $collected[] = $lines[$i]; + } + } + + if ($diff !== null && \count($collected)) { + $this->parseFileDiff($diff, $collected); + + $diffs[] = $diff; + } + + return $diffs; + } + + /** + * @param Diff $diff + * @param array $lines + */ + private function parseFileDiff(Diff $diff, array $lines) + { + $chunks = array(); + $chunk = null; + + foreach ($lines as $line) { + if (\preg_match('/^@@\s+-(?P<start>\d+)(?:,\s*(?P<startrange>\d+))?\s+\+(?P<end>\d+)(?:,\s*(?P<endrange>\d+))?\s+@@/', $line, $match)) { + $chunk = new Chunk( + $match['start'], + isset($match['startrange']) ? \max(1, $match['startrange']) : 1, + $match['end'], + isset($match['endrange']) ? \max(1, $match['endrange']) : 1 + ); + + $chunks[] = $chunk; + $diffLines = array(); + + continue; + } + + if (\preg_match('/^(?P<type>[+ -])?(?P<line>.*)/', $line, $match)) { + $type = Line::UNCHANGED; + + if ($match['type'] === '+') { + $type = Line::ADDED; + } elseif ($match['type'] === '-') { + $type = Line::REMOVED; + } + + $diffLines[] = new Line($type, $match['line']); + + if (null !== $chunk) { + $chunk->setLines($diffLines); + } + } + } + + $diff->setChunks($chunks); + } +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Chunk.php b/vendor/php-cs-fixer/diff/src/v2_0/Chunk.php new file mode 100644 index 0000000..b80ddfc --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Chunk.php @@ -0,0 +1,78 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0; + +final class Chunk +{ + /** + * @var int + */ + private $start; + + /** + * @var int + */ + private $startRange; + + /** + * @var int + */ + private $end; + + /** + * @var int + */ + private $endRange; + + /** + * @var array + */ + private $lines; + + public function __construct($start = 0, $startRange = 1, $end = 0, $endRange = 1, array $lines = []) + { + $this->start = $start; + $this->startRange = $startRange; + $this->end = $end; + $this->endRange = $endRange; + $this->lines = $lines; + } + + public function getStart() + { + return $this->start; + } + + public function getStartRange() + { + return $this->startRange; + } + + public function getEnd() + { + return $this->end; + } + + public function getEndRange() + { + return $this->endRange; + } + + public function getLines() + { + return $this->lines; + } + + public function setLines(array $lines) + { + $this->lines = $lines; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Diff.php b/vendor/php-cs-fixer/diff/src/v2_0/Diff.php new file mode 100644 index 0000000..e89b8e9 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Diff.php @@ -0,0 +1,67 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0; + +final class Diff +{ + /** + * @var string + */ + private $from; + + /** + * @var string + */ + private $to; + + /** + * @var Chunk[] + */ + private $chunks; + + /** + * @param string $from + * @param string $to + * @param Chunk[] $chunks + */ + public function __construct($from, $to, array $chunks = []) + { + $this->from = $from; + $this->to = $to; + $this->chunks = $chunks; + } + + public function getFrom() + { + return $this->from; + } + + public function getTo() + { + return $this->to; + } + + /** + * @return Chunk[] + */ + public function getChunks() + { + return $this->chunks; + } + + /** + * @param Chunk[] $chunks + */ + public function setChunks(array $chunks) + { + $this->chunks = $chunks; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Differ.php b/vendor/php-cs-fixer/diff/src/v2_0/Differ.php new file mode 100644 index 0000000..a8f7dba --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Differ.php @@ -0,0 +1,321 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0; + +use PhpCsFixer\Diff\v2_0\Output\DiffOutputBuilderInterface; +use PhpCsFixer\Diff\v2_0\Output\UnifiedDiffOutputBuilder; + +/** + * Diff implementation. + */ +final class Differ +{ + /** + * @var DiffOutputBuilderInterface + */ + private $outputBuilder; + + /** + * @param DiffOutputBuilderInterface $outputBuilder + * + * @throws InvalidArgumentException + */ + public function __construct($outputBuilder = null) + { + if ($outputBuilder instanceof DiffOutputBuilderInterface) { + $this->outputBuilder = $outputBuilder; + } elseif (null === $outputBuilder) { + $this->outputBuilder = new UnifiedDiffOutputBuilder; + } elseif (\is_string($outputBuilder)) { + // PHPUnit 6.1.4, 6.2.0, 6.2.1, 6.2.2, and 6.2.3 support + // @see https://github.com/sebastianbergmann/phpunit/issues/2734#issuecomment-314514056 + // @deprecated + $this->outputBuilder = new UnifiedDiffOutputBuilder($outputBuilder); + } else { + throw new InvalidArgumentException( + \sprintf( + 'Expected builder to be an instance of DiffOutputBuilderInterface, <null> or a string, got %s.', + \is_object($outputBuilder) ? 'instance of "' . \get_class($outputBuilder) . '"' : \gettype($outputBuilder) . ' "' . $outputBuilder . '"' + ) + ); + } + } + + /** + * Returns the diff between two arrays or strings as string. + * + * @param array|string $from + * @param array|string $to + * @param LongestCommonSubsequenceCalculator|null $lcs + * + * @return string + */ + public function diff($from, $to, LongestCommonSubsequenceCalculator $lcs = null) + { + $from = $this->validateDiffInput($from); + $to = $this->validateDiffInput($to); + $diff = $this->diffToArray($from, $to, $lcs); + + return $this->outputBuilder->getDiff($diff); + } + + /** + * Casts variable to string if it is not a string or array. + * + * @param mixed $input + * + * @return string + */ + private function validateDiffInput($input) + { + if (!\is_array($input) && !\is_string($input)) { + return (string) $input; + } + + return $input; + } + + /** + * Returns the diff between two arrays or strings as array. + * + * Each array element contains two elements: + * - [0] => mixed $token + * - [1] => 2|1|0 + * + * - 2: REMOVED: $token was removed from $from + * - 1: ADDED: $token was added to $from + * - 0: OLD: $token is not changed in $to + * + * @param array|string $from + * @param array|string $to + * @param LongestCommonSubsequenceCalculator $lcs + * + * @return array + */ + public function diffToArray($from, $to, LongestCommonSubsequenceCalculator $lcs = null) + { + if (\is_string($from)) { + $from = $this->splitStringByLines($from); + } elseif (!\is_array($from)) { + throw new \InvalidArgumentException('"from" must be an array or string.'); + } + + if (\is_string($to)) { + $to = $this->splitStringByLines($to); + } elseif (!\is_array($to)) { + throw new \InvalidArgumentException('"to" must be an array or string.'); + } + + list($from, $to, $start, $end) = self::getArrayDiffParted($from, $to); + + if ($lcs === null) { + $lcs = $this->selectLcsImplementation($from, $to); + } + + $common = $lcs->calculate(\array_values($from), \array_values($to)); + $diff = []; + + foreach ($start as $token) { + $diff[] = [$token, 0 /* OLD */]; + } + + \reset($from); + \reset($to); + + foreach ($common as $token) { + while (($fromToken = \reset($from)) !== $token) { + $diff[] = [\array_shift($from), 2 /* REMOVED */]; + } + + while (($toToken = \reset($to)) !== $token) { + $diff[] = [\array_shift($to), 1 /* ADDED */]; + } + + $diff[] = [$token, 0 /* OLD */]; + + \array_shift($from); + \array_shift($to); + } + + while (($token = \array_shift($from)) !== null) { + $diff[] = [$token, 2 /* REMOVED */]; + } + + while (($token = \array_shift($to)) !== null) { + $diff[] = [$token, 1 /* ADDED */]; + } + + foreach ($end as $token) { + $diff[] = [$token, 0 /* OLD */]; + } + + if ($this->detectUnmatchedLineEndings($diff)) { + \array_unshift($diff, ["#Warnings contain different line endings!\n", 3]); + } + + return $diff; + } + + /** + * Checks if input is string, if so it will split it line-by-line. + * + * @param string $input + * + * @return array + */ + private function splitStringByLines($input) + { + return \preg_split('/(.*\R)/', $input, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + } + + /** + * @param array $from + * @param array $to + * + * @return LongestCommonSubsequenceCalculator + */ + private function selectLcsImplementation(array $from, array $to) + { + // We do not want to use the time-efficient implementation if its memory + // footprint will probably exceed this value. Note that the footprint + // calculation is only an estimation for the matrix and the LCS method + // will typically allocate a bit more memory than this. + $memoryLimit = 100 * 1024 * 1024; + + if ($this->calculateEstimatedFootprint($from, $to) > $memoryLimit) { + return new MemoryEfficientLongestCommonSubsequenceCalculator; + } + + return new TimeEfficientLongestCommonSubsequenceCalculator; + } + + /** + * Calculates the estimated memory footprint for the DP-based method. + * + * @param array $from + * @param array $to + * + * @return int|float + */ + private function calculateEstimatedFootprint(array $from, array $to) + { + $itemSize = PHP_INT_SIZE === 4 ? 76 : 144; + + return $itemSize * \min(\count($from), \count($to)) ** 2; + } + + /** + * Returns true if line ends don't match in a diff. + * + * @param array $diff + * + * @return bool + */ + private function detectUnmatchedLineEndings(array $diff) + { + $newLineBreaks = ['' => true]; + $oldLineBreaks = ['' => true]; + + foreach ($diff as $entry) { + if (0 === $entry[1]) { /* OLD */ + $ln = $this->getLinebreak($entry[0]); + $oldLineBreaks[$ln] = true; + $newLineBreaks[$ln] = true; + } elseif (1 === $entry[1]) { /* ADDED */ + $newLineBreaks[$this->getLinebreak($entry[0])] = true; + } elseif (2 === $entry[1]) { /* REMOVED */ + $oldLineBreaks[$this->getLinebreak($entry[0])] = true; + } + } + + // if either input or output is a single line without breaks than no warning should be raised + if (['' => true] === $newLineBreaks || ['' => true] === $oldLineBreaks) { + return false; + } + + // two way compare + foreach ($newLineBreaks as $break => $set) { + if (!isset($oldLineBreaks[$break])) { + return true; + } + } + + foreach ($oldLineBreaks as $break => $set) { + if (!isset($newLineBreaks[$break])) { + return true; + } + } + + return false; + } + + private function getLinebreak($line) + { + if (!\is_string($line)) { + return ''; + } + + $lc = \substr($line, -1); + if ("\r" === $lc) { + return "\r"; + } + + if ("\n" !== $lc) { + return ''; + } + + if ("\r\n" === \substr($line, -2)) { + return "\r\n"; + } + + return "\n"; + } + + private static function getArrayDiffParted(array &$from, array &$to) + { + $start = []; + $end = []; + + \reset($to); + + foreach ($from as $k => $v) { + $toK = \key($to); + + if ($toK === $k && $v === $to[$k]) { + $start[$k] = $v; + + unset($from[$k], $to[$k]); + } else { + break; + } + } + + \end($from); + \end($to); + + do { + $fromK = \key($from); + $toK = \key($to); + + if (null === $fromK || null === $toK || \current($from) !== \current($to)) { + break; + } + + \prev($from); + \prev($to); + + $end = [$fromK => $from[$fromK]] + $end; + unset($from[$fromK], $to[$toK]); + } while (true); + + return [$from, $to, $start, $end]; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Exception/Exception.php b/vendor/php-cs-fixer/diff/src/v2_0/Exception/Exception.php new file mode 100644 index 0000000..b7e9e92 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Exception/Exception.php @@ -0,0 +1,15 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0; + +interface Exception +{ +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Exception/InvalidArgumentException.php b/vendor/php-cs-fixer/diff/src/v2_0/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..e1a0c0b --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Exception/InvalidArgumentException.php @@ -0,0 +1,15 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0; + +class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Line.php b/vendor/php-cs-fixer/diff/src/v2_0/Line.php new file mode 100644 index 0000000..75d5ec8 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Line.php @@ -0,0 +1,44 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0; + +final class Line +{ + const ADDED = 1; + const REMOVED = 2; + const UNCHANGED = 3; + + /** + * @var int + */ + private $type; + + /** + * @var string + */ + private $content; + + public function __construct($type = self::UNCHANGED, $content = '') + { + $this->type = $type; + $this->content = $content; + } + + public function getContent() + { + return $this->content; + } + + public function getType() + { + return $this->type; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/LongestCommonSubsequenceCalculator.php b/vendor/php-cs-fixer/diff/src/v2_0/LongestCommonSubsequenceCalculator.php new file mode 100644 index 0000000..25eda02 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/LongestCommonSubsequenceCalculator.php @@ -0,0 +1,24 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0; + +interface LongestCommonSubsequenceCalculator +{ + /** + * Calculates the longest common subsequence of two arrays. + * + * @param array $from + * @param array $to + * + * @return array + */ + public function calculate(array $from, array $to); +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/MemoryEfficientLongestCommonSubsequenceCalculator.php b/vendor/php-cs-fixer/diff/src/v2_0/MemoryEfficientLongestCommonSubsequenceCalculator.php new file mode 100644 index 0000000..e6ce284 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/MemoryEfficientLongestCommonSubsequenceCalculator.php @@ -0,0 +1,81 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0; + +final class MemoryEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator +{ + /** + * {@inheritdoc} + */ + public function calculate(array $from, array $to) + { + $cFrom = \count($from); + $cTo = \count($to); + + if ($cFrom === 0) { + return []; + } + + if ($cFrom === 1) { + if (\in_array($from[0], $to, true)) { + return [$from[0]]; + } + + return []; + } + + $i = (int) ($cFrom / 2); + $fromStart = \array_slice($from, 0, $i); + $fromEnd = \array_slice($from, $i); + $llB = $this->length($fromStart, $to); + $llE = $this->length(\array_reverse($fromEnd), \array_reverse($to)); + $jMax = 0; + $max = 0; + + for ($j = 0; $j <= $cTo; $j++) { + $m = $llB[$j] + $llE[$cTo - $j]; + + if ($m >= $max) { + $max = $m; + $jMax = $j; + } + } + + $toStart = \array_slice($to, 0, $jMax); + $toEnd = \array_slice($to, $jMax); + + return \array_merge( + $this->calculate($fromStart, $toStart), + $this->calculate($fromEnd, $toEnd) + ); + } + + private function length(array $from, array $to) + { + $current = \array_fill(0, \count($to) + 1, 0); + $cFrom = \count($from); + $cTo = \count($to); + + for ($i = 0; $i < $cFrom; $i++) { + $prev = $current; + + for ($j = 0; $j < $cTo; $j++) { + if ($from[$i] === $to[$j]) { + $current[$j + 1] = $prev[$j] + 1; + } else { + $current[$j + 1] = \max($current[$j], $prev[$j + 1]); + } + } + } + + return $current; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Output/AbstractChunkOutputBuilder.php b/vendor/php-cs-fixer/diff/src/v2_0/Output/AbstractChunkOutputBuilder.php new file mode 100644 index 0000000..d7d78d7 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Output/AbstractChunkOutputBuilder.php @@ -0,0 +1,56 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0\Output; + +abstract class AbstractChunkOutputBuilder implements DiffOutputBuilderInterface +{ + /** + * Takes input of the diff array and returns the common parts. + * Iterates through diff line by line. + * + * @param array $diff + * @param int $lineThreshold + * + * @return array + */ + protected function getCommonChunks(array $diff, $lineThreshold = 5) + { + $diffSize = \count($diff); + $capturing = false; + $chunkStart = 0; + $chunkSize = 0; + $commonChunks = []; + + for ($i = 0; $i < $diffSize; ++$i) { + if ($diff[$i][1] === 0 /* OLD */) { + if ($capturing === false) { + $capturing = true; + $chunkStart = $i; + $chunkSize = 0; + } else { + ++$chunkSize; + } + } elseif ($capturing !== false) { + if ($chunkSize >= $lineThreshold) { + $commonChunks[$chunkStart] = $chunkStart + $chunkSize; + } + + $capturing = false; + } + } + + if ($capturing !== false && $chunkSize >= $lineThreshold) { + $commonChunks[$chunkStart] = $chunkStart + $chunkSize; + } + + return $commonChunks; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Output/DiffOnlyOutputBuilder.php b/vendor/php-cs-fixer/diff/src/v2_0/Output/DiffOnlyOutputBuilder.php new file mode 100644 index 0000000..51cb2de --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Output/DiffOnlyOutputBuilder.php @@ -0,0 +1,63 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PhpCsFixer\Diff\v2_0\Output; + +/** + * Builds a diff string representation in a loose unified diff format + * listing only changes lines. Does not include line numbers. + */ +final class DiffOnlyOutputBuilder implements DiffOutputBuilderInterface +{ + /** + * @var string + */ + private $header; + + public function __construct($header = "--- Original\n+++ New\n") + { + $this->header = $header; + } + + public function getDiff(array $diff) + { + $buffer = \fopen('php://memory', 'r+b'); + + if ('' !== $this->header) { + \fwrite($buffer, $this->header); + if ("\n" !== \substr($this->header, -1, 1)) { + \fwrite($buffer, "\n"); + } + } + + foreach ($diff as $diffEntry) { + if ($diffEntry[1] === 1 /* ADDED */) { + \fwrite($buffer, '+' . $diffEntry[0]); + } elseif ($diffEntry[1] === 2 /* REMOVED */) { + \fwrite($buffer, '-' . $diffEntry[0]); + } elseif ($diffEntry[1] === 3 /* WARNING */) { + \fwrite($buffer, ' ' . $diffEntry[0]); + + continue; // Warnings should not be tested for line break, it will always be there + } else { /* Not changed (old) 0 */ + continue; // we didn't write the non changs line, so do not add a line break either + } + + $lc = \substr($diffEntry[0], -1); + if ($lc !== "\n" && $lc !== "\r") { + \fwrite($buffer, "\n"); // \No newline at end of file + } + } + + $diff = \stream_get_contents($buffer, -1, 0); + \fclose($buffer); + + return $diff; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Output/DiffOutputBuilderInterface.php b/vendor/php-cs-fixer/diff/src/v2_0/Output/DiffOutputBuilderInterface.php new file mode 100644 index 0000000..b52b8ac --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Output/DiffOutputBuilderInterface.php @@ -0,0 +1,19 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PhpCsFixer\Diff\v2_0\Output; + +/** + * Defines how an output builder should take a generated + * diff array and return a string representation of that diff. + */ +interface DiffOutputBuilderInterface +{ + public function getDiff(array $diff); +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Output/UnifiedDiffOutputBuilder.php b/vendor/php-cs-fixer/diff/src/v2_0/Output/UnifiedDiffOutputBuilder.php new file mode 100644 index 0000000..e761865 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Output/UnifiedDiffOutputBuilder.php @@ -0,0 +1,165 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0\Output; + +/** + * Builds a diff string representation in unified diff format in chunks. + */ +final class UnifiedDiffOutputBuilder extends AbstractChunkOutputBuilder +{ + /** + * @var string + */ + private $header; + + /** + * @var bool + */ + private $addLineNumbers; + + public function __construct($header = "--- Original\n+++ New\n", $addLineNumbers = false) + { + $this->header = $header; + $this->addLineNumbers = $addLineNumbers; + } + + public function getDiff(array $diff) + { + $buffer = \fopen('php://memory', 'r+b'); + + if ('' !== $this->header) { + \fwrite($buffer, $this->header); + if ("\n" !== \substr($this->header, -1, 1)) { + \fwrite($buffer, "\n"); + } + } + + $this->writeDiffChunked($buffer, $diff, $this->getCommonChunks($diff)); + + $diff = \stream_get_contents($buffer, -1, 0); + + \fclose($buffer); + + return $diff; + } + + // `old` is an array with key => value pairs . Each pair represents a start and end index of `diff` + // of a list of elements all containing `same` (0) entries. + private function writeDiffChunked($output, array $diff, array $old) + { + $upperLimit = \count($diff); + $start = 0; + $fromStart = 0; + $toStart = 0; + + if (\count($old)) { // no common parts, list all diff entries + \reset($old); + + // iterate the diff, go from chunk to chunk skipping common chunk of lines between those + do { + $commonStart = \key($old); + $commonEnd = \current($old); + + if ($commonStart !== $start) { + list($fromRange, $toRange) = $this->getChunkRange($diff, $start, $commonStart); + $this->writeChunk($output, $diff, $start, $commonStart, $fromStart, $fromRange, $toStart, $toRange); + + $fromStart += $fromRange; + $toStart += $toRange; + } + + $start = $commonEnd + 1; + $commonLength = $commonEnd - $commonStart + 1; // calculate number of non-change lines in the common part + $fromStart += $commonLength; + $toStart += $commonLength; + } while (false !== \next($old)); + + \end($old); // short cut for finding possible last `change entry` + $tmp = \key($old); + \reset($old); + if ($old[$tmp] === $upperLimit - 1) { + $upperLimit = $tmp; + } + } + + if ($start < $upperLimit - 1) { // check for trailing (non) diff entries + do { + --$upperLimit; + } while (isset($diff[$upperLimit][1]) && $diff[$upperLimit][1] === 0); + ++$upperLimit; + + list($fromRange, $toRange) = $this->getChunkRange($diff, $start, $upperLimit); + $this->writeChunk($output, $diff, $start, $upperLimit, $fromStart, $fromRange, $toStart, $toRange); + } + } + + private function writeChunk( + $output, + array $diff, + $diffStartIndex, + $diffEndIndex, + $fromStart, + $fromRange, + $toStart, + $toRange + ) { + if ($this->addLineNumbers) { + \fwrite($output, '@@ -' . (1 + $fromStart)); + + if ($fromRange !== 1) { + \fwrite($output, ',' . $fromRange); + } + + \fwrite($output, ' +' . (1 + $toStart)); + if ($toRange !== 1) { + \fwrite($output, ',' . $toRange); + } + + \fwrite($output, " @@\n"); + } else { + \fwrite($output, "@@ @@\n"); + } + + for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { + if ($diff[$i][1] === 1 /* ADDED */) { + \fwrite($output, '+' . $diff[$i][0]); + } elseif ($diff[$i][1] === 2 /* REMOVED */) { + \fwrite($output, '-' . $diff[$i][0]); + } else { /* Not changed (old) 0 or Warning 3 */ + \fwrite($output, ' ' . $diff[$i][0]); + } + + $lc = \substr($diff[$i][0], -1); + if ($lc !== "\n" && $lc !== "\r") { + \fwrite($output, "\n"); // \No newline at end of file + } + } + } + + private function getChunkRange(array $diff, $diffStartIndex, $diffEndIndex) + { + $toRange = 0; + $fromRange = 0; + + for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { + if ($diff[$i][1] === 1) { // added + ++$toRange; + } elseif ($diff[$i][1] === 2) { // removed + ++$fromRange; + } elseif ($diff[$i][1] === 0) { // same + ++$fromRange; + ++$toRange; + } + } + + return [$fromRange, $toRange]; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/Parser.php b/vendor/php-cs-fixer/diff/src/v2_0/Parser.php new file mode 100644 index 0000000..9c0ee83 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/Parser.php @@ -0,0 +1,106 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0; + +/** + * Unified diff parser. + */ +final class Parser +{ + /** + * @param string $string + * + * @return Diff[] + */ + public function parse($string) + { + $lines = \preg_split('(\r\n|\r|\n)', $string); + + if (!empty($lines) && $lines[\count($lines) - 1] === '') { + \array_pop($lines); + } + + $lineCount = \count($lines); + $diffs = []; + $diff = null; + $collected = []; + + for ($i = 0; $i < $lineCount; ++$i) { + if (\preg_match('(^---\\s+(?P<file>\\S+))', $lines[$i], $fromMatch) && + \preg_match('(^\\+\\+\\+\\s+(?P<file>\\S+))', $lines[$i + 1], $toMatch)) { + if ($diff !== null) { + $this->parseFileDiff($diff, $collected); + + $diffs[] = $diff; + $collected = []; + } + + $diff = new Diff($fromMatch['file'], $toMatch['file']); + + ++$i; + } else { + if (\preg_match('/^(?:diff --git |index [\da-f\.]+|[+-]{3} [ab])/', $lines[$i])) { + continue; + } + + $collected[] = $lines[$i]; + } + } + + if ($diff !== null && \count($collected)) { + $this->parseFileDiff($diff, $collected); + + $diffs[] = $diff; + } + + return $diffs; + } + + private function parseFileDiff(Diff $diff, array $lines) + { + $chunks = []; + $chunk = null; + + foreach ($lines as $line) { + if (\preg_match('/^@@\s+-(?P<start>\d+)(?:,\s*(?P<startrange>\d+))?\s+\+(?P<end>\d+)(?:,\s*(?P<endrange>\d+))?\s+@@/', $line, $match)) { + $chunk = new Chunk( + (int) $match['start'], + isset($match['startrange']) ? \max(1, (int) $match['startrange']) : 1, + (int) $match['end'], + isset($match['endrange']) ? \max(1, (int) $match['endrange']) : 1 + ); + + $chunks[] = $chunk; + $diffLines = []; + + continue; + } + + if (\preg_match('/^(?P<type>[+ -])?(?P<line>.*)/', $line, $match)) { + $type = Line::UNCHANGED; + + if ($match['type'] === '+') { + $type = Line::ADDED; + } elseif ($match['type'] === '-') { + $type = Line::REMOVED; + } + + $diffLines[] = new Line($type, $match['line']); + + if (null !== $chunk) { + $chunk->setLines($diffLines); + } + } + } + + $diff->setChunks($chunks); + } +} diff --git a/vendor/php-cs-fixer/diff/src/v2_0/TimeEfficientLongestCommonSubsequenceCalculator.php b/vendor/php-cs-fixer/diff/src/v2_0/TimeEfficientLongestCommonSubsequenceCalculator.php new file mode 100644 index 0000000..51489af --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v2_0/TimeEfficientLongestCommonSubsequenceCalculator.php @@ -0,0 +1,66 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v2_0; + +final class TimeEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator +{ + /** + * {@inheritdoc} + */ + public function calculate(array $from, array $to) + { + $common = []; + $fromLength = \count($from); + $toLength = \count($to); + $width = $fromLength + 1; + $matrix = new \SplFixedArray($width * ($toLength + 1)); + + for ($i = 0; $i <= $fromLength; ++$i) { + $matrix[$i] = 0; + } + + for ($j = 0; $j <= $toLength; ++$j) { + $matrix[$j * $width] = 0; + } + + for ($i = 1; $i <= $fromLength; ++$i) { + for ($j = 1; $j <= $toLength; ++$j) { + $o = ($j * $width) + $i; + $matrix[$o] = \max( + $matrix[$o - 1], + $matrix[$o - $width], + $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0 + ); + } + } + + $i = $fromLength; + $j = $toLength; + + while ($i > 0 && $j > 0) { + if ($from[$i - 1] === $to[$j - 1]) { + $common[] = $from[$i - 1]; + --$i; + --$j; + } else { + $o = ($j * $width) + $i; + + if ($matrix[$o - $width] > $matrix[$o - 1]) { + --$j; + } else { + --$i; + } + } + } + + return \array_reverse($common); + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Chunk.php b/vendor/php-cs-fixer/diff/src/v3_0/Chunk.php new file mode 100644 index 0000000..6b633c1 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Chunk.php @@ -0,0 +1,78 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +final class Chunk +{ + /** + * @var int + */ + private $start; + + /** + * @var int + */ + private $startRange; + + /** + * @var int + */ + private $end; + + /** + * @var int + */ + private $endRange; + + /** + * @var array + */ + private $lines; + + public function __construct($start = 0, $startRange = 1, $end = 0, $endRange = 1, array $lines = []) + { + $this->start = $start; + $this->startRange = $startRange; + $this->end = $end; + $this->endRange = $endRange; + $this->lines = $lines; + } + + public function getStart() + { + return $this->start; + } + + public function getStartRange() + { + return $this->startRange; + } + + public function getEnd() + { + return $this->end; + } + + public function getEndRange() + { + return $this->endRange; + } + + public function getLines() + { + return $this->lines; + } + + public function setLines(array $lines) + { + $this->lines = $lines; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Diff.php b/vendor/php-cs-fixer/diff/src/v3_0/Diff.php new file mode 100644 index 0000000..9f537ec --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Diff.php @@ -0,0 +1,67 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +final class Diff +{ + /** + * @var string + */ + private $from; + + /** + * @var string + */ + private $to; + + /** + * @var Chunk[] + */ + private $chunks; + + /** + * @param string $from + * @param string $to + * @param Chunk[] $chunks + */ + public function __construct($from, $to, array $chunks = []) + { + $this->from = $from; + $this->to = $to; + $this->chunks = $chunks; + } + + public function getFrom() + { + return $this->from; + } + + public function getTo() + { + return $this->to; + } + + /** + * @return Chunk[] + */ + public function getChunks() + { + return $this->chunks; + } + + /** + * @param Chunk[] $chunks + */ + public function setChunks(array $chunks) + { + $this->chunks = $chunks; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Differ.php b/vendor/php-cs-fixer/diff/src/v3_0/Differ.php new file mode 100644 index 0000000..42315f5 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Differ.php @@ -0,0 +1,329 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +use PhpCsFixer\Diff\v3_0\Output\DiffOutputBuilderInterface; +use PhpCsFixer\Diff\v3_0\Output\UnifiedDiffOutputBuilder; + +/** + * Diff implementation. + */ +final class Differ +{ + const OLD = 0; + const ADDED = 1; + const REMOVED = 2; + const DIFF_LINE_END_WARNING = 3; + const NO_LINE_END_EOF_WARNING = 4; + + /** + * @var DiffOutputBuilderInterface + */ + private $outputBuilder; + + /** + * @param DiffOutputBuilderInterface $outputBuilder + * + * @throws InvalidArgumentException + */ + public function __construct($outputBuilder = null) + { + if ($outputBuilder instanceof DiffOutputBuilderInterface) { + $this->outputBuilder = $outputBuilder; + } elseif (null === $outputBuilder) { + $this->outputBuilder = new UnifiedDiffOutputBuilder; + } elseif (\is_string($outputBuilder)) { + // PHPUnit 6.1.4, 6.2.0, 6.2.1, 6.2.2, and 6.2.3 support + // @see https://github.com/sebastianbergmann/phpunit/issues/2734#issuecomment-314514056 + // @deprecated + $this->outputBuilder = new UnifiedDiffOutputBuilder($outputBuilder); + } else { + throw new InvalidArgumentException( + \sprintf( + 'Expected builder to be an instance of DiffOutputBuilderInterface, <null> or a string, got %s.', + \is_object($outputBuilder) ? 'instance of "' . \get_class($outputBuilder) . '"' : \gettype($outputBuilder) . ' "' . $outputBuilder . '"' + ) + ); + } + } + + /** + * Returns the diff between two arrays or strings as string. + * + * @param array|string $from + * @param array|string $to + * @param null|LongestCommonSubsequenceCalculator $lcs + * + * @return string + */ + public function diff($from, $to, LongestCommonSubsequenceCalculator $lcs = null) + { + $diff = $this->diffToArray( + $this->normalizeDiffInput($from), + $this->normalizeDiffInput($to), + $lcs + ); + + return $this->outputBuilder->getDiff($diff); + } + + /** + * Returns the diff between two arrays or strings as array. + * + * Each array element contains two elements: + * - [0] => mixed $token + * - [1] => 2|1|0 + * + * - 2: REMOVED: $token was removed from $from + * - 1: ADDED: $token was added to $from + * - 0: OLD: $token is not changed in $to + * + * @param array|string $from + * @param array|string $to + * @param LongestCommonSubsequenceCalculator $lcs + * + * @return array + */ + public function diffToArray($from, $to, LongestCommonSubsequenceCalculator $lcs = null) + { + if (\is_string($from)) { + $from = $this->splitStringByLines($from); + } elseif (!\is_array($from)) { + throw new InvalidArgumentException('"from" must be an array or string.'); + } + + if (\is_string($to)) { + $to = $this->splitStringByLines($to); + } elseif (!\is_array($to)) { + throw new InvalidArgumentException('"to" must be an array or string.'); + } + + list($from, $to, $start, $end) = self::getArrayDiffParted($from, $to); + + if ($lcs === null) { + $lcs = $this->selectLcsImplementation($from, $to); + } + + $common = $lcs->calculate(\array_values($from), \array_values($to)); + $diff = []; + + foreach ($start as $token) { + $diff[] = [$token, self::OLD]; + } + + \reset($from); + \reset($to); + + foreach ($common as $token) { + while (($fromToken = \reset($from)) !== $token) { + $diff[] = [\array_shift($from), self::REMOVED]; + } + + while (($toToken = \reset($to)) !== $token) { + $diff[] = [\array_shift($to), self::ADDED]; + } + + $diff[] = [$token, self::OLD]; + + \array_shift($from); + \array_shift($to); + } + + while (($token = \array_shift($from)) !== null) { + $diff[] = [$token, self::REMOVED]; + } + + while (($token = \array_shift($to)) !== null) { + $diff[] = [$token, self::ADDED]; + } + + foreach ($end as $token) { + $diff[] = [$token, self::OLD]; + } + + if ($this->detectUnmatchedLineEndings($diff)) { + \array_unshift($diff, ["#Warnings contain different line endings!\n", self::DIFF_LINE_END_WARNING]); + } + + return $diff; + } + + /** + * Casts variable to string if it is not a string or array. + * + * @param mixed $input + * + * @return array|string + */ + private function normalizeDiffInput($input) + { + if (!\is_array($input) && !\is_string($input)) { + return (string) $input; + } + + return $input; + } + + /** + * Checks if input is string, if so it will split it line-by-line. + * + * @param string $input + * + * @return array + */ + private function splitStringByLines($input) + { + return \preg_split('/(.*\R)/', $input, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + } + + /** + * @param array $from + * @param array $to + * + * @return LongestCommonSubsequenceCalculator + */ + private function selectLcsImplementation(array $from, array $to) + { + // We do not want to use the time-efficient implementation if its memory + // footprint will probably exceed this value. Note that the footprint + // calculation is only an estimation for the matrix and the LCS method + // will typically allocate a bit more memory than this. + $memoryLimit = 100 * 1024 * 1024; + + if ($this->calculateEstimatedFootprint($from, $to) > $memoryLimit) { + return new MemoryEfficientLongestCommonSubsequenceCalculator; + } + + return new TimeEfficientLongestCommonSubsequenceCalculator; + } + + /** + * Calculates the estimated memory footprint for the DP-based method. + * + * @param array $from + * @param array $to + * + * @return float|int + */ + private function calculateEstimatedFootprint(array $from, array $to) + { + $itemSize = PHP_INT_SIZE === 4 ? 76 : 144; + + return $itemSize * \min(\count($from), \count($to)) ** 2; + } + + /** + * Returns true if line ends don't match in a diff. + * + * @param array $diff + * + * @return bool + */ + private function detectUnmatchedLineEndings(array $diff) + { + $newLineBreaks = ['' => true]; + $oldLineBreaks = ['' => true]; + + foreach ($diff as $entry) { + if (self::OLD === $entry[1]) { + $ln = $this->getLinebreak($entry[0]); + $oldLineBreaks[$ln] = true; + $newLineBreaks[$ln] = true; + } elseif (self::ADDED === $entry[1]) { + $newLineBreaks[$this->getLinebreak($entry[0])] = true; + } elseif (self::REMOVED === $entry[1]) { + $oldLineBreaks[$this->getLinebreak($entry[0])] = true; + } + } + + // if either input or output is a single line without breaks than no warning should be raised + if (['' => true] === $newLineBreaks || ['' => true] === $oldLineBreaks) { + return false; + } + + // two way compare + foreach ($newLineBreaks as $break => $set) { + if (!isset($oldLineBreaks[$break])) { + return true; + } + } + + foreach ($oldLineBreaks as $break => $set) { + if (!isset($newLineBreaks[$break])) { + return true; + } + } + + return false; + } + + private function getLinebreak($line) + { + if (!\is_string($line)) { + return ''; + } + + $lc = \substr($line, -1); + if ("\r" === $lc) { + return "\r"; + } + + if ("\n" !== $lc) { + return ''; + } + + if ("\r\n" === \substr($line, -2)) { + return "\r\n"; + } + + return "\n"; + } + + private static function getArrayDiffParted(array &$from, array &$to) + { + $start = []; + $end = []; + + \reset($to); + + foreach ($from as $k => $v) { + $toK = \key($to); + + if ($toK === $k && $v === $to[$k]) { + $start[$k] = $v; + + unset($from[$k], $to[$k]); + } else { + break; + } + } + + \end($from); + \end($to); + + do { + $fromK = \key($from); + $toK = \key($to); + + if (null === $fromK || null === $toK || \current($from) !== \current($to)) { + break; + } + + \prev($from); + \prev($to); + + $end = [$fromK => $from[$fromK]] + $end; + unset($from[$fromK], $to[$toK]); + } while (true); + + return [$from, $to, $start, $end]; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Exception/ConfigurationException.php b/vendor/php-cs-fixer/diff/src/v3_0/Exception/ConfigurationException.php new file mode 100644 index 0000000..8892d8f --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Exception/ConfigurationException.php @@ -0,0 +1,40 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +final class ConfigurationException extends InvalidArgumentException +{ + /** + * @param string $option + * @param string $expected + * @param mixed $value + * @param int $code + * @param null|\Exception $previous + */ + public function __construct( + $option, + $expected, + $value, + $code = 0, + \Exception $previous = null + ) { + parent::__construct( + \sprintf( + 'Option "%s" must be %s, got "%s".', + $option, + $expected, + \is_object($value) ? \get_class($value) : (null === $value ? '<null>' : \gettype($value) . '#' . $value) + ), + $code, + $previous + ); + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Exception/Exception.php b/vendor/php-cs-fixer/diff/src/v3_0/Exception/Exception.php new file mode 100644 index 0000000..7a391db --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Exception/Exception.php @@ -0,0 +1,15 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +interface Exception +{ +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Exception/InvalidArgumentException.php b/vendor/php-cs-fixer/diff/src/v3_0/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..5085482 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Exception/InvalidArgumentException.php @@ -0,0 +1,15 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Line.php b/vendor/php-cs-fixer/diff/src/v3_0/Line.php new file mode 100644 index 0000000..07be880 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Line.php @@ -0,0 +1,44 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +final class Line +{ + const ADDED = 1; + const REMOVED = 2; + const UNCHANGED = 3; + + /** + * @var int + */ + private $type; + + /** + * @var string + */ + private $content; + + public function __construct($type = self::UNCHANGED, $content = '') + { + $this->type = $type; + $this->content = $content; + } + + public function getContent() + { + return $this->content; + } + + public function getType() + { + return $this->type; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/LongestCommonSubsequenceCalculator.php b/vendor/php-cs-fixer/diff/src/v3_0/LongestCommonSubsequenceCalculator.php new file mode 100644 index 0000000..be5ed5a --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/LongestCommonSubsequenceCalculator.php @@ -0,0 +1,24 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +interface LongestCommonSubsequenceCalculator +{ + /** + * Calculates the longest common subsequence of two arrays. + * + * @param array $from + * @param array $to + * + * @return array + */ + public function calculate(array $from, array $to); +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/MemoryEfficientLongestCommonSubsequenceCalculator.php b/vendor/php-cs-fixer/diff/src/v3_0/MemoryEfficientLongestCommonSubsequenceCalculator.php new file mode 100644 index 0000000..85a1c4e --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/MemoryEfficientLongestCommonSubsequenceCalculator.php @@ -0,0 +1,81 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +final class MemoryEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator +{ + /** + * {@inheritdoc} + */ + public function calculate(array $from, array $to) + { + $cFrom = \count($from); + $cTo = \count($to); + + if ($cFrom === 0) { + return []; + } + + if ($cFrom === 1) { + if (\in_array($from[0], $to, true)) { + return [$from[0]]; + } + + return []; + } + + $i = (int) ($cFrom / 2); + $fromStart = \array_slice($from, 0, $i); + $fromEnd = \array_slice($from, $i); + $llB = $this->length($fromStart, $to); + $llE = $this->length(\array_reverse($fromEnd), \array_reverse($to)); + $jMax = 0; + $max = 0; + + for ($j = 0; $j <= $cTo; $j++) { + $m = $llB[$j] + $llE[$cTo - $j]; + + if ($m >= $max) { + $max = $m; + $jMax = $j; + } + } + + $toStart = \array_slice($to, 0, $jMax); + $toEnd = \array_slice($to, $jMax); + + return \array_merge( + $this->calculate($fromStart, $toStart), + $this->calculate($fromEnd, $toEnd) + ); + } + + private function length(array $from, array $to) + { + $current = \array_fill(0, \count($to) + 1, 0); + $cFrom = \count($from); + $cTo = \count($to); + + for ($i = 0; $i < $cFrom; $i++) { + $prev = $current; + + for ($j = 0; $j < $cTo; $j++) { + if ($from[$i] === $to[$j]) { + $current[$j + 1] = $prev[$j] + 1; + } else { + $current[$j + 1] = \max($current[$j], $prev[$j + 1]); + } + } + } + + return $current; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Output/AbstractChunkOutputBuilder.php b/vendor/php-cs-fixer/diff/src/v3_0/Output/AbstractChunkOutputBuilder.php new file mode 100644 index 0000000..ecf7d32 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Output/AbstractChunkOutputBuilder.php @@ -0,0 +1,56 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0\Output; + +abstract class AbstractChunkOutputBuilder implements DiffOutputBuilderInterface +{ + /** + * Takes input of the diff array and returns the common parts. + * Iterates through diff line by line. + * + * @param array $diff + * @param int $lineThreshold + * + * @return array + */ + protected function getCommonChunks(array $diff, $lineThreshold = 5) + { + $diffSize = \count($diff); + $capturing = false; + $chunkStart = 0; + $chunkSize = 0; + $commonChunks = []; + + for ($i = 0; $i < $diffSize; ++$i) { + if ($diff[$i][1] === 0 /* OLD */) { + if ($capturing === false) { + $capturing = true; + $chunkStart = $i; + $chunkSize = 0; + } else { + ++$chunkSize; + } + } elseif ($capturing !== false) { + if ($chunkSize >= $lineThreshold) { + $commonChunks[$chunkStart] = $chunkStart + $chunkSize; + } + + $capturing = false; + } + } + + if ($capturing !== false && $chunkSize >= $lineThreshold) { + $commonChunks[$chunkStart] = $chunkStart + $chunkSize; + } + + return $commonChunks; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Output/DiffOnlyOutputBuilder.php b/vendor/php-cs-fixer/diff/src/v3_0/Output/DiffOnlyOutputBuilder.php new file mode 100644 index 0000000..0f3b81f --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Output/DiffOnlyOutputBuilder.php @@ -0,0 +1,66 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0\Output; + +use PhpCsFixer\Diff\v3_0\Differ; + +/** + * Builds a diff string representation in a loose unified diff format + * listing only changes lines. Does not include line numbers. + */ +final class DiffOnlyOutputBuilder implements DiffOutputBuilderInterface +{ + /** + * @var string + */ + private $header; + + public function __construct($header = "--- Original\n+++ New\n") + { + $this->header = $header; + } + + public function getDiff(array $diff) + { + $buffer = \fopen('php://memory', 'r+b'); + + if ('' !== $this->header) { + \fwrite($buffer, $this->header); + if ("\n" !== \substr($this->header, -1, 1)) { + \fwrite($buffer, "\n"); + } + } + + foreach ($diff as $diffEntry) { + if ($diffEntry[1] === Differ::ADDED) { + \fwrite($buffer, '+' . $diffEntry[0]); + } elseif ($diffEntry[1] === Differ::REMOVED) { + \fwrite($buffer, '-' . $diffEntry[0]); + } elseif ($diffEntry[1] === Differ::DIFF_LINE_END_WARNING) { + \fwrite($buffer, ' ' . $diffEntry[0]); + + continue; // Warnings should not be tested for line break, it will always be there + } else { /* Not changed (old) 0 */ + continue; // we didn't write the non changs line, so do not add a line break either + } + + $lc = \substr($diffEntry[0], -1); + if ($lc !== "\n" && $lc !== "\r") { + \fwrite($buffer, "\n"); // \No newline at end of file + } + } + + $diff = \stream_get_contents($buffer, -1, 0); + \fclose($buffer); + + return $diff; + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Output/DiffOutputBuilderInterface.php b/vendor/php-cs-fixer/diff/src/v3_0/Output/DiffOutputBuilderInterface.php new file mode 100644 index 0000000..ae690e6 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Output/DiffOutputBuilderInterface.php @@ -0,0 +1,20 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0\Output; + +/** + * Defines how an output builder should take a generated + * diff array and return a string representation of that diff. + */ +interface DiffOutputBuilderInterface +{ + public function getDiff(array $diff); +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Output/StrictUnifiedDiffOutputBuilder.php b/vendor/php-cs-fixer/diff/src/v3_0/Output/StrictUnifiedDiffOutputBuilder.php new file mode 100644 index 0000000..49faa8a --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Output/StrictUnifiedDiffOutputBuilder.php @@ -0,0 +1,315 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0\Output; + +use PhpCsFixer\Diff\v3_0\ConfigurationException; +use PhpCsFixer\Diff\v3_0\Differ; + +/** + * Strict Unified diff output builder. + * + * Generates (strict) Unified diff's (unidiffs) with hunks. + */ +final class StrictUnifiedDiffOutputBuilder implements DiffOutputBuilderInterface +{ + /** + * @var bool + */ + private $changed; + + /** + * @var bool + */ + private $collapseRanges; + + /** + * @var int >= 0 + */ + private $commonLineThreshold; + + /** + * @var string + */ + private $header; + + /** + * @var int >= 0 + */ + private $contextLines; + + private static $default = [ + 'collapseRanges' => true, // ranges of length one are rendered with the trailing `,1` + 'commonLineThreshold' => 6, // number of same lines before ending a new hunk and creating a new one (if needed) + 'contextLines' => 3, // like `diff: -u, -U NUM, --unified[=NUM]`, for patch/git apply compatibility best to keep at least @ 3 + 'fromFile' => null, + 'fromFileDate' => null, + 'toFile' => null, + 'toFileDate' => null, + ]; + + public function __construct(array $options = []) + { + $options = \array_merge(self::$default, $options); + + if (!\is_bool($options['collapseRanges'])) { + throw new ConfigurationException('collapseRanges', 'a bool', $options['collapseRanges']); + } + + if (!\is_int($options['contextLines']) || $options['contextLines'] < 0) { + throw new ConfigurationException('contextLines', 'an int >= 0', $options['contextLines']); + } + + if (!\is_int($options['commonLineThreshold']) || $options['commonLineThreshold'] <= 0) { + throw new ConfigurationException('commonLineThreshold', 'an int > 0', $options['commonLineThreshold']); + } + + foreach (['fromFile', 'toFile'] as $option) { + if (!\is_string($options[$option])) { + throw new ConfigurationException($option, 'a string', $options[$option]); + } + } + + foreach (['fromFileDate', 'toFileDate'] as $option) { + if (null !== $options[$option] && !\is_string($options[$option])) { + throw new ConfigurationException($option, 'a string or <null>', $options[$option]); + } + } + + $this->header = \sprintf( + "--- %s%s\n+++ %s%s\n", + $options['fromFile'], + null === $options['fromFileDate'] ? '' : "\t" . $options['fromFileDate'], + $options['toFile'], + null === $options['toFileDate'] ? '' : "\t" . $options['toFileDate'] + ); + + $this->collapseRanges = $options['collapseRanges']; + $this->commonLineThreshold = $options['commonLineThreshold']; + $this->contextLines = $options['contextLines']; + } + + public function getDiff(array $diff) + { + if (0 === \count($diff)) { + return ''; + } + + $this->changed = false; + + $buffer = \fopen('php://memory', 'r+b'); + \fwrite($buffer, $this->header); + + $this->writeDiffHunks($buffer, $diff); + + if (!$this->changed) { + \fclose($buffer); + + return ''; + } + + $diff = \stream_get_contents($buffer, -1, 0); + + \fclose($buffer); + + // If the last char is not a linebreak: add it. + // This might happen when both the `from` and `to` do not have a trailing linebreak + $last = \substr($diff, -1); + + return "\n" !== $last && "\r" !== $last + ? $diff . "\n" + : $diff + ; + } + + private function writeDiffHunks($output, array $diff) + { + // detect "No newline at end of file" and insert into `$diff` if needed + + $upperLimit = \count($diff); + + if (0 === $diff[$upperLimit - 1][1]) { + $lc = \substr($diff[$upperLimit - 1][0], -1); + if ("\n" !== $lc) { + \array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]); + } + } else { + // search back for the last `+` and `-` line, + // check if has trailing linebreak, else add under it warning under it + $toFind = [1 => true, 2 => true]; + for ($i = $upperLimit - 1; $i >= 0; --$i) { + if (isset($toFind[$diff[$i][1]])) { + unset($toFind[$diff[$i][1]]); + $lc = \substr($diff[$i][0], -1); + if ("\n" !== $lc) { + \array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]); + } + + if (!\count($toFind)) { + break; + } + } + } + } + + // write hunks to output buffer + + $cutOff = \max($this->commonLineThreshold, $this->contextLines); + $hunkCapture = false; + $sameCount = $toRange = $fromRange = 0; + $toStart = $fromStart = 1; + + foreach ($diff as $i => $entry) { + if (0 === $entry[1]) { // same + if (false === $hunkCapture) { + ++$fromStart; + ++$toStart; + + continue; + } + + ++$sameCount; + ++$toRange; + ++$fromRange; + + if ($sameCount === $cutOff) { + $contextStartOffset = ($hunkCapture - $this->contextLines) < 0 + ? $hunkCapture + : $this->contextLines + ; + + // note: $contextEndOffset = $this->contextLines; + // + // because we never go beyond the end of the diff. + // with the cutoff/contextlines here the follow is never true; + // + // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) { + // $contextEndOffset = count($diff) - 1; + // } + // + // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop + + $this->writeHunk( + $diff, + $hunkCapture - $contextStartOffset, + $i - $cutOff + $this->contextLines + 1, + $fromStart - $contextStartOffset, + $fromRange - $cutOff + $contextStartOffset + $this->contextLines, + $toStart - $contextStartOffset, + $toRange - $cutOff + $contextStartOffset + $this->contextLines, + $output + ); + + $fromStart += $fromRange; + $toStart += $toRange; + + $hunkCapture = false; + $sameCount = $toRange = $fromRange = 0; + } + + continue; + } + + $sameCount = 0; + + if ($entry[1] === Differ::NO_LINE_END_EOF_WARNING) { + continue; + } + + $this->changed = true; + + if (false === $hunkCapture) { + $hunkCapture = $i; + } + + if (Differ::ADDED === $entry[1]) { // added + ++$toRange; + } + + if (Differ::REMOVED === $entry[1]) { // removed + ++$fromRange; + } + } + + if (false === $hunkCapture) { + return; + } + + // we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk, + // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold + + $contextStartOffset = $hunkCapture - $this->contextLines < 0 + ? $hunkCapture + : $this->contextLines + ; + + // prevent trying to write out more common lines than there are in the diff _and_ + // do not write more than configured through the context lines + $contextEndOffset = \min($sameCount, $this->contextLines); + + $fromRange -= $sameCount; + $toRange -= $sameCount; + + $this->writeHunk( + $diff, + $hunkCapture - $contextStartOffset, + $i - $sameCount + $contextEndOffset + 1, + $fromStart - $contextStartOffset, + $fromRange + $contextStartOffset + $contextEndOffset, + $toStart - $contextStartOffset, + $toRange + $contextStartOffset + $contextEndOffset, + $output + ); + } + + private function writeHunk( + array $diff, + $diffStartIndex, + $diffEndIndex, + $fromStart, + $fromRange, + $toStart, + $toRange, + $output + ) { + \fwrite($output, '@@ -' . $fromStart); + + if (!$this->collapseRanges || 1 !== $fromRange) { + \fwrite($output, ',' . $fromRange); + } + + \fwrite($output, ' +' . $toStart); + if (!$this->collapseRanges || 1 !== $toRange) { + \fwrite($output, ',' . $toRange); + } + + \fwrite($output, " @@\n"); + + for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { + if ($diff[$i][1] === Differ::ADDED) { + $this->changed = true; + \fwrite($output, '+' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::REMOVED) { + $this->changed = true; + \fwrite($output, '-' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::OLD) { + \fwrite($output, ' ' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::NO_LINE_END_EOF_WARNING) { + $this->changed = true; + \fwrite($output, $diff[$i][0]); + } + //} elseif ($diff[$i][1] === Differ::DIFF_LINE_END_WARNING) { // custom comment inserted by PHPUnit/diff package + // skip + //} else { + // unknown/invalid + //} + } + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Output/UnifiedDiffOutputBuilder.php b/vendor/php-cs-fixer/diff/src/v3_0/Output/UnifiedDiffOutputBuilder.php new file mode 100644 index 0000000..fb4d227 --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Output/UnifiedDiffOutputBuilder.php @@ -0,0 +1,259 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0\Output; + +use PhpCsFixer\Diff\v3_0\Differ; + +/** + * Builds a diff string representation in unified diff format in chunks. + */ +final class UnifiedDiffOutputBuilder extends AbstractChunkOutputBuilder +{ + /** + * @var bool + */ + private $collapseRanges = true; + + /** + * @var int >= 0 + */ + private $commonLineThreshold = 6; + + /** + * @var int >= 0 + */ + private $contextLines = 3; + + /** + * @var string + */ + private $header; + + /** + * @var bool + */ + private $addLineNumbers; + + public function __construct($header = "--- Original\n+++ New\n", $addLineNumbers = false) + { + $this->header = $header; + $this->addLineNumbers = $addLineNumbers; + } + + public function getDiff(array $diff) + { + $buffer = \fopen('php://memory', 'r+b'); + + if ('' !== $this->header) { + \fwrite($buffer, $this->header); + if ("\n" !== \substr($this->header, -1, 1)) { + \fwrite($buffer, "\n"); + } + } + + if (0 !== \count($diff)) { + $this->writeDiffHunks($buffer, $diff); + } + + $diff = \stream_get_contents($buffer, -1, 0); + + \fclose($buffer); + + // If the diff is non-empty and a linebreak: add it. + // This might happen when both the `from` and `to` do not have a trailing linebreak + $last = \substr($diff, -1); + + return 0 !== \strlen($diff) && "\n" !== $last && "\r" !== $last + ? $diff . "\n" + : $diff + ; + } + + private function writeDiffHunks($output, array $diff) + { + // detect "No newline at end of file" and insert into `$diff` if needed + + $upperLimit = \count($diff); + + if (0 === $diff[$upperLimit - 1][1]) { + $lc = \substr($diff[$upperLimit - 1][0], -1); + if ("\n" !== $lc) { + \array_splice($diff, $upperLimit, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]); + } + } else { + // search back for the last `+` and `-` line, + // check if has trailing linebreak, else add under it warning under it + $toFind = [1 => true, 2 => true]; + for ($i = $upperLimit - 1; $i >= 0; --$i) { + if (isset($toFind[$diff[$i][1]])) { + unset($toFind[$diff[$i][1]]); + $lc = \substr($diff[$i][0], -1); + if ("\n" !== $lc) { + \array_splice($diff, $i + 1, 0, [["\n\\ No newline at end of file\n", Differ::NO_LINE_END_EOF_WARNING]]); + } + + if (!\count($toFind)) { + break; + } + } + } + } + + // write hunks to output buffer + + $cutOff = \max($this->commonLineThreshold, $this->contextLines); + $hunkCapture = false; + $sameCount = $toRange = $fromRange = 0; + $toStart = $fromStart = 1; + + foreach ($diff as $i => $entry) { + if (0 === $entry[1]) { // same + if (false === $hunkCapture) { + ++$fromStart; + ++$toStart; + + continue; + } + + ++$sameCount; + ++$toRange; + ++$fromRange; + + if ($sameCount === $cutOff) { + $contextStartOffset = ($hunkCapture - $this->contextLines) < 0 + ? $hunkCapture + : $this->contextLines + ; + + // note: $contextEndOffset = $this->contextLines; + // + // because we never go beyond the end of the diff. + // with the cutoff/contextlines here the follow is never true; + // + // if ($i - $cutOff + $this->contextLines + 1 > \count($diff)) { + // $contextEndOffset = count($diff) - 1; + // } + // + // ; that would be true for a trailing incomplete hunk case which is dealt with after this loop + + $this->writeHunk( + $diff, + $hunkCapture - $contextStartOffset, + $i - $cutOff + $this->contextLines + 1, + $fromStart - $contextStartOffset, + $fromRange - $cutOff + $contextStartOffset + $this->contextLines, + $toStart - $contextStartOffset, + $toRange - $cutOff + $contextStartOffset + $this->contextLines, + $output + ); + + $fromStart += $fromRange; + $toStart += $toRange; + + $hunkCapture = false; + $sameCount = $toRange = $fromRange = 0; + } + + continue; + } + + $sameCount = 0; + + if ($entry[1] === Differ::NO_LINE_END_EOF_WARNING) { + continue; + } + + if (false === $hunkCapture) { + $hunkCapture = $i; + } + + if (Differ::ADDED === $entry[1]) { + ++$toRange; + } + + if (Differ::REMOVED === $entry[1]) { + ++$fromRange; + } + } + + if (false === $hunkCapture) { + return; + } + + // we end here when cutoff (commonLineThreshold) was not reached, but we where capturing a hunk, + // do not render hunk till end automatically because the number of context lines might be less than the commonLineThreshold + + $contextStartOffset = $hunkCapture - $this->contextLines < 0 + ? $hunkCapture + : $this->contextLines + ; + + // prevent trying to write out more common lines than there are in the diff _and_ + // do not write more than configured through the context lines + $contextEndOffset = \min($sameCount, $this->contextLines); + + $fromRange -= $sameCount; + $toRange -= $sameCount; + + $this->writeHunk( + $diff, + $hunkCapture - $contextStartOffset, + $i - $sameCount + $contextEndOffset + 1, + $fromStart - $contextStartOffset, + $fromRange + $contextStartOffset + $contextEndOffset, + $toStart - $contextStartOffset, + $toRange + $contextStartOffset + $contextEndOffset, + $output + ); + } + + private function writeHunk( + array $diff, + $diffStartIndex, + $diffEndIndex, + $fromStart, + $fromRange, + $toStart, + $toRange, + $output + ) { + if ($this->addLineNumbers) { + \fwrite($output, '@@ -' . $fromStart); + + if (!$this->collapseRanges || 1 !== $fromRange) { + \fwrite($output, ',' . $fromRange); + } + + \fwrite($output, ' +' . $toStart); + if (!$this->collapseRanges || 1 !== $toRange) { + \fwrite($output, ',' . $toRange); + } + + \fwrite($output, " @@\n"); + } else { + \fwrite($output, "@@ @@\n"); + } + + for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { + if ($diff[$i][1] === Differ::ADDED) { + \fwrite($output, '+' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::REMOVED) { + \fwrite($output, '-' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::OLD) { + \fwrite($output, ' ' . $diff[$i][0]); + } elseif ($diff[$i][1] === Differ::NO_LINE_END_EOF_WARNING) { + \fwrite($output, "\n"); // $diff[$i][0] + } else { /* Not changed (old) Differ::OLD or Warning Differ::DIFF_LINE_END_WARNING */ + \fwrite($output, ' ' . $diff[$i][0]); + } + } + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/Parser.php b/vendor/php-cs-fixer/diff/src/v3_0/Parser.php new file mode 100644 index 0000000..aa7175a --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/Parser.php @@ -0,0 +1,106 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +/** + * Unified diff parser. + */ +final class Parser +{ + /** + * @param string $string + * + * @return Diff[] + */ + public function parse($string) + { + $lines = \preg_split('(\r\n|\r|\n)', $string); + + if (!empty($lines) && $lines[\count($lines) - 1] === '') { + \array_pop($lines); + } + + $lineCount = \count($lines); + $diffs = []; + $diff = null; + $collected = []; + + for ($i = 0; $i < $lineCount; ++$i) { + if (\preg_match('(^---\\s+(?P<file>\\S+))', $lines[$i], $fromMatch) && + \preg_match('(^\\+\\+\\+\\s+(?P<file>\\S+))', $lines[$i + 1], $toMatch)) { + if ($diff !== null) { + $this->parseFileDiff($diff, $collected); + + $diffs[] = $diff; + $collected = []; + } + + $diff = new Diff($fromMatch['file'], $toMatch['file']); + + ++$i; + } else { + if (\preg_match('/^(?:diff --git |index [\da-f\.]+|[+-]{3} [ab])/', $lines[$i])) { + continue; + } + + $collected[] = $lines[$i]; + } + } + + if ($diff !== null && \count($collected)) { + $this->parseFileDiff($diff, $collected); + + $diffs[] = $diff; + } + + return $diffs; + } + + private function parseFileDiff(Diff $diff, array $lines) + { + $chunks = []; + $chunk = null; + + foreach ($lines as $line) { + if (\preg_match('/^@@\s+-(?P<start>\d+)(?:,\s*(?P<startrange>\d+))?\s+\+(?P<end>\d+)(?:,\s*(?P<endrange>\d+))?\s+@@/', $line, $match)) { + $chunk = new Chunk( + (int) $match['start'], + isset($match['startrange']) ? \max(1, (int) $match['startrange']) : 1, + (int) $match['end'], + isset($match['endrange']) ? \max(1, (int) $match['endrange']) : 1 + ); + + $chunks[] = $chunk; + $diffLines = []; + + continue; + } + + if (\preg_match('/^(?P<type>[+ -])?(?P<line>.*)/', $line, $match)) { + $type = Line::UNCHANGED; + + if ($match['type'] === '+') { + $type = Line::ADDED; + } elseif ($match['type'] === '-') { + $type = Line::REMOVED; + } + + $diffLines[] = new Line($type, $match['line']); + + if (null !== $chunk) { + $chunk->setLines($diffLines); + } + } + } + + $diff->setChunks($chunks); + } +} diff --git a/vendor/php-cs-fixer/diff/src/v3_0/TimeEfficientLongestCommonSubsequenceCalculator.php b/vendor/php-cs-fixer/diff/src/v3_0/TimeEfficientLongestCommonSubsequenceCalculator.php new file mode 100644 index 0000000..644968a --- /dev/null +++ b/vendor/php-cs-fixer/diff/src/v3_0/TimeEfficientLongestCommonSubsequenceCalculator.php @@ -0,0 +1,66 @@ +<?php +/* + * This file is part of sebastian/diff. + * + * (c) Sebastian Bergmann <sebastian@phpunit.de> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpCsFixer\Diff\v3_0; + +final class TimeEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator +{ + /** + * {@inheritdoc} + */ + public function calculate(array $from, array $to) + { + $common = []; + $fromLength = \count($from); + $toLength = \count($to); + $width = $fromLength + 1; + $matrix = new \SplFixedArray($width * ($toLength + 1)); + + for ($i = 0; $i <= $fromLength; ++$i) { + $matrix[$i] = 0; + } + + for ($j = 0; $j <= $toLength; ++$j) { + $matrix[$j * $width] = 0; + } + + for ($i = 1; $i <= $fromLength; ++$i) { + for ($j = 1; $j <= $toLength; ++$j) { + $o = ($j * $width) + $i; + $matrix[$o] = \max( + $matrix[$o - 1], + $matrix[$o - $width], + $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0 + ); + } + } + + $i = $fromLength; + $j = $toLength; + + while ($i > 0 && $j > 0) { + if ($from[$i - 1] === $to[$j - 1]) { + $common[] = $from[$i - 1]; + --$i; + --$j; + } else { + $o = ($j * $width) + $i; + + if ($matrix[$o - $width] > $matrix[$o - 1]) { + --$j; + } else { + --$i; + } + } + } + + return \array_reverse($common); + } +} diff --git a/vendor/phpdocumentor/reflection-common/.github/dependabot.yml b/vendor/phpdocumentor/reflection-common/.github/dependabot.yml new file mode 100644 index 0000000..c630ffa --- /dev/null +++ b/vendor/phpdocumentor/reflection-common/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: +- package-ecosystem: composer + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 diff --git a/vendor/phpdocumentor/reflection-common/.github/workflows/push.yml b/vendor/phpdocumentor/reflection-common/.github/workflows/push.yml new file mode 100644 index 0000000..484410e --- /dev/null +++ b/vendor/phpdocumentor/reflection-common/.github/workflows/push.yml @@ -0,0 +1,223 @@ +on: + push: + branches: + - 2.x + pull_request: +name: Qa workflow +jobs: + setup: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Restore/cache vendor folder + uses: actions/cache@v1 + with: + path: vendor + key: all-build-${{ hashFiles('**/composer.lock') }} + restore-keys: | + all-build-${{ hashFiles('**/composer.lock') }} + all-build- + + - name: Restore/cache tools folder + uses: actions/cache@v1 + with: + path: tools + key: all-tools-${{ github.sha }} + restore-keys: | + all-tools-${{ github.sha }}- + all-tools- + + - name: composer + uses: docker://composer + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: install --no-interaction --prefer-dist --optimize-autoloader + + - name: Install phive + run: make install-phive + + - name: Install PHAR dependencies + run: tools/phive.phar --no-progress install --copy --trust-gpg-keys 4AA394086372C20A,8A03EA3B385DBAA1 --force-accept-unsigned + + phpunit-with-coverage: + runs-on: ubuntu-latest + name: Unit tests + needs: setup + steps: + - uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 7.2 + ini-values: memory_limit=2G, display_errors=On, error_reporting=-1 + coverage: pcov + + - name: Restore/cache tools folder + uses: actions/cache@v1 + with: + path: tools + key: all-tools-${{ github.sha }} + restore-keys: | + all-tools-${{ github.sha }}- + all-tools- + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ubuntu-latest-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ubuntu-latest-composer- + + - name: Install Composer dependencies + run: | + composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + + - name: Run PHPUnit + run: php tools/phpunit + + phpunit: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: + - ubuntu-latest + - windows-latest + - macOS-latest + php-versions: ['7.2', '7.3', '7.4', '8.0'] + name: Unit tests for PHP version ${{ matrix.php-versions }} on ${{ matrix.operating-system }} + needs: + - setup + - phpunit-with-coverage + steps: + - uses: actions/checkout@v2 + + - name: Restore/cache tools folder + uses: actions/cache@v1 + with: + path: tools + key: all-tools-${{ github.sha }} + restore-keys: | + all-tools-${{ github.sha }}- + all-tools- + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + ini-values: memory_limit=2G, display_errors=On, error_reporting=-1 + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: | + composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + + - name: Run PHPUnit + continue-on-error: true + run: php tools/phpunit + + codestyle: + runs-on: ubuntu-latest + needs: [setup, phpunit] + steps: + - uses: actions/checkout@v2 + - name: Restore/cache vendor folder + uses: actions/cache@v1 + with: + path: vendor + key: all-build-${{ hashFiles('**/composer.lock') }} + restore-keys: | + all-build-${{ hashFiles('**/composer.lock') }} + all-build- + - name: Code style check + uses: phpDocumentor/coding-standard@latest + with: + args: -s + + phpstan: + runs-on: ubuntu-latest + needs: [setup, phpunit] + steps: + - uses: actions/checkout@v2 + - name: Restore/cache vendor folder + uses: actions/cache@v1 + with: + path: vendor + key: all-build-${{ hashFiles('**/composer.lock') }} + restore-keys: | + all-build-${{ hashFiles('**/composer.lock') }} + all-build- + - name: PHPStan + uses: phpDocumentor/phpstan-ga@latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: analyse src --configuration phpstan.neon + + psalm: + runs-on: ubuntu-latest + needs: [setup, phpunit] + steps: + - uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 7.2 + ini-values: memory_limit=2G, display_errors=On, error_reporting=-1 + tools: psalm + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: | + composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + + - name: Psalm + run: psalm --output-format=github + + bc_check: + name: BC Check + runs-on: ubuntu-latest + needs: [setup, phpunit] + steps: + - uses: actions/checkout@v2 + - name: fetch tags + run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* + - name: Restore/cache vendor folder + uses: actions/cache@v1 + with: + path: vendor + key: all-build-${{ hashFiles('**/composer.lock') }} + restore-keys: | + all-build-${{ hashFiles('**/composer.lock') }} + all-build- + - name: Roave BC Check + uses: docker://nyholm/roave-bc-check-ga diff --git a/vendor/phpdocumentor/reflection-common/.travis.yml b/vendor/phpdocumentor/reflection-common/.travis.yml deleted file mode 100644 index 958ecf8..0000000 --- a/vendor/phpdocumentor/reflection-common/.travis.yml +++ /dev/null @@ -1,35 +0,0 @@ -language: php -php: - - 5.5 - - 5.6 - - 7.0 - - 7.1 - - hhvm - - nightly - -matrix: - allow_failures: - - php: - - hhvm - - nightly - -cache: - directories: - - $HOME/.composer/cache - -script: - - vendor/bin/phpunit --coverage-clover=coverage.clover -v - - composer update --no-interaction --prefer-source - - vendor/bin/phpunit -v - -before_script: - - composer install --no-interaction - -after_script: - - if [ $TRAVIS_PHP_VERSION = '5.6' ]; then wget https://scrutinizer-ci.com/ocular.phar; php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi - -notifications: - irc: "irc.freenode.org#phpdocumentor" - email: - - me@mikevanriel.com - - ashnazg@php.net diff --git a/vendor/phpdocumentor/reflection-common/README.md b/vendor/phpdocumentor/reflection-common/README.md index 68a80c8..70f830d 100644 --- a/vendor/phpdocumentor/reflection-common/README.md +++ b/vendor/phpdocumentor/reflection-common/README.md @@ -1,2 +1,11 @@ -# ReflectionCommon -[![Build Status](https://travis-ci.org/phpDocumentor/ReflectionCommon.svg?branch=master)](https://travis-ci.org/phpDocumentor/ReflectionCommon) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +![Qa workflow](https://github.com/phpDocumentor/ReflectionCommon/workflows/Qa%20workflow/badge.svg) +[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/ReflectionCommon.svg)](https://coveralls.io/github/phpDocumentor/ReflectionCommon?branch=master) +[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/ReflectionCommon.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionCommon/?branch=master) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/ReflectionCommon.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionCommon/?branch=master) +[![Stable Version](https://img.shields.io/packagist/v/phpDocumentor/Reflection-Common.svg)](https://packagist.org/packages/phpDocumentor/Reflection-Common) +[![Unstable Version](https://img.shields.io/packagist/vpre/phpDocumentor/Reflection-Common.svg)](https://packagist.org/packages/phpDocumentor/Reflection-Common) + + +ReflectionCommon +================ diff --git a/vendor/phpdocumentor/reflection-common/composer.json b/vendor/phpdocumentor/reflection-common/composer.json index 90eee0f..4d128b4 100644 --- a/vendor/phpdocumentor/reflection-common/composer.json +++ b/vendor/phpdocumentor/reflection-common/composer.json @@ -11,19 +11,18 @@ } ], "require": { - "php": ">=5.5" + "php": "^7.2 || ^8.0" }, "autoload" : { "psr-4" : { - "phpDocumentor\\Reflection\\": ["src"] + "phpDocumentor\\Reflection\\": "src/" } }, "require-dev": { - "phpunit/phpunit": "^4.6" }, "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-2.x": "2.x-dev" } } } diff --git a/vendor/phpdocumentor/reflection-common/src/Element.php b/vendor/phpdocumentor/reflection-common/src/Element.php index 712e30e..8923e4f 100644 --- a/vendor/phpdocumentor/reflection-common/src/Element.php +++ b/vendor/phpdocumentor/reflection-common/src/Element.php @@ -1,11 +1,13 @@ <?php + +declare(strict_types=1); + /** * phpDocumentor * - * PHP Version 5.5 + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel / Naenius (http://www.naenius.com) - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,15 +20,11 @@ interface Element { /** * Returns the Fqsen of the element. - * - * @return Fqsen */ - public function getFqsen(); + public function getFqsen() : Fqsen; /** * Returns the name of the element. - * - * @return string */ - public function getName(); -} \ No newline at end of file + public function getName() : string; +} diff --git a/vendor/phpdocumentor/reflection-common/src/File.php b/vendor/phpdocumentor/reflection-common/src/File.php index 0187594..239c137 100644 --- a/vendor/phpdocumentor/reflection-common/src/File.php +++ b/vendor/phpdocumentor/reflection-common/src/File.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -19,22 +20,16 @@ interface File { /** * Returns the content of the file as a string. - * - * @return string */ - public function getContents(); + public function getContents() : string; /** * Returns md5 hash of the file. - * - * @return string */ - public function md5(); + public function md5() : string; /** * Returns an relative path to the file. - * - * @return string */ - public function path(); + public function path() : string; } diff --git a/vendor/phpdocumentor/reflection-common/src/Fqsen.php b/vendor/phpdocumentor/reflection-common/src/Fqsen.php index ce88d03..8fc5d34 100644 --- a/vendor/phpdocumentor/reflection-common/src/Fqsen.php +++ b/vendor/phpdocumentor/reflection-common/src/Fqsen.php @@ -1,51 +1,60 @@ <?php + +declare(strict_types=1); + /** * phpDocumentor * - * PHP Version 5.5 + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel / Naenius (http://www.naenius.com) - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection; +use InvalidArgumentException; +use function assert; +use function end; +use function explode; +use function is_string; +use function preg_match; +use function sprintf; +use function trim; + /** * Value Object for Fqsen. * * @link https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc-meta.md + * + * @psalm-immutable */ final class Fqsen { - /** - * @var string full quallified class name - */ + /** @var string full quallified class name */ private $fqsen; - /** - * @var string name of the element without path. - */ + /** @var string name of the element without path. */ private $name; /** * Initializes the object. * - * @param string $fqsen - * - * @throws \InvalidArgumentException when $fqsen is not matching the format. + * @throws InvalidArgumentException when $fqsen is not matching the format. */ - public function __construct($fqsen) + public function __construct(string $fqsen) { - $matches = array(); + $matches = []; + $result = preg_match( + //phpcs:ignore Generic.Files.LineLength.TooLong '/^\\\\([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff\\\\]*)?(?:[:]{2}\\$?([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*))?(?:\\(\\))?$/', - $fqsen, - $matches + $fqsen, + $matches ); if ($result === 0) { - throw new \InvalidArgumentException( + throw new InvalidArgumentException( sprintf('"%s" is not a valid Fqsen.', $fqsen) ); } @@ -56,26 +65,24 @@ public function __construct($fqsen) $this->name = $matches[2]; } else { $matches = explode('\\', $fqsen); - $this->name = trim(end($matches), '()'); + $name = end($matches); + assert(is_string($name)); + $this->name = trim($name, '()'); } } /** * converts this class to string. - * - * @return string */ - public function __toString() + public function __toString() : string { return $this->fqsen; } /** * Returns the name of the element without path. - * - * @return string */ - public function getName() + public function getName() : string { return $this->name; } diff --git a/vendor/phpdocumentor/reflection-common/src/Location.php b/vendor/phpdocumentor/reflection-common/src/Location.php index 5760321..177deed 100644 --- a/vendor/phpdocumentor/reflection-common/src/Location.php +++ b/vendor/phpdocumentor/reflection-common/src/Location.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -14,10 +15,12 @@ /** * The location where an element occurs within a file. + * + * @psalm-immutable */ final class Location { - /** @var int */ + /** @var int */ private $lineNumber = 0; /** @var int */ @@ -25,32 +28,25 @@ final class Location /** * Initializes the location for an element using its line number in the file and optionally the column number. - * - * @param int $lineNumber - * @param int $columnNumber */ - public function __construct($lineNumber, $columnNumber = 0) + public function __construct(int $lineNumber, int $columnNumber = 0) { - $this->lineNumber = $lineNumber; + $this->lineNumber = $lineNumber; $this->columnNumber = $columnNumber; } /** * Returns the line number that is covered by this location. - * - * @return integer */ - public function getLineNumber() + public function getLineNumber() : int { return $this->lineNumber; } /** * Returns the column number (character position on a line) for this location object. - * - * @return integer */ - public function getColumnNumber() + public function getColumnNumber() : int { return $this->columnNumber; } diff --git a/vendor/phpdocumentor/reflection-common/src/Project.php b/vendor/phpdocumentor/reflection-common/src/Project.php index 3ed1e39..57839fd 100644 --- a/vendor/phpdocumentor/reflection-common/src/Project.php +++ b/vendor/phpdocumentor/reflection-common/src/Project.php @@ -1,11 +1,13 @@ <?php + +declare(strict_types=1); + /** * phpDocumentor * - * PHP Version 5.5 + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel / Naenius (http://www.naenius.com) - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,8 +20,6 @@ interface Project { /** * Returns the name of the project. - * - * @return string */ - public function getName(); + public function getName() : string; } diff --git a/vendor/phpdocumentor/reflection-common/src/ProjectFactory.php b/vendor/phpdocumentor/reflection-common/src/ProjectFactory.php index 5602f84..8bdc606 100644 --- a/vendor/phpdocumentor/reflection-common/src/ProjectFactory.php +++ b/vendor/phpdocumentor/reflection-common/src/ProjectFactory.php @@ -1,13 +1,16 @@ <?php + +declare(strict_types=1); + /** * phpDocumentor * - * PHP Version 5.5 + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel / Naenius (http://www.naenius.com) - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ + namespace phpDocumentor\Reflection; /** @@ -19,9 +22,7 @@ interface ProjectFactory /** * Creates a project from the set of files. * - * @param string $name * @param File[] $files - * @return Project */ - public function create($name, array $files); + public function create(string $name, array $files) : Project; } diff --git a/vendor/phpdocumentor/reflection-docblock/.coveralls.yml b/vendor/phpdocumentor/reflection-docblock/.coveralls.yml deleted file mode 100644 index c512a3d..0000000 --- a/vendor/phpdocumentor/reflection-docblock/.coveralls.yml +++ /dev/null @@ -1,3 +0,0 @@ -service_name: travis-ci -coverage_clover: coverage.xml -json_path: coverage.json diff --git a/vendor/phpdocumentor/reflection-docblock/README.md b/vendor/phpdocumentor/reflection-docblock/README.md index 5a7d326..51f1088 100644 --- a/vendor/phpdocumentor/reflection-docblock/README.md +++ b/vendor/phpdocumentor/reflection-docblock/README.md @@ -1,5 +1,13 @@ -The ReflectionDocBlock Component [![Build Status](https://secure.travis-ci.org/phpDocumentor/ReflectionDocBlock.png)](https://travis-ci.org/phpDocumentor/ReflectionDocBlock) -================================ +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +![Qa workflow](https://github.com/phpDocumentor/ReflectionDocBlock/workflows/Qa%20workflow/badge.svg) +[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/ReflectionDocBlock.svg)](https://coveralls.io/github/phpDocumentor/ReflectionDocBlock?branch=master) +[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/ReflectionDocBlock.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionDocBlock/?branch=master) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/ReflectionDocBlock.svg)](https://scrutinizer-ci.com/g/phpDocumentor/ReflectionDocBlock/?branch=master) +[![Stable Version](https://img.shields.io/packagist/v/phpdocumentor/reflection-docblock.svg)](https://packagist.org/packages/phpdocumentor/reflection-docblock) +[![Unstable Version](https://img.shields.io/packagist/vpre/phpdocumentor/reflection-docblock.svg)](https://packagist.org/packages/phpdocumentor/reflection-docblock) + +ReflectionDocBlock +================== Introduction ------------ @@ -27,8 +35,8 @@ instantiated using its `createInstance` factory method like this: $factory = \phpDocumentor\Reflection\DocBlockFactory::createInstance(); ``` -Then we can use the `create` method of the factory to interpret the DocBlock. -Please note that it is also possible to provide a class that has the +Then we can use the `create` method of the factory to interpret the DocBlock. +Please note that it is also possible to provide a class that has the `getDocComment()` method, such as an object of type `ReflectionClass`, the create method will read that if it exists. diff --git a/vendor/phpdocumentor/reflection-docblock/composer.json b/vendor/phpdocumentor/reflection-docblock/composer.json index e3dc38a..d907630 100644 --- a/vendor/phpdocumentor/reflection-docblock/composer.json +++ b/vendor/phpdocumentor/reflection-docblock/composer.json @@ -1,34 +1,42 @@ { - "name": "phpdocumentor/reflection-docblock", + "name": "phpdocumentor/reflection-docblock", "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "type": "library", + "type": "library", "license": "MIT", "authors": [ { "name": "Mike van Riel", "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" + "php": "^7.2 || ^8.0", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1", + "phpdocumentor/reflection-common": "^2.2", + "ext-filter": "*" + }, + "require-dev": { + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" }, "autoload": { - "psr-4": {"phpDocumentor\\Reflection\\": ["src/"]} + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } }, "autoload-dev": { - "psr-4": {"phpDocumentor\\Reflection\\": ["tests/unit"]} - }, - "require-dev": { - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4", - "doctrine/instantiator": "~1.0.5" + "psr-4": { + "phpDocumentor\\Reflection\\": ["tests/unit", "tests/integration"] + } }, "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } } } diff --git a/vendor/phpdocumentor/reflection-docblock/easy-coding-standard.neon b/vendor/phpdocumentor/reflection-docblock/easy-coding-standard.neon deleted file mode 100644 index 7c2ba6e..0000000 --- a/vendor/phpdocumentor/reflection-docblock/easy-coding-standard.neon +++ /dev/null @@ -1,31 +0,0 @@ -includes: - - temp/ecs/config/clean-code.neon - - temp/ecs/config/psr2-checkers.neon - - temp/ecs/config/spaces.neon - - temp/ecs/config/common.neon - -checkers: - PhpCsFixer\Fixer\Operator\ConcatSpaceFixer: - spacing: one - -parameters: - exclude_checkers: - # from temp/ecs/config/common.neon - - PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer - - PhpCsFixer\Fixer\PhpUnit\PhpUnitStrictFixer - - PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer - # from temp/ecs/config/spaces.neon - - PhpCsFixer\Fixer\Operator\NotOperatorWithSuccessorSpaceFixer - - skip: - SlevomatCodingStandard\Sniffs\Classes\UnusedPrivateElementsSniff: - # WIP code - - src/DocBlock/StandardTagFactory.php - PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\EmptyStatementSniff: - # WIP code - - src/DocBlock/StandardTagFactory.php - PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\ValidClassNameSniff: - - src/DocBlock/Tags/Return_.php - - src/DocBlock/Tags/Var_.php - PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff: - - */tests/** diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock.php index 46605b7..cc33e60 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock.php @@ -1,111 +1,96 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection; use phpDocumentor\Reflection\DocBlock\Tag; +use phpDocumentor\Reflection\DocBlock\Tags\TagWithType; use Webmozart\Assert\Assert; final class DocBlock { /** @var string The opening line for this docblock. */ - private $summary = ''; + private $summary; /** @var DocBlock\Description The actual description for this docblock. */ - private $description = null; + private $description; /** @var Tag[] An array containing all the tags in this docblock; except inline. */ private $tags = []; - /** @var Types\Context Information about the context of this DocBlock. */ - private $context = null; + /** @var Types\Context|null Information about the context of this DocBlock. */ + private $context; - /** @var Location Information about the location of this DocBlock. */ - private $location = null; + /** @var Location|null Information about the location of this DocBlock. */ + private $location; /** @var bool Is this DocBlock (the start of) a template? */ - private $isTemplateStart = false; + private $isTemplateStart; /** @var bool Does this DocBlock signify the end of a DocBlock template? */ - private $isTemplateEnd = false; + private $isTemplateEnd; /** - * @param string $summary - * @param DocBlock\Description $description * @param DocBlock\Tag[] $tags - * @param Types\Context $context The context in which the DocBlock occurs. - * @param Location $location The location within the file that this DocBlock occurs in. - * @param bool $isTemplateStart - * @param bool $isTemplateEnd + * @param Types\Context $context The context in which the DocBlock occurs. + * @param Location $location The location within the file that this DocBlock occurs in. */ public function __construct( - $summary = '', - DocBlock\Description $description = null, + string $summary = '', + ?DocBlock\Description $description = null, array $tags = [], - Types\Context $context = null, - Location $location = null, - $isTemplateStart = false, - $isTemplateEnd = false + ?Types\Context $context = null, + ?Location $location = null, + bool $isTemplateStart = false, + bool $isTemplateEnd = false ) { - Assert::string($summary); - Assert::boolean($isTemplateStart); - Assert::boolean($isTemplateEnd); Assert::allIsInstanceOf($tags, Tag::class); - $this->summary = $summary; + $this->summary = $summary; $this->description = $description ?: new DocBlock\Description(''); foreach ($tags as $tag) { $this->addTag($tag); } - $this->context = $context; + $this->context = $context; $this->location = $location; - $this->isTemplateEnd = $isTemplateEnd; + $this->isTemplateEnd = $isTemplateEnd; $this->isTemplateStart = $isTemplateStart; } - /** - * @return string - */ - public function getSummary() + public function getSummary(): string { return $this->summary; } - /** - * @return DocBlock\Description - */ - public function getDescription() + public function getDescription(): DocBlock\Description { return $this->description; } /** * Returns the current context. - * - * @return Types\Context */ - public function getContext() + public function getContext(): ?Types\Context { return $this->context; } /** * Returns the current location. - * - * @return Location */ - public function getLocation() + public function getLocation(): ?Location { return $this->location; } @@ -128,10 +113,8 @@ public function getLocation() * elements that follow until another DocBlock is found that contains the closing marker (`#@-`). * * @see self::isTemplateEnd() for the check whether a closing marker was provided. - * - * @return boolean */ - public function isTemplateStart() + public function isTemplateStart(): bool { return $this->isTemplateStart; } @@ -140,10 +123,8 @@ public function isTemplateStart() * Returns whether this DocBlock is the end of a Template section. * * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality. - * - * @return boolean */ - public function isTemplateEnd() + public function isTemplateEnd(): bool { return $this->isTemplateEnd; } @@ -153,7 +134,7 @@ public function isTemplateEnd() * * @return Tag[] */ - public function getTags() + public function getTags(): array { return $this->tags; } @@ -166,13 +147,10 @@ public function getTags() * * @return Tag[] */ - public function getTagsByName($name) + public function getTagsByName(string $name): array { - Assert::string($name); - $result = []; - /** @var Tag $tag */ foreach ($this->getTags() as $tag) { if ($tag->getName() !== $name) { continue; @@ -185,17 +163,35 @@ public function getTagsByName($name) } /** - * Checks if a tag of a certain type is present in this DocBlock. + * Returns an array of tags with type matching the given name. If no tags are found + * an empty array is returned. * - * @param string $name Tag name to check for. + * @param string $name String to search by. * - * @return bool + * @return TagWithType[] */ - public function hasTag($name) + public function getTagsWithTypeByName(string $name): array { - Assert::string($name); + $result = []; - /** @var Tag $tag */ + foreach ($this->getTagsByName($name) as $tag) { + if (!$tag instanceof TagWithType) { + continue; + } + + $result[] = $tag; + } + + return $result; + } + + /** + * Checks if a tag of a certain type is present in this DocBlock. + * + * @param string $name Tag name to check for. + */ + public function hasTag(string $name): bool + { foreach ($this->getTags() as $tag) { if ($tag->getName() === $name) { return true; @@ -208,11 +204,9 @@ public function hasTag($name) /** * Remove a tag from this DocBlock. * - * @param Tag $tag The tag to remove. - * - * @return void + * @param Tag $tagToRemove The tag to remove. */ - public function removeTag(Tag $tagToRemove) + public function removeTag(Tag $tagToRemove): void { foreach ($this->tags as $key => $tag) { if ($tag === $tagToRemove) { @@ -226,10 +220,8 @@ public function removeTag(Tag $tagToRemove) * Adds a tag to this DocBlock. * * @param Tag $tag The tag to add. - * - * @return void */ - private function addTag(Tag $tag) + private function addTag(Tag $tag): void { $this->tags[] = $tag; } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php index 25a79e0..a31b289 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -14,7 +15,8 @@ use phpDocumentor\Reflection\DocBlock\Tags\Formatter; use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter; -use Webmozart\Assert\Assert; + +use function vsprintf; /** * Object representing to description for a DocBlock. @@ -59,15 +61,20 @@ class Description /** * Initializes a Description with its body (template) and a listing of the tags used in the body template. * - * @param string $bodyTemplate * @param Tag[] $tags */ - public function __construct($bodyTemplate, array $tags = []) + public function __construct(string $bodyTemplate, array $tags = []) { - Assert::string($bodyTemplate); - $this->bodyTemplate = $bodyTemplate; - $this->tags = $tags; + $this->tags = $tags; + } + + /** + * Returns the body template. + */ + public function getBodyTemplate(): string + { + return $this->bodyTemplate; } /** @@ -75,7 +82,7 @@ public function __construct($bodyTemplate, array $tags = []) * * @return Tag[] */ - public function getTags() + public function getTags(): array { return $this->tags; } @@ -83,12 +90,8 @@ public function getTags() /** * Renders this description as a string where the provided formatter will format the tags in the expected string * format. - * - * @param Formatter|null $formatter - * - * @return string */ - public function render(Formatter $formatter = null) + public function render(?Formatter $formatter = null): string { if ($formatter === null) { $formatter = new PassthroughFormatter(); @@ -104,10 +107,8 @@ public function render(Formatter $formatter = null) /** * Returns a plain string representation of this description. - * - * @return string */ - public function __toString() + public function __toString(): string { return $this->render(); } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php index 48f9c21..1a519ec 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php @@ -1,18 +1,32 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Utils; + +use function count; +use function implode; +use function ltrim; +use function min; +use function str_replace; +use function strlen; +use function strpos; +use function substr; +use function trim; + +use const PREG_SPLIT_DELIM_CAPTURE; /** * Creates a new Description object given a body of text. @@ -38,8 +52,6 @@ class DescriptionFactory /** * Initializes this factory with the means to construct (inline) tags. - * - * @param TagFactory $tagFactory */ public function __construct(TagFactory $tagFactory) { @@ -48,27 +60,36 @@ public function __construct(TagFactory $tagFactory) /** * Returns the parsed text of this description. - * - * @param string $contents - * @param TypeContext $context - * - * @return Description */ - public function create($contents, TypeContext $context = null) + public function create(string $contents, ?TypeContext $context = null): Description { - list($text, $tags) = $this->parse($this->lex($contents), $context); + $tokens = $this->lex($contents); + $count = count($tokens); + $tagCount = 0; + $tags = []; + + for ($i = 1; $i < $count; $i += 2) { + $tags[] = $this->tagFactory->create($tokens[$i], $context); + $tokens[$i] = '%' . ++$tagCount . '$s'; + } - return new Description($text, $tags); + //In order to allow "literal" inline tags, the otherwise invalid + //sequence "{@}" is changed to "@", and "{}" is changed to "}". + //"%" is escaped to "%%" because of vsprintf. + //See unit tests for examples. + for ($i = 0; $i < $count; $i += 2) { + $tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]); + } + + return new Description(implode('', $tokens), $tags); } /** * Strips the contents from superfluous whitespace and splits the description into a series of tokens. * - * @param string $contents - * * @return string[] A series of tokens of which the description text is composed. */ - private function lex($contents) + private function lex(string $contents): array { $contents = $this->removeSuperfluousStartingWhitespace($contents); @@ -77,7 +98,7 @@ private function lex($contents) return [$contents]; } - return preg_split( + return Utils::pregSplit( '/\{ # "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally. (?!@\}) @@ -103,41 +124,11 @@ private function lex($contents) ) \}/Sux', $contents, - null, + 0, PREG_SPLIT_DELIM_CAPTURE ); } - /** - * Parses the stream of tokens in to a new set of tokens containing Tags. - * - * @param string[] $tokens - * @param TypeContext $context - * - * @return string[]|Tag[] - */ - private function parse($tokens, TypeContext $context) - { - $count = count($tokens); - $tagCount = 0; - $tags = []; - - for ($i = 1; $i < $count; $i += 2) { - $tags[] = $this->tagFactory->create($tokens[$i], $context); - $tokens[$i] = '%' . ++$tagCount . '$s'; - } - - //In order to allow "literal" inline tags, the otherwise invalid - //sequence "{@}" is changed to "@", and "{}" is changed to "}". - //"%" is escaped to "%%" because of vsprintf. - //See unit tests for examples. - for ($i = 0; $i < $count; $i += 2) { - $tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]); - } - - return [implode('', $tokens), $tags]; - } - /** * Removes the superfluous from a multi-line description. * @@ -151,14 +142,10 @@ private function parse($tokens, TypeContext $context) * * If we do not normalize the indentation then we have superfluous whitespace on the second and subsequent * lines and this may cause rendering issues when, for example, using a Markdown converter. - * - * @param string $contents - * - * @return string */ - private function removeSuperfluousStartingWhitespace($contents) + private function removeSuperfluousStartingWhitespace(string $contents): string { - $lines = explode("\n", $contents); + $lines = Utils::pregSplit("/\r\n?|\n/", $contents); // if there is only one line then we don't have lines with superfluous whitespace and // can use the contents as-is @@ -168,9 +155,9 @@ private function removeSuperfluousStartingWhitespace($contents) // determine how many whitespace characters need to be stripped $startingSpaceCount = 9999999; - for ($i = 1; $i < count($lines); $i++) { + for ($i = 1, $iMax = count($lines); $i < $iMax; ++$i) { // lines with a no length do not count as they are not indented at all - if (strlen(trim($lines[$i])) === 0) { + if (trim($lines[$i]) === '') { continue; } @@ -181,7 +168,7 @@ private function removeSuperfluousStartingWhitespace($contents) // strip the number of spaces from each line if ($startingSpaceCount > 0) { - for ($i = 1; $i < count($lines); $i++) { + for ($i = 1, $iMax = count($lines); $i < $iMax; ++$i) { $lines[$i] = substr($lines[$i], $startingSpaceCount); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php index 571ed74..6a6b472 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -14,6 +15,17 @@ use phpDocumentor\Reflection\DocBlock\Tags\Example; +use function array_slice; +use function file; +use function getcwd; +use function implode; +use function is_readable; +use function rtrim; +use function sprintf; +use function trim; + +use const DIRECTORY_SEPARATOR; + /** * Class used to find an example file's location based on a given ExampleDescriptor. */ @@ -27,18 +39,14 @@ class ExampleFinder /** * Attempts to find the example contents for the given descriptor. - * - * @param Example $example - * - * @return string */ - public function find(Example $example) + public function find(Example $example): string { $filename = $example->getFilePath(); $file = $this->getExampleFileContents($filename); if (!$file) { - return "** File not found : {$filename} **"; + return sprintf('** File not found : %s **', $filename); } return implode('', array_slice($file, $example->getStartingLine() - 1, $example->getLineCount())); @@ -46,22 +54,16 @@ public function find(Example $example) /** * Registers the project's root directory where an 'examples' folder can be expected. - * - * @param string $directory - * - * @return void */ - public function setSourceDirectory($directory = '') + public function setSourceDirectory(string $directory = ''): void { $this->sourceDirectory = $directory; } /** * Returns the project's root directory where an 'examples' folder can be expected. - * - * @return string */ - public function getSourceDirectory() + public function getSourceDirectory(): string { return $this->sourceDirectory; } @@ -71,7 +73,7 @@ public function getSourceDirectory() * * @param string[] $directories */ - public function setExampleDirectories(array $directories) + public function setExampleDirectories(array $directories): void { $this->exampleDirectories = $directories; } @@ -81,7 +83,7 @@ public function setExampleDirectories(array $directories) * * @return string[] */ - public function getExampleDirectories() + public function getExampleDirectories(): array { return $this->exampleDirectories; } @@ -97,11 +99,9 @@ public function getExampleDirectories() * 3. Checks the 'examples' folder in the current working directory for examples * 4. Checks the path relative to the current working directory for the given filename * - * @param string $filename - * - * @return string|null + * @return string[] all lines of the example file */ - private function getExampleFileContents($filename) + private function getExampleFileContents(string $filename): ?array { $normalizedPath = null; @@ -123,42 +123,31 @@ private function getExampleFileContents($filename) } } - return $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : null; + $lines = $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : false; + + return $lines !== false ? $lines : null; } /** * Get example filepath based on the example directory inside your project. - * - * @param string $file - * - * @return string */ - private function getExamplePathFromExampleDirectory($file) + private function getExamplePathFromExampleDirectory(string $file): string { return getcwd() . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $file; } /** * Returns a path to the example file in the given directory.. - * - * @param string $directory - * @param string $file - * - * @return string */ - private function constructExamplePath($directory, $file) + private function constructExamplePath(string $directory, string $file): string { return rtrim($directory, '\\/') . DIRECTORY_SEPARATOR . $file; } /** * Get example filepath based on sourcecode. - * - * @param string $file - * - * @return string */ - private function getExamplePathFromSource($file) + private function getExamplePathFromSource(string $file): string { return sprintf( '%s%s%s', diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php index 0f355f5..77e5fb5 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php @@ -1,19 +1,27 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlock; -use Webmozart\Assert\Assert; +use phpDocumentor\Reflection\DocBlock\Tags\Formatter; +use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter; + +use function sprintf; +use function str_repeat; +use function str_replace; +use function strlen; +use function wordwrap; /** * Converts a DocBlock back from an object to a complete DocComment including Asterisks. @@ -30,33 +38,37 @@ class Serializer protected $isFirstLineIndented = true; /** @var int|null The max length of a line. */ - protected $lineLength = null; + protected $lineLength; - /** @var DocBlock\Tags\Formatter A custom tag formatter. */ - protected $tagFormatter = null; + /** @var Formatter A custom tag formatter. */ + protected $tagFormatter; + /** @var string */ + private $lineEnding; /** * Create a Serializer instance. * - * @param int $indent The number of times the indent string is repeated. - * @param string $indentString The string to indent the comment with. - * @param bool $indentFirstLine Whether to indent the first line. - * @param int|null $lineLength The max length of a line or NULL to disable line wrapping. - * @param DocBlock\Tags\Formatter $tagFormatter A custom tag formatter, defaults to PassthroughFormatter. + * @param int $indent The number of times the indent string is repeated. + * @param string $indentString The string to indent the comment with. + * @param bool $indentFirstLine Whether to indent the first line. + * @param int|null $lineLength The max length of a line or NULL to disable line wrapping. + * @param Formatter $tagFormatter A custom tag formatter, defaults to PassthroughFormatter. + * @param string $lineEnding Line ending used in the output, by default \n is used. */ - public function __construct($indent = 0, $indentString = ' ', $indentFirstLine = true, $lineLength = null, $tagFormatter = null) - { - Assert::integer($indent); - Assert::string($indentString); - Assert::boolean($indentFirstLine); - Assert::nullOrInteger($lineLength); - Assert::nullOrIsInstanceOf($tagFormatter, 'phpDocumentor\Reflection\DocBlock\Tags\Formatter'); - - $this->indent = $indent; - $this->indentString = $indentString; + public function __construct( + int $indent = 0, + string $indentString = ' ', + bool $indentFirstLine = true, + ?int $lineLength = null, + ?Formatter $tagFormatter = null, + string $lineEnding = "\n" + ) { + $this->indent = $indent; + $this->indentString = $indentString; $this->isFirstLineIndented = $indentFirstLine; - $this->lineLength = $lineLength; - $this->tagFormatter = $tagFormatter ?: new DocBlock\Tags\Formatter\PassthroughFormatter(); + $this->lineLength = $lineLength; + $this->tagFormatter = $tagFormatter ?: new PassthroughFormatter(); + $this->lineEnding = $lineEnding; } /** @@ -66,9 +78,9 @@ public function __construct($indent = 0, $indentString = ' ', $indentFirstLine = * * @return string The serialized doc block. */ - public function getDocComment(DocBlock $docblock) + public function getDocComment(DocBlock $docblock): string { - $indent = str_repeat($this->indentString, $this->indent); + $indent = str_repeat($this->indentString, $this->indent); $firstIndent = $this->isFirstLineIndented ? $indent : ''; // 3 === strlen(' * ') $wrapLength = $this->lineLength ? $this->lineLength - strlen($indent) - 3 : null; @@ -81,63 +93,49 @@ public function getDocComment(DocBlock $docblock) ) ); - $comment = "{$firstIndent}/**\n"; + $comment = $firstIndent . "/**\n"; if ($text) { - $comment .= "{$indent} * {$text}\n"; - $comment .= "{$indent} *\n"; + $comment .= $indent . ' * ' . $text . "\n"; + $comment .= $indent . " *\n"; } $comment = $this->addTagBlock($docblock, $wrapLength, $indent, $comment); - $comment .= $indent . ' */'; - return $comment; + return str_replace("\n", $this->lineEnding, $comment . $indent . ' */'); } - /** - * @param $indent - * @param $text - * @return mixed - */ - private function removeTrailingSpaces($indent, $text) + private function removeTrailingSpaces(string $indent, string $text): string { - return str_replace("\n{$indent} * \n", "\n{$indent} *\n", $text); + return str_replace( + sprintf("\n%s * \n", $indent), + sprintf("\n%s *\n", $indent), + $text + ); } - /** - * @param $indent - * @param $text - * @return mixed - */ - private function addAsterisksForEachLine($indent, $text) + private function addAsterisksForEachLine(string $indent, string $text): string { - return str_replace("\n", "\n{$indent} * ", $text); + return str_replace( + "\n", + sprintf("\n%s * ", $indent), + $text + ); } - /** - * @param DocBlock $docblock - * @param $wrapLength - * @return string - */ - private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, $wrapLength) + private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, ?int $wrapLength): string { - $text = $docblock->getSummary() . ((string)$docblock->getDescription() ? "\n\n" . $docblock->getDescription() + $text = $docblock->getSummary() . ((string) $docblock->getDescription() ? "\n\n" . $docblock->getDescription() : ''); if ($wrapLength !== null) { $text = wordwrap($text, $wrapLength); + return $text; } return $text; } - /** - * @param DocBlock $docblock - * @param $wrapLength - * @param $indent - * @param $comment - * @return string - */ - private function addTagBlock(DocBlock $docblock, $wrapLength, $indent, $comment) + private function addTagBlock(DocBlock $docblock, ?int $wrapLength, string $indent, string $comment): string { foreach ($docblock->getTags() as $tag) { $tagText = $this->tagFormatter->format($tag); @@ -145,9 +143,13 @@ private function addTagBlock(DocBlock $docblock, $wrapLength, $indent, $comment) $tagText = wordwrap($tagText, $wrapLength); } - $tagText = str_replace("\n", "\n{$indent} * ", $tagText); + $tagText = str_replace( + "\n", + sprintf("\n%s * ", $indent), + $tagText + ); - $comment .= "{$indent} * {$tagText}\n"; + $comment .= sprintf("%s * %s\n", $indent, $tagText); } return $comment; diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php index 5a8143c..8d76595 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php @@ -1,23 +1,54 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; -use phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod; +use InvalidArgumentException; +use phpDocumentor\Reflection\DocBlock\Tags\Author; +use phpDocumentor\Reflection\DocBlock\Tags\Covers; +use phpDocumentor\Reflection\DocBlock\Tags\Deprecated; use phpDocumentor\Reflection\DocBlock\Tags\Generic; +use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag; +use phpDocumentor\Reflection\DocBlock\Tags\Link as LinkTag; +use phpDocumentor\Reflection\DocBlock\Tags\Method; +use phpDocumentor\Reflection\DocBlock\Tags\Param; +use phpDocumentor\Reflection\DocBlock\Tags\Property; +use phpDocumentor\Reflection\DocBlock\Tags\PropertyRead; +use phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite; +use phpDocumentor\Reflection\DocBlock\Tags\Return_; +use phpDocumentor\Reflection\DocBlock\Tags\See as SeeTag; +use phpDocumentor\Reflection\DocBlock\Tags\Since; +use phpDocumentor\Reflection\DocBlock\Tags\Source; +use phpDocumentor\Reflection\DocBlock\Tags\Throws; +use phpDocumentor\Reflection\DocBlock\Tags\Uses; +use phpDocumentor\Reflection\DocBlock\Tags\Var_; +use phpDocumentor\Reflection\DocBlock\Tags\Version; use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use ReflectionMethod; +use ReflectionNamedType; +use ReflectionParameter; use Webmozart\Assert\Assert; +use function array_merge; +use function array_slice; +use function call_user_func_array; +use function count; +use function get_class; +use function preg_match; +use function strpos; +use function trim; + /** * Creates a Tag object given the contents of a tag. * @@ -38,41 +69,47 @@ final class StandardTagFactory implements TagFactory { /** PCRE regular expression matching a tag name. */ - const REGEX_TAGNAME = '[\w\-\_\\\\]+'; + public const REGEX_TAGNAME = '[\w\-\_\\\\:]+'; /** - * @var string[] An array with a tag as a key, and an FQCN to a class that handles it as an array value. + * @var array<class-string<Tag>> An array with a tag as a key, and an + * FQCN to a class that handles it as an array value. */ private $tagHandlerMappings = [ - 'author' => '\phpDocumentor\Reflection\DocBlock\Tags\Author', - 'covers' => '\phpDocumentor\Reflection\DocBlock\Tags\Covers', - 'deprecated' => '\phpDocumentor\Reflection\DocBlock\Tags\Deprecated', + 'author' => Author::class, + 'covers' => Covers::class, + 'deprecated' => Deprecated::class, // 'example' => '\phpDocumentor\Reflection\DocBlock\Tags\Example', - 'link' => '\phpDocumentor\Reflection\DocBlock\Tags\Link', - 'method' => '\phpDocumentor\Reflection\DocBlock\Tags\Method', - 'param' => '\phpDocumentor\Reflection\DocBlock\Tags\Param', - 'property-read' => '\phpDocumentor\Reflection\DocBlock\Tags\PropertyRead', - 'property' => '\phpDocumentor\Reflection\DocBlock\Tags\Property', - 'property-write' => '\phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite', - 'return' => '\phpDocumentor\Reflection\DocBlock\Tags\Return_', - 'see' => '\phpDocumentor\Reflection\DocBlock\Tags\See', - 'since' => '\phpDocumentor\Reflection\DocBlock\Tags\Since', - 'source' => '\phpDocumentor\Reflection\DocBlock\Tags\Source', - 'throw' => '\phpDocumentor\Reflection\DocBlock\Tags\Throws', - 'throws' => '\phpDocumentor\Reflection\DocBlock\Tags\Throws', - 'uses' => '\phpDocumentor\Reflection\DocBlock\Tags\Uses', - 'var' => '\phpDocumentor\Reflection\DocBlock\Tags\Var_', - 'version' => '\phpDocumentor\Reflection\DocBlock\Tags\Version' + 'link' => LinkTag::class, + 'method' => Method::class, + 'param' => Param::class, + 'property-read' => PropertyRead::class, + 'property' => Property::class, + 'property-write' => PropertyWrite::class, + 'return' => Return_::class, + 'see' => SeeTag::class, + 'since' => Since::class, + 'source' => Source::class, + 'throw' => Throws::class, + 'throws' => Throws::class, + 'uses' => Uses::class, + 'var' => Var_::class, + 'version' => Version::class, ]; /** - * @var \ReflectionParameter[][] a lazy-loading cache containing parameters for each tagHandler that has been used. + * @var array<class-string<Tag>> An array with a anotation s a key, and an + * FQCN to a class that handles it as an array value. */ - private $tagHandlerParameterCache = []; + private $annotationMappings = []; /** - * @var FqsenResolver + * @var ReflectionParameter[][] a lazy-loading cache containing parameters + * for each tagHandler that has been used. */ + private $tagHandlerParameterCache = []; + + /** @var FqsenResolver */ private $fqsenResolver; /** @@ -87,12 +124,11 @@ final class StandardTagFactory implements TagFactory * If no tag handlers are provided than the default list in the {@see self::$tagHandlerMappings} property * is used. * - * @param FqsenResolver $fqsenResolver - * @param string[] $tagHandlers - * * @see self::registerTagHandler() to add a new tag handler to the existing default list. + * + * @param array<class-string<Tag>> $tagHandlers */ - public function __construct(FqsenResolver $fqsenResolver, array $tagHandlers = null) + public function __construct(FqsenResolver $fqsenResolver, ?array $tagHandlers = null) { $this->fqsenResolver = $fqsenResolver; if ($tagHandlers !== null) { @@ -102,54 +138,38 @@ public function __construct(FqsenResolver $fqsenResolver, array $tagHandlers = n $this->addService($fqsenResolver, FqsenResolver::class); } - /** - * {@inheritDoc} - */ - public function create($tagLine, TypeContext $context = null) + public function create(string $tagLine, ?TypeContext $context = null): Tag { - if (! $context) { + if (!$context) { $context = new TypeContext(''); } - list($tagName, $tagBody) = $this->extractTagParts($tagLine); - - if ($tagBody !== '' && $tagBody[0] === '[') { - throw new \InvalidArgumentException( - 'The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors' - ); - } + [$tagName, $tagBody] = $this->extractTagParts($tagLine); - return $this->createTag($tagBody, $tagName, $context); + return $this->createTag(trim($tagBody), $tagName, $context); } /** - * {@inheritDoc} + * @param mixed $value */ - public function addParameter($name, $value) + public function addParameter(string $name, $value): void { $this->serviceLocator[$name] = $value; } - /** - * {@inheritDoc} - */ - public function addService($service, $alias = null) + public function addService(object $service, ?string $alias = null): void { $this->serviceLocator[$alias ?: get_class($service)] = $service; } - /** - * {@inheritDoc} - */ - public function registerTagHandler($tagName, $handler) + public function registerTagHandler(string $tagName, string $handler): void { Assert::stringNotEmpty($tagName); - Assert::stringNotEmpty($handler); Assert::classExists($handler); - Assert::implementsInterface($handler, StaticMethod::class); + Assert::implementsInterface($handler, Tag::class); if (strpos($tagName, '\\') && $tagName[0] !== '\\') { - throw new \InvalidArgumentException( + throw new InvalidArgumentException( 'A namespaced tag must have a leading backslash as it must be fully qualified' ); } @@ -160,15 +180,13 @@ public function registerTagHandler($tagName, $handler) /** * Extracts all components for a tag. * - * @param string $tagLine - * * @return string[] */ - private function extractTagParts($tagLine) + private function extractTagParts(string $tagLine): array { $matches = []; - if (! preg_match('/^@(' . self::REGEX_TAGNAME . ')(?:\s*([^\s].*)|$)/us', $tagLine, $matches)) { - throw new \InvalidArgumentException( + if (!preg_match('/^@(' . self::REGEX_TAGNAME . ')((?:[\s\(\{])\s*([^\s].*)|$)/us', $tagLine, $matches)) { + throw new InvalidArgumentException( 'The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors' ); } @@ -183,14 +201,8 @@ private function extractTagParts($tagLine) /** * Creates a new tag object with the given name and body or returns null if the tag name was recognized but the * body was invalid. - * - * @param string $body - * @param string $name - * @param TypeContext $context - * - * @return Tag|null */ - private function createTag($body, $name, TypeContext $context) + private function createTag(string $body, string $name, TypeContext $context): Tag { $handlerClassName = $this->findHandlerClassName($name, $context); $arguments = $this->getArgumentsForParametersFromWiring( @@ -198,28 +210,34 @@ private function createTag($body, $name, TypeContext $context) $this->getServiceLocatorWithDynamicParameters($context, $name, $body) ); - return call_user_func_array([$handlerClassName, 'create'], $arguments); + try { + $callable = [$handlerClassName, 'create']; + Assert::isCallable($callable); + /** @phpstan-var callable(string): ?Tag $callable */ + $tag = call_user_func_array($callable, $arguments); + + return $tag ?? InvalidTag::create($body, $name); + } catch (InvalidArgumentException $e) { + return InvalidTag::create($body, $name)->withError($e); + } } /** * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`). * - * @param string $tagName - * @param TypeContext $context - * - * @return string + * @return class-string<Tag> */ - private function findHandlerClassName($tagName, TypeContext $context) + private function findHandlerClassName(string $tagName, TypeContext $context): string { $handlerClassName = Generic::class; if (isset($this->tagHandlerMappings[$tagName])) { $handlerClassName = $this->tagHandlerMappings[$tagName]; } elseif ($this->isAnnotation($tagName)) { // TODO: Annotation support is planned for a later stage and as such is disabled for now - // $tagName = (string)$this->fqsenResolver->resolve($tagName, $context); - // if (isset($this->annotationMappings[$tagName])) { - // $handlerClassName = $this->annotationMappings[$tagName]; - // } + $tagName = (string) $this->fqsenResolver->resolve($tagName, $context); + if (isset($this->annotationMappings[$tagName])) { + $handlerClassName = $this->annotationMappings[$tagName]; + } } return $handlerClassName; @@ -228,17 +246,28 @@ private function findHandlerClassName($tagName, TypeContext $context) /** * Retrieves the arguments that need to be passed to the Factory Method with the given Parameters. * - * @param \ReflectionParameter[] $parameters - * @param mixed[] $locator + * @param ReflectionParameter[] $parameters + * @param mixed[] $locator * * @return mixed[] A series of values that can be passed to the Factory Method of the tag whose parameters * is provided with this method. */ - private function getArgumentsForParametersFromWiring($parameters, $locator) + private function getArgumentsForParametersFromWiring(array $parameters, array $locator): array { $arguments = []; - foreach ($parameters as $index => $parameter) { - $typeHint = $parameter->getClass() ? $parameter->getClass()->getName() : null; + foreach ($parameters as $parameter) { + $type = $parameter->getType(); + $typeHint = null; + if ($type instanceof ReflectionNamedType) { + $typeHint = $type->getName(); + if ($typeHint === 'self') { + $declaringClass = $parameter->getDeclaringClass(); + if ($declaringClass !== null) { + $typeHint = $declaringClass->getName(); + } + } + } + if (isset($locator[$typeHint])) { $arguments[] = $locator[$typeHint]; continue; @@ -260,14 +289,14 @@ private function getArgumentsForParametersFromWiring($parameters, $locator) * Retrieves a series of ReflectionParameter objects for the static 'create' method of the given * tag handler class name. * - * @param string $handlerClassName + * @param class-string $handlerClassName * - * @return \ReflectionParameter[] + * @return ReflectionParameter[] */ - private function fetchParametersForHandlerFactoryMethod($handlerClassName) + private function fetchParametersForHandlerFactoryMethod(string $handlerClassName): array { - if (! isset($this->tagHandlerParameterCache[$handlerClassName])) { - $methodReflection = new \ReflectionMethod($handlerClassName, 'create'); + if (!isset($this->tagHandlerParameterCache[$handlerClassName])) { + $methodReflection = new ReflectionMethod($handlerClassName, 'create'); $this->tagHandlerParameterCache[$handlerClassName] = $methodReflection->getParameters(); } @@ -275,39 +304,39 @@ private function fetchParametersForHandlerFactoryMethod($handlerClassName) } /** - * Returns a copy of this class' Service Locator with added dynamic parameters, such as the tag's name, body and - * Context. + * Returns a copy of this class' Service Locator with added dynamic parameters, + * such as the tag's name, body and Context. * - * @param TypeContext $context The Context (namespace and aliasses) that may be passed and is used to resolve FQSENs. - * @param string $tagName The name of the tag that may be passed onto the factory method of the Tag class. - * @param string $tagBody The body of the tag that may be passed onto the factory method of the Tag class. + * @param TypeContext $context The Context (namespace and aliasses) that may be + * passed and is used to resolve FQSENs. + * @param string $tagName The name of the tag that may be + * passed onto the factory method of the Tag class. + * @param string $tagBody The body of the tag that may be + * passed onto the factory method of the Tag class. * * @return mixed[] */ - private function getServiceLocatorWithDynamicParameters(TypeContext $context, $tagName, $tagBody) - { - $locator = array_merge( + private function getServiceLocatorWithDynamicParameters( + TypeContext $context, + string $tagName, + string $tagBody + ): array { + return array_merge( $this->serviceLocator, [ - 'name' => $tagName, - 'body' => $tagBody, - TypeContext::class => $context + 'name' => $tagName, + 'body' => $tagBody, + TypeContext::class => $context, ] ); - - return $locator; } /** * Returns whether the given tag belongs to an annotation. * - * @param string $tagContent - * * @todo this method should be populated once we implement Annotation notation support. - * - * @return bool */ - private function isAnnotation($tagContent) + private function isAnnotation(string $tagContent): bool { // 1. Contains a namespace separator // 2. Contains parenthesis diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php index e765367..7cf07b4 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,11 +17,15 @@ interface Tag { - public function getName(); + public function getName(): string; - public static function create($body); + /** + * @return Tag|mixed Class that implements Tag + * @phpstan-return ?Tag + */ + public static function create(string $body); - public function render(Formatter $formatter = null); + public function render(?Formatter $formatter = null): string; - public function __toString(); + public function __toString(): string; } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php index 3c1d113..c0868dc 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php @@ -1,17 +1,19 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; +use InvalidArgumentException; use phpDocumentor\Reflection\Types\Context as TypeContext; interface TagFactory @@ -34,60 +36,49 @@ interface TagFactory * * These parameters are injected at the last moment and will override any existing parameter with those names. * - * @param string $name - * @param mixed $value - * - * @return void + * @param mixed $value */ - public function addParameter($name, $value); + public function addParameter(string $name, $value): void; /** - * Registers a service with the Service Locator using the FQCN of the class or the alias, if provided. - * - * When calling a tag's "create" method we always check the signature for dependencies to inject. If a parameter - * has a typehint then the ServiceLocator is queried to see if a Service is registered for that typehint. + * Factory method responsible for instantiating the correct sub type. * - * Because interfaces are regularly used as type-hints this method provides an alias parameter; if the FQCN of the - * interface is passed as alias then every time that interface is requested the provided service will be returned. + * @param string $tagLine The text for this tag, including description. * - * @param object $service - * @param string $alias + * @return Tag A new tag object. * - * @return void + * @throws InvalidArgumentException If an invalid tag line was presented. */ - public function addService($service); + public function create(string $tagLine, ?TypeContext $context = null): Tag; /** - * Factory method responsible for instantiating the correct sub type. - * - * @param string $tagLine The text for this tag, including description. - * @param TypeContext $context + * Registers a service with the Service Locator using the FQCN of the class or the alias, if provided. * - * @throws \InvalidArgumentException if an invalid tag line was presented. + * When calling a tag's "create" method we always check the signature for dependencies to inject. If a parameter + * has a typehint then the ServiceLocator is queried to see if a Service is registered for that typehint. * - * @return Tag A new tag object. + * Because interfaces are regularly used as type-hints this method provides an alias parameter; if the FQCN of the + * interface is passed as alias then every time that interface is requested the provided service will be returned. */ - public function create($tagLine, TypeContext $context = null); + public function addService(object $service): void; /** * Registers a handler for tags. * - * If you want to use your own tags then you can use this method to instruct the TagFactory to register the name - * of a tag with the FQCN of a 'Tag Handler'. The Tag handler should implement the {@see Tag} interface (and thus - * the create method). - * - * @param string $tagName Name of tag to register a handler for. When registering a namespaced tag, the full - * name, along with a prefixing slash MUST be provided. - * @param string $handler FQCN of handler. + * If you want to use your own tags then you can use this method to instruct the TagFactory + * to register the name of a tag with the FQCN of a 'Tag Handler'. The Tag handler should implement + * the {@see Tag} interface (and thus the create method). * - * @throws \InvalidArgumentException if the tag name is not a string - * @throws \InvalidArgumentException if the tag name is namespaced (contains backslashes) but does not start with - * a backslash - * @throws \InvalidArgumentException if the handler is not a string - * @throws \InvalidArgumentException if the handler is not an existing class - * @throws \InvalidArgumentException if the handler does not implement the {@see Tag} interface + * @param string $tagName Name of tag to register a handler for. When registering a namespaced + * tag, the full name, along with a prefixing slash MUST be provided. + * @param class-string<Tag> $handler FQCN of handler. * - * @return void + * @throws InvalidArgumentException If the tag name is not a string. + * @throws InvalidArgumentException If the tag name is namespaced (contains backslashes) but + * does not start with a backslash. + * @throws InvalidArgumentException If the handler is not a string. + * @throws InvalidArgumentException If the handler is not an existing class. + * @throws InvalidArgumentException If the handler does not implement the {@see Tag} interface. */ - public function registerTagHandler($tagName, $handler); + public function registerTagHandler(string $tagName, string $handler): void; } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php index 29d7f1d..ae09ecf 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php @@ -1,18 +1,25 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; -use Webmozart\Assert\Assert; +use InvalidArgumentException; + +use function filter_var; +use function preg_match; +use function trim; + +use const FILTER_VALIDATE_EMAIL; /** * Reflection class for an {@}author tag in a Docblock. @@ -23,23 +30,18 @@ final class Author extends BaseTag implements Factory\StaticMethod protected $name = 'author'; /** @var string The name of the author */ - private $authorName = ''; + private $authorName; /** @var string The email of the author */ - private $authorEmail = ''; + private $authorEmail; /** * Initializes this tag with the author name and e-mail. - * - * @param string $authorName - * @param string $authorEmail */ - public function __construct($authorName, $authorEmail) + public function __construct(string $authorName, string $authorEmail) { - Assert::string($authorName); - Assert::string($authorEmail); if ($authorEmail && !filter_var($authorEmail, FILTER_VALIDATE_EMAIL)) { - throw new \InvalidArgumentException('The author tag does not have a valid e-mail address'); + throw new InvalidArgumentException('The author tag does not have a valid e-mail address'); } $this->authorName = $authorName; @@ -51,7 +53,7 @@ public function __construct($authorName, $authorEmail) * * @return string The author's name. */ - public function getAuthorName() + public function getAuthorName(): string { return $this->authorName; } @@ -61,39 +63,39 @@ public function getAuthorName() * * @return string The author's email. */ - public function getEmail() + public function getEmail(): string { return $this->authorEmail; } /** * Returns this tag in string form. - * - * @return string */ - public function __toString() + public function __toString(): string { - return $this->authorName . (strlen($this->authorEmail) ? ' <' . $this->authorEmail . '>' : ''); + if ($this->authorEmail) { + $authorEmail = '<' . $this->authorEmail . '>'; + } else { + $authorEmail = ''; + } + + $authorName = $this->authorName; + + return $authorName . ($authorEmail !== '' ? ($authorName !== '' ? ' ' : '') . $authorEmail : ''); } /** - * Attempts to create a new Author object based on †he tag body. - * - * @param string $body - * - * @return static + * Attempts to create a new Author object based on the tag body. */ - public static function create($body) + public static function create(string $body): ?self { - Assert::string($body); - $splitTagContent = preg_match('/^([^\<]*)(?:\<([^\>]*)\>)?$/u', $body, $matches); if (!$splitTagContent) { return null; } $authorName = trim($matches[1]); - $email = isset($matches[2]) ? trim($matches[2]) : ''; + $email = isset($matches[2]) ? trim($matches[2]) : ''; return new static($authorName, $email); } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php index 14bb717..a28d5bf 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php @@ -1,13 +1,14 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -31,17 +32,17 @@ abstract class BaseTag implements DocBlock\Tag * * @return string The name of this tag. */ - public function getName() + public function getName(): string { return $this->name; } - public function getDescription() + public function getDescription(): ?Description { return $this->description; } - public function render(Formatter $formatter = null) + public function render(?Formatter $formatter = null): string { if ($formatter === null) { $formatter = new Formatter\PassthroughFormatter(); diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php index 8d65403..3eff9d8 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php @@ -1,13 +1,14 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -17,67 +18,84 @@ use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Utils; use Webmozart\Assert\Assert; +use function array_key_exists; +use function explode; + /** * Reflection class for a @covers tag in a Docblock. */ final class Covers extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'covers'; /** @var Fqsen */ - private $refers = null; + private $refers; /** * Initializes this tag. - * - * @param Fqsen $refers - * @param Description $description */ - public function __construct(Fqsen $refers, Description $description = null) + public function __construct(Fqsen $refers, ?Description $description = null) { - $this->refers = $refers; + $this->refers = $refers; $this->description = $description; } - /** - * {@inheritdoc} - */ public static function create( - $body, - DescriptionFactory $descriptionFactory = null, - FqsenResolver $resolver = null, - TypeContext $context = null - ) { - Assert::string($body); - Assert::notEmpty($body); + string $body, + ?DescriptionFactory $descriptionFactory = null, + ?FqsenResolver $resolver = null, + ?TypeContext $context = null + ): self { + Assert::stringNotEmpty($body); + Assert::notNull($descriptionFactory); + Assert::notNull($resolver); - $parts = preg_split('/\s+/Su', $body, 2); + $parts = Utils::pregSplit('/\s+/Su', $body, 2); return new static( - $resolver->resolve($parts[0], $context), - $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context) + self::resolveFqsen($parts[0], $resolver, $context), + $descriptionFactory->create($parts[1] ?? '', $context) ); } + private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context): Fqsen + { + Assert::notNull($fqsenResolver); + $fqsenParts = explode('::', $parts); + $resolved = $fqsenResolver->resolve($fqsenParts[0], $context); + + if (!array_key_exists(1, $fqsenParts)) { + return $resolved; + } + + return new Fqsen($resolved . '::' . $fqsenParts[1]); + } + /** * Returns the structural element this tag refers to. - * - * @return Fqsen */ - public function getReference() + public function getReference(): Fqsen { return $this->refers; } /** * Returns a string representation of this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return $this->refers . ($this->description ? ' ' . $this->description->render() : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $refers = (string) $this->refers; + + return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php index 822c305..dbcad28 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -17,18 +18,21 @@ use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; + /** * Reflection class for a {@}deprecated tag in a Docblock. */ final class Deprecated extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'deprecated'; /** * PCRE regular expression matching a version vector. * Assumes the "x" modifier. */ - const REGEX_VECTOR = '(?: + public const REGEX_VECTOR = '(?: # Normal release vectors. \d\S* | @@ -40,23 +44,25 @@ final class Deprecated extends BaseTag implements Factory\StaticMethod [^\s\:]+\:\s*\$[^\$]+\$ )'; - /** @var string The version vector. */ - private $version = ''; + /** @var string|null The version vector. */ + private $version; - public function __construct($version = null, Description $description = null) + public function __construct(?string $version = null, ?Description $description = null) { - Assert::nullOrStringNotEmpty($version); + Assert::nullOrNotEmpty($version); - $this->version = $version; + $this->version = $version; $this->description = $description; } /** * @return static */ - public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) - { - Assert::nullOrString($body); + public static function create( + ?string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { if (empty($body)) { return new static(); } @@ -65,33 +71,39 @@ public static function create($body, DescriptionFactory $descriptionFactory = nu if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { return new static( null, - null !== $descriptionFactory ? $descriptionFactory->create($body, $context) : null + $descriptionFactory !== null ? $descriptionFactory->create($body, $context) : null ); } + Assert::notNull($descriptionFactory); + return new static( $matches[1], - $descriptionFactory->create(isset($matches[2]) ? $matches[2] : '', $context) + $descriptionFactory->create($matches[2] ?? '', $context) ); } /** * Gets the version section of the tag. - * - * @return string */ - public function getVersion() + public function getVersion(): ?string { return $this->version; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return $this->version . ($this->description ? ' ' . $this->description->render() : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $version = (string) $this->version; + + return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php index ecb199b..825355a 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php @@ -1,103 +1,110 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; -use phpDocumentor\Reflection\DocBlock\Description; use phpDocumentor\Reflection\DocBlock\Tag; use Webmozart\Assert\Assert; +use function array_key_exists; +use function preg_match; +use function rawurlencode; +use function str_replace; +use function strpos; +use function trim; + /** * Reflection class for a {@}example tag in a Docblock. */ -final class Example extends BaseTag +final class Example implements Tag, Factory\StaticMethod { - /** - * @var string Path to a file to use as an example. May also be an absolute URI. - */ + /** @var string Path to a file to use as an example. May also be an absolute URI. */ private $filePath; /** * @var bool Whether the file path component represents an URI. This determines how the file portion * appears at {@link getContent()}. */ - private $isURI = false; + private $isURI; - /** - * @var int - */ + /** @var int */ private $startingLine; - /** - * @var int - */ + /** @var int */ private $lineCount; - public function __construct($filePath, $isURI, $startingLine, $lineCount, $description) - { - Assert::notEmpty($filePath); - Assert::integer($startingLine); - Assert::greaterThanEq($startingLine, 0); - - $this->filePath = $filePath; + /** @var string|null */ + private $content; + + public function __construct( + string $filePath, + bool $isURI, + int $startingLine, + int $lineCount, + ?string $content + ) { + Assert::stringNotEmpty($filePath); + Assert::greaterThanEq($startingLine, 1); + Assert::greaterThanEq($lineCount, 0); + + $this->filePath = $filePath; $this->startingLine = $startingLine; - $this->lineCount = $lineCount; - $this->name = 'example'; - if ($description !== null) { - $this->description = trim($description); + $this->lineCount = $lineCount; + if ($content !== null) { + $this->content = trim($content); } $this->isURI = $isURI; } - /** - * {@inheritdoc} - */ - public function getContent() + public function getContent(): string { - if (null === $this->description) { - $filePath = '"' . $this->filePath . '"'; + if ($this->content === null || $this->content === '') { + $filePath = $this->filePath; if ($this->isURI) { $filePath = $this->isUriRelative($this->filePath) ? str_replace('%2F', '/', rawurlencode($this->filePath)) - :$this->filePath; + : $this->filePath; } - return trim($filePath . ' ' . parent::getDescription()); + return trim($filePath); } - return $this->description; + return $this->content; } - /** - * {@inheritdoc} - */ - public static function create($body) + public function getDescription(): ?string + { + return $this->content; + } + + public static function create(string $body): ?Tag { // File component: File path in quotes or File URI / Source information - if (! preg_match('/^(?:\"([^\"]+)\"|(\S+))(?:\s+(.*))?$/sux', $body, $matches)) { + if (!preg_match('/^\s*(?:(\"[^\"]+\")|(\S+))(?:\s+(.*))?$/sux', $body, $matches)) { return null; } $filePath = null; $fileUri = null; - if ('' !== $matches[1]) { + if ($matches[1] !== '') { $filePath = $matches[1]; } else { $fileUri = $matches[2]; } $startingLine = 1; - $lineCount = null; + $lineCount = 0; $description = null; if (array_key_exists(3, $matches)) { @@ -105,9 +112,9 @@ public static function create($body) // Starting line / Number of lines / Description if (preg_match('/^([1-9]\d*)(?:\s+((?1))\s*)?(.*)$/sux', $matches[3], $contentMatches)) { - $startingLine = (int)$contentMatches[1]; - if (isset($contentMatches[2]) && $contentMatches[2] !== '') { - $lineCount = (int)$contentMatches[2]; + $startingLine = (int) $contentMatches[1]; + if (isset($contentMatches[2])) { + $lineCount = (int) $contentMatches[2]; } if (array_key_exists(3, $contentMatches)) { @@ -117,7 +124,7 @@ public static function create($body) } return new static( - $filePath !== null?$filePath:$fileUri, + $filePath ?? ($fileUri ?? ''), $fileUri !== null, $startingLine, $lineCount, @@ -131,46 +138,63 @@ public static function create($body) * @return string Path to a file to use as an example. * May also be an absolute URI. */ - public function getFilePath() + public function getFilePath(): string { - return $this->filePath; + return trim($this->filePath, '"'); } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return $this->filePath . ($this->description ? ' ' . $this->description : ''); + $filePath = $this->filePath; + $isDefaultLine = $this->startingLine === 1 && $this->lineCount === 0; + $startingLine = !$isDefaultLine ? (string) $this->startingLine : ''; + $lineCount = !$isDefaultLine ? (string) $this->lineCount : ''; + $content = (string) $this->content; + + return $filePath + . ($startingLine !== '' + ? ($filePath !== '' ? ' ' : '') . $startingLine + : '') + . ($lineCount !== '' + ? ($filePath !== '' || $startingLine !== '' ? ' ' : '') . $lineCount + : '') + . ($content !== '' + ? ($filePath !== '' || $startingLine !== '' || $lineCount !== '' ? ' ' : '') . $content + : ''); } /** * Returns true if the provided URI is relative or contains a complete scheme (and thus is absolute). - * - * @param string $uri - * - * @return bool */ - private function isUriRelative($uri) + private function isUriRelative(string $uri): bool { - return false === strpos($uri, ':'); + return strpos($uri, ':') === false; } - /** - * @return int - */ - public function getStartingLine() + public function getStartingLine(): int { return $this->startingLine; } - /** - * @return int - */ - public function getLineCount() + public function getLineCount(): int { return $this->lineCount; } + + public function getName(): string + { + return 'example'; + } + + public function render(?Formatter $formatter = null): string + { + if ($formatter === null) { + $formatter = new Formatter\PassthroughFormatter(); + } + + return $formatter->format($this); + } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php index 98aea45..f6f0bb5 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php @@ -1,18 +1,25 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags\Factory; +/** + * @deprecated This contract is totally covered by Tag contract. Every class using StaticMethod also use Tag + */ interface StaticMethod { - public static function create($body); + /** + * @return mixed + */ + public static function create(string $body); } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Strategy.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Strategy.php deleted file mode 100644 index b9ca0b8..0000000 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Strategy.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php -/** - * This file is part of phpDocumentor. - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org - */ - -namespace phpDocumentor\Reflection\DocBlock\Tags\Factory; - -interface Strategy -{ - public function create($body); -} diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php index 64b2c60..36b9983 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,10 +19,6 @@ interface Formatter { /** * Formats a tag into a string representation according to a specific format, such as Markdown. - * - * @param Tag $tag - * - * @return string */ - public function format(Tag $tag); + public function format(Tag $tag): string; } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php index ceb40cc..9464434 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php @@ -1,13 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @author Jan Schneider <jan@horde.org> - * @copyright 2017 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,14 +16,16 @@ use phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tags\Formatter; +use function max; +use function str_repeat; +use function strlen; + class AlignFormatter implements Formatter { /** @var int The maximum tag name length. */ protected $maxLen = 0; /** - * Constructor. - * * @param Tag[] $tags All tags that should later be aligned with the formatter. */ public function __construct(array $tags) @@ -35,13 +37,14 @@ public function __construct(array $tags) /** * Formats the given tag to return a simple plain text version. - * - * @param Tag $tag - * - * @return string */ - public function format(Tag $tag) + public function format(Tag $tag): string { - return '@' . $tag->getName() . str_repeat(' ', $this->maxLen - strlen($tag->getName()) + 1) . (string)$tag; + return '@' . $tag->getName() . + str_repeat( + ' ', + $this->maxLen - strlen($tag->getName()) + 1 + ) . + $tag; } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php index 4e2c576..2afdfe5 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -15,17 +16,15 @@ use phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tags\Formatter; +use function trim; + class PassthroughFormatter implements Formatter { /** * Formats the given tag to return a simple plain text version. - * - * @param Tag $tag - * - * @return string */ - public function format(Tag $tag) + public function format(Tag $tag): string { - return trim('@' . $tag->getName() . ' ' . (string)$tag); + return trim('@' . $tag->getName() . ' ' . $tag); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php index e4c53e0..bc1ab10 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php @@ -1,88 +1,86 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; +use InvalidArgumentException; use phpDocumentor\Reflection\DocBlock\Description; use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\DocBlock\StandardTagFactory; use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; + /** * Parses a tag definition for a DocBlock. */ -class Generic extends BaseTag implements Factory\StaticMethod +final class Generic extends BaseTag implements Factory\StaticMethod { /** * Parses a tag and populates the member variables. * - * @param string $name Name of the tag. + * @param string $name Name of the tag. * @param Description $description The contents of the given tag. */ - public function __construct($name, Description $description = null) + public function __construct(string $name, ?Description $description = null) { $this->validateTagName($name); - $this->name = $name; + $this->name = $name; $this->description = $description; } /** * Creates a new tag that represents any unknown tag type. * - * @param string $body - * @param string $name - * @param DescriptionFactory $descriptionFactory - * @param TypeContext $context - * * @return static */ public static function create( - $body, - $name = '', - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { - Assert::string($body); + string $body, + string $name = '', + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { Assert::stringNotEmpty($name); Assert::notNull($descriptionFactory); - $description = $descriptionFactory && $body ? $descriptionFactory->create($body, $context) : null; + $description = $body !== '' ? $descriptionFactory->create($body, $context) : null; return new static($name, $description); } /** * Returns the tag as a serialized string - * - * @return string */ - public function __toString() + public function __toString(): string { - return ($this->description ? $this->description->render() : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + return $description; } /** * Validates if the tag name matches the expected format, otherwise throws an exception. - * - * @param string $name - * - * @return void */ - private function validateTagName($name) + private function validateTagName(string $name): void { - if (! preg_match('/^' . StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) { - throw new \InvalidArgumentException( + if (!preg_match('/^' . StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) { + throw new InvalidArgumentException( 'The tag name "' . $name . '" is not wellformed. Tags may only consist of letters, underscores, ' . 'hyphens and backslashes.' ); diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php new file mode 100644 index 0000000..4e6abb8 --- /dev/null +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/InvalidTag.php @@ -0,0 +1,145 @@ +<?php + +declare(strict_types=1); + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use Closure; +use Exception; +use phpDocumentor\Reflection\DocBlock\Tag; +use ReflectionClass; +use ReflectionException; +use ReflectionFunction; +use Throwable; + +use function array_map; +use function get_class; +use function get_resource_type; +use function is_array; +use function is_object; +use function is_resource; +use function sprintf; + +/** + * This class represents an exception during the tag creation + * + * Since the internals of the library are relaying on the correct syntax of a docblock + * we cannot simply throw exceptions at all time because the exceptions will break the creation of a + * docklock. Just silently ignore the exceptions is not an option because the user as an issue to fix. + * + * This tag holds that error information until a using application is able to display it. The object wil just behave + * like any normal tag. So the normal application flow will not break. + */ +final class InvalidTag implements Tag +{ + /** @var string */ + private $name; + + /** @var string */ + private $body; + + /** @var Throwable|null */ + private $throwable; + + private function __construct(string $name, string $body) + { + $this->name = $name; + $this->body = $body; + } + + public function getException(): ?Throwable + { + return $this->throwable; + } + + public function getName(): string + { + return $this->name; + } + + public static function create(string $body, string $name = ''): self + { + return new self($name, $body); + } + + public function withError(Throwable $exception): self + { + $this->flattenExceptionBacktrace($exception); + $tag = new self($this->name, $this->body); + $tag->throwable = $exception; + + return $tag; + } + + /** + * Removes all complex types from backtrace + * + * Not all objects are serializable. So we need to remove them from the + * stored exception to be sure that we do not break existing library usage. + */ + private function flattenExceptionBacktrace(Throwable $exception): void + { + $traceProperty = (new ReflectionClass(Exception::class))->getProperty('trace'); + $traceProperty->setAccessible(true); + + do { + $trace = $exception->getTrace(); + if (isset($trace[0]['args'])) { + $trace = array_map( + function (array $call): array { + $call['args'] = array_map([$this, 'flattenArguments'], $call['args'] ?? []); + + return $call; + }, + $trace + ); + } + + $traceProperty->setValue($exception, $trace); + $exception = $exception->getPrevious(); + } while ($exception !== null); + + $traceProperty->setAccessible(false); + } + + /** + * @param mixed $value + * + * @return mixed + * + * @throws ReflectionException + */ + private function flattenArguments($value) + { + if ($value instanceof Closure) { + $closureReflection = new ReflectionFunction($value); + $value = sprintf( + '(Closure at %s:%s)', + $closureReflection->getFileName(), + $closureReflection->getStartLine() + ); + } elseif (is_object($value)) { + $value = sprintf('object(%s)', get_class($value)); + } elseif (is_resource($value)) { + $value = sprintf('resource(%s)', get_resource_type($value)); + } elseif (is_array($value)) { + $value = array_map([$this, 'flattenArguments'], $value); + } + + return $value; + } + + public function render(?Formatter $formatter = null): string + { + if ($formatter === null) { + $formatter = new Formatter\PassthroughFormatter(); + } + + return $formatter->format($this); + } + + public function __toString(): string + { + return $this->body; + } +} diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php index 9c0e367..ee242e3 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php @@ -1,13 +1,14 @@ <?php + +declare(strict_types=1); + /** - * phpDocumentor + * This file is part of phpDocumentor. * - * PHP Version 5.3 + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. * - * @author Ben Selby <benmatselby@gmail.com> - * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -15,63 +16,63 @@ use phpDocumentor\Reflection\DocBlock\Description; use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Utils; use Webmozart\Assert\Assert; /** - * Reflection class for a @link tag in a Docblock. + * Reflection class for a {@}link tag in a Docblock. */ final class Link extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'link'; /** @var string */ - private $link = ''; + private $link; /** * Initializes a link to a URL. - * - * @param string $link - * @param Description $description */ - public function __construct($link, Description $description = null) + public function __construct(string $link, ?Description $description = null) { - Assert::string($link); - - $this->link = $link; + $this->link = $link; $this->description = $description; } - /** - * {@inheritdoc} - */ - public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) - { - Assert::string($body); + public static function create( + string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { Assert::notNull($descriptionFactory); - $parts = preg_split('/\s+/Su', $body, 2); + $parts = Utils::pregSplit('/\s+/Su', $body, 2); $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; return new static($parts[0], $description); } /** - * Gets the link - * - * @return string - */ - public function getLink() + * Gets the link + */ + public function getLink(): string { return $this->link; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return $this->link . ($this->description ? ' ' . $this->description->render() : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $link = $this->link; + + return $link . ($description !== '' ? ($link !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php index 7522529..f08bfff 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php @@ -1,53 +1,74 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; +use InvalidArgumentException; use phpDocumentor\Reflection\DocBlock\Description; use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\Type; use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Types\Mixed_; use phpDocumentor\Reflection\Types\Void_; use Webmozart\Assert\Assert; +use function array_keys; +use function explode; +use function implode; +use function is_string; +use function preg_match; +use function sort; +use function strpos; +use function substr; +use function trim; +use function var_export; + /** * Reflection class for an {@}method in a Docblock. */ final class Method extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'method'; /** @var string */ - private $methodName = ''; + private $methodName; - /** @var string[] */ - private $arguments = []; + /** + * @phpstan-var array<int, array{name: string, type: Type}> + * @var array<int, array<string, Type|string>> + */ + private $arguments; /** @var bool */ - private $isStatic = false; + private $isStatic; /** @var Type */ private $returnType; + /** + * @param array<int, array<string, Type|string>> $arguments + * @phpstan-param array<int, array{name: string, type: Type}|string> $arguments + */ public function __construct( - $methodName, + string $methodName, array $arguments = [], - Type $returnType = null, - $static = false, - Description $description = null + ?Type $returnType = null, + bool $static = false, + ?Description $description = null ) { Assert::stringNotEmpty($methodName); - Assert::boolean($static); if ($returnType === null) { $returnType = new Void_(); @@ -60,17 +81,15 @@ public function __construct( $this->description = $description; } - /** - * {@inheritdoc} - */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): ?self { Assert::stringNotEmpty($body); - Assert::allNotNull([ $typeResolver, $descriptionFactory ]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); // 1. none or more whitespace // 2. optionally the keyword "static" followed by whitespace @@ -81,8 +100,9 @@ public static function create( // 5. then a word with underscores, followed by ( and any character // until a ) and whitespace : as method name with signature // 6. any remaining text : as description - if (!preg_match( - '/^ + if ( + !preg_match( + '/^ # Static keyword # Declares a static method ONLY if type is also present (?: @@ -91,23 +111,19 @@ public static function create( )? # Return type (?: - ( + ( (?:[\w\|_\\\\]*\$this[\w\|_\\\\]*) | (?: (?:[\w\|_\\\\]+) - # array notation + # array notation (?:\[\])* - )* + )*+ ) \s+ )? - # Legacy method name (not captured) - (?: - [\w_]+\(\)\s+ - )? # Method name - ([\w\|_\\\\]+) + ([\w_]+) # Arguments (?: \(([^\)]*)\) @@ -116,15 +132,16 @@ public static function create( # Description (.*) $/sux', - $body, - $matches - )) { + $body, + $matches + ) + ) { return null; } - list(, $static, $returnType, $methodName, $arguments, $description) = $matches; + [, $static, $returnType, $methodName, $argumentLines, $description] = $matches; - $static = $static === 'static'; + $static = $static === 'static'; if ($returnType === '') { $returnType = 'void'; @@ -133,26 +150,26 @@ public static function create( $returnType = $typeResolver->resolve($returnType, $context); $description = $descriptionFactory->create($description, $context); - if (is_string($arguments) && strlen($arguments) > 0) { - $arguments = explode(',', $arguments); - foreach ($arguments as &$argument) { + /** @phpstan-var array<int, array{name: string, type: Type}> $arguments */ + $arguments = []; + if ($argumentLines !== '') { + $argumentsExploded = explode(',', $argumentLines); + foreach ($argumentsExploded as $argument) { $argument = explode(' ', self::stripRestArg(trim($argument)), 2); - if ($argument[0][0] === '$') { + if (strpos($argument[0], '$') === 0) { $argumentName = substr($argument[0], 1); - $argumentType = new Void_(); + $argumentType = new Mixed_(); } else { $argumentType = $typeResolver->resolve($argument[0], $context); $argumentName = ''; if (isset($argument[1])) { - $argument[1] = self::stripRestArg($argument[1]); + $argument[1] = self::stripRestArg($argument[1]); $argumentName = substr($argument[1], 1); } } - $argument = [ 'name' => $argumentName, 'type' => $argumentType]; + $arguments[] = ['name' => $argumentName, 'type' => $argumentType]; } - } else { - $arguments = []; } return new static($methodName, $arguments, $returnType, $static, $description); @@ -160,18 +177,17 @@ public static function create( /** * Retrieves the method name. - * - * @return string */ - public function getMethodName() + public function getMethodName(): string { return $this->methodName; } /** - * @return string[] + * @return array<int, array<string, Type|string>> + * @phpstan-return array<int, array{name: string, type: Type}> */ - public function getArguments() + public function getArguments(): array { return $this->arguments; } @@ -181,57 +197,78 @@ public function getArguments() * * @return bool TRUE if the method declaration is for a static method, FALSE otherwise. */ - public function isStatic() + public function isStatic(): bool { return $this->isStatic; } - /** - * @return Type - */ - public function getReturnType() + public function getReturnType(): Type { return $this->returnType; } - public function __toString() + public function __toString(): string { $arguments = []; foreach ($this->arguments as $argument) { $arguments[] = $argument['type'] . ' $' . $argument['name']; } - return trim(($this->isStatic() ? 'static ' : '') - . (string)$this->returnType . ' ' - . $this->methodName - . '(' . implode(', ', $arguments) . ')' - . ($this->description ? ' ' . $this->description->render() : '')); + $argumentStr = '(' . implode(', ', $arguments) . ')'; + + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $static = $this->isStatic ? 'static' : ''; + + $returnType = (string) $this->returnType; + + $methodName = $this->methodName; + + return $static + . ($returnType !== '' ? ($static !== '' ? ' ' : '') . $returnType : '') + . ($methodName !== '' ? ($static !== '' || $returnType !== '' ? ' ' : '') . $methodName : '') + . $argumentStr + . ($description !== '' ? ' ' . $description : ''); } - private function filterArguments($arguments) + /** + * @param mixed[][]|string[] $arguments + * @phpstan-param array<int, array{name: string, type: Type}|string> $arguments + * + * @return mixed[][] + * @phpstan-return array<int, array{name: string, type: Type}> + */ + private function filterArguments(array $arguments = []): array { - foreach ($arguments as &$argument) { + $result = []; + foreach ($arguments as $argument) { if (is_string($argument)) { - $argument = [ 'name' => $argument ]; + $argument = ['name' => $argument]; } - if (! isset($argument['type'])) { - $argument['type'] = new Void_(); + if (!isset($argument['type'])) { + $argument['type'] = new Mixed_(); } $keys = array_keys($argument); sort($keys); - if ($keys !== [ 'name', 'type' ]) { - throw new \InvalidArgumentException( + if ($keys !== ['name', 'type']) { + throw new InvalidArgumentException( 'Arguments can only have the "name" and "type" fields, found: ' . var_export($keys, true) ); } + + $result[] = $argument; } - return $arguments; + return $result; } - private static function stripRestArg($argument) + private static function stripRestArg(string $argument): string { if (strpos($argument, '...') === 0) { $argument = trim(substr($argument, 3)); diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php index 7d699d8..3399649 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -17,125 +18,157 @@ use phpDocumentor\Reflection\Type; use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Utils; use Webmozart\Assert\Assert; +use function array_shift; +use function array_unshift; +use function implode; +use function strpos; +use function substr; + +use const PREG_SPLIT_DELIM_CAPTURE; + /** * Reflection class for the {@}param tag in a Docblock. */ -final class Param extends BaseTag implements Factory\StaticMethod +final class Param extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'param'; - - /** @var Type */ - private $type; - - /** @var string */ - private $variableName = ''; + /** @var string|null */ + private $variableName; /** @var bool determines whether this is a variadic argument */ - private $isVariadic = false; + private $isVariadic; - /** - * @param string $variableName - * @param Type $type - * @param bool $isVariadic - * @param Description $description - */ - public function __construct($variableName, Type $type = null, $isVariadic = false, Description $description = null) - { - Assert::string($variableName); - Assert::boolean($isVariadic); + /** @var bool determines whether this is passed by reference */ + private $isReference; + public function __construct( + ?string $variableName, + ?Type $type = null, + bool $isVariadic = false, + ?Description $description = null, + bool $isReference = false + ) { + $this->name = 'param'; $this->variableName = $variableName; - $this->type = $type; - $this->isVariadic = $isVariadic; - $this->description = $description; + $this->type = $type; + $this->isVariadic = $isVariadic; + $this->description = $description; + $this->isReference = $isReference; } - /** - * {@inheritdoc} - */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { Assert::stringNotEmpty($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + + [$firstPart, $body] = self::extractTypeFromBody($body); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); - $type = null; + $type = null; + $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); $variableName = ''; - $isVariadic = false; + $isVariadic = false; + $isReference = false; // if the first item that is encountered is not a variable; it is a type - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { - $type = $typeResolver->resolve(array_shift($parts), $context); - array_shift($parts); + if ($firstPart && !self::strStartsWithVariable($firstPart)) { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); } - // if the next item starts with a $ or ...$ it must be the variable name - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$' || substr($parts[0], 0, 4) === '...$')) { + // if the next item starts with a $ or ...$ or &$ or &...$ it must be the variable name + if (isset($parts[0]) && self::strStartsWithVariable($parts[0])) { $variableName = array_shift($parts); - array_shift($parts); - - if (substr($variableName, 0, 3) === '...') { - $isVariadic = true; - $variableName = substr($variableName, 3); + if ($type) { + array_shift($parts); } - if (substr($variableName, 0, 1) === '$') { + Assert::notNull($variableName); + + if (strpos($variableName, '$') === 0) { $variableName = substr($variableName, 1); + } elseif (strpos($variableName, '&$') === 0) { + $isReference = true; + $variableName = substr($variableName, 2); + } elseif (strpos($variableName, '...$') === 0) { + $isVariadic = true; + $variableName = substr($variableName, 4); + } elseif (strpos($variableName, '&...$') === 0) { + $isVariadic = true; + $isReference = true; + $variableName = substr($variableName, 5); } } $description = $descriptionFactory->create(implode('', $parts), $context); - return new static($variableName, $type, $isVariadic, $description); + return new static($variableName, $type, $isVariadic, $description, $isReference); } /** * Returns the variable's name. - * - * @return string */ - public function getVariableName() + public function getVariableName(): ?string { return $this->variableName; } /** - * Returns the variable's type or null if unknown. - * - * @return Type|null + * Returns whether this tag is variadic. */ - public function getType() + public function isVariadic(): bool { - return $this->type; + return $this->isVariadic; } /** - * Returns whether this tag is variadic. - * - * @return boolean + * Returns whether this tag is passed by reference. */ - public function isVariadic() + public function isReference(): bool { - return $this->isVariadic; + return $this->isReference; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString(): string + { + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $variableName = ''; + if ($this->variableName) { + $variableName .= ($this->isReference ? '&' : '') . ($this->isVariadic ? '...' : ''); + $variableName .= '$' . $this->variableName; + } + + $type = (string) $this->type; + + return $type + . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') + . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); + } + + private static function strStartsWithVariable(string $str): bool { - return ($this->type ? $this->type . ' ' : '') - . ($this->isVariadic() ? '...' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + return strpos($str, '$') === 0 + || + strpos($str, '...$') === 0 + || + strpos($str, '&$') === 0 + || + strpos($str, '&...$') === 0; } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php index f0ef7c0..2521fb3 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -17,66 +18,68 @@ use phpDocumentor\Reflection\Type; use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Utils; use Webmozart\Assert\Assert; +use function array_shift; +use function array_unshift; +use function implode; +use function strpos; +use function substr; + +use const PREG_SPLIT_DELIM_CAPTURE; + /** * Reflection class for a {@}property tag in a Docblock. */ -class Property extends BaseTag implements Factory\StaticMethod +final class Property extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'property'; - - /** @var Type */ - private $type; - - /** @var string */ - protected $variableName = ''; + /** @var string|null */ + protected $variableName; - /** - * @param string $variableName - * @param Type $type - * @param Description $description - */ - public function __construct($variableName, Type $type = null, Description $description = null) + public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null) { Assert::string($variableName); + $this->name = 'property'; $this->variableName = $variableName; - $this->type = $type; - $this->description = $description; + $this->type = $type; + $this->description = $description; } - /** - * {@inheritdoc} - */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { Assert::stringNotEmpty($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); - $type = null; + [$firstPart, $body] = self::extractTypeFromBody($body); + $type = null; + $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); $variableName = ''; // if the first item that is encountered is not a variable; it is a type - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { - $type = $typeResolver->resolve(array_shift($parts), $context); - array_shift($parts); + if ($firstPart && $firstPart[0] !== '$') { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); } - // if the next item starts with a $ or ...$ it must be the variable name - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) { + // if the next item starts with a $ it must be the variable name + if (isset($parts[0]) && strpos($parts[0], '$') === 0) { $variableName = array_shift($parts); - array_shift($parts); - - if (substr($variableName, 0, 1) === '$') { - $variableName = substr($variableName, 1); + if ($type) { + array_shift($parts); } + + Assert::notNull($variableName); + + $variableName = substr($variableName, 1); } $description = $descriptionFactory->create(implode('', $parts), $context); @@ -86,33 +89,33 @@ public static function create( /** * Returns the variable's name. - * - * @return string */ - public function getVariableName() + public function getVariableName(): ?string { return $this->variableName; } - /** - * Returns the variable's type or null if unknown. - * - * @return Type|null - */ - public function getType() - { - return $this->type; - } - /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return ($this->type ? $this->type . ' ' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + if ($this->variableName) { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + + $type = (string) $this->type; + + return $type + . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') + . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php index e41c0c1..9491b39 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -17,66 +18,68 @@ use phpDocumentor\Reflection\Type; use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Utils; use Webmozart\Assert\Assert; +use function array_shift; +use function array_unshift; +use function implode; +use function strpos; +use function substr; + +use const PREG_SPLIT_DELIM_CAPTURE; + /** * Reflection class for a {@}property-read tag in a Docblock. */ -class PropertyRead extends BaseTag implements Factory\StaticMethod +final class PropertyRead extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'property-read'; - - /** @var Type */ - private $type; - - /** @var string */ - protected $variableName = ''; + /** @var string|null */ + protected $variableName; - /** - * @param string $variableName - * @param Type $type - * @param Description $description - */ - public function __construct($variableName, Type $type = null, Description $description = null) + public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null) { Assert::string($variableName); + $this->name = 'property-read'; $this->variableName = $variableName; - $this->type = $type; - $this->description = $description; + $this->type = $type; + $this->description = $description; } - /** - * {@inheritdoc} - */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { Assert::stringNotEmpty($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); - $type = null; + [$firstPart, $body] = self::extractTypeFromBody($body); + $type = null; + $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); $variableName = ''; // if the first item that is encountered is not a variable; it is a type - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { - $type = $typeResolver->resolve(array_shift($parts), $context); - array_shift($parts); + if ($firstPart && $firstPart[0] !== '$') { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); } - // if the next item starts with a $ or ...$ it must be the variable name - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) { + // if the next item starts with a $ it must be the variable name + if (isset($parts[0]) && strpos($parts[0], '$') === 0) { $variableName = array_shift($parts); - array_shift($parts); - - if (substr($variableName, 0, 1) === '$') { - $variableName = substr($variableName, 1); + if ($type) { + array_shift($parts); } + + Assert::notNull($variableName); + + $variableName = substr($variableName, 1); } $description = $descriptionFactory->create(implode('', $parts), $context); @@ -86,33 +89,33 @@ public static function create( /** * Returns the variable's name. - * - * @return string */ - public function getVariableName() + public function getVariableName(): ?string { return $this->variableName; } - /** - * Returns the variable's type or null if unknown. - * - * @return Type|null - */ - public function getType() - { - return $this->type; - } - /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return ($this->type ? $this->type . ' ' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + if ($this->variableName) { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + + $type = (string) $this->type; + + return $type + . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') + . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php index cfdb0ed..2bfdac6 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -17,66 +18,68 @@ use phpDocumentor\Reflection\Type; use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Utils; use Webmozart\Assert\Assert; +use function array_shift; +use function array_unshift; +use function implode; +use function strpos; +use function substr; + +use const PREG_SPLIT_DELIM_CAPTURE; + /** * Reflection class for a {@}property-write tag in a Docblock. */ -class PropertyWrite extends BaseTag implements Factory\StaticMethod +final class PropertyWrite extends TagWithType implements Factory\StaticMethod { /** @var string */ - protected $name = 'property-write'; - - /** @var Type */ - private $type; - - /** @var string */ - protected $variableName = ''; + protected $variableName; - /** - * @param string $variableName - * @param Type $type - * @param Description $description - */ - public function __construct($variableName, Type $type = null, Description $description = null) + public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null) { Assert::string($variableName); + $this->name = 'property-write'; $this->variableName = $variableName; - $this->type = $type; - $this->description = $description; + $this->type = $type; + $this->description = $description; } - /** - * {@inheritdoc} - */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { Assert::stringNotEmpty($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); - $type = null; + [$firstPart, $body] = self::extractTypeFromBody($body); + $type = null; + $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); $variableName = ''; // if the first item that is encountered is not a variable; it is a type - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { - $type = $typeResolver->resolve(array_shift($parts), $context); - array_shift($parts); + if ($firstPart && $firstPart[0] !== '$') { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); } - // if the next item starts with a $ or ...$ it must be the variable name - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) { + // if the next item starts with a $ it must be the variable name + if (isset($parts[0]) && strpos($parts[0], '$') === 0) { $variableName = array_shift($parts); - array_shift($parts); - - if (substr($variableName, 0, 1) === '$') { - $variableName = substr($variableName, 1); + if ($type) { + array_shift($parts); } + + Assert::notNull($variableName); + + $variableName = substr($variableName, 1); } $description = $descriptionFactory->create(implode('', $parts), $context); @@ -86,33 +89,33 @@ public static function create( /** * Returns the variable's name. - * - * @return string */ - public function getVariableName() + public function getVariableName(): ?string { return $this->variableName; } - /** - * Returns the variable's type or null if unknown. - * - * @return Type|null - */ - public function getType() - { - return $this->type; - } - /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return ($this->type ? $this->type . ' ' : '') - . '$' . $this->variableName - . ($this->description ? ' ' . $this->description : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + if ($this->variableName) { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + + $type = (string) $this->type; + + return $type + . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') + . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php index dc7b8b6..532003d 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php @@ -1,13 +1,14 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2017 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags\Reference; @@ -15,18 +16,13 @@ use phpDocumentor\Reflection\Fqsen as RealFqsen; /** - * Fqsen reference used by {@see phpDocumentor\Reflection\DocBlock\Tags\See} + * Fqsen reference used by {@see \phpDocumentor\Reflection\DocBlock\Tags\See} */ final class Fqsen implements Reference { - /** - * @var RealFqsen - */ + /** @var RealFqsen */ private $fqsen; - /** - * Fqsen constructor. - */ public function __construct(RealFqsen $fqsen) { $this->fqsen = $fqsen; @@ -35,8 +31,8 @@ public function __construct(RealFqsen $fqsen) /** * @return string string representation of the referenced fqsen */ - public function __toString() + public function __toString(): string { - return (string)$this->fqsen; + return (string) $this->fqsen; } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php index a3ffd24..e7dea86 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php @@ -1,21 +1,22 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2017 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags\Reference; /** - * Interface for references in {@see phpDocumentor\Reflection\DocBlock\Tags\See} + * Interface for references in {@see \phpDocumentor\Reflection\DocBlock\Tags\See} */ interface Reference { - public function __toString(); + public function __toString(): string; } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php index 2671d5e..edfba3f 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php @@ -1,13 +1,14 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2017 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags\Reference; @@ -15,25 +16,20 @@ use Webmozart\Assert\Assert; /** - * Url reference used by {@see phpDocumentor\Reflection\DocBlock\Tags\See} + * Url reference used by {@see \phpDocumentor\Reflection\DocBlock\Tags\See} */ final class Url implements Reference { - /** - * @var string - */ + /** @var string */ private $uri; - /** - * Url constructor. - */ - public function __construct($uri) + public function __construct(string $uri) { Assert::stringNotEmpty($uri); $this->uri = $uri; } - public function __toString() + public function __toString(): string { return $this->uri; } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php index ca5bda7..f021b60 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -22,51 +23,42 @@ /** * Reflection class for a {@}return tag in a Docblock. */ -final class Return_ extends BaseTag implements Factory\StaticMethod +final class Return_ extends TagWithType implements Factory\StaticMethod { - protected $name = 'return'; - - /** @var Type */ - private $type; - - public function __construct(Type $type, Description $description = null) + public function __construct(Type $type, ?Description $description = null) { - $this->type = $type; + $this->name = 'return'; + $this->type = $type; $this->description = $description; } - /** - * {@inheritdoc} - */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { - Assert::string($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/\s+/Su', $body, 2); + [$type, $description] = self::extractTypeFromBody($body); - $type = $typeResolver->resolve(isset($parts[0]) ? $parts[0] : '', $context); - $description = $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context); + $type = $typeResolver->resolve($type, $context); + $description = $descriptionFactory->create($description, $context); return new static($type, $description); } - /** - * Returns the type section of the variable. - * - * @return Type - */ - public function getType() + public function __toString(): string { - return $this->type; - } + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } - public function __toString() - { - return $this->type . ' ' . $this->description; + $type = $this->type ? '' . $this->type : 'mixed'; + + return $type . ($description !== '' ? ' ' . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php index 9e9e723..a194c7d 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php @@ -1,13 +1,14 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -17,72 +18,89 @@ use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef; use phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference; use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url; +use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Utils; use Webmozart\Assert\Assert; +use function array_key_exists; +use function explode; +use function preg_match; + /** * Reflection class for an {@}see tag in a Docblock. */ -class See extends BaseTag implements Factory\StaticMethod +final class See extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'see'; /** @var Reference */ - protected $refers = null; + protected $refers; /** * Initializes this tag. - * - * @param Reference $refers - * @param Description $description */ - public function __construct(Reference $refers, Description $description = null) + public function __construct(Reference $refers, ?Description $description = null) { - $this->refers = $refers; + $this->refers = $refers; $this->description = $description; } - /** - * {@inheritdoc} - */ public static function create( - $body, - FqsenResolver $resolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { - Assert::string($body); - Assert::allNotNull([$resolver, $descriptionFactory]); - - $parts = preg_split('/\s+/Su', $body, 2); + string $body, + ?FqsenResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { + Assert::notNull($descriptionFactory); + + $parts = Utils::pregSplit('/\s+/Su', $body, 2); $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; // https://tools.ietf.org/html/rfc2396#section-3 - if (preg_match('/\w:\/\/\w/i', $parts[0])) { + if (preg_match('#\w://\w#', $parts[0])) { return new static(new Url($parts[0]), $description); } - return new static(new FqsenRef($resolver->resolve($parts[0], $context)), $description); + return new static(new FqsenRef(self::resolveFqsen($parts[0], $typeResolver, $context)), $description); + } + + private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context): Fqsen + { + Assert::notNull($fqsenResolver); + $fqsenParts = explode('::', $parts); + $resolved = $fqsenResolver->resolve($fqsenParts[0], $context); + + if (!array_key_exists(1, $fqsenParts)) { + return $resolved; + } + + return new Fqsen($resolved . '::' . $fqsenParts[1]); } /** * Returns the ref of this tag. - * - * @return Reference */ - public function getReference() + public function getReference(): Reference { return $this->refers; } /** * Returns a string representation of this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return $this->refers . ($this->description ? ' ' . $this->description->render() : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $refers = (string) $this->refers; + + return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php index 835fb0d..54af43c 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -17,18 +18,21 @@ use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; + /** * Reflection class for a {@}since tag in a Docblock. */ final class Since extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'since'; /** * PCRE regular expression matching a version vector. * Assumes the "x" modifier. */ - const REGEX_VECTOR = '(?: + public const REGEX_VECTOR = '(?: # Normal release vectors. \d\S* | @@ -40,55 +44,60 @@ final class Since extends BaseTag implements Factory\StaticMethod [^\s\:]+\:\s*\$[^\$]+\$ )'; - /** @var string The version vector. */ - private $version = ''; + /** @var string|null The version vector. */ + private $version; - public function __construct($version = null, Description $description = null) + public function __construct(?string $version = null, ?Description $description = null) { - Assert::nullOrStringNotEmpty($version); + Assert::nullOrNotEmpty($version); $this->version = $version; $this->description = $description; } - /** - * @return static - */ - public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) - { - Assert::nullOrString($body); + public static function create( + ?string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): ?self { if (empty($body)) { return new static(); } $matches = []; - if (! preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { + if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { return null; } + Assert::notNull($descriptionFactory); + return new static( $matches[1], - $descriptionFactory->create(isset($matches[2]) ? $matches[2] : '', $context) + $descriptionFactory->create($matches[2] ?? '', $context) ); } /** * Gets the version section of the tag. - * - * @return string */ - public function getVersion() + public function getVersion(): ?string { return $this->version; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return $this->version . ($this->description ? ' ' . $this->description->render() : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $version = (string) $this->version; + + return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php index 247b1b3..8b8c0fb 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -17,6 +18,8 @@ use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; + /** * Reflection class for a {@}source tag in a Docblock. */ @@ -26,26 +29,30 @@ final class Source extends BaseTag implements Factory\StaticMethod protected $name = 'source'; /** @var int The starting line, relative to the structural element's location. */ - private $startingLine = 1; + private $startingLine; /** @var int|null The number of lines, relative to the starting line. NULL means "to the end". */ - private $lineCount = null; + private $lineCount; - public function __construct($startingLine, $lineCount = null, Description $description = null) + /** + * @param int|string $startingLine should be a to int convertible value + * @param int|string|null $lineCount should be a to int convertible value + */ + public function __construct($startingLine, $lineCount = null, ?Description $description = null) { Assert::integerish($startingLine); Assert::nullOrIntegerish($lineCount); - $this->startingLine = (int)$startingLine; - $this->lineCount = $lineCount !== null ? (int)$lineCount : null; + $this->startingLine = (int) $startingLine; + $this->lineCount = $lineCount !== null ? (int) $lineCount : null; $this->description = $description; } - /** - * {@inheritdoc} - */ - public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) - { + public static function create( + string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { Assert::stringNotEmpty($body); Assert::notNull($descriptionFactory); @@ -55,15 +62,15 @@ public static function create($body, DescriptionFactory $descriptionFactory = nu // Starting line / Number of lines / Description if (preg_match('/^([1-9]\d*)\s*(?:((?1))\s+)?(.*)$/sux', $body, $matches)) { - $startingLine = (int)$matches[1]; + $startingLine = (int) $matches[1]; if (isset($matches[2]) && $matches[2] !== '') { - $lineCount = (int)$matches[2]; + $lineCount = (int) $matches[2]; } $description = $matches[3]; } - return new static($startingLine, $lineCount, $descriptionFactory->create($description, $context)); + return new static($startingLine, $lineCount, $descriptionFactory->create($description ?? '', $context)); } /** @@ -72,7 +79,7 @@ public static function create($body, DescriptionFactory $descriptionFactory = nu * @return int The starting line, relative to the structural element's * location. */ - public function getStartingLine() + public function getStartingLine(): int { return $this->startingLine; } @@ -83,15 +90,27 @@ public function getStartingLine() * @return int|null The number of lines, relative to the starting line. NULL * means "to the end". */ - public function getLineCount() + public function getLineCount(): ?int { return $this->lineCount; } - public function __toString() + public function __toString(): string { - return $this->startingLine - . ($this->lineCount !== null ? ' ' . $this->lineCount : '') - . ($this->description ? ' ' . $this->description->render() : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $startingLine = (string) $this->startingLine; + + $lineCount = $this->lineCount !== null ? ' ' . $this->lineCount : ''; + + return $startingLine + . $lineCount + . ($description !== '' + ? ' ' . $description + : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php new file mode 100644 index 0000000..158578b --- /dev/null +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/TagWithType.php @@ -0,0 +1,66 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\Type; + +use function in_array; +use function strlen; +use function substr; +use function trim; + +abstract class TagWithType extends BaseTag +{ + /** @var ?Type */ + protected $type; + + /** + * Returns the type section of the variable. + */ + public function getType(): ?Type + { + return $this->type; + } + + /** + * @return string[] + */ + protected static function extractTypeFromBody(string $body): array + { + $type = ''; + $nestingLevel = 0; + for ($i = 0, $iMax = strlen($body); $i < $iMax; $i++) { + $character = $body[$i]; + + if ($nestingLevel === 0 && trim($character) === '') { + break; + } + + $type .= $character; + if (in_array($character, ['<', '(', '[', '{'])) { + $nestingLevel++; + continue; + } + + if (in_array($character, ['>', ')', ']', '}'])) { + $nestingLevel--; + continue; + } + } + + $description = trim(substr($body, strlen($type))); + + return [$type, $description]; + } +} diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php index 349e773..f21c910 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -22,51 +23,42 @@ /** * Reflection class for a {@}throws tag in a Docblock. */ -final class Throws extends BaseTag implements Factory\StaticMethod +final class Throws extends TagWithType implements Factory\StaticMethod { - protected $name = 'throws'; - - /** @var Type */ - private $type; - - public function __construct(Type $type, Description $description = null) + public function __construct(Type $type, ?Description $description = null) { + $this->name = 'throws'; $this->type = $type; $this->description = $description; } - /** - * {@inheritdoc} - */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { - Assert::string($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/\s+/Su', $body, 2); + [$type, $description] = self::extractTypeFromBody($body); - $type = $typeResolver->resolve(isset($parts[0]) ? $parts[0] : '', $context); - $description = $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context); + $type = $typeResolver->resolve($type, $context); + $description = $descriptionFactory->create($description, $context); return new static($type, $description); } - /** - * Returns the type section of the variable. - * - * @return Type - */ - public function getType() + public function __toString(): string { - return $this->type; - } + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } - public function __toString() - { - return $this->type . ' ' . $this->description; + $type = (string) $this->type; + + return $type . ($description !== '' ? ($type !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php index 00dc3e3..b72f403 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php @@ -1,13 +1,14 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -17,67 +18,83 @@ use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Utils; use Webmozart\Assert\Assert; +use function array_key_exists; +use function explode; + /** * Reflection class for a {@}uses tag in a Docblock. */ final class Uses extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'uses'; /** @var Fqsen */ - protected $refers = null; + protected $refers; /** * Initializes this tag. - * - * @param Fqsen $refers - * @param Description $description */ - public function __construct(Fqsen $refers, Description $description = null) + public function __construct(Fqsen $refers, ?Description $description = null) { $this->refers = $refers; $this->description = $description; } - /** - * {@inheritdoc} - */ public static function create( - $body, - FqsenResolver $resolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { - Assert::string($body); - Assert::allNotNull([$resolver, $descriptionFactory]); + string $body, + ?FqsenResolver $resolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { + Assert::notNull($resolver); + Assert::notNull($descriptionFactory); - $parts = preg_split('/\s+/Su', $body, 2); + $parts = Utils::pregSplit('/\s+/Su', $body, 2); return new static( - $resolver->resolve($parts[0], $context), - $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context) + self::resolveFqsen($parts[0], $resolver, $context), + $descriptionFactory->create($parts[1] ?? '', $context) ); } + private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context): Fqsen + { + Assert::notNull($fqsenResolver); + $fqsenParts = explode('::', $parts); + $resolved = $fqsenResolver->resolve($fqsenParts[0], $context); + + if (!array_key_exists(1, $fqsenParts)) { + return $resolved; + } + + return new Fqsen($resolved . '::' . $fqsenParts[1]); + } + /** * Returns the structural element this tag refers to. - * - * @return Fqsen */ - public function getReference() + public function getReference(): Fqsen { return $this->refers; } /** * Returns a string representation of this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return $this->refers . ' ' . $this->description->render(); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $refers = (string) $this->refers; + + return $refers . ($description !== '' ? ($refers !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php index 8907c95..fa1f9db 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -17,66 +18,69 @@ use phpDocumentor\Reflection\Type; use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Utils; use Webmozart\Assert\Assert; +use function array_shift; +use function array_unshift; +use function implode; +use function strpos; +use function substr; + +use const PREG_SPLIT_DELIM_CAPTURE; + /** * Reflection class for a {@}var tag in a Docblock. */ -class Var_ extends BaseTag implements Factory\StaticMethod +final class Var_ extends TagWithType implements Factory\StaticMethod { - /** @var string */ - protected $name = 'var'; - - /** @var Type */ - private $type; - - /** @var string */ + /** @var string|null */ protected $variableName = ''; - /** - * @param string $variableName - * @param Type $type - * @param Description $description - */ - public function __construct($variableName, Type $type = null, Description $description = null) + public function __construct(?string $variableName, ?Type $type = null, ?Description $description = null) { Assert::string($variableName); + $this->name = 'var'; $this->variableName = $variableName; $this->type = $type; $this->description = $description; } - /** - * {@inheritdoc} - */ public static function create( - $body, - TypeResolver $typeResolver = null, - DescriptionFactory $descriptionFactory = null, - TypeContext $context = null - ) { + string $body, + ?TypeResolver $typeResolver = null, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): self { Assert::stringNotEmpty($body); - Assert::allNotNull([$typeResolver, $descriptionFactory]); + Assert::notNull($typeResolver); + Assert::notNull($descriptionFactory); + + [$firstPart, $body] = self::extractTypeFromBody($body); - $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + $parts = Utils::pregSplit('/(\s+)/Su', $body, 2, PREG_SPLIT_DELIM_CAPTURE); $type = null; $variableName = ''; // if the first item that is encountered is not a variable; it is a type - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { - $type = $typeResolver->resolve(array_shift($parts), $context); - array_shift($parts); + if ($firstPart && $firstPart[0] !== '$') { + $type = $typeResolver->resolve($firstPart, $context); + } else { + // first part is not a type; we should prepend it to the parts array for further processing + array_unshift($parts, $firstPart); } - // if the next item starts with a $ or ...$ it must be the variable name - if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) { + // if the next item starts with a $ it must be the variable name + if (isset($parts[0]) && strpos($parts[0], '$') === 0) { $variableName = array_shift($parts); - array_shift($parts); - - if (substr($variableName, 0, 1) === '$') { - $variableName = substr($variableName, 1); + if ($type) { + array_shift($parts); } + + Assert::notNull($variableName); + + $variableName = substr($variableName, 1); } $description = $descriptionFactory->create(implode('', $parts), $context); @@ -86,33 +90,33 @@ public static function create( /** * Returns the variable's name. - * - * @return string */ - public function getVariableName() + public function getVariableName(): ?string { return $this->variableName; } - /** - * Returns the variable's type or null if unknown. - * - * @return Type|null - */ - public function getType() - { - return $this->type; - } - /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return ($this->type ? $this->type . ' ' : '') - . (empty($this->variableName) ? null : ('$' . $this->variableName)) - . ($this->description ? ' ' . $this->description : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + if ($this->variableName) { + $variableName = '$' . $this->variableName; + } else { + $variableName = ''; + } + + $type = (string) $this->type; + + return $type + . ($variableName !== '' ? ($type !== '' ? ' ' : '') . $variableName : '') + . ($description !== '' ? ($type !== '' || $variableName !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php index 7bb0420..f46e4b8 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php @@ -1,13 +1,14 @@ <?php + +declare(strict_types=1); + /** - * phpDocumentor + * This file is part of phpDocumentor. * - * PHP Version 5.3 + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. * - * @author Vasil Rangelov <boen.robot@gmail.com> - * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://phpdoc.org + * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tags; @@ -17,18 +18,21 @@ use phpDocumentor\Reflection\Types\Context as TypeContext; use Webmozart\Assert\Assert; +use function preg_match; + /** * Reflection class for a {@}version tag in a Docblock. */ final class Version extends BaseTag implements Factory\StaticMethod { + /** @var string */ protected $name = 'version'; /** * PCRE regular expression matching a version vector. * Assumes the "x" modifier. */ - const REGEX_VECTOR = '(?: + public const REGEX_VECTOR = '(?: # Normal release vectors. \d\S* | @@ -40,23 +44,22 @@ final class Version extends BaseTag implements Factory\StaticMethod [^\s\:]+\:\s*\$[^\$]+\$ )'; - /** @var string The version vector. */ - private $version = ''; + /** @var string|null The version vector. */ + private $version; - public function __construct($version = null, Description $description = null) + public function __construct(?string $version = null, ?Description $description = null) { Assert::nullOrStringNotEmpty($version); - $this->version = $version; + $this->version = $version; $this->description = $description; } - /** - * @return static - */ - public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) - { - Assert::nullOrString($body); + public static function create( + ?string $body, + ?DescriptionFactory $descriptionFactory = null, + ?TypeContext $context = null + ): ?self { if (empty($body)) { return new static(); } @@ -66,29 +69,38 @@ public static function create($body, DescriptionFactory $descriptionFactory = nu return null; } + $description = null; + if ($descriptionFactory !== null) { + $description = $descriptionFactory->create($matches[2] ?? '', $context); + } + return new static( $matches[1], - $descriptionFactory->create(isset($matches[2]) ? $matches[2] : '', $context) + $description ); } /** * Gets the version section of the tag. - * - * @return string */ - public function getVersion() + public function getVersion(): ?string { return $this->version; } /** * Returns a string representation for this tag. - * - * @return string */ - public function __toString() + public function __toString(): string { - return $this->version . ($this->description ? ' ' . $this->description->render() : ''); + if ($this->description) { + $description = $this->description->render(); + } else { + $description = ''; + } + + $version = (string) $this->version; + + return $version . ($description !== '' ? ($version !== '' ? ' ' : '') . $description : ''); } } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php index 1bdb8f4..37f72dd 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php @@ -1,23 +1,38 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection; +use InvalidArgumentException; +use LogicException; use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\DocBlock\StandardTagFactory; use phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\TagFactory; use Webmozart\Assert\Assert; +use function array_shift; +use function count; +use function explode; +use function is_object; +use function method_exists; +use function preg_match; +use function preg_replace; +use function str_replace; +use function strpos; +use function substr; +use function trim; + final class DocBlockFactory implements DocBlockFactoryInterface { /** @var DocBlock\DescriptionFactory */ @@ -28,27 +43,22 @@ final class DocBlockFactory implements DocBlockFactoryInterface /** * Initializes this factory with the required subcontractors. - * - * @param DescriptionFactory $descriptionFactory - * @param TagFactory $tagFactory */ public function __construct(DescriptionFactory $descriptionFactory, TagFactory $tagFactory) { $this->descriptionFactory = $descriptionFactory; - $this->tagFactory = $tagFactory; + $this->tagFactory = $tagFactory; } /** * Factory method for easy instantiation. * - * @param string[] $additionalTags - * - * @return DocBlockFactory + * @param array<string, class-string<Tag>> $additionalTags */ - public static function createInstance(array $additionalTags = []) + public static function createInstance(array $additionalTags = []): self { - $fqsenResolver = new FqsenResolver(); - $tagFactory = new StandardTagFactory($fqsenResolver); + $fqsenResolver = new FqsenResolver(); + $tagFactory = new StandardTagFactory($fqsenResolver); $descriptionFactory = new DescriptionFactory($tagFactory); $tagFactory->addService($descriptionFactory); @@ -65,20 +75,18 @@ public static function createInstance(array $additionalTags = []) /** * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the * getDocComment method (such as a ReflectionClass object). - * @param Types\Context $context - * @param Location $location - * - * @return DocBlock */ - public function create($docblock, Types\Context $context = null, Location $location = null) + public function create($docblock, ?Types\Context $context = null, ?Location $location = null): DocBlock { if (is_object($docblock)) { if (!method_exists($docblock, 'getDocComment')) { $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method'; - throw new \InvalidArgumentException($exceptionMessage); + + throw new InvalidArgumentException($exceptionMessage); } $docblock = $docblock->getDocComment(); + Assert::string($docblock); } Assert::stringNotEmpty($docblock); @@ -88,14 +96,13 @@ public function create($docblock, Types\Context $context = null, Location $locat } $parts = $this->splitDocBlock($this->stripDocComment($docblock)); - list($templateMarker, $summary, $description, $tags) = $parts; + + [$templateMarker, $summary, $description, $tags] = $parts; return new DocBlock( $summary, $description ? $this->descriptionFactory->create($description, $context) : null, - array_filter($this->parseTagBlock($tags, $context), function ($tag) { - return $tag instanceof Tag; - }), + $this->parseTagBlock($tags, $context), $context, $location, $templateMarker === '#@+', @@ -103,7 +110,10 @@ public function create($docblock, Types\Context $context = null, Location $locat ); } - public function registerTagHandler($tagName, $handler) + /** + * @param class-string<Tag> $handler + */ + public function registerTagHandler(string $tagName, string $handler): void { $this->tagFactory->registerTagHandler($tagName, $handler); } @@ -112,12 +122,12 @@ public function registerTagHandler($tagName, $handler) * Strips the asterisks from the DocBlock comment. * * @param string $comment String containing the comment text. - * - * @return string */ - private function stripDocComment($comment) + private function stripDocComment(string $comment): string { - $comment = trim(preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]{0,1}(.*)?#u', '$1', $comment)); + $comment = preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]?(.*)?#u', '$1', $comment); + Assert::string($comment); + $comment = trim($comment); // reg ex above is not able to remove */ from a single line docblock if (substr($comment, -2) === '*/') { @@ -127,18 +137,21 @@ private function stripDocComment($comment) return str_replace(["\r\n", "\r"], "\n", $comment); } + // phpcs:disable /** * Splits the DocBlock into a template marker, summary, description and block of tags. * * @param string $comment Comment to split into the sub-parts. * - * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. + * @return string[] containing the template marker (if any), summary, description and a string containing the tags. + * * @author Mike van Riel <me@mikevanriel.com> for extending the regex with template marker support. * - * @return string[] containing the template marker (if any), summary, description and a string containing the tags. + * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. */ - private function splitDocBlock($comment) + private function splitDocBlock(string $comment) : array { + // phpcs:enable // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the // performance impact of running a regular expression @@ -148,7 +161,7 @@ private function splitDocBlock($comment) // clears all extra horizontal whitespace from the line endings to prevent parsing issues $comment = preg_replace('/\h*$/Sum', '', $comment); - + Assert::string($comment); /* * Splits the docblock into a template marker, summary, description and tags section. * @@ -176,7 +189,7 @@ private function splitDocBlock($comment) [^\n.]+ (?: (?! \. \n | \n{2} ) # End summary upon a dot followed by newline or two newlines - [\n.] (?! [ \t]* @\pL ) # End summary when an @ is found as first character on a new line + [\n.]* (?! [ \t]* @\pL ) # End summary when an @ is found as first character on a new line [^\n.]+ # Include anything else )* \.? @@ -214,20 +227,21 @@ private function splitDocBlock($comment) /** * Creates the tag objects. * - * @param string $tags Tag block to parse. + * @param string $tags Tag block to parse. * @param Types\Context $context Context of the parsed Tag * * @return DocBlock\Tag[] */ - private function parseTagBlock($tags, Types\Context $context) + private function parseTagBlock(string $tags, Types\Context $context): array { $tags = $this->filterTagBlock($tags); - if (!$tags) { + if ($tags === null) { return []; } - $result = $this->splitTagBlockIntoTagLines($tags); - foreach ($result as $key => $tagLine) { + $result = []; + $lines = $this->splitTagBlockIntoTagLines($tags); + foreach ($lines as $key => $tagLine) { $result[$key] = $this->tagFactory->create(trim($tagLine), $context); } @@ -235,40 +249,36 @@ private function parseTagBlock($tags, Types\Context $context) } /** - * @param string $tags - * * @return string[] */ - private function splitTagBlockIntoTagLines($tags) + private function splitTagBlockIntoTagLines(string $tags): array { $result = []; - foreach (explode("\n", $tags) as $tag_line) { - if (isset($tag_line[0]) && ($tag_line[0] === '@')) { - $result[] = $tag_line; + foreach (explode("\n", $tags) as $tagLine) { + if ($tagLine !== '' && strpos($tagLine, '@') === 0) { + $result[] = $tagLine; } else { - $result[count($result) - 1] .= "\n" . $tag_line; + $result[count($result) - 1] .= "\n" . $tagLine; } } return $result; } - /** - * @param $tags - * @return string - */ - private function filterTagBlock($tags) + private function filterTagBlock(string $tags): ?string { $tags = trim($tags); if (!$tags) { return null; } - if ('@' !== $tags[0]) { + if ($tags[0] !== '@') { // @codeCoverageIgnoreStart // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that // we didn't foresee. - throw new \LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); + + throw new LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); + // @codeCoverageIgnoreEnd } diff --git a/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php b/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php index b353342..9995c0c 100644 --- a/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php +++ b/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php @@ -1,23 +1,23 @@ <?php + +declare(strict_types=1); + namespace phpDocumentor\Reflection; +use phpDocumentor\Reflection\DocBlock\Tag; + +// phpcs:ignore SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming.SuperfluousSuffix interface DocBlockFactoryInterface { /** * Factory method for easy instantiation. * - * @param string[] $additionalTags - * - * @return DocBlockFactory + * @param array<string, class-string<Tag>> $additionalTags */ - public static function createInstance(array $additionalTags = []); + public static function createInstance(array $additionalTags = []): DocBlockFactory; /** - * @param string $docblock - * @param Types\Context $context - * @param Location $location - * - * @return DocBlock + * @param string|object $docblock */ - public function create($docblock, Types\Context $context = null, Location $location = null); + public function create($docblock, ?Types\Context $context = null, ?Location $location = null): DocBlock; } diff --git a/vendor/phpdocumentor/reflection-docblock/src/Exception/PcreException.php b/vendor/phpdocumentor/reflection-docblock/src/Exception/PcreException.php new file mode 100644 index 0000000..b8b6da8 --- /dev/null +++ b/vendor/phpdocumentor/reflection-docblock/src/Exception/PcreException.php @@ -0,0 +1,44 @@ +<?php + +declare(strict_types=1); + +namespace phpDocumentor\Reflection\Exception; + +use InvalidArgumentException; + +use const PREG_BACKTRACK_LIMIT_ERROR; +use const PREG_BAD_UTF8_ERROR; +use const PREG_BAD_UTF8_OFFSET_ERROR; +use const PREG_INTERNAL_ERROR; +use const PREG_JIT_STACKLIMIT_ERROR; +use const PREG_NO_ERROR; +use const PREG_RECURSION_LIMIT_ERROR; + +final class PcreException extends InvalidArgumentException +{ + public static function createFromPhpError(int $errorCode): self + { + switch ($errorCode) { + case PREG_BACKTRACK_LIMIT_ERROR: + return new self('Backtrack limit error'); + + case PREG_RECURSION_LIMIT_ERROR: + return new self('Recursion limit error'); + + case PREG_BAD_UTF8_ERROR: + return new self('Bad UTF8 error'); + + case PREG_BAD_UTF8_OFFSET_ERROR: + return new self('Bad UTF8 offset error'); + + case PREG_JIT_STACKLIMIT_ERROR: + return new self('Jit stacklimit error'); + + case PREG_NO_ERROR: + case PREG_INTERNAL_ERROR: + default: + } + + return new self('Unknown Pcre error'); + } +} diff --git a/vendor/phpdocumentor/reflection-docblock/src/Utils.php b/vendor/phpdocumentor/reflection-docblock/src/Utils.php new file mode 100644 index 0000000..ddd0f61 --- /dev/null +++ b/vendor/phpdocumentor/reflection-docblock/src/Utils.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection; + +use phpDocumentor\Reflection\Exception\PcreException; +use Webmozart\Assert\Assert; + +use function preg_last_error; +use function preg_split as php_preg_split; + +abstract class Utils +{ + /** + * Wrapper function for phps preg_split + * + * This function is inspired by {@link https://github.com/thecodingmachine/safe/blob/master/generated/pcre.php}. But + * since this library is all about performance we decided to strip everything we don't need. Reducing the amount + * of files that have to be loaded, ect. + * + * @param string $pattern The pattern to search for, as a string. + * @param string $subject The input string. + * @param int $limit If specified, then only substrings up to limit are returned with the + * rest of the string being placed in the last substring. A limit of -1 or 0 means "no limit". + * @param int $flags flags can be any combination of the following flags (combined with the | bitwise operator): + * *PREG_SPLIT_NO_EMPTY* + * If this flag is set, only non-empty pieces will be returned by preg_split(). + * *PREG_SPLIT_DELIM_CAPTURE* + * If this flag is set, parenthesized expression in the delimiter pattern will be captured + * and returned as well. + * *PREG_SPLIT_OFFSET_CAPTURE* + * If this flag is set, for every occurring match the appendant string offset will also be returned. + * Note that this changes the return value in an array where every element is an array consisting of the + * matched string at offset 0 and its string offset into subject at offset 1. + * + * @return string[] Returns an array containing substrings of subject + * split along boundaries matched by pattern + * + * @throws PcreException + */ + public static function pregSplit(string $pattern, string $subject, int $limit = -1, int $flags = 0): array + { + $parts = php_preg_split($pattern, $subject, $limit, $flags); + if ($parts === false) { + throw PcreException::createFromPhpError(preg_last_error()); + } + + Assert::allString($parts); + + return $parts; + } +} diff --git a/vendor/phpdocumentor/type-resolver/README.md b/vendor/phpdocumentor/type-resolver/README.md index fad3400..f30d3a2 100644 --- a/vendor/phpdocumentor/type-resolver/README.md +++ b/vendor/phpdocumentor/type-resolver/README.md @@ -1,3 +1,11 @@ +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +![](https://github.com/phpdocumentor/typeresolver/workflows/Qa%20workflow/badge.svg?branch=1.x) +[![Coveralls Coverage](https://img.shields.io/coveralls/github/phpDocumentor/TypeResolver.svg)](https://coveralls.io/github/phpDocumentor/TypeResolver?branch=1.x) +[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/phpDocumentor/TypeResolver.svg)](https://scrutinizer-ci.com/g/phpDocumentor/TypeResolver/?branch=1.x) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/phpDocumentor/TypeResolver.svg)](https://scrutinizer-ci.com/g/phpDocumentor/TypeResolver/?branch=1.x) +![Packagist Version](https://img.shields.io/packagist/v/phpdocumentor/type-resolver?label=Packagist%20stable) +![Packagist Version](https://img.shields.io/packagist/vpre/phpdocumentor/type-resolver?label=Packagist%20unstable) + TypeResolver and FqsenResolver ============================== @@ -22,8 +30,7 @@ The easiest way to install this library is with [Composer](https://getcomposer.o ## Examples -Ready to dive in and don't want to read through all that text below? Just consult the [examples](examples) folder and -check which type of action that your want to accomplish. +Ready to dive in and don't want to read through all that text below? Just consult the [examples](examples) folder and check which type of action that your want to accomplish. ## On Types and Element Names @@ -39,6 +46,7 @@ The TypeResolver can resolve: - a php primitive or pseudo-primitive such as a string or void (`@var string` or `@return void`). - a composite such as an array of string (`@var string[]`). - a compound such as a string or integer (`@var string|integer`). +- an array expression (`@var (string|TypeResolver)[]`) - an object or interface such as the TypeResolver class (`@var TypeResolver` or `@var \phpDocumentor\Reflection\TypeResolver`) @@ -58,8 +66,7 @@ Where the FqsenResolver can resolve: ## Resolving a type -In order to resolve a type you will have to instantiate the class `\phpDocumentor\Reflection\TypeResolver` -and call its `resolve` method like this: +In order to resolve a type you will have to instantiate the class `\phpDocumentor\Reflection\TypeResolver` and call its `resolve` method like this: ```php $typeResolver = new \phpDocumentor\Reflection\TypeResolver(); @@ -70,31 +77,30 @@ In this example you will receive a Value Object of class `\phpDocumentor\Reflect elements, one of type `\phpDocumentor\Reflection\Types\String_` and one of type `\phpDocumentor\Reflection\Types\Integer`. -The real power of this resolver is in its capability to expand partial class names into fully qualified class names; but -in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver -in which namespace the given expression occurs and which namespace aliases (or imports) apply. +The real power of this resolver is in its capability to expand partial class names into fully qualified class names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply. + +### Resolving nullable types + +Php 7.1 introduced nullable types e.g. `?string`. Type resolver will resolve the original type without the nullable notation `?` +just like it would do without the `?`. After that the type is wrapped in a `\phpDocumentor\Reflection\Types\Nullable` object. +The `Nullable` type has a method to fetch the actual type. ## Resolving an FQSEN -A Fully Qualified Structural Element Name is a reference to another element in your code bases and can be resolved using -the `\phpDocumentor\Reflection\FqsenResolver` class' `resolve` method, like this: +A Fully Qualified Structural Element Name is a reference to another element in your code bases and can be resolved using the `\phpDocumentor\Reflection\FqsenResolver` class' `resolve` method, like this: ```php $fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver(); $fqsen = $fqsenResolver->resolve('\phpDocumentor\Reflection\FqsenResolver::resolve()'); ``` -In this example we resolve a Fully Qualified Structural Element Name (meaning that it includes the full namespace, class -name and element name) and receive a Value Object of type `\phpDocumentor\Reflection\Fqsen`. +In this example we resolve a Fully Qualified Structural Element Name (meaning that it includes the full namespace, class name and element name) and receive a Value Object of type `\phpDocumentor\Reflection\Fqsen`. -The real power of this resolver is in its capability to expand partial element names into Fully Qualified Structural -Element Names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will -inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply. +The real power of this resolver is in its capability to expand partial element names into Fully Qualified Structural Element Names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply. ## Resolving partial Classes and Structural Element Names -Perhaps the best feature of this library is that it knows how to resolve partial class names into fully qualified class -names. +Perhaps the best feature of this library is that it knows how to resolve partial class names into fully qualified class names. For example, you have this file: @@ -116,9 +122,8 @@ class Classy ``` Suppose that you would want to resolve (and expand) the type in the `@var` tag and the element name in the `@see` tag. -For the resolvers to know how to expand partial names you have to provide a bit of _Context_ for them by instantiating -a new class named `\phpDocumentor\Reflection\Types\Context` with the name of the namespace and the aliases that are in -play. + +For the resolvers to know how to expand partial names you have to provide a bit of _Context_ for them by instantiating a new class named `\phpDocumentor\Reflection\Types\Context` with the name of the namespace and the aliases that are in play. ### Creating a Context @@ -131,9 +136,7 @@ $context = new \phpDocumentor\Reflection\Types\Context( ); ``` -Or by using the `\phpDocumentor\Reflection\Types\ContextFactory` to instantiate a new context based on a Reflector -object or by providing the namespace that you'd like to extract and the source code of the file in which the given -type expression occurs. +Or by using the `\phpDocumentor\Reflection\Types\ContextFactory` to instantiate a new context based on a Reflector object or by providing the namespace that you'd like to extract and the source code of the file in which the given type expression occurs. ```php $contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory(); @@ -149,8 +152,7 @@ $context = $contextFactory->createForNamespace('\My\Example', file_get_contents( ### Using the Context -After you have obtained a Context it is just a matter of passing it along with the `resolve` method of either Resolver -class as second argument and the Resolvers will take this into account when resolving partial names. +After you have obtained a Context it is just a matter of passing it along with the `resolve` method of either Resolver class as second argument and the Resolvers will take this into account when resolving partial names. To obtain the resolved class name for the `@var` tag in the example above you can do: @@ -159,24 +161,17 @@ $typeResolver = new \phpDocumentor\Reflection\TypeResolver(); $type = $typeResolver->resolve('Types\Context', $context); ``` -When you do this you will receive an object of class `\phpDocumentor\Reflection\Types\Object_` for which you can call -the `getFqsen` method to receive a Value Object that represents the complete FQSEN. So that would be -`phpDocumentor\Reflection\Types\Context`. +When you do this you will receive an object of class `\phpDocumentor\Reflection\Types\Object_` for which you can call the `getFqsen` method to receive a Value Object that represents the complete FQSEN. So that would be `phpDocumentor\Reflection\Types\Context`. > Why is the FQSEN wrapped in another object `Object_`? > -> The resolve method of the TypeResolver only returns object with the interface `Type` and the FQSEN is a common -> type that does not represent a Type. Also: in some cases a type can represent an "Untyped Object", meaning that it -> is an object (signified by the `object` keyword) but does not refer to a specific element using an FQSEN. +> The resolve method of the TypeResolver only returns object with the interface `Type` and the FQSEN is a common type that does not represent a Type. Also: in some cases a type can represent an "Untyped Object", meaning that it is an object (signified by the `object` keyword) but does not refer to a specific element using an FQSEN. -Another example is on how to resolve the FQSEN of a method as can be seen with the `@see` tag in the example above. To -resolve that you can do the following: +Another example is on how to resolve the FQSEN of a method as can be seen with the `@see` tag in the example above. To resolve that you can do the following: ```php $fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver(); $type = $fqsenResolver->resolve('Classy::otherFunction()', $context); ``` -Because Classy is a Class in the current namespace its FQSEN will have the `My\Example` namespace and by calling the -`resolve` method of the FQSEN Resolver you will receive an `Fqsen` object that refers to -`\My\Example\Classy::otherFunction()`. +Because Classy is a Class in the current namespace its FQSEN will have the `My\Example` namespace and by calling the `resolve` method of the FQSEN Resolver you will receive an `Fqsen` object that refers to `\My\Example\Classy::otherFunction()`. diff --git a/vendor/phpdocumentor/type-resolver/composer.json b/vendor/phpdocumentor/type-resolver/composer.json index 82ead15..4dbf623 100644 --- a/vendor/phpdocumentor/type-resolver/composer.json +++ b/vendor/phpdocumentor/type-resolver/composer.json @@ -1,27 +1,35 @@ { - "name": "phpdocumentor/type-resolver", - "type": "library", + "name": "phpdocumentor/type-resolver", + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "type": "library", "license": "MIT", "authors": [ - {"name": "Mike van Riel", "email": "me@mikevanriel.com"} + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } ], "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "*", + "psalm/phar": "^4.8" }, "autoload": { - "psr-4": {"phpDocumentor\\Reflection\\": ["src/"]} + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } }, "autoload-dev": { - "psr-4": {"phpDocumentor\\Reflection\\": ["tests/unit"]} - }, - "require-dev": { - "phpunit/phpunit": "^5.2||^4.8.24", - "mockery/mockery": "^0.9.4" + "psr-4": { + "phpDocumentor\\Reflection\\": ["tests/unit", "tests/benchmark"] + } }, "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-1.x": "1.x-dev" } } } diff --git a/vendor/phpdocumentor/type-resolver/src/FqsenResolver.php b/vendor/phpdocumentor/type-resolver/src/FqsenResolver.php index 9aa6ba3..068fa20 100644 --- a/vendor/phpdocumentor/type-resolver/src/FqsenResolver.php +++ b/vendor/phpdocumentor/type-resolver/src/FqsenResolver.php @@ -1,25 +1,36 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection; +use InvalidArgumentException; use phpDocumentor\Reflection\Types\Context; +use function explode; +use function implode; +use function strpos; + +/** + * Resolver for Fqsen using Context information + * + * @psalm-immutable + */ class FqsenResolver { /** @var string Definition of the NAMESPACE operator in PHP */ - const OPERATOR_NAMESPACE = '\\'; + private const OPERATOR_NAMESPACE = '\\'; - public function resolve($fqsen, Context $context = null) + public function resolve(string $fqsen, ?Context $context = null): Fqsen { if ($context === null) { $context = new Context(''); @@ -34,12 +45,8 @@ public function resolve($fqsen, Context $context = null) /** * Tests whether the given type is a Fully Qualified Structural Element Name. - * - * @param string $type - * - * @return bool */ - private function isFqsen($type) + private function isFqsen(string $type): bool { return strpos($type, self::OPERATOR_NAMESPACE) === 0; } @@ -48,13 +55,9 @@ private function isFqsen($type) * Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation * (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context. * - * @param string $type - * @param Context $context - * - * @return Fqsen - * @throws \InvalidArgumentException when type is not a valid FQSEN. + * @throws InvalidArgumentException When type is not a valid FQSEN. */ - private function resolvePartialStructuralElementName($type, Context $context) + private function resolvePartialStructuralElementName(string $type, Context $context): Fqsen { $typeParts = explode(self::OPERATOR_NAMESPACE, $type, 2); @@ -63,7 +66,7 @@ private function resolvePartialStructuralElementName($type, Context $context) // if the first segment is not an alias; prepend namespace name and return if (!isset($namespaceAliases[$typeParts[0]])) { $namespace = $context->getNamespace(); - if ('' !== $namespace) { + if ($namespace !== '') { $namespace .= self::OPERATOR_NAMESPACE; } diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoType.php b/vendor/phpdocumentor/type-resolver/src/PseudoType.php new file mode 100644 index 0000000..dd91ed7 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoType.php @@ -0,0 +1,19 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection; + +interface PseudoType extends Type +{ + public function underlyingType(): Type; +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php new file mode 100644 index 0000000..b693456 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/CallableString.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\String_; + +/** + * Value Object representing the type 'string'. + * + * @psalm-immutable + */ +final class CallableString extends String_ implements PseudoType +{ + public function underlyingType(): Type + { + return new String_(); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'callable-string'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/False_.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/False_.php new file mode 100644 index 0000000..4ec6885 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/False_.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link https://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\Boolean; + +use function class_alias; + +/** + * Value Object representing the PseudoType 'False', which is a Boolean type. + * + * @psalm-immutable + */ +final class False_ extends Boolean implements PseudoType +{ + public function underlyingType(): Type + { + return new Boolean(); + } + + public function __toString(): string + { + return 'false'; + } +} + +class_alias('\phpDocumentor\Reflection\PseudoTypes\False_', 'phpDocumentor\Reflection\Types\False_', false); diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php new file mode 100644 index 0000000..aa4d8db --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/HtmlEscapedString.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\String_; + +/** + * Value Object representing the type 'string'. + * + * @psalm-immutable + */ +final class HtmlEscapedString extends String_ implements PseudoType +{ + public function underlyingType(): Type + { + return new String_(); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'html-escaped-string'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php new file mode 100644 index 0000000..c5a3bc5 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php @@ -0,0 +1,61 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\Integer; + +/** + * Value Object representing the type 'int'. + * + * @psalm-immutable + */ +final class IntegerRange extends Integer implements PseudoType +{ + /** @var string */ + private $minValue; + + /** @var string */ + private $maxValue; + + public function __construct(string $minValue, string $maxValue) + { + $this->minValue = $minValue; + $this->maxValue = $maxValue; + } + + public function underlyingType(): Type + { + return new Integer(); + } + + public function getMinValue(): string + { + return $this->minValue; + } + + public function getMaxValue(): string + { + return $this->maxValue; + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'int<' . $this->minValue . ', ' . $this->maxValue . '>'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/List_.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/List_.php new file mode 100644 index 0000000..f9f0c6b --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/List_.php @@ -0,0 +1,50 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\Array_; +use phpDocumentor\Reflection\Types\Integer; +use phpDocumentor\Reflection\Types\Mixed_; + +/** + * Value Object representing the type 'list'. + * + * @psalm-immutable + */ +final class List_ extends Array_ implements PseudoType +{ + public function underlyingType(): Type + { + return new Array_(); + } + + public function __construct(?Type $valueType = null) + { + parent::__construct($valueType, new Integer()); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + if ($this->valueType instanceof Mixed_) { + return 'list'; + } + + return 'list<' . $this->valueType . '>'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.php new file mode 100644 index 0000000..690f782 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/LiteralString.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\String_; + +/** + * Value Object representing the type 'string'. + * + * @psalm-immutable + */ +final class LiteralString extends String_ implements PseudoType +{ + public function underlyingType(): Type + { + return new String_(); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'literal-string'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php new file mode 100644 index 0000000..6325492 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/LowercaseString.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\String_; + +/** + * Value Object representing the type 'string'. + * + * @psalm-immutable + */ +final class LowercaseString extends String_ implements PseudoType +{ + public function underlyingType(): Type + { + return new String_(); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'lowercase-string'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.php new file mode 100644 index 0000000..c51d3fe --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NegativeInteger.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\Integer; + +/** + * Value Object representing the type 'int'. + * + * @psalm-immutable + */ +final class NegativeInteger extends Integer implements PseudoType +{ + public function underlyingType(): Type + { + return new Integer(); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'negative-int'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php new file mode 100644 index 0000000..8640016 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyLowercaseString.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\String_; + +/** + * Value Object representing the type 'string'. + * + * @psalm-immutable + */ +final class NonEmptyLowercaseString extends String_ implements PseudoType +{ + public function underlyingType(): Type + { + return new String_(); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'non-empty-lowercase-string'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php new file mode 100644 index 0000000..d72d127 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NonEmptyString.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\String_; + +/** + * Value Object representing the type 'string'. + * + * @psalm-immutable + */ +final class NonEmptyString extends String_ implements PseudoType +{ + public function underlyingType(): Type + { + return new String_(); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'non-empty-string'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.php new file mode 100644 index 0000000..b62aa45 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/NumericString.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\String_; + +/** + * Value Object representing the type 'string'. + * + * @psalm-immutable + */ +final class NumericString extends String_ implements PseudoType +{ + public function underlyingType(): Type + { + return new String_(); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'numeric-string'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php new file mode 100644 index 0000000..46620cd --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/Numeric_.php @@ -0,0 +1,47 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\AggregatedType; +use phpDocumentor\Reflection\Types\Compound; +use phpDocumentor\Reflection\Types\Float_; +use phpDocumentor\Reflection\Types\Integer; + +/** + * Value Object representing the 'numeric' pseudo-type, which is either a numeric-string, integer or float. + * + * @psalm-immutable + */ +final class Numeric_ extends AggregatedType implements PseudoType +{ + public function __construct() + { + AggregatedType::__construct([new NumericString(), new Integer(), new Float_()], '|'); + } + + public function underlyingType(): Type + { + return new Compound([new NumericString(), new Integer(), new Float_()]); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'numeric'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.php new file mode 100644 index 0000000..c52184d --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/PositiveInteger.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\Integer; + +/** + * Value Object representing the type 'int'. + * + * @psalm-immutable + */ +final class PositiveInteger extends Integer implements PseudoType +{ + public function underlyingType(): Type + { + return new Integer(); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'positive-int'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.php new file mode 100644 index 0000000..ac217c2 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/TraitString.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\String_; + +/** + * Value Object representing the type 'string'. + * + * @psalm-immutable + */ +final class TraitString extends String_ implements PseudoType +{ + public function underlyingType(): Type + { + return new String_(); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'trait-string'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/PseudoTypes/True_.php b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/True_.php new file mode 100644 index 0000000..dc970b3 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/PseudoTypes/True_.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link https://phpdoc.org + */ + +namespace phpDocumentor\Reflection\PseudoTypes; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\Types\Boolean; + +use function class_alias; + +/** + * Value Object representing the PseudoType 'False', which is a Boolean type. + * + * @psalm-immutable + */ +final class True_ extends Boolean implements PseudoType +{ + public function underlyingType(): Type + { + return new Boolean(); + } + + public function __toString(): string + { + return 'true'; + } +} + +class_alias('\phpDocumentor\Reflection\PseudoTypes\True_', 'phpDocumentor\Reflection\Types\True_', false); diff --git a/vendor/phpdocumentor/type-resolver/src/Type.php b/vendor/phpdocumentor/type-resolver/src/Type.php index 33ca559..c71d8b0 100644 --- a/vendor/phpdocumentor/type-resolver/src/Type.php +++ b/vendor/phpdocumentor/type-resolver/src/Type.php @@ -1,18 +1,25 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection; +/** + * @psalm-immutable + */ interface Type { - public function __toString(); + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string; } diff --git a/vendor/phpdocumentor/type-resolver/src/TypeResolver.php b/vendor/phpdocumentor/type-resolver/src/TypeResolver.php index 08b2a5f..ca36026 100644 --- a/vendor/phpdocumentor/type-resolver/src/TypeResolver.php +++ b/vendor/phpdocumentor/type-resolver/src/TypeResolver.php @@ -1,68 +1,134 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection; +use ArrayIterator; +use InvalidArgumentException; +use phpDocumentor\Reflection\PseudoTypes\IntegerRange; +use phpDocumentor\Reflection\PseudoTypes\List_; use phpDocumentor\Reflection\Types\Array_; +use phpDocumentor\Reflection\Types\ArrayKey; +use phpDocumentor\Reflection\Types\ClassString; +use phpDocumentor\Reflection\Types\Collection; use phpDocumentor\Reflection\Types\Compound; use phpDocumentor\Reflection\Types\Context; +use phpDocumentor\Reflection\Types\Expression; +use phpDocumentor\Reflection\Types\Integer; +use phpDocumentor\Reflection\Types\InterfaceString; +use phpDocumentor\Reflection\Types\Intersection; use phpDocumentor\Reflection\Types\Iterable_; use phpDocumentor\Reflection\Types\Nullable; use phpDocumentor\Reflection\Types\Object_; +use phpDocumentor\Reflection\Types\String_; +use RuntimeException; + +use function array_key_exists; +use function array_pop; +use function array_values; +use function class_exists; +use function class_implements; +use function count; +use function current; +use function end; +use function in_array; +use function is_numeric; +use function key; +use function preg_split; +use function strpos; +use function strtolower; +use function trim; + +use const PREG_SPLIT_DELIM_CAPTURE; +use const PREG_SPLIT_NO_EMPTY; final class TypeResolver { /** @var string Definition of the ARRAY operator for types */ - const OPERATOR_ARRAY = '[]'; + private const OPERATOR_ARRAY = '[]'; /** @var string Definition of the NAMESPACE operator in PHP */ - const OPERATOR_NAMESPACE = '\\'; + private const OPERATOR_NAMESPACE = '\\'; + + /** @var int the iterator parser is inside a compound context */ + private const PARSER_IN_COMPOUND = 0; + + /** @var int the iterator parser is inside a nullable expression context */ + private const PARSER_IN_NULLABLE = 1; - /** @var string[] List of recognized keywords and unto which Value Object they map */ - private $keywords = array( + /** @var int the iterator parser is inside an array expression context */ + private const PARSER_IN_ARRAY_EXPRESSION = 2; + + /** @var int the iterator parser is inside a collection expression context */ + private const PARSER_IN_COLLECTION_EXPRESSION = 3; + + /** + * @var array<string, string> List of recognized keywords and unto which Value Object they map + * @psalm-var array<string, class-string<Type>> + */ + private $keywords = [ 'string' => Types\String_::class, + 'class-string' => Types\ClassString::class, + 'interface-string' => Types\InterfaceString::class, + 'html-escaped-string' => PseudoTypes\HtmlEscapedString::class, + 'lowercase-string' => PseudoTypes\LowercaseString::class, + 'non-empty-lowercase-string' => PseudoTypes\NonEmptyLowercaseString::class, + 'non-empty-string' => PseudoTypes\NonEmptyString::class, + 'numeric-string' => PseudoTypes\NumericString::class, + 'numeric' => PseudoTypes\Numeric_::class, + 'trait-string' => PseudoTypes\TraitString::class, 'int' => Types\Integer::class, 'integer' => Types\Integer::class, + 'positive-int' => PseudoTypes\PositiveInteger::class, + 'negative-int' => PseudoTypes\NegativeInteger::class, 'bool' => Types\Boolean::class, 'boolean' => Types\Boolean::class, + 'real' => Types\Float_::class, 'float' => Types\Float_::class, 'double' => Types\Float_::class, - 'object' => Object_::class, + 'object' => Types\Object_::class, 'mixed' => Types\Mixed_::class, - 'array' => Array_::class, + 'array' => Types\Array_::class, + 'array-key' => Types\ArrayKey::class, 'resource' => Types\Resource_::class, 'void' => Types\Void_::class, 'null' => Types\Null_::class, 'scalar' => Types\Scalar::class, 'callback' => Types\Callable_::class, 'callable' => Types\Callable_::class, - 'false' => Types\Boolean::class, - 'true' => Types\Boolean::class, + 'callable-string' => PseudoTypes\CallableString::class, + 'false' => PseudoTypes\False_::class, + 'true' => PseudoTypes\True_::class, + 'literal-string' => PseudoTypes\LiteralString::class, 'self' => Types\Self_::class, '$this' => Types\This::class, 'static' => Types\Static_::class, 'parent' => Types\Parent_::class, - 'iterable' => Iterable_::class, - ); + 'iterable' => Types\Iterable_::class, + 'never' => Types\Never_::class, + 'list' => PseudoTypes\List_::class, + ]; - /** @var FqsenResolver */ + /** + * @var FqsenResolver + * @psalm-readonly + */ private $fqsenResolver; /** * Initializes this TypeResolver with the means to create and resolve Fqsen objects. - * - * @param FqsenResolver $fqsenResolver */ - public function __construct(FqsenResolver $fqsenResolver = null) + public function __construct(?FqsenResolver $fqsenResolver = null) { $this->fqsenResolver = $fqsenResolver ?: new FqsenResolver(); } @@ -77,74 +143,257 @@ public function __construct(FqsenResolver $fqsenResolver = null) * This method only works as expected if the namespace and aliases are set; * no dynamic reflection is being performed here. * - * @param string $type The relative or absolute type. - * @param Context $context - * - * @uses Context::getNamespace() to determine with what to prefix the type name. * @uses Context::getNamespaceAliases() to check whether the first part of the relative type name should not be - * replaced with another namespace. + * replaced with another namespace. + * @uses Context::getNamespace() to determine with what to prefix the type name. * - * @return Type|null + * @param string $type The relative or absolute type. */ - public function resolve($type, Context $context = null) + public function resolve(string $type, ?Context $context = null): Type { - if (!is_string($type)) { - throw new \InvalidArgumentException( - 'Attempted to resolve type but it appeared not to be a string, received: ' . var_export($type, true) - ); - } - $type = trim($type); if (!$type) { - throw new \InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty'); + throw new InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty'); } if ($context === null) { $context = new Context(''); } + // split the type string into tokens `|`, `?`, `<`, `>`, `,`, `(`, `)`, `[]`, '<', '>' and type names + $tokens = preg_split( + '/(\\||\\?|<|>|&|, ?|\\(|\\)|\\[\\]+)/', + $type, + -1, + PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE + ); + + if ($tokens === false) { + throw new InvalidArgumentException('Unable to split the type string "' . $type . '" into tokens'); + } + + /** @var ArrayIterator<int, string|null> $tokenIterator */ + $tokenIterator = new ArrayIterator($tokens); + + return $this->parseTypes($tokenIterator, $context, self::PARSER_IN_COMPOUND); + } + + /** + * Analyse each tokens and creates types + * + * @param ArrayIterator<int, string|null> $tokens the iterator on tokens + * @param int $parserContext on of self::PARSER_* constants, indicating + * the context where we are in the parsing + */ + private function parseTypes(ArrayIterator $tokens, Context $context, int $parserContext): Type + { + $types = []; + $token = ''; + $compoundToken = '|'; + while ($tokens->valid()) { + $token = $tokens->current(); + if ($token === null) { + throw new RuntimeException( + 'Unexpected nullable character' + ); + } + + if ($token === '|' || $token === '&') { + if (count($types) === 0) { + throw new RuntimeException( + 'A type is missing before a type separator' + ); + } + + if ( + !in_array($parserContext, [ + self::PARSER_IN_COMPOUND, + self::PARSER_IN_ARRAY_EXPRESSION, + self::PARSER_IN_COLLECTION_EXPRESSION, + ], true) + ) { + throw new RuntimeException( + 'Unexpected type separator' + ); + } + + $compoundToken = $token; + $tokens->next(); + } elseif ($token === '?') { + if ( + !in_array($parserContext, [ + self::PARSER_IN_COMPOUND, + self::PARSER_IN_ARRAY_EXPRESSION, + self::PARSER_IN_COLLECTION_EXPRESSION, + ], true) + ) { + throw new RuntimeException( + 'Unexpected nullable character' + ); + } + + $tokens->next(); + $type = $this->parseTypes($tokens, $context, self::PARSER_IN_NULLABLE); + $types[] = new Nullable($type); + } elseif ($token === '(') { + $tokens->next(); + $type = $this->parseTypes($tokens, $context, self::PARSER_IN_ARRAY_EXPRESSION); + + $token = $tokens->current(); + if ($token === null) { // Someone did not properly close their array expression .. + break; + } + + $tokens->next(); + + $resolvedType = new Expression($type); + + $types[] = $resolvedType; + } elseif ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION && isset($token[0]) && $token[0] === ')') { + break; + } elseif ($token === '<') { + if (count($types) === 0) { + throw new RuntimeException( + 'Unexpected collection operator "<", class name is missing' + ); + } + + $classType = array_pop($types); + if ($classType !== null) { + if ((string) $classType === 'class-string') { + $types[] = $this->resolveClassString($tokens, $context); + } elseif ((string) $classType === 'int') { + $types[] = $this->resolveIntRange($tokens); + } elseif ((string) $classType === 'interface-string') { + $types[] = $this->resolveInterfaceString($tokens, $context); + } else { + $types[] = $this->resolveCollection($tokens, $classType, $context); + } + } + + $tokens->next(); + } elseif ( + $parserContext === self::PARSER_IN_COLLECTION_EXPRESSION + && ($token === '>' || trim($token) === ',') + ) { + break; + } elseif ($token === self::OPERATOR_ARRAY) { + end($types); + $last = key($types); + if ($last === null) { + throw new InvalidArgumentException('Unexpected array operator'); + } + + $lastItem = $types[$last]; + if ($lastItem instanceof Expression) { + $lastItem = $lastItem->getValueType(); + } + + $types[$last] = new Array_($lastItem); + + $tokens->next(); + } else { + $type = $this->resolveSingleType($token, $context); + $tokens->next(); + if ($parserContext === self::PARSER_IN_NULLABLE) { + return $type; + } + + $types[] = $type; + } + } + + if ($token === '|' || $token === '&') { + throw new RuntimeException( + 'A type is missing after a type separator' + ); + } + + if (count($types) === 0) { + if ($parserContext === self::PARSER_IN_NULLABLE) { + throw new RuntimeException( + 'A type is missing after a nullable character' + ); + } + + if ($parserContext === self::PARSER_IN_ARRAY_EXPRESSION) { + throw new RuntimeException( + 'A type is missing in an array expression' + ); + } + + if ($parserContext === self::PARSER_IN_COLLECTION_EXPRESSION) { + throw new RuntimeException( + 'A type is missing in a collection expression' + ); + } + } elseif (count($types) === 1) { + return current($types); + } + + if ($compoundToken === '|') { + return new Compound(array_values($types)); + } + + return new Intersection(array_values($types)); + } + + /** + * resolve the given type into a type object + * + * @param string $type the type string, representing a single type + * + * @return Type|Array_|Object_ + * + * @psalm-mutation-free + */ + private function resolveSingleType(string $type, Context $context): object + { switch (true) { - case $this->isNullableType($type): - return $this->resolveNullableType($type, $context); case $this->isKeyword($type): return $this->resolveKeyword($type); - case ($this->isCompoundType($type)): - return $this->resolveCompoundType($type, $context); - case $this->isTypedArray($type): - return $this->resolveTypedArray($type, $context); + case $this->isFqsen($type): return $this->resolveTypedObject($type); + case $this->isPartialStructuralElementName($type): return $this->resolveTypedObject($type, $context); + // @codeCoverageIgnoreStart default: // I haven't got the foggiest how the logic would come here but added this as a defense. - throw new \RuntimeException( + throw new RuntimeException( 'Unable to resolve type "' . $type . '", there is no known method to resolve it' ); } + // @codeCoverageIgnoreEnd } /** * Adds a keyword to the list of Keywords and associates it with a specific Value Object. * - * @param string $keyword - * @param string $typeClassName - * - * @return void + * @psalm-param class-string<Type> $typeClassName */ - public function addKeyword($keyword, $typeClassName) + public function addKeyword(string $keyword, string $typeClassName): void { if (!class_exists($typeClassName)) { - throw new \InvalidArgumentException( + throw new InvalidArgumentException( + 'The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class' + . ' but we could not find the class ' . $typeClassName + ); + } + + $interfaces = class_implements($typeClassName); + if ($interfaces === false) { + throw new InvalidArgumentException( 'The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class' . ' but we could not find the class ' . $typeClassName ); } - if (!in_array(Type::class, class_implements($typeClassName))) { - throw new \InvalidArgumentException( + if (!in_array(Type::class, $interfaces, true)) { + throw new InvalidArgumentException( 'The class "' . $typeClassName . '" must implement the interface "phpDocumentor\Reflection\Type"' ); } @@ -152,28 +401,16 @@ public function addKeyword($keyword, $typeClassName) $this->keywords[$keyword] = $typeClassName; } - /** - * Detects whether the given type represents an array. - * - * @param string $type A relative or absolute type as defined in the phpDocumentor documentation. - * - * @return bool - */ - private function isTypedArray($type) - { - return substr($type, -2) === self::OPERATOR_ARRAY; - } - /** * Detects whether the given type represents a PHPDoc keyword. * * @param string $type A relative or absolute type as defined in the phpDocumentor documentation. * - * @return bool + * @psalm-mutation-free */ - private function isKeyword($type) + private function isKeyword(string $type): bool { - return in_array(strtolower($type), array_keys($this->keywords), true); + return array_key_exists(strtolower($type), $this->keywords); } /** @@ -181,118 +418,283 @@ private function isKeyword($type) * * @param string $type A relative or absolute type as defined in the phpDocumentor documentation. * - * @return bool + * @psalm-mutation-free */ - private function isPartialStructuralElementName($type) + private function isPartialStructuralElementName(string $type): bool { - return ($type[0] !== self::OPERATOR_NAMESPACE) && !$this->isKeyword($type); + return (isset($type[0]) && $type[0] !== self::OPERATOR_NAMESPACE) && !$this->isKeyword($type); } /** * Tests whether the given type is a Fully Qualified Structural Element Name. * - * @param string $type - * - * @return bool + * @psalm-mutation-free */ - private function isFqsen($type) + private function isFqsen(string $type): bool { return strpos($type, self::OPERATOR_NAMESPACE) === 0; } /** - * Tests whether the given type is a compound type (i.e. `string|int`). - * - * @param string $type + * Resolves the given keyword (such as `string`) into a Type object representing that keyword. * - * @return bool + * @psalm-mutation-free */ - private function isCompoundType($type) + private function resolveKeyword(string $type): Type { - return strpos($type, '|') !== false; + $className = $this->keywords[strtolower($type)]; + + return new $className(); } /** - * Test whether the given type is a nullable type (i.e. `?string`) - * - * @param string $type + * Resolves the given FQSEN string into an FQSEN object. * - * @return bool + * @psalm-mutation-free */ - private function isNullableType($type) + private function resolveTypedObject(string $type, ?Context $context = null): Object_ { - return $type[0] === '?'; + return new Object_($this->fqsenResolver->resolve($type, $context)); } /** - * Resolves the given typed array string (i.e. `string[]`) into an Array object with the right types set. - * - * @param string $type - * @param Context $context + * Resolves class string * - * @return Array_ + * @param ArrayIterator<int, (string|null)> $tokens */ - private function resolveTypedArray($type, Context $context) + private function resolveClassString(ArrayIterator $tokens, Context $context): Type { - return new Array_($this->resolve(substr($type, 0, -2), $context)); + $tokens->next(); + + $classType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION); + + if (!$classType instanceof Object_ || $classType->getFqsen() === null) { + throw new RuntimeException( + $classType . ' is not a class string' + ); + } + + $token = $tokens->current(); + if ($token !== '>') { + if (empty($token)) { + throw new RuntimeException( + 'class-string: ">" is missing' + ); + } + + throw new RuntimeException( + 'Unexpected character "' . $token . '", ">" is missing' + ); + } + + return new ClassString($classType->getFqsen()); } /** - * Resolves the given keyword (such as `string`) into a Type object representing that keyword. - * - * @param string $type + * Resolves integer ranges * - * @return Type + * @param ArrayIterator<int, (string|null)> $tokens */ - private function resolveKeyword($type) + private function resolveIntRange(ArrayIterator $tokens): Type { - $className = $this->keywords[strtolower($type)]; + $tokens->next(); - return new $className(); + $token = ''; + $minValue = null; + $maxValue = null; + $commaFound = false; + $tokenCounter = 0; + while ($tokens->valid()) { + $tokenCounter++; + $token = $tokens->current(); + if ($token === null) { + throw new RuntimeException( + 'Unexpected nullable character' + ); + } + + $token = trim($token); + + if ($token === '>') { + break; + } + + if ($token === ',') { + $commaFound = true; + } + + if ($commaFound === false && $minValue === null) { + if (is_numeric($token) || $token === 'max' || $token === 'min') { + $minValue = $token; + } + } + + if ($commaFound === true && $maxValue === null) { + if (is_numeric($token) || $token === 'max' || $token === 'min') { + $maxValue = $token; + } + } + + $tokens->next(); + } + + if ($token !== '>') { + if (empty($token)) { + throw new RuntimeException( + 'interface-string: ">" is missing' + ); + } + + throw new RuntimeException( + 'Unexpected character "' . $token . '", ">" is missing' + ); + } + + if ($minValue === null || $maxValue === null || $tokenCounter > 4) { + throw new RuntimeException( + 'int<min,max> has not the correct format' + ); + } + + return new IntegerRange($minValue, $maxValue); } /** - * Resolves the given FQSEN string into an FQSEN object. + * Resolves class string * - * @param string $type - * @param Context|null $context - * - * @return Object_ + * @param ArrayIterator<int, (string|null)> $tokens */ - private function resolveTypedObject($type, Context $context = null) + private function resolveInterfaceString(ArrayIterator $tokens, Context $context): Type { - return new Object_($this->fqsenResolver->resolve($type, $context)); + $tokens->next(); + + $classType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION); + + if (!$classType instanceof Object_ || $classType->getFqsen() === null) { + throw new RuntimeException( + $classType . ' is not a interface string' + ); + } + + $token = $tokens->current(); + if ($token !== '>') { + if (empty($token)) { + throw new RuntimeException( + 'interface-string: ">" is missing' + ); + } + + throw new RuntimeException( + 'Unexpected character "' . $token . '", ">" is missing' + ); + } + + return new InterfaceString($classType->getFqsen()); } /** - * Resolves a compound type (i.e. `string|int`) into the appropriate Type objects or FQSEN. + * Resolves the collection values and keys * - * @param string $type - * @param Context $context + * @param ArrayIterator<int, (string|null)> $tokens * - * @return Compound + * @return Array_|Iterable_|Collection */ - private function resolveCompoundType($type, Context $context) + private function resolveCollection(ArrayIterator $tokens, Type $classType, Context $context): Type { - $types = []; + $isArray = ((string) $classType === 'array'); + $isIterable = ((string) $classType === 'iterable'); + $isList = ((string) $classType === 'list'); + + // allow only "array", "iterable" or class name before "<" + if ( + !$isArray && !$isIterable && !$isList + && (!$classType instanceof Object_ || $classType->getFqsen() === null) + ) { + throw new RuntimeException( + $classType . ' is not a collection' + ); + } + + $tokens->next(); + + $valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION); + $keyType = null; + + $token = $tokens->current(); + if ($token !== null && trim($token) === ',' && !$isList) { + // if we have a comma, then we just parsed the key type, not the value type + $keyType = $valueType; + if ($isArray) { + // check the key type for an "array" collection. We allow only + // strings or integers. + if ( + !$keyType instanceof ArrayKey && + !$keyType instanceof String_ && + !$keyType instanceof Integer && + !$keyType instanceof Compound + ) { + throw new RuntimeException( + 'An array can have only integers or strings as keys' + ); + } + + if ($keyType instanceof Compound) { + foreach ($keyType->getIterator() as $item) { + if ( + !$item instanceof ArrayKey && + !$item instanceof String_ && + !$item instanceof Integer + ) { + throw new RuntimeException( + 'An array can have only integers or strings as keys' + ); + } + } + } + } + + $tokens->next(); + // now let's parse the value type + $valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION); + } + + $token = $tokens->current(); + if ($token !== '>') { + if (empty($token)) { + throw new RuntimeException( + 'Collection: ">" is missing' + ); + } + + throw new RuntimeException( + 'Unexpected character "' . $token . '", ">" is missing' + ); + } + + if ($isArray) { + return new Array_($valueType, $keyType); + } + + if ($isIterable) { + return new Iterable_($valueType, $keyType); + } + + if ($isList) { + return new List_($valueType); + } - foreach (explode('|', $type) as $part) { - $types[] = $this->resolve($part, $context); + if ($classType instanceof Object_) { + return $this->makeCollectionFromObject($classType, $valueType, $keyType); } - return new Compound($types); + throw new RuntimeException('Invalid $classType provided'); } /** - * Resolve nullable types (i.e. `?string`) into a Nullable type wrapper - * - * @param string $type - * @param Context $context - * - * @return Nullable + * @psalm-pure */ - private function resolveNullableType($type, Context $context) + private function makeCollectionFromObject(Object_ $object, Type $valueType, ?Type $keyType = null): Collection { - return new Nullable($this->resolve(ltrim($type, '?'), $context)); + return new Collection($object->getFqsen(), $valueType, $keyType); } } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/AbstractList.php b/vendor/phpdocumentor/type-resolver/src/Types/AbstractList.php new file mode 100644 index 0000000..b674862 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/Types/AbstractList.php @@ -0,0 +1,83 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Represents a list of values. This is an abstract class for Array_ and Collection. + * + * @psalm-immutable + */ +abstract class AbstractList implements Type +{ + /** @var Type */ + protected $valueType; + + /** @var Type|null */ + protected $keyType; + + /** @var Type */ + protected $defaultKeyType; + + /** + * Initializes this representation of an array with the given Type. + */ + public function __construct(?Type $valueType = null, ?Type $keyType = null) + { + if ($valueType === null) { + $valueType = new Mixed_(); + } + + $this->valueType = $valueType; + $this->defaultKeyType = new Compound([new String_(), new Integer()]); + $this->keyType = $keyType; + } + + /** + * Returns the type for the keys of this array. + */ + public function getKeyType(): Type + { + return $this->keyType ?? $this->defaultKeyType; + } + + /** + * Returns the value for the keys of this array. + */ + public function getValueType(): Type + { + return $this->valueType; + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + if ($this->keyType) { + return 'array<' . $this->keyType . ',' . $this->valueType . '>'; + } + + if ($this->valueType instanceof Mixed_) { + return 'array'; + } + + if ($this->valueType instanceof Compound) { + return '(' . $this->valueType . ')[]'; + } + + return $this->valueType . '[]'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/Types/AggregatedType.php b/vendor/phpdocumentor/type-resolver/src/Types/AggregatedType.php new file mode 100644 index 0000000..472a1cd --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/Types/AggregatedType.php @@ -0,0 +1,125 @@ +<?php +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +declare(strict_types=1); + +namespace phpDocumentor\Reflection\Types; + +use ArrayIterator; +use IteratorAggregate; +use phpDocumentor\Reflection\Type; + +use function array_key_exists; +use function implode; + +/** + * Base class for aggregated types like Compound and Intersection + * + * A Aggregated Type is not so much a special keyword or object reference but is a series of Types that are separated + * using separator. + * + * @psalm-immutable + * @template-implements IteratorAggregate<int, Type> + */ +abstract class AggregatedType implements Type, IteratorAggregate +{ + /** + * @psalm-allow-private-mutation + * @var array<int, Type> + */ + private $types = []; + + /** @var string */ + private $token; + + /** + * @param array<Type> $types + */ + public function __construct(array $types, string $token) + { + foreach ($types as $type) { + $this->add($type); + } + + $this->token = $token; + } + + /** + * Returns the type at the given index. + */ + public function get(int $index): ?Type + { + if (!$this->has($index)) { + return null; + } + + return $this->types[$index]; + } + + /** + * Tests if this compound type has a type with the given index. + */ + public function has(int $index): bool + { + return array_key_exists($index, $this->types); + } + + /** + * Tests if this compound type contains the given type. + */ + public function contains(Type $type): bool + { + foreach ($this->types as $typePart) { + // if the type is duplicate; do not add it + if ((string) $typePart === (string) $type) { + return true; + } + } + + return false; + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return implode($this->token, $this->types); + } + + /** + * @return ArrayIterator<int, Type> + */ + public function getIterator(): ArrayIterator + { + return new ArrayIterator($this->types); + } + + /** + * @psalm-suppress ImpureMethodCall + */ + private function add(Type $type): void + { + if ($type instanceof self) { + foreach ($type->getIterator() as $subType) { + $this->add($subType); + } + + return; + } + + // if the type is duplicate; do not add it + if ($this->contains($type)) { + return; + } + + $this->types[] = $type; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/Types/ArrayKey.php b/vendor/phpdocumentor/type-resolver/src/Types/ArrayKey.php new file mode 100644 index 0000000..cf86df0 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/Types/ArrayKey.php @@ -0,0 +1,42 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing a array-key Type. + * + * A array-key Type is the supertype (but not a union) of int and string. + * + * @psalm-immutable + */ +final class ArrayKey extends AggregatedType implements PseudoType +{ + public function __construct() + { + parent::__construct([new String_(), new Integer()], '|'); + } + + public function underlyingType(): Type + { + return new Compound([new String_(), new Integer()]); + } + + public function __toString(): string + { + return 'array-key'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Array_.php b/vendor/phpdocumentor/type-resolver/src/Types/Array_.php index 49b7c6e..bc17225 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Array_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Array_.php @@ -1,19 +1,18 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\Types; -use phpDocumentor\Reflection\Type; - /** * Represents an array type as described in the PSR-5, the PHPDoc Standard. * @@ -22,65 +21,9 @@ * 1. Untyped (`array`), where the key and value type is unknown and hence classified as 'Mixed_'. * 2. Types (`string[]`), where the value type is provided by preceding an opening and closing square bracket with a * type name. + * + * @psalm-immutable */ -final class Array_ implements Type +class Array_ extends AbstractList { - /** @var Type */ - private $valueType; - - /** @var Type */ - private $keyType; - - /** - * Initializes this representation of an array with the given Type or Fqsen. - * - * @param Type $valueType - * @param Type $keyType - */ - public function __construct(Type $valueType = null, Type $keyType = null) - { - if ($keyType === null) { - $keyType = new Compound([ new String_(), new Integer() ]); - } - if ($valueType === null) { - $valueType = new Mixed_(); - } - - $this->valueType = $valueType; - $this->keyType = $keyType; - } - - /** - * Returns the type for the keys of this array. - * - * @return Type - */ - public function getKeyType() - { - return $this->keyType; - } - - /** - * Returns the value for the keys of this array. - * - * @return Type - */ - public function getValueType() - { - return $this->valueType; - } - - /** - * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string - */ - public function __toString() - { - if ($this->valueType instanceof Mixed_) { - return 'array'; - } - - return $this->valueType . '[]'; - } } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Boolean.php b/vendor/phpdocumentor/type-resolver/src/Types/Boolean.php index f82b19e..8b1a3f3 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Boolean.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Boolean.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,15 +17,15 @@ /** * Value Object representing a Boolean type. + * + * @psalm-immutable */ -final class Boolean implements Type +class Boolean implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'bool'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Callable_.php b/vendor/phpdocumentor/type-resolver/src/Types/Callable_.php index 68ebfbd..4e67aa4 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Callable_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Callable_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,15 +17,15 @@ /** * Value Object representing a Callable type. + * + * @psalm-immutable */ final class Callable_ implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'callable'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/ClassString.php b/vendor/phpdocumentor/type-resolver/src/Types/ClassString.php new file mode 100644 index 0000000..fbdd879 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/Types/ClassString.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Fqsen; +use phpDocumentor\Reflection\PseudoType; +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the type 'string'. + * + * @psalm-immutable + */ +final class ClassString extends String_ implements PseudoType +{ + /** @var Fqsen|null */ + private $fqsen; + + /** + * Initializes this representation of a class string with the given Fqsen. + */ + public function __construct(?Fqsen $fqsen = null) + { + $this->fqsen = $fqsen; + } + + public function underlyingType(): Type + { + return new String_(); + } + + /** + * Returns the FQSEN associated with this object. + */ + public function getFqsen(): ?Fqsen + { + return $this->fqsen; + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + if ($this->fqsen === null) { + return 'class-string'; + } + + return 'class-string<' . (string) $this->fqsen . '>'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Collection.php b/vendor/phpdocumentor/type-resolver/src/Types/Collection.php new file mode 100644 index 0000000..943cc22 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/Types/Collection.php @@ -0,0 +1,68 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Fqsen; +use phpDocumentor\Reflection\Type; + +/** + * Represents a collection type as described in the PSR-5, the PHPDoc Standard. + * + * A collection can be represented in two forms: + * + * 1. `ACollectionObject<aValueType>` + * 2. `ACollectionObject<aValueType,aKeyType>` + * + * - ACollectionObject can be 'array' or an object that can act as an array + * - aValueType and aKeyType can be any type expression + * + * @psalm-immutable + */ +final class Collection extends AbstractList +{ + /** @var Fqsen|null */ + private $fqsen; + + /** + * Initializes this representation of an array with the given Type or Fqsen. + */ + public function __construct(?Fqsen $fqsen, Type $valueType, ?Type $keyType = null) + { + parent::__construct($valueType, $keyType); + + $this->fqsen = $fqsen; + } + + /** + * Returns the FQSEN associated with this object. + */ + public function getFqsen(): ?Fqsen + { + return $this->fqsen; + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + $objectType = (string) ($this->fqsen ?? 'object'); + + if ($this->keyType === null) { + return $objectType . '<' . $this->valueType . '>'; + } + + return $objectType . '<' . $this->keyType . ',' . $this->valueType . '>'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Compound.php b/vendor/phpdocumentor/type-resolver/src/Types/Compound.php index be986c3..ad426cc 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Compound.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Compound.php @@ -1,19 +1,18 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\Types; -use ArrayIterator; -use IteratorAggregate; use phpDocumentor\Reflection\Type; /** @@ -22,72 +21,18 @@ * A Compound Type is not so much a special keyword or object reference but is a series of Types that are separated * using an OR operator (`|`). This combination of types signifies that whatever is associated with this compound type * may contain a value with any of the given types. + * + * @psalm-immutable */ -final class Compound implements Type, IteratorAggregate +final class Compound extends AggregatedType { - /** @var Type[] */ - private $types; - /** * Initializes a compound type (i.e. `string|int`) and tests if the provided types all implement the Type interface. * - * @param Type[] $types - * @throws \InvalidArgumentException when types are not all instance of Type + * @param array<Type> $types */ public function __construct(array $types) { - foreach ($types as $type) { - if (!$type instanceof Type) { - throw new \InvalidArgumentException('A compound type can only have other types as elements'); - } - } - - $this->types = $types; - } - - /** - * Returns the type at the given index. - * - * @param integer $index - * - * @return Type|null - */ - public function get($index) - { - if (!$this->has($index)) { - return null; - } - - return $this->types[$index]; - } - - /** - * Tests if this compound type has a type with the given index. - * - * @param integer $index - * - * @return bool - */ - public function has($index) - { - return isset($this->types[$index]); - } - - /** - * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string - */ - public function __toString() - { - return implode('|', $this->types); - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - return new ArrayIterator($this->types); + parent::__construct($types, '|'); } } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Context.php b/vendor/phpdocumentor/type-resolver/src/Types/Context.php index 4e9ce5a..79aadaf 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Context.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Context.php @@ -1,17 +1,22 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\Types; +use function strlen; +use function substr; +use function trim; + /** * Provides information about the Context in which the DocBlock occurs that receives this context. * @@ -25,32 +30,39 @@ * * @see ContextFactory::createFromClassReflector() * @see ContextFactory::createForNamespace() + * + * @psalm-immutable */ final class Context { /** @var string The current namespace. */ private $namespace; - /** @var array List of namespace aliases => Fully Qualified Namespace. */ + /** + * @var string[] List of namespace aliases => Fully Qualified Namespace. + * @psalm-var array<string, string> + */ private $namespaceAliases; /** * Initializes the new context and normalizes all passed namespaces to be in Qualified Namespace Name (QNN) * format (without a preceding `\`). * - * @param string $namespace The namespace where this DocBlock resides in. - * @param array $namespaceAliases List of namespace aliases => Fully Qualified Namespace. + * @param string $namespace The namespace where this DocBlock resides in. + * @param string[] $namespaceAliases List of namespace aliases => Fully Qualified Namespace. + * @psalm-param array<string, string> $namespaceAliases */ - public function __construct($namespace, array $namespaceAliases = []) + public function __construct(string $namespace, array $namespaceAliases = []) { - $this->namespace = ('global' !== $namespace && 'default' !== $namespace) - ? trim((string)$namespace, '\\') + $this->namespace = $namespace !== 'global' && $namespace !== 'default' + ? trim($namespace, '\\') : ''; foreach ($namespaceAliases as $alias => $fqnn) { if ($fqnn[0] === '\\') { $fqnn = substr($fqnn, 1); } + if ($fqnn[strlen($fqnn) - 1] === '\\') { $fqnn = substr($fqnn, 0, -1); } @@ -63,10 +75,8 @@ public function __construct($namespace, array $namespaceAliases = []) /** * Returns the Qualified Namespace Name (thus without `\` in front) where the associated element is in. - * - * @return string */ - public function getNamespace() + public function getNamespace(): string { return $this->namespace; } @@ -76,8 +86,9 @@ public function getNamespace() * the alias for the imported Namespace. * * @return string[] + * @psalm-return array<string, string> */ - public function getNamespaceAliases() + public function getNamespaceAliases(): array { return $this->namespaceAliases; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php b/vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php index 30936a3..892ee0f 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php @@ -1,17 +1,60 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\Types; +use ArrayIterator; +use InvalidArgumentException; +use ReflectionClass; +use ReflectionClassConstant; +use ReflectionMethod; +use ReflectionParameter; +use ReflectionProperty; +use Reflector; +use RuntimeException; +use UnexpectedValueException; + +use function define; +use function defined; +use function file_exists; +use function file_get_contents; +use function get_class; +use function in_array; +use function is_string; +use function strrpos; +use function substr; +use function token_get_all; +use function trim; + +use const T_AS; +use const T_CLASS; +use const T_CURLY_OPEN; +use const T_DOLLAR_OPEN_CURLY_BRACES; +use const T_NAME_FULLY_QUALIFIED; +use const T_NAME_QUALIFIED; +use const T_NAMESPACE; +use const T_NS_SEPARATOR; +use const T_STRING; +use const T_USE; + +if (!defined('T_NAME_QUALIFIED')) { + define('T_NAME_QUALIFIED', 'T_NAME_QUALIFIED'); +} + +if (!defined('T_NAME_FULLY_QUALIFIED')) { + define('T_NAME_FULLY_QUALIFIED', 'T_NAME_FULLY_QUALIFIED'); +} + /** * Convenience class to create a Context for DocBlocks when not using the Reflection Component of phpDocumentor. * @@ -24,31 +67,92 @@ final class ContextFactory { /** The literal used at the end of a use statement. */ - const T_LITERAL_END_OF_USE = ';'; + private const T_LITERAL_END_OF_USE = ';'; /** The literal used between sets of use statements */ - const T_LITERAL_USE_SEPARATOR = ','; + private const T_LITERAL_USE_SEPARATOR = ','; /** * Build a Context given a Class Reflection. * - * @param \Reflector $reflector - * * @see Context for more information on Contexts. - * - * @return Context */ - public function createFromReflector(\Reflector $reflector) + public function createFromReflector(Reflector $reflector): Context { - if (method_exists($reflector, 'getDeclaringClass')) { - $reflector = $reflector->getDeclaringClass(); + if ($reflector instanceof ReflectionClass) { + //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable + /** @var ReflectionClass<object> $reflector */ + + return $this->createFromReflectionClass($reflector); + } + + if ($reflector instanceof ReflectionParameter) { + return $this->createFromReflectionParameter($reflector); + } + + if ($reflector instanceof ReflectionMethod) { + return $this->createFromReflectionMethod($reflector); + } + + if ($reflector instanceof ReflectionProperty) { + return $this->createFromReflectionProperty($reflector); + } + + if ($reflector instanceof ReflectionClassConstant) { + return $this->createFromReflectionClassConstant($reflector); } - $fileName = $reflector->getFileName(); - $namespace = $reflector->getNamespaceName(); + throw new UnexpectedValueException('Unhandled \Reflector instance given: ' . get_class($reflector)); + } + + private function createFromReflectionParameter(ReflectionParameter $parameter): Context + { + $class = $parameter->getDeclaringClass(); + if (!$class) { + throw new InvalidArgumentException('Unable to get class of ' . $parameter->getName()); + } + + return $this->createFromReflectionClass($class); + } + + private function createFromReflectionMethod(ReflectionMethod $method): Context + { + $class = $method->getDeclaringClass(); + + return $this->createFromReflectionClass($class); + } + + private function createFromReflectionProperty(ReflectionProperty $property): Context + { + $class = $property->getDeclaringClass(); + + return $this->createFromReflectionClass($class); + } + + private function createFromReflectionClassConstant(ReflectionClassConstant $constant): Context + { + //phpcs:ignore SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.MissingVariable + /** @phpstan-var ReflectionClass<object> $class */ + $class = $constant->getDeclaringClass(); + + return $this->createFromReflectionClass($class); + } + + /** + * @phpstan-param ReflectionClass<object> $class + */ + private function createFromReflectionClass(ReflectionClass $class): Context + { + $fileName = $class->getFileName(); + $namespace = $class->getNamespaceName(); + + if (is_string($fileName) && file_exists($fileName)) { + $contents = file_get_contents($fileName); + if ($contents === false) { + throw new RuntimeException('Unable to read file "' . $fileName . '"'); + } - if (file_exists($fileName)) { - return $this->createForNamespace($namespace, file_get_contents($fileName)); + return $this->createForNamespace($namespace, $contents); } return new Context($namespace, []); @@ -57,22 +161,22 @@ public function createFromReflector(\Reflector $reflector) /** * Build a Context for a namespace in the provided file contents. * - * @param string $namespace It does not matter if a `\` precedes the namespace name, this method first normalizes. - * @param string $fileContents the file's contents to retrieve the aliases from with the given namespace. - * * @see Context for more information on Contexts. * - * @return Context + * @param string $namespace It does not matter if a `\` precedes the namespace name, + * this method first normalizes. + * @param string $fileContents The file's contents to retrieve the aliases from with the given namespace. */ - public function createForNamespace($namespace, $fileContents) + public function createForNamespace(string $namespace, string $fileContents): Context { - $namespace = trim($namespace, '\\'); - $useStatements = []; + $namespace = trim($namespace, '\\'); + $useStatements = []; $currentNamespace = ''; - $tokens = new \ArrayIterator(token_get_all($fileContents)); + $tokens = new ArrayIterator(token_get_all($fileContents)); while ($tokens->valid()) { - switch ($tokens->current()[0]) { + $currentToken = $tokens->current(); + switch ($currentToken[0]) { case T_NAMESPACE: $currentNamespace = $this->parseNamespace($tokens); break; @@ -80,30 +184,37 @@ public function createForNamespace($namespace, $fileContents) // Fast-forward the iterator through the class so that any // T_USE tokens found within are skipped - these are not // valid namespace use statements so should be ignored. - $braceLevel = 0; + $braceLevel = 0; $firstBraceFound = false; while ($tokens->valid() && ($braceLevel > 0 || !$firstBraceFound)) { - if ($tokens->current() === '{' - || $tokens->current()[0] === T_CURLY_OPEN - || $tokens->current()[0] === T_DOLLAR_OPEN_CURLY_BRACES) { + $currentToken = $tokens->current(); + if ( + $currentToken === '{' + || in_array($currentToken[0], [T_CURLY_OPEN, T_DOLLAR_OPEN_CURLY_BRACES], true) + ) { if (!$firstBraceFound) { $firstBraceFound = true; } - $braceLevel++; + + ++$braceLevel; } - if ($tokens->current() === '}') { - $braceLevel--; + if ($currentToken === '}') { + --$braceLevel; } + $tokens->next(); } + break; case T_USE: if ($currentNamespace === $namespace) { - $useStatements = array_merge($useStatements, $this->parseUseStatement($tokens)); + $useStatements += $this->parseUseStatement($tokens); } + break; } + $tokens->next(); } @@ -113,18 +224,16 @@ public function createForNamespace($namespace, $fileContents) /** * Deduce the name from tokens when we are at the T_NAMESPACE token. * - * @param \ArrayIterator $tokens - * - * @return string + * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens */ - private function parseNamespace(\ArrayIterator $tokens) + private function parseNamespace(ArrayIterator $tokens): string { // skip to the first string or namespace separator $this->skipToNextStringOrNamespaceSeparator($tokens); $name = ''; - while ($tokens->valid() && ($tokens->current()[0] === T_STRING || $tokens->current()[0] === T_NS_SEPARATOR) - ) { + $acceptedTokens = [T_STRING, T_NS_SEPARATOR, T_NAME_QUALIFIED]; + while ($tokens->valid() && in_array($tokens->current()[0], $acceptedTokens, true)) { $name .= $tokens->current()[1]; $tokens->next(); } @@ -135,22 +244,22 @@ private function parseNamespace(\ArrayIterator $tokens) /** * Deduce the names of all imports when we are at the T_USE token. * - * @param \ArrayIterator $tokens + * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens * * @return string[] + * @psalm-return array<string, string> */ - private function parseUseStatement(\ArrayIterator $tokens) + private function parseUseStatement(ArrayIterator $tokens): array { $uses = []; - $continue = true; - while ($continue) { + while ($tokens->valid()) { $this->skipToNextStringOrNamespaceSeparator($tokens); - list($alias, $fqnn) = $this->extractUseStatement($tokens); - $uses[$alias] = $fqnn; - if ($tokens->current()[0] === self::T_LITERAL_END_OF_USE) { - $continue = false; + $uses += $this->extractUseStatements($tokens); + $currentToken = $tokens->current(); + if ($currentToken[0] === self::T_LITERAL_END_OF_USE) { + return $uses; } } @@ -160,51 +269,152 @@ private function parseUseStatement(\ArrayIterator $tokens) /** * Fast-forwards the iterator as longs as we don't encounter a T_STRING or T_NS_SEPARATOR token. * - * @param \ArrayIterator $tokens - * - * @return void + * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens */ - private function skipToNextStringOrNamespaceSeparator(\ArrayIterator $tokens) + private function skipToNextStringOrNamespaceSeparator(ArrayIterator $tokens): void { - while ($tokens->valid() && ($tokens->current()[0] !== T_STRING) && ($tokens->current()[0] !== T_NS_SEPARATOR)) { + while ($tokens->valid()) { + $currentToken = $tokens->current(); + if (in_array($currentToken[0], [T_STRING, T_NS_SEPARATOR], true)) { + break; + } + + if ($currentToken[0] === T_NAME_QUALIFIED) { + break; + } + + if (defined('T_NAME_FULLY_QUALIFIED') && $currentToken[0] === T_NAME_FULLY_QUALIFIED) { + break; + } + $tokens->next(); } } /** * Deduce the namespace name and alias of an import when we are at the T_USE token or have not reached the end of - * a USE statement yet. + * a USE statement yet. This will return a key/value array of the alias => namespace. + * + * @param ArrayIterator<int, string|array{0:int,1:string,2:int}> $tokens * - * @param \ArrayIterator $tokens + * @return string[] + * @psalm-return array<string, string> * - * @return string + * @psalm-suppress TypeDoesNotContainType */ - private function extractUseStatement(\ArrayIterator $tokens) + private function extractUseStatements(ArrayIterator $tokens): array { - $result = ['']; - while ($tokens->valid() - && ($tokens->current()[0] !== self::T_LITERAL_USE_SEPARATOR) - && ($tokens->current()[0] !== self::T_LITERAL_END_OF_USE) - ) { - if ($tokens->current()[0] === T_AS) { - $result[] = ''; + $extractedUseStatements = []; + $groupedNs = ''; + $currentNs = ''; + $currentAlias = ''; + $state = 'start'; + + while ($tokens->valid()) { + $currentToken = $tokens->current(); + $tokenId = is_string($currentToken) ? $currentToken : $currentToken[0]; + $tokenValue = is_string($currentToken) ? null : $currentToken[1]; + switch ($state) { + case 'start': + switch ($tokenId) { + case T_STRING: + case T_NS_SEPARATOR: + $currentNs .= (string) $tokenValue; + $currentAlias = $tokenValue; + break; + case T_NAME_QUALIFIED: + case T_NAME_FULLY_QUALIFIED: + $currentNs .= (string) $tokenValue; + $currentAlias = substr( + (string) $tokenValue, + (int) (strrpos((string) $tokenValue, '\\')) + 1 + ); + break; + case T_CURLY_OPEN: + case '{': + $state = 'grouped'; + $groupedNs = $currentNs; + break; + case T_AS: + $state = 'start-alias'; + break; + case self::T_LITERAL_USE_SEPARATOR: + case self::T_LITERAL_END_OF_USE: + $state = 'end'; + break; + default: + break; + } + + break; + case 'start-alias': + switch ($tokenId) { + case T_STRING: + $currentAlias = $tokenValue; + break; + case self::T_LITERAL_USE_SEPARATOR: + case self::T_LITERAL_END_OF_USE: + $state = 'end'; + break; + default: + break; + } + + break; + case 'grouped': + switch ($tokenId) { + case T_STRING: + case T_NS_SEPARATOR: + $currentNs .= (string) $tokenValue; + $currentAlias = $tokenValue; + break; + case T_AS: + $state = 'grouped-alias'; + break; + case self::T_LITERAL_USE_SEPARATOR: + $state = 'grouped'; + $extractedUseStatements[(string) $currentAlias] = $currentNs; + $currentNs = $groupedNs; + $currentAlias = ''; + break; + case self::T_LITERAL_END_OF_USE: + $state = 'end'; + break; + default: + break; + } + + break; + case 'grouped-alias': + switch ($tokenId) { + case T_STRING: + $currentAlias = $tokenValue; + break; + case self::T_LITERAL_USE_SEPARATOR: + $state = 'grouped'; + $extractedUseStatements[(string) $currentAlias] = $currentNs; + $currentNs = $groupedNs; + $currentAlias = ''; + break; + case self::T_LITERAL_END_OF_USE: + $state = 'end'; + break; + default: + break; + } } - if ($tokens->current()[0] === T_STRING || $tokens->current()[0] === T_NS_SEPARATOR) { - $result[count($result) - 1] .= $tokens->current()[1]; + + if ($state === 'end') { + break; } + $tokens->next(); } - if (count($result) == 1) { - $backslashPos = strrpos($result[0], '\\'); - - if (false !== $backslashPos) { - $result[] = substr($result[0], $backslashPos + 1); - } else { - $result[] = $result[0]; - } + if ($groupedNs !== $currentNs) { + $extractedUseStatements[(string) $currentAlias] = $currentNs; } - return array_reverse($result); + return $extractedUseStatements; } } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Expression.php b/vendor/phpdocumentor/type-resolver/src/Types/Expression.php new file mode 100644 index 0000000..da5f65d --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/Types/Expression.php @@ -0,0 +1,51 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Represents an expression type as described in the PSR-5, the PHPDoc Standard. + * + * @psalm-immutable + */ +final class Expression implements Type +{ + /** @var Type */ + protected $valueType; + + /** + * Initializes this representation of an array with the given Type. + */ + public function __construct(Type $valueType) + { + $this->valueType = $valueType; + } + + /** + * Returns the value for the keys of this array. + */ + public function getValueType(): Type + { + return $this->valueType; + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return '(' . $this->valueType . ')'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Float_.php b/vendor/phpdocumentor/type-resolver/src/Types/Float_.php index e58d896..86138c0 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Float_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Float_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,15 +17,15 @@ /** * Value Object representing a Float. + * + * @psalm-immutable */ final class Float_ implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'float'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Integer.php b/vendor/phpdocumentor/type-resolver/src/Types/Integer.php index be4555e..10ce3c5 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Integer.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Integer.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -14,14 +15,17 @@ use phpDocumentor\Reflection\Type; -final class Integer implements Type +/** + * Value object representing Integer type + * + * @psalm-immutable + */ +class Integer implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'int'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/InterfaceString.php b/vendor/phpdocumentor/type-resolver/src/Types/InterfaceString.php new file mode 100644 index 0000000..9836961 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/Types/InterfaceString.php @@ -0,0 +1,56 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Fqsen; +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the type 'string'. + * + * @psalm-immutable + */ +final class InterfaceString implements Type +{ + /** @var Fqsen|null */ + private $fqsen; + + /** + * Initializes this representation of a class string with the given Fqsen. + */ + public function __construct(?Fqsen $fqsen = null) + { + $this->fqsen = $fqsen; + } + + /** + * Returns the FQSEN associated with this object. + */ + public function getFqsen(): ?Fqsen + { + return $this->fqsen; + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + if ($this->fqsen === null) { + return 'interface-string'; + } + + return 'interface-string<' . (string) $this->fqsen . '>'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Intersection.php b/vendor/phpdocumentor/type-resolver/src/Types/Intersection.php new file mode 100644 index 0000000..ced37b6 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/Types/Intersection.php @@ -0,0 +1,37 @@ +<?php +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +declare(strict_types=1); + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing a Compound Type. + * + * A Intersection Type is not so much a special keyword or object reference but is a series of Types that are separated + * using an AND operator (`&`). This combination of types signifies that whatever is associated with this Intersection + * type may contain a value with any of the given types. + * + * @psalm-immutable + */ +final class Intersection extends AggregatedType +{ + /** + * Initializes a intersection type (i.e. `\A&\B`) and tests if the provided types all implement the Type interface. + * + * @param array<Type> $types + */ + public function __construct(array $types) + { + parent::__construct($types, '&'); + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php b/vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php index 0cbf48f..1ca069f 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php @@ -1,31 +1,38 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2017 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\Types; -use phpDocumentor\Reflection\Type; - /** * Value Object representing iterable type + * + * @psalm-immutable */ -final class Iterable_ implements Type +final class Iterable_ extends AbstractList { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { - return 'iterable'; + if ($this->keyType) { + return 'iterable<' . $this->keyType . ',' . $this->valueType . '>'; + } + + if ($this->valueType instanceof Mixed_) { + return 'iterable'; + } + + return 'iterable<' . $this->valueType . '>'; } } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php b/vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php index c1c165f..56d1b6d 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,15 +17,15 @@ /** * Value Object representing an unknown, or mixed, type. + * + * @psalm-immutable */ final class Mixed_ implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'mixed'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Never_.php b/vendor/phpdocumentor/type-resolver/src/Types/Never_.php new file mode 100644 index 0000000..40a99c9 --- /dev/null +++ b/vendor/phpdocumentor/type-resolver/src/Types/Never_.php @@ -0,0 +1,35 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of phpDocumentor. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the return-type 'never'. + * + * Never is generally only used when working with return types as it signifies that the method that only + * ever throw or exit. + * + * @psalm-immutable + */ +final class Never_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + */ + public function __toString(): string + { + return 'never'; + } +} diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Null_.php b/vendor/phpdocumentor/type-resolver/src/Types/Null_.php index 203b422..7ae802c 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Null_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Null_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,15 +17,15 @@ /** * Value Object representing a null value or type. + * + * @psalm-immutable */ final class Null_ implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'null'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Nullable.php b/vendor/phpdocumentor/type-resolver/src/Types/Nullable.php index 3c6d1b1..a946935 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Nullable.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Nullable.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2017 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,18 +17,16 @@ /** * Value Object representing a nullable type. The real type is wrapped. + * + * @psalm-immutable */ final class Nullable implements Type { - /** - * @var Type - */ + /** @var Type The actual type that is wrapped */ private $realType; /** * Initialises this nullable type using the real type embedded - * - * @param Type $realType */ public function __construct(Type $realType) { @@ -36,20 +35,16 @@ public function __construct(Type $realType) /** * Provide access to the actual type directly, if needed. - * - * @return Type */ - public function getActualType() + public function getActualType(): Type { return $this->realType; } /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return '?' . $this->realType->__toString(); } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Object_.php b/vendor/phpdocumentor/type-resolver/src/Types/Object_.php index 389f7c7..90dee57 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Object_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Object_.php @@ -1,26 +1,32 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\Types; +use InvalidArgumentException; use phpDocumentor\Reflection\Fqsen; use phpDocumentor\Reflection\Type; +use function strpos; + /** * Value Object representing an object. * * An object can be either typed or untyped. When an object is typed it means that it has an identifier, the FQSEN, * pointing to an element in PHP. Object types that are untyped do not refer to a specific class but represent objects * in general. + * + * @psalm-immutable */ final class Object_ implements Type { @@ -30,15 +36,14 @@ final class Object_ implements Type /** * Initializes this object with an optional FQSEN, if not provided this object is considered 'untyped'. * - * @param Fqsen $fqsen - * @throws \InvalidArgumentException when provided $fqsen is not a valid type. + * @throws InvalidArgumentException When provided $fqsen is not a valid type. */ - public function __construct(Fqsen $fqsen = null) + public function __construct(?Fqsen $fqsen = null) { - if (strpos((string)$fqsen, '::') !== false || strpos((string)$fqsen, '()') !== false) { - throw new \InvalidArgumentException( + if (strpos((string) $fqsen, '::') !== false || strpos((string) $fqsen, '()') !== false) { + throw new InvalidArgumentException( 'Object types can only refer to a class, interface or trait but a method, function, constant or ' - . 'property was received: ' . (string)$fqsen + . 'property was received: ' . (string) $fqsen ); } @@ -47,23 +52,16 @@ public function __construct(Fqsen $fqsen = null) /** * Returns the FQSEN associated with this object. - * - * @return Fqsen|null */ - public function getFqsen() + public function getFqsen(): ?Fqsen { return $this->fqsen; } - /** - * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string - */ - public function __toString() + public function __toString(): string { if ($this->fqsen) { - return (string)$this->fqsen; + return (string) $this->fqsen; } return 'object'; diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Parent_.php b/vendor/phpdocumentor/type-resolver/src/Types/Parent_.php index aabdbfb..3483859 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Parent_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Parent_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,15 +19,15 @@ * Value Object representing the 'parent' type. * * Parent, as a Type, represents the parent class of class in which the associated element was defined. + * + * @psalm-immutable */ final class Parent_ implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'parent'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Resource_.php b/vendor/phpdocumentor/type-resolver/src/Types/Resource_.php index a1b613d..1998ee0 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Resource_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Resource_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,15 +17,15 @@ /** * Value Object representing the 'resource' Type. + * + * @psalm-immutable */ final class Resource_ implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'resource'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Scalar.php b/vendor/phpdocumentor/type-resolver/src/Types/Scalar.php index 1e2a660..80241c2 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Scalar.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Scalar.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,15 +17,15 @@ /** * Value Object representing the 'scalar' pseudo-type, which is either a string, integer, float or boolean. + * + * @psalm-immutable */ final class Scalar implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'scalar'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Self_.php b/vendor/phpdocumentor/type-resolver/src/Types/Self_.php index 1ba3fc5..5096126 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Self_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Self_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -18,15 +19,15 @@ * Value Object representing the 'self' type. * * Self, as a Type, represents the class in which the associated element was defined. + * + * @psalm-immutable */ final class Self_ implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'self'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Static_.php b/vendor/phpdocumentor/type-resolver/src/Types/Static_.php index 9eb6729..6fe365f 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Static_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Static_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -23,15 +24,15 @@ * * See the documentation on late static binding in the PHP Documentation for more information on the difference between * static and self. + * + * @psalm-immutable */ final class Static_ implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'static'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/String_.php b/vendor/phpdocumentor/type-resolver/src/Types/String_.php index 8db5968..a4bb47f 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/String_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/String_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -16,15 +17,15 @@ /** * Value Object representing the type 'string'. + * + * @psalm-immutable */ -final class String_ implements Type +class String_ implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'string'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/This.php b/vendor/phpdocumentor/type-resolver/src/Types/This.php index c098a93..602fc69 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/This.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/This.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -19,15 +20,15 @@ * * $this, as a Type, represents the instance of the class associated with the element as it was called. $this is * commonly used when documenting fluent interfaces since it represents that the same object is returned. + * + * @psalm-immutable */ final class This implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return '$this'; } diff --git a/vendor/phpdocumentor/type-resolver/src/Types/Void_.php b/vendor/phpdocumentor/type-resolver/src/Types/Void_.php index 3d1be27..23a601d 100644 --- a/vendor/phpdocumentor/type-resolver/src/Types/Void_.php +++ b/vendor/phpdocumentor/type-resolver/src/Types/Void_.php @@ -1,12 +1,13 @@ <?php + +declare(strict_types=1); + /** * This file is part of phpDocumentor. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. * - * @copyright 2010-2015 Mike van Riel<mike@phpdoc.org> - * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ @@ -15,19 +16,19 @@ use phpDocumentor\Reflection\Type; /** - * Value Object representing the pseudo-type 'void'. + * Value Object representing the return-type 'void'. * * Void is generally only used when working with return types as it signifies that the method intentionally does not * return any value. + * + * @psalm-immutable */ final class Void_ implements Type { /** * Returns a rendered output of the Type as it would be used in a DocBlock. - * - * @return string */ - public function __toString() + public function __toString(): string { return 'void'; } diff --git a/vendor/phpspec/prophecy/CHANGES.md b/vendor/phpspec/prophecy/CHANGES.md index fddfc41..97baaf1 100644 --- a/vendor/phpspec/prophecy/CHANGES.md +++ b/vendor/phpspec/prophecy/CHANGES.md @@ -1,3 +1,38 @@ +1.10.3 / 2020/03/05 +=================== + +* [fixed] removed fatal error when phpdocumentor/reflection-docblock 5 parses an invalid `@method` tag (@stof) + +1.10.2 / 2020/01/20 +=================== + +* [added] support for new versions of `sebastian/comparator` and `sebastian/recursion-context` (@sebastianbergmann) + +1.10.1 / 2019/12/22 +=================== + +* [fixed] identical callables no longer match as arguments (@ciaranmcnulty) + +1.10.0 / 2019/12/17 +=================== + +* [added] shouldHaveBeenCalled evaluation happens later so un-stubbed calls don't throw (@elvetemedve) +* [added] methods can now be doubled case-insensitively to match PHP semantics (@michalbundyra) +* [fixed] reduced memory usage by optimising CachedDoubler (@DonCallisto) +* [fixed] removed fatal error nesting level when comparing large objects (@scroach) + +1.9.0 / 2019/10/03 +================== + +* [added] Add willYield feature to Method Prophecy(@tkotosz) +* [fixed] Allow `MethodProphecy::willThrow()` to accept Throwable as string (@timoschinkel ) +* [fixed] Allow new version of phpdocumentor/reflection-docblock (@ricpelo) + +1.8.1 / 2019/06/13 +================== + +* [fixed] Don't try to patch final constructors (@NiR) + 1.8.0 / 2018/08/05 ================== diff --git a/vendor/phpspec/prophecy/README.md b/vendor/phpspec/prophecy/README.md index b190d43..3da9b59 100644 --- a/vendor/phpspec/prophecy/README.md +++ b/vendor/phpspec/prophecy/README.md @@ -12,7 +12,7 @@ enough to be used inside any testing framework out there with minimal effort. ```php <?php -class UserTest extends PHPUnit_Framework_TestCase +class UserTest extends PHPUnit\Framework\TestCase { private $prophet; @@ -28,7 +28,7 @@ class UserTest extends PHPUnit_Framework_TestCase $this->assertEquals('hashed_pass', $user->getPassword()); } - protected function setup() + protected function setUp() { $this->prophet = new \Prophecy\Prophet; } @@ -206,6 +206,17 @@ $user->setName('everzet')->will(function ($args) use ($user) { And now it doesn't matter how many times or in which order your methods are called. What matters is their behaviors and how well you faked it. +Note: If the method is called several times, you can use the following syntax to return different +values for each call: + +```php +$prophecy->read('123')->willReturn(1, 2, 3); +``` + +This feature is actually not recommended for most cases. Relying on the order of +calls for the same arguments tends to make test fragile, as adding one more call +can break everything. + #### Arguments wildcarding The previous example is awesome (at least I hope it is for you), but that's not diff --git a/vendor/phpspec/prophecy/composer.json b/vendor/phpspec/prophecy/composer.json index 816f147..7151160 100644 --- a/vendor/phpspec/prophecy/composer.json +++ b/vendor/phpspec/prophecy/composer.json @@ -19,20 +19,20 @@ "require": { "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", "doctrine/instantiator": "^1.0.2", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" }, "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", + "phpspec/phpspec": "^2.5 || ^3.2", "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "Prophecy\\": "src/Prophecy" } }, @@ -44,7 +44,7 @@ "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "1.10.x-dev" } } } diff --git a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ExactValueToken.php b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ExactValueToken.php index aa960f3..045a1b9 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ExactValueToken.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Argument/Token/ExactValueToken.php @@ -59,7 +59,9 @@ public function scoreArgument($argument) try { $comparator->assertEquals($argument, $this->value); return 10; - } catch (ComparisonFailure $failure) {} + } catch (ComparisonFailure $failure) { + return false; + } } // If either one is an object it should be castable to a string diff --git a/vendor/phpspec/prophecy/src/Prophecy/Call/CallCenter.php b/vendor/phpspec/prophecy/src/Prophecy/Call/CallCenter.php index bc936c8..d4bdba0 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Call/CallCenter.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Call/CallCenter.php @@ -12,11 +12,11 @@ namespace Prophecy\Call; use Prophecy\Exception\Prophecy\MethodProphecyException; -use Prophecy\Prophecy\MethodProphecy; use Prophecy\Prophecy\ObjectProphecy; use Prophecy\Argument\ArgumentsWildcard; use Prophecy\Util\StringUtil; use Prophecy\Exception\Call\UnexpectedCallException; +use SplObjectStorage; /** * Calls receiver & manager. @@ -32,6 +32,11 @@ class CallCenter */ private $recordedCalls = array(); + /** + * @var SplObjectStorage + */ + private $unexpectedCalls; + /** * Initializes call center. * @@ -40,6 +45,7 @@ class CallCenter public function __construct(StringUtil $util = null) { $this->util = $util ?: new StringUtil; + $this->unexpectedCalls = new SplObjectStorage(); } /** @@ -74,23 +80,21 @@ public function makeCall(ObjectProphecy $prophecy, $methodName, array $arguments } // If no method prophecies defined, then it's a dummy, so we'll just return null - if ('__destruct' === $methodName || 0 == count($prophecy->getMethodProphecies())) { + if ('__destruct' === strtolower($methodName) || 0 == count($prophecy->getMethodProphecies())) { $this->recordedCalls[] = new Call($methodName, $arguments, null, null, $file, $line); return null; } // There are method prophecies, so it's a fake/stub. Searching prophecy for this call - $matches = array(); - foreach ($prophecy->getMethodProphecies($methodName) as $methodProphecy) { - if (0 < $score = $methodProphecy->getArgumentsWildcard()->scoreArguments($arguments)) { - $matches[] = array($score, $methodProphecy); - } - } + $matches = $this->findMethodProphecies($prophecy, $methodName, $arguments); // If fake/stub doesn't have method prophecy for this call - throw exception if (!count($matches)) { - throw $this->createUnexpectedCallException($prophecy, $methodName, $arguments); + $this->unexpectedCalls->attach(new Call($methodName, $arguments, null, null, $file, $line), $prophecy); + $this->recordedCalls[] = new Call($methodName, $arguments, null, null, $file, $line); + + return null; } // Sort matches by their score value @@ -138,15 +142,33 @@ public function makeCall(ObjectProphecy $prophecy, $methodName, array $arguments */ public function findCalls($methodName, ArgumentsWildcard $wildcard) { + $methodName = strtolower($methodName); + return array_values( array_filter($this->recordedCalls, function (Call $call) use ($methodName, $wildcard) { - return $methodName === $call->getMethodName() + return $methodName === strtolower($call->getMethodName()) && 0 < $call->getScore($wildcard) ; }) ); } + /** + * @throws UnexpectedCallException + */ + public function checkUnexpectedCalls() + { + /** @var Call $call */ + foreach ($this->unexpectedCalls as $call) { + $prophecy = $this->unexpectedCalls[$call]; + + // If fake/stub doesn't have method prophecy for this call - throw exception + if (!count($this->findMethodProphecies($prophecy, $call->getMethodName(), $call->getArguments()))) { + throw $this->createUnexpectedCallException($prophecy, $call->getMethodName(), $call->getArguments()); + } + } + } + private function createUnexpectedCallException(ObjectProphecy $prophecy, $methodName, array $arguments) { @@ -194,28 +216,6 @@ private function createUnexpectedCallException(ObjectProphecy $prophecy, $method ); } - private function formatExceptionMessage(MethodProphecy $methodProphecy) - { - return sprintf( - " - %s(\n". - "%s\n". - " )", - $methodProphecy->getMethodName(), - implode( - ",\n", - $this->indentArguments( - array_map( - function ($token) { - return (string) $token; - }, - $methodProphecy->getArgumentsWildcard()->getTokens() - ), - $indentationLength - ) - ) - ); - } - private function indentArguments(array $arguments, $indentationLength) { return preg_replace_callback( @@ -226,4 +226,23 @@ function () use ($indentationLength) { $arguments ); } + + /** + * @param ObjectProphecy $prophecy + * @param string $methodName + * @param array $arguments + * + * @return array + */ + private function findMethodProphecies(ObjectProphecy $prophecy, $methodName, array $arguments) + { + $matches = array(); + foreach ($prophecy->getMethodProphecies($methodName) as $methodProphecy) { + if (0 < $score = $methodProphecy->getArgumentsWildcard()->scoreArguments($arguments)) { + $matches[] = array($score, $methodProphecy); + } + } + + return $matches; + } } diff --git a/vendor/phpspec/prophecy/src/Prophecy/Comparator/ClosureComparator.php b/vendor/phpspec/prophecy/src/Prophecy/Comparator/ClosureComparator.php index 874e474..fa4f578 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Comparator/ClosureComparator.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Comparator/ClosureComparator.php @@ -27,16 +27,18 @@ public function accepts($expected, $actual) && is_object($actual) && $actual instanceof \Closure; } - public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false) + public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = array()) { - throw new ComparisonFailure( - $expected, - $actual, - // we don't need a diff - '', - '', - false, - 'all closures are born different' - ); + if ($expected !== $actual) { + throw new ComparisonFailure( + $expected, + $actual, + // we don't need a diff + '', + '', + false, + 'all closures are different if not identical' + ); + } } } diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/CachedDoubler.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/CachedDoubler.php index d6b6b1a..2b87521 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Doubler/CachedDoubler.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/CachedDoubler.php @@ -21,17 +21,7 @@ */ class CachedDoubler extends Doubler { - private $classes = array(); - - /** - * {@inheritdoc} - */ - public function registerClassPatch(ClassPatch\ClassPatchInterface $patch) - { - $this->classes[] = array(); - - parent::registerClassPatch($patch); - } + private static $classes = array(); /** * {@inheritdoc} @@ -39,11 +29,11 @@ public function registerClassPatch(ClassPatch\ClassPatchInterface $patch) protected function createDoubleClass(ReflectionClass $class = null, array $interfaces) { $classId = $this->generateClassId($class, $interfaces); - if (isset($this->classes[$classId])) { - return $this->classes[$classId]; + if (isset(self::$classes[$classId])) { + return self::$classes[$classId]; } - return $this->classes[$classId] = parent::createDoubleClass($class, $interfaces); + return self::$classes[$classId] = parent::createDoubleClass($class, $interfaces); } /** @@ -61,8 +51,16 @@ private function generateClassId(ReflectionClass $class = null, array $interface foreach ($interfaces as $interface) { $parts[] = $interface->getName(); } + foreach ($this->getClassPatches() as $patch) { + $parts[] = get_class($patch); + } sort($parts); return md5(implode('', $parts)); } + + public function resetCache() + { + self::$classes = array(); + } } diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.php index 61998fc..9d84309 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.php @@ -41,6 +41,10 @@ public function supports(ClassNode $node) */ public function apply(ClassNode $node) { + if (!$node->isExtendable('__construct')) { + return; + } + if (!$node->hasMethod('__construct')) { $node->addMethod(new MethodNode('__construct', '')); diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php index 081dea8..ef40366 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php @@ -43,7 +43,7 @@ public function supports(ClassNode $node) public function apply(ClassNode $node) { $node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface'); - $node->addProperty('objectProphecy', 'private'); + $node->addProperty('objectProphecyClosure', 'private'); foreach ($node->getMethods() as $name => $method) { if ('__construct' === strtolower($name)) { @@ -65,10 +65,10 @@ public function apply(ClassNode $node) $prophecyArgument = new ArgumentNode('prophecy'); $prophecyArgument->setTypeHint('Prophecy\Prophecy\ProphecyInterface'); $prophecySetter->addArgument($prophecyArgument); - $prophecySetter->setCode('$this->objectProphecy = $prophecy;'); + $prophecySetter->setCode('$this->objectProphecyClosure = function () use ($prophecy) { return $prophecy; };'); $prophecyGetter = new MethodNode('getProphecy'); - $prophecyGetter->setCode('return $this->objectProphecy;'); + $prophecyGetter->setCode('return call_user_func($this->objectProphecyClosure);'); if ($node->hasMethod('__call')) { $__call = $node->getMethod('__call'); diff --git a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassMirror.php b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassMirror.php index c5f9a5c..6dab2d9 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassMirror.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassMirror.php @@ -144,7 +144,7 @@ private function reflectMethodToNode(ReflectionMethod $method, Node\ClassNode $c } if (version_compare(PHP_VERSION, '7.0', '>=') && $method->hasReturnType()) { - $returnType = (string) $method->getReturnType(); + $returnType = PHP_VERSION_ID >= 70100 ? $method->getReturnType()->getName() : (string) $method->getReturnType(); $returnTypeLower = strtolower($returnType); if ('self' === $returnTypeLower) { @@ -231,7 +231,7 @@ private function getTypeHint(ReflectionParameter $parameter) } if (version_compare(PHP_VERSION, '7.0', '>=') && true === $parameter->hasType()) { - return (string) $parameter->getType(); + return PHP_VERSION_ID >= 70100 ? $parameter->getType()->getName() : (string) $parameter->getType(); } return null; diff --git a/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/ClassTagRetriever.php b/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/ClassTagRetriever.php index 1d2da8f..9817a44 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/ClassTagRetriever.php +++ b/vendor/phpspec/prophecy/src/Prophecy/PhpDocumentor/ClassTagRetriever.php @@ -44,7 +44,15 @@ public function getTagList(\ReflectionClass $reflectionClass) $this->contextFactory->createFromReflector($reflectionClass) ); - return $phpdoc->getTagsByName('method'); + $methods = array(); + + foreach ($phpdoc->getTagsByName('method') as $tag) { + if ($tag instanceof Method) { + $methods[] = $tag; + } + } + + return $methods; } catch (\InvalidArgumentException $e) { return array(); } diff --git a/vendor/phpspec/prophecy/src/Prophecy/Promise/ThrowPromise.php b/vendor/phpspec/prophecy/src/Prophecy/Promise/ThrowPromise.php index 7250fa3..26ec19e 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Promise/ThrowPromise.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Promise/ThrowPromise.php @@ -41,7 +41,7 @@ class ThrowPromise implements PromiseInterface public function __construct($exception) { if (is_string($exception)) { - if (!class_exists($exception) || !$this->isAValidThrowable($exception)) { + if ((!class_exists($exception) && !interface_exists($exception)) || !$this->isAValidThrowable($exception)) { throw new InvalidArgumentException(sprintf( 'Exception / Throwable class or instance expected as argument to ThrowPromise, but got %s.', $exception @@ -94,6 +94,7 @@ public function execute(array $args, ObjectProphecy $object, MethodProphecy $met */ private function isAValidThrowable($exception) { - return is_a($exception, 'Exception', true) || is_subclass_of($exception, 'Throwable', true); + return is_a($exception, 'Exception', true) + || is_a($exception, 'Throwable', true); } } diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prophecy/MethodProphecy.php b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/MethodProphecy.php index 7084ed6..f33364c 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Prophecy/MethodProphecy.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/MethodProphecy.php @@ -71,7 +71,7 @@ public function __construct(ObjectProphecy $objectProphecy, $methodName, $argume } if (version_compare(PHP_VERSION, '7.0', '>=') && true === $reflectedMethod->hasReturnType()) { - $type = (string) $reflectedMethod->getReturnType(); + $type = PHP_VERSION_ID >= 70100 ? $reflectedMethod->getReturnType()->getName() : (string) $reflectedMethod->getReturnType(); if ('void' === $type) { $this->voidReturnType = true; @@ -180,6 +180,40 @@ public function willReturn() return $this->will(new Promise\ReturnPromise(func_get_args())); } + /** + * @param array $items + * + * @return $this + * + * @throws \Prophecy\Exception\InvalidArgumentException + */ + public function willYield($items) + { + if ($this->voidReturnType) { + throw new MethodProphecyException( + "The method \"$this->methodName\" has a void return type, and so cannot yield anything", + $this + ); + } + + if (!is_array($items)) { + throw new InvalidArgumentException(sprintf( + 'Expected array, but got %s.', + gettype($items) + )); + } + + // Remove eval() when minimum version >=5.5 + /** @var callable $generator */ + $generator = eval('return function() use ($items) { + foreach ($items as $key => $value) { + yield $key => $value; + } + };'); + + return $this->will($generator); + } + /** * Sets return argument promise to the prophecy. * diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ObjectProphecy.php b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ObjectProphecy.php index 8d8f8a1..11b87cf 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ObjectProphecy.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Prophecy/ObjectProphecy.php @@ -146,7 +146,7 @@ public function addMethodProphecy(MethodProphecy $methodProphecy) ), $methodProphecy); } - $methodName = $methodProphecy->getMethodName(); + $methodName = strtolower($methodProphecy->getMethodName()); if (!isset($this->methodProphecies[$methodName])) { $this->methodProphecies[$methodName] = array(); @@ -168,6 +168,8 @@ public function getMethodProphecies($methodName = null) return $this->methodProphecies; } + $methodName = strtolower($methodName); + if (!isset($this->methodProphecies[$methodName])) { return array(); } @@ -208,12 +210,15 @@ public function findProphecyMethodCalls($methodName, ArgumentsWildcard $wildcard * Checks that registered method predictions do not fail. * * @throws \Prophecy\Exception\Prediction\AggregateException If any of registered predictions fail + * @throws \Prophecy\Exception\Call\UnexpectedCallException */ public function checkProphecyMethodsPredictions() { $exception = new AggregateException(sprintf("%s:\n", get_class($this->reveal()))); $exception->setObjectProphecy($this); + $this->callCenter->checkUnexpectedCalls(); + foreach ($this->methodProphecies as $prophecies) { foreach ($prophecies as $prophecy) { try { diff --git a/vendor/phpspec/prophecy/src/Prophecy/Prophet.php b/vendor/phpspec/prophecy/src/Prophecy/Prophet.php index a4fe4b0..d37c92a 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Prophet.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Prophet.php @@ -11,6 +11,7 @@ namespace Prophecy; +use Prophecy\Doubler\CachedDoubler; use Prophecy\Doubler\Doubler; use Prophecy\Doubler\LazyDouble; use Prophecy\Doubler\ClassPatch; @@ -45,11 +46,13 @@ class Prophet * @param null|RevealerInterface $revealer * @param null|StringUtil $util */ - public function __construct(Doubler $doubler = null, RevealerInterface $revealer = null, - StringUtil $util = null) - { + public function __construct( + Doubler $doubler = null, + RevealerInterface $revealer = null, + StringUtil $util = null + ) { if (null === $doubler) { - $doubler = new Doubler; + $doubler = new CachedDoubler(); $doubler->registerClassPatch(new ClassPatch\SplFileInfoPatch); $doubler->registerClassPatch(new ClassPatch\TraversablePatch); $doubler->registerClassPatch(new ClassPatch\ThrowablePatch); diff --git a/vendor/phpspec/prophecy/src/Prophecy/Util/ExportUtil.php b/vendor/phpspec/prophecy/src/Prophecy/Util/ExportUtil.php index 50dd3f3..1090a80 100644 --- a/vendor/phpspec/prophecy/src/Prophecy/Util/ExportUtil.php +++ b/vendor/phpspec/prophecy/src/Prophecy/Util/ExportUtil.php @@ -181,9 +181,7 @@ protected static function recursiveExport(&$value, $indentation, $processed = nu if (is_object($value)) { $class = get_class($value); - if ($value instanceof ProphecyInterface) { - return sprintf('%s Object (*Prophecy*)', $class); - } elseif ($hash = $processed->contains($value)) { + if ($hash = $processed->contains($value)) { return sprintf('%s:%s Object', $class, $hash); } diff --git a/vendor/psr/cache/CHANGELOG.md b/vendor/psr/cache/CHANGELOG.md new file mode 100644 index 0000000..58ddab0 --- /dev/null +++ b/vendor/psr/cache/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.0.1 - 2016-08-06 + +### Fixed + +- Make spacing consistent in phpdoc annotations php-fig/cache#9 - chalasr +- Fix grammar in phpdoc annotations php-fig/cache#10 - chalasr +- Be more specific in docblocks that `getItems()` and `deleteItems()` take an array of strings (`string[]`) compared to just `array` php-fig/cache#8 - GrahamCampbell +- For `expiresAt()` and `expiresAfter()` in CacheItemInterface fix docblock to specify null as a valid parameters as well as an implementation of DateTimeInterface php-fig/cache#7 - GrahamCampbell + +## 1.0.0 - 2015-12-11 + +Initial stable release; reflects accepted PSR-6 specification diff --git a/vendor/psr/cache/LICENSE.txt b/vendor/psr/cache/LICENSE.txt new file mode 100644 index 0000000..b1c2c97 --- /dev/null +++ b/vendor/psr/cache/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2015 PHP Framework Interoperability Group + +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/vendor/psr/cache/README.md b/vendor/psr/cache/README.md new file mode 100644 index 0000000..c8706ce --- /dev/null +++ b/vendor/psr/cache/README.md @@ -0,0 +1,9 @@ +PSR Cache +========= + +This repository holds all interfaces defined by +[PSR-6](http://www.php-fig.org/psr/psr-6/). + +Note that this is not a Cache implementation of its own. It is merely an +interface that describes a Cache implementation. See the specification for more +details. diff --git a/vendor/psr/cache/composer.json b/vendor/psr/cache/composer.json new file mode 100644 index 0000000..e828fec --- /dev/null +++ b/vendor/psr/cache/composer.json @@ -0,0 +1,25 @@ +{ + "name": "psr/cache", + "description": "Common interface for caching libraries", + "keywords": ["psr", "psr-6", "cache"], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/psr/cache/src/CacheException.php b/vendor/psr/cache/src/CacheException.php new file mode 100644 index 0000000..e27f22f --- /dev/null +++ b/vendor/psr/cache/src/CacheException.php @@ -0,0 +1,10 @@ +<?php + +namespace Psr\Cache; + +/** + * Exception interface for all exceptions thrown by an Implementing Library. + */ +interface CacheException +{ +} diff --git a/vendor/psr/cache/src/CacheItemInterface.php b/vendor/psr/cache/src/CacheItemInterface.php new file mode 100644 index 0000000..63d05dd --- /dev/null +++ b/vendor/psr/cache/src/CacheItemInterface.php @@ -0,0 +1,105 @@ +<?php + +namespace Psr\Cache; + +/** + * CacheItemInterface defines an interface for interacting with objects inside a cache. + * + * Each Item object MUST be associated with a specific key, which can be set + * according to the implementing system and is typically passed by the + * Cache\CacheItemPoolInterface object. + * + * The Cache\CacheItemInterface object encapsulates the storage and retrieval of + * cache items. Each Cache\CacheItemInterface is generated by a + * Cache\CacheItemPoolInterface object, which is responsible for any required + * setup as well as associating the object with a unique Key. + * Cache\CacheItemInterface objects MUST be able to store and retrieve any type + * of PHP value defined in the Data section of the specification. + * + * Calling Libraries MUST NOT instantiate Item objects themselves. They may only + * be requested from a Pool object via the getItem() method. Calling Libraries + * SHOULD NOT assume that an Item created by one Implementing Library is + * compatible with a Pool from another Implementing Library. + */ +interface CacheItemInterface +{ + /** + * Returns the key for the current cache item. + * + * The key is loaded by the Implementing Library, but should be available to + * the higher level callers when needed. + * + * @return string + * The key string for this cache item. + */ + public function getKey(); + + /** + * Retrieves the value of the item from the cache associated with this object's key. + * + * The value returned must be identical to the value originally stored by set(). + * + * If isHit() returns false, this method MUST return null. Note that null + * is a legitimate cached value, so the isHit() method SHOULD be used to + * differentiate between "null value was found" and "no value was found." + * + * @return mixed + * The value corresponding to this cache item's key, or null if not found. + */ + public function get(); + + /** + * Confirms if the cache item lookup resulted in a cache hit. + * + * Note: This method MUST NOT have a race condition between calling isHit() + * and calling get(). + * + * @return bool + * True if the request resulted in a cache hit. False otherwise. + */ + public function isHit(); + + /** + * Sets the value represented by this cache item. + * + * The $value argument may be any item that can be serialized by PHP, + * although the method of serialization is left up to the Implementing + * Library. + * + * @param mixed $value + * The serializable value to be stored. + * + * @return static + * The invoked object. + */ + public function set($value); + + /** + * Sets the expiration time for this cache item. + * + * @param \DateTimeInterface|null $expiration + * The point in time after which the item MUST be considered expired. + * If null is passed explicitly, a default value MAY be used. If none is set, + * the value should be stored permanently or for as long as the + * implementation allows. + * + * @return static + * The called object. + */ + public function expiresAt($expiration); + + /** + * Sets the expiration time for this cache item. + * + * @param int|\DateInterval|null $time + * The period of time from the present after which the item MUST be considered + * expired. An integer parameter is understood to be the time in seconds until + * expiration. If null is passed explicitly, a default value MAY be used. + * If none is set, the value should be stored permanently or for as long as the + * implementation allows. + * + * @return static + * The called object. + */ + public function expiresAfter($time); +} diff --git a/vendor/psr/cache/src/CacheItemPoolInterface.php b/vendor/psr/cache/src/CacheItemPoolInterface.php new file mode 100644 index 0000000..0351419 --- /dev/null +++ b/vendor/psr/cache/src/CacheItemPoolInterface.php @@ -0,0 +1,138 @@ +<?php + +namespace Psr\Cache; + +/** + * CacheItemPoolInterface generates CacheItemInterface objects. + * + * The primary purpose of Cache\CacheItemPoolInterface is to accept a key from + * the Calling Library and return the associated Cache\CacheItemInterface object. + * It is also the primary point of interaction with the entire cache collection. + * All configuration and initialization of the Pool is left up to an + * Implementing Library. + */ +interface CacheItemPoolInterface +{ + /** + * Returns a Cache Item representing the specified key. + * + * This method must always return a CacheItemInterface object, even in case of + * a cache miss. It MUST NOT return null. + * + * @param string $key + * The key for which to return the corresponding Cache Item. + * + * @throws InvalidArgumentException + * If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException + * MUST be thrown. + * + * @return CacheItemInterface + * The corresponding Cache Item. + */ + public function getItem($key); + + /** + * Returns a traversable set of cache items. + * + * @param string[] $keys + * An indexed array of keys of items to retrieve. + * + * @throws InvalidArgumentException + * If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException + * MUST be thrown. + * + * @return array|\Traversable + * A traversable collection of Cache Items keyed by the cache keys of + * each item. A Cache item will be returned for each key, even if that + * key is not found. However, if no keys are specified then an empty + * traversable MUST be returned instead. + */ + public function getItems(array $keys = array()); + + /** + * Confirms if the cache contains specified cache item. + * + * Note: This method MAY avoid retrieving the cached value for performance reasons. + * This could result in a race condition with CacheItemInterface::get(). To avoid + * such situation use CacheItemInterface::isHit() instead. + * + * @param string $key + * The key for which to check existence. + * + * @throws InvalidArgumentException + * If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException + * MUST be thrown. + * + * @return bool + * True if item exists in the cache, false otherwise. + */ + public function hasItem($key); + + /** + * Deletes all items in the pool. + * + * @return bool + * True if the pool was successfully cleared. False if there was an error. + */ + public function clear(); + + /** + * Removes the item from the pool. + * + * @param string $key + * The key to delete. + * + * @throws InvalidArgumentException + * If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException + * MUST be thrown. + * + * @return bool + * True if the item was successfully removed. False if there was an error. + */ + public function deleteItem($key); + + /** + * Removes multiple items from the pool. + * + * @param string[] $keys + * An array of keys that should be removed from the pool. + + * @throws InvalidArgumentException + * If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException + * MUST be thrown. + * + * @return bool + * True if the items were successfully removed. False if there was an error. + */ + public function deleteItems(array $keys); + + /** + * Persists a cache item immediately. + * + * @param CacheItemInterface $item + * The cache item to save. + * + * @return bool + * True if the item was successfully persisted. False if there was an error. + */ + public function save(CacheItemInterface $item); + + /** + * Sets a cache item to be persisted later. + * + * @param CacheItemInterface $item + * The cache item to save. + * + * @return bool + * False if the item could not be queued or if a commit was attempted and failed. True otherwise. + */ + public function saveDeferred(CacheItemInterface $item); + + /** + * Persists any deferred cache items. + * + * @return bool + * True if all not-yet-saved items were successfully saved or there were none. False otherwise. + */ + public function commit(); +} diff --git a/vendor/psr/cache/src/InvalidArgumentException.php b/vendor/psr/cache/src/InvalidArgumentException.php new file mode 100644 index 0000000..be7c6fa --- /dev/null +++ b/vendor/psr/cache/src/InvalidArgumentException.php @@ -0,0 +1,13 @@ +<?php + +namespace Psr\Cache; + +/** + * Exception interface for invalid cache arguments. + * + * Any time an invalid argument is passed into a method it must throw an + * exception class which implements Psr\Cache\InvalidArgumentException. + */ +interface InvalidArgumentException extends CacheException +{ +} diff --git a/vendor/psr/container/.gitignore b/vendor/psr/container/.gitignore new file mode 100644 index 0000000..b2395aa --- /dev/null +++ b/vendor/psr/container/.gitignore @@ -0,0 +1,3 @@ +composer.lock +composer.phar +/vendor/ diff --git a/vendor/psr/container/LICENSE b/vendor/psr/container/LICENSE new file mode 100644 index 0000000..2877a48 --- /dev/null +++ b/vendor/psr/container/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013-2016 container-interop +Copyright (c) 2016 PHP Framework Interoperability Group + +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/vendor/psr/container/README.md b/vendor/psr/container/README.md new file mode 100644 index 0000000..1b9d9e5 --- /dev/null +++ b/vendor/psr/container/README.md @@ -0,0 +1,13 @@ +Container interface +============== + +This repository holds all interfaces related to [PSR-11 (Container Interface)][psr-url]. + +Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container. + +The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. + +[psr-url]: https://www.php-fig.org/psr/psr-11/ +[package-url]: https://packagist.org/packages/psr/container +[implementation-url]: https://packagist.org/providers/psr/container-implementation + diff --git a/vendor/psr/container/composer.json b/vendor/psr/container/composer.json new file mode 100644 index 0000000..3797a25 --- /dev/null +++ b/vendor/psr/container/composer.json @@ -0,0 +1,22 @@ +{ + "name": "psr/container", + "type": "library", + "description": "Common Container Interface (PHP FIG PSR-11)", + "keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"], + "homepage": "https://github.com/php-fig/container", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": ">=7.2.0" + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + } +} diff --git a/vendor/psr/container/src/ContainerExceptionInterface.php b/vendor/psr/container/src/ContainerExceptionInterface.php new file mode 100644 index 0000000..cf10b8b --- /dev/null +++ b/vendor/psr/container/src/ContainerExceptionInterface.php @@ -0,0 +1,10 @@ +<?php + +namespace Psr\Container; + +/** + * Base interface representing a generic exception in a container. + */ +interface ContainerExceptionInterface +{ +} diff --git a/vendor/psr/container/src/ContainerInterface.php b/vendor/psr/container/src/ContainerInterface.php new file mode 100644 index 0000000..cf8e7fd --- /dev/null +++ b/vendor/psr/container/src/ContainerInterface.php @@ -0,0 +1,36 @@ +<?php + +declare(strict_types=1); + +namespace Psr\Container; + +/** + * Describes the interface of a container that exposes methods to read its entries. + */ +interface ContainerInterface +{ + /** + * Finds an entry of the container by its identifier and returns it. + * + * @param string $id Identifier of the entry to look for. + * + * @throws NotFoundExceptionInterface No entry was found for **this** identifier. + * @throws ContainerExceptionInterface Error while retrieving the entry. + * + * @return mixed Entry. + */ + public function get(string $id); + + /** + * Returns true if the container can return an entry for the given identifier. + * Returns false otherwise. + * + * `has($id)` returning true does not mean that `get($id)` will not throw an exception. + * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`. + * + * @param string $id Identifier of the entry to look for. + * + * @return bool + */ + public function has(string $id); +} diff --git a/vendor/psr/container/src/NotFoundExceptionInterface.php b/vendor/psr/container/src/NotFoundExceptionInterface.php new file mode 100644 index 0000000..650bf46 --- /dev/null +++ b/vendor/psr/container/src/NotFoundExceptionInterface.php @@ -0,0 +1,10 @@ +<?php + +namespace Psr\Container; + +/** + * No entry was found in the container. + */ +interface NotFoundExceptionInterface extends ContainerExceptionInterface +{ +} diff --git a/vendor/psr/event-dispatcher/.editorconfig b/vendor/psr/event-dispatcher/.editorconfig new file mode 100644 index 0000000..164f092 --- /dev/null +++ b/vendor/psr/event-dispatcher/.editorconfig @@ -0,0 +1,15 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[Makefile] +indent_style = tab diff --git a/vendor/psr/event-dispatcher/.gitignore b/vendor/psr/event-dispatcher/.gitignore new file mode 100644 index 0000000..3a9875b --- /dev/null +++ b/vendor/psr/event-dispatcher/.gitignore @@ -0,0 +1,2 @@ +/vendor/ +composer.lock diff --git a/vendor/psr/event-dispatcher/LICENSE b/vendor/psr/event-dispatcher/LICENSE new file mode 100644 index 0000000..3f1559b --- /dev/null +++ b/vendor/psr/event-dispatcher/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 PHP-FIG + +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/vendor/psr/event-dispatcher/README.md b/vendor/psr/event-dispatcher/README.md new file mode 100644 index 0000000..294214a --- /dev/null +++ b/vendor/psr/event-dispatcher/README.md @@ -0,0 +1,6 @@ +PSR Event Dispatcher +==================== + +This repository holds the interfaces related to [PSR-14](http://www.php-fig.org/psr/psr-14/). + +Note that this is not an Event Dispatcher implementation of its own. It is merely interfaces that describe the components of an Event Dispatcher. See the specification for more details. diff --git a/vendor/psr/event-dispatcher/composer.json b/vendor/psr/event-dispatcher/composer.json new file mode 100644 index 0000000..667a714 --- /dev/null +++ b/vendor/psr/event-dispatcher/composer.json @@ -0,0 +1,26 @@ +{ + "name": "psr/event-dispatcher", + "description": "Standard interfaces for event handling.", + "type": "library", + "keywords": ["psr", "psr-14", "events"], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": ">=7.2.0" + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/psr/event-dispatcher/src/EventDispatcherInterface.php b/vendor/psr/event-dispatcher/src/EventDispatcherInterface.php new file mode 100644 index 0000000..4306fa9 --- /dev/null +++ b/vendor/psr/event-dispatcher/src/EventDispatcherInterface.php @@ -0,0 +1,21 @@ +<?php +declare(strict_types=1); + +namespace Psr\EventDispatcher; + +/** + * Defines a dispatcher for events. + */ +interface EventDispatcherInterface +{ + /** + * Provide all relevant listeners with an event to process. + * + * @param object $event + * The object to process. + * + * @return object + * The Event that was passed, now modified by listeners. + */ + public function dispatch(object $event); +} diff --git a/vendor/psr/event-dispatcher/src/ListenerProviderInterface.php b/vendor/psr/event-dispatcher/src/ListenerProviderInterface.php new file mode 100644 index 0000000..bdacb6e --- /dev/null +++ b/vendor/psr/event-dispatcher/src/ListenerProviderInterface.php @@ -0,0 +1,19 @@ +<?php +declare(strict_types=1); + +namespace Psr\EventDispatcher; + +/** + * Mapper from an event to the listeners that are applicable to that event. + */ +interface ListenerProviderInterface +{ + /** + * @param object $event + * An event for which to return the relevant listeners. + * @return iterable[callable] + * An iterable (array, iterator, or generator) of callables. Each + * callable MUST be type-compatible with $event. + */ + public function getListenersForEvent(object $event) : iterable; +} diff --git a/vendor/psr/event-dispatcher/src/StoppableEventInterface.php b/vendor/psr/event-dispatcher/src/StoppableEventInterface.php new file mode 100644 index 0000000..5955081 --- /dev/null +++ b/vendor/psr/event-dispatcher/src/StoppableEventInterface.php @@ -0,0 +1,26 @@ +<?php +declare(strict_types=1); + +namespace Psr\EventDispatcher; + +/** + * An Event whose processing may be interrupted when the event has been handled. + * + * A Dispatcher implementation MUST check to determine if an Event + * is marked as stopped after each listener is called. If it is then it should + * return immediately without calling any further Listeners. + */ +interface StoppableEventInterface +{ + /** + * Is propagation stopped? + * + * This will typically only be used by the Dispatcher to determine if the + * previous listener halted propagation. + * + * @return bool + * True if the Event is complete and no further listeners should be called. + * False to continue calling listeners. + */ + public function isPropagationStopped() : bool; +} diff --git a/vendor/psr/http-client/CHANGELOG.md b/vendor/psr/http-client/CHANGELOG.md new file mode 100644 index 0000000..e2dc25f --- /dev/null +++ b/vendor/psr/http-client/CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.0.1 + +Allow installation with PHP 8. No code changes. + +## 1.0.0 + +First stable release. No changes since 0.3.0. + +## 0.3.0 + +Added Interface suffix on exceptions + +## 0.2.0 + +All exceptions are in `Psr\Http\Client` namespace + +## 0.1.0 + +First release diff --git a/vendor/psr/http-client/LICENSE b/vendor/psr/http-client/LICENSE new file mode 100644 index 0000000..cd5e002 --- /dev/null +++ b/vendor/psr/http-client/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2017 PHP Framework Interoperability Group + +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/vendor/psr/http-client/README.md b/vendor/psr/http-client/README.md new file mode 100644 index 0000000..84af5c5 --- /dev/null +++ b/vendor/psr/http-client/README.md @@ -0,0 +1,12 @@ +HTTP Client +=========== + +This repository holds all the common code related to [PSR-18 (HTTP Client)][psr-url]. + +Note that this is not a HTTP Client implementation of its own. It is merely abstractions that describe the components of a HTTP Client. + +The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. + +[psr-url]: https://www.php-fig.org/psr/psr-18 +[package-url]: https://packagist.org/packages/psr/http-client +[implementation-url]: https://packagist.org/providers/psr/http-client-implementation diff --git a/vendor/psr/http-client/composer.json b/vendor/psr/http-client/composer.json new file mode 100644 index 0000000..e4cab2f --- /dev/null +++ b/vendor/psr/http-client/composer.json @@ -0,0 +1,27 @@ +{ + "name": "psr/http-client", + "description": "Common interface for HTTP clients", + "keywords": ["psr", "psr-18", "http", "http-client"], + "homepage": "https://github.com/php-fig/http-client", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/psr/http-client/src/ClientExceptionInterface.php b/vendor/psr/http-client/src/ClientExceptionInterface.php new file mode 100644 index 0000000..aa0b9cf --- /dev/null +++ b/vendor/psr/http-client/src/ClientExceptionInterface.php @@ -0,0 +1,10 @@ +<?php + +namespace Psr\Http\Client; + +/** + * Every HTTP client related exception MUST implement this interface. + */ +interface ClientExceptionInterface extends \Throwable +{ +} diff --git a/vendor/psr/http-client/src/ClientInterface.php b/vendor/psr/http-client/src/ClientInterface.php new file mode 100644 index 0000000..ad99fd4 --- /dev/null +++ b/vendor/psr/http-client/src/ClientInterface.php @@ -0,0 +1,20 @@ +<?php + +namespace Psr\Http\Client; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +interface ClientInterface +{ + /** + * Sends a PSR-7 request and returns a PSR-7 response. + * + * @param RequestInterface $request + * + * @return ResponseInterface + * + * @throws \Psr\Http\Client\ClientExceptionInterface If an error happens while processing the request. + */ + public function sendRequest(RequestInterface $request): ResponseInterface; +} diff --git a/vendor/psr/http-client/src/NetworkExceptionInterface.php b/vendor/psr/http-client/src/NetworkExceptionInterface.php new file mode 100644 index 0000000..4a11627 --- /dev/null +++ b/vendor/psr/http-client/src/NetworkExceptionInterface.php @@ -0,0 +1,24 @@ +<?php + +namespace Psr\Http\Client; + +use Psr\Http\Message\RequestInterface; + +/** + * Thrown when the request cannot be completed because of network issues. + * + * There is no response object as this exception is thrown when no response has been received. + * + * Example: the target host name can not be resolved or the connection failed. + */ +interface NetworkExceptionInterface extends ClientExceptionInterface +{ + /** + * Returns the request. + * + * The request object MAY be a different object from the one passed to ClientInterface::sendRequest() + * + * @return RequestInterface + */ + public function getRequest(): RequestInterface; +} diff --git a/vendor/psr/http-client/src/RequestExceptionInterface.php b/vendor/psr/http-client/src/RequestExceptionInterface.php new file mode 100644 index 0000000..b17fc34 --- /dev/null +++ b/vendor/psr/http-client/src/RequestExceptionInterface.php @@ -0,0 +1,24 @@ +<?php + +namespace Psr\Http\Client; + +use Psr\Http\Message\RequestInterface; + +/** + * Exception for when a request failed. + * + * Examples: + * - Request is invalid (e.g. method is missing) + * - Runtime request errors (e.g. the body stream is not seekable) + */ +interface RequestExceptionInterface extends ClientExceptionInterface +{ + /** + * Returns the request. + * + * The request object MAY be a different object from the one passed to ClientInterface::sendRequest() + * + * @return RequestInterface + */ + public function getRequest(): RequestInterface; +} diff --git a/vendor/psr/http-factory/LICENSE b/vendor/psr/http-factory/LICENSE new file mode 100644 index 0000000..3f1559b --- /dev/null +++ b/vendor/psr/http-factory/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 PHP-FIG + +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/vendor/psr/http-factory/README.md b/vendor/psr/http-factory/README.md new file mode 100644 index 0000000..bf8913b --- /dev/null +++ b/vendor/psr/http-factory/README.md @@ -0,0 +1,12 @@ +HTTP Factories +============== + +This repository holds all interfaces related to [PSR-17 (HTTP Factories)][psr-url]. + +Note that this is not a HTTP Factory implementation of its own. It is merely interfaces that describe the components of a HTTP Factory. + +The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. + +[psr-url]: https://www.php-fig.org/psr/psr-17/ +[package-url]: https://packagist.org/packages/psr/http-factory +[implementation-url]: https://packagist.org/providers/psr/http-factory-implementation diff --git a/vendor/psr/http-factory/composer.json b/vendor/psr/http-factory/composer.json new file mode 100644 index 0000000..d1bbdde --- /dev/null +++ b/vendor/psr/http-factory/composer.json @@ -0,0 +1,35 @@ +{ + "name": "psr/http-factory", + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "psr", + "psr-7", + "psr-17", + "http", + "factory", + "message", + "request", + "response" + ], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/psr/http-factory/src/RequestFactoryInterface.php b/vendor/psr/http-factory/src/RequestFactoryInterface.php new file mode 100644 index 0000000..cb39a08 --- /dev/null +++ b/vendor/psr/http-factory/src/RequestFactoryInterface.php @@ -0,0 +1,18 @@ +<?php + +namespace Psr\Http\Message; + +interface RequestFactoryInterface +{ + /** + * Create a new request. + * + * @param string $method The HTTP method associated with the request. + * @param UriInterface|string $uri The URI associated with the request. If + * the value is a string, the factory MUST create a UriInterface + * instance based on it. + * + * @return RequestInterface + */ + public function createRequest(string $method, $uri): RequestInterface; +} diff --git a/vendor/psr/http-factory/src/ResponseFactoryInterface.php b/vendor/psr/http-factory/src/ResponseFactoryInterface.php new file mode 100644 index 0000000..212562f --- /dev/null +++ b/vendor/psr/http-factory/src/ResponseFactoryInterface.php @@ -0,0 +1,18 @@ +<?php + +namespace Psr\Http\Message; + +interface ResponseFactoryInterface +{ + /** + * Create a new response. + * + * @param int $code HTTP status code; defaults to 200 + * @param string $reasonPhrase Reason phrase to associate with status code + * in generated response; if none is provided implementations MAY use + * the defaults as suggested in the HTTP specification. + * + * @return ResponseInterface + */ + public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface; +} diff --git a/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php b/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php new file mode 100644 index 0000000..9fe031a --- /dev/null +++ b/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php @@ -0,0 +1,24 @@ +<?php + +namespace Psr\Http\Message; + +interface ServerRequestFactoryInterface +{ + /** + * Create a new server request. + * + * Note that server-params are taken precisely as given - no parsing/processing + * of the given values is performed, and, in particular, no attempt is made to + * determine the HTTP method or URI, which must be provided explicitly. + * + * @param string $method The HTTP method associated with the request. + * @param UriInterface|string $uri The URI associated with the request. If + * the value is a string, the factory MUST create a UriInterface + * instance based on it. + * @param array $serverParams Array of SAPI parameters with which to seed + * the generated request instance. + * + * @return ServerRequestInterface + */ + public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface; +} diff --git a/vendor/psr/http-factory/src/StreamFactoryInterface.php b/vendor/psr/http-factory/src/StreamFactoryInterface.php new file mode 100644 index 0000000..90e3240 --- /dev/null +++ b/vendor/psr/http-factory/src/StreamFactoryInterface.php @@ -0,0 +1,45 @@ +<?php + +namespace Psr\Http\Message; + +interface StreamFactoryInterface +{ + /** + * Create a new stream from a string. + * + * The stream SHOULD be created with a temporary resource. + * + * @param string $content String content with which to populate the stream. + * + * @return StreamInterface + */ + public function createStream(string $content = ''): StreamInterface; + + /** + * Create a stream from an existing file. + * + * The file MUST be opened using the given mode, which may be any mode + * supported by the `fopen` function. + * + * The `$filename` MAY be any string supported by `fopen()`. + * + * @param string $filename Filename or stream URI to use as basis of stream. + * @param string $mode Mode with which to open the underlying filename/stream. + * + * @return StreamInterface + * @throws \RuntimeException If the file cannot be opened. + * @throws \InvalidArgumentException If the mode is invalid. + */ + public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface; + + /** + * Create a new stream from an existing resource. + * + * The stream MUST be readable and may be writable. + * + * @param resource $resource PHP resource to use as basis of stream. + * + * @return StreamInterface + */ + public function createStreamFromResource($resource): StreamInterface; +} diff --git a/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php b/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php new file mode 100644 index 0000000..7db4e30 --- /dev/null +++ b/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php @@ -0,0 +1,34 @@ +<?php + +namespace Psr\Http\Message; + +interface UploadedFileFactoryInterface +{ + /** + * Create a new uploaded file. + * + * If a size is not provided it will be determined by checking the size of + * the file. + * + * @see http://php.net/manual/features.file-upload.post-method.php + * @see http://php.net/manual/features.file-upload.errors.php + * + * @param StreamInterface $stream Underlying stream representing the + * uploaded file content. + * @param int $size in bytes + * @param int $error PHP file upload error + * @param string $clientFilename Filename as provided by the client, if any. + * @param string $clientMediaType Media type as provided by the client, if any. + * + * @return UploadedFileInterface + * + * @throws \InvalidArgumentException If the file resource is not readable. + */ + public function createUploadedFile( + StreamInterface $stream, + int $size = null, + int $error = \UPLOAD_ERR_OK, + string $clientFilename = null, + string $clientMediaType = null + ): UploadedFileInterface; +} diff --git a/vendor/psr/http-factory/src/UriFactoryInterface.php b/vendor/psr/http-factory/src/UriFactoryInterface.php new file mode 100644 index 0000000..06df0b4 --- /dev/null +++ b/vendor/psr/http-factory/src/UriFactoryInterface.php @@ -0,0 +1,17 @@ +<?php + +namespace Psr\Http\Message; + +interface UriFactoryInterface +{ + /** + * Create a new URI. + * + * @param string $uri + * + * @return UriInterface + * + * @throws \InvalidArgumentException If the given URI cannot be parsed. + */ + public function createUri(string $uri = ''): UriInterface; +} diff --git a/vendor/psr/http-message/README.md b/vendor/psr/http-message/README.md index 2818533..2668be6 100644 --- a/vendor/psr/http-message/README.md +++ b/vendor/psr/http-message/README.md @@ -10,4 +10,7 @@ interface that describes a HTTP message. See the specification for more details. Usage ----- -We'll certainly need some stuff in here. \ No newline at end of file +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 diff --git a/vendor/psr/http-message/composer.json b/vendor/psr/http-message/composer.json index b0d2937..c66e5ab 100644 --- a/vendor/psr/http-message/composer.json +++ b/vendor/psr/http-message/composer.json @@ -7,11 +7,11 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, "autoload": { "psr-4": { @@ -20,7 +20,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } } } diff --git a/vendor/psr/http-message/docs/PSR7-Interfaces.md b/vendor/psr/http-message/docs/PSR7-Interfaces.md new file mode 100644 index 0000000..3a7e7dd --- /dev/null +++ b/vendor/psr/http-message/docs/PSR7-Interfaces.md @@ -0,0 +1,130 @@ +# 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/vendor/psr/http-message/docs/PSR7-Usage.md b/vendor/psr/http-message/docs/PSR7-Usage.md new file mode 100644 index 0000000..b6d048a --- /dev/null +++ b/vendor/psr/http-message/docs/PSR7-Usage.md @@ -0,0 +1,159 @@ +### 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/vendor/psr/http-message/src/MessageInterface.php b/vendor/psr/http-message/src/MessageInterface.php index dd46e5e..a83c985 100644 --- a/vendor/psr/http-message/src/MessageInterface.php +++ b/vendor/psr/http-message/src/MessageInterface.php @@ -23,7 +23,7 @@ interface MessageInterface * * @return string HTTP protocol version. */ - public function getProtocolVersion(); + public function getProtocolVersion(): string; /** * Return an instance with the specified HTTP protocol version. @@ -38,7 +38,7 @@ public function getProtocolVersion(); * @param string $version HTTP protocol version * @return static */ - public function withProtocolVersion($version); + public function withProtocolVersion(string $version): MessageInterface; /** * Retrieves all message header values. @@ -65,7 +65,7 @@ public function withProtocolVersion($version); * key MUST be a header name, and each value MUST be an array of strings * for that header. */ - public function getHeaders(); + public function getHeaders(): array; /** * Checks if a header exists by the given case-insensitive name. @@ -75,7 +75,7 @@ public function getHeaders(); * name using a case-insensitive string comparison. Returns false if * no matching header name is found in the message. */ - public function hasHeader($name); + public function hasHeader(string $name): bool; /** * Retrieves a message header value by the given case-insensitive name. @@ -91,7 +91,7 @@ public function hasHeader($name); * header. If the header does not appear in the message, this method MUST * return an empty array. */ - public function getHeader($name); + public function getHeader(string $name): array; /** * Retrieves a comma-separated string of the values for a single header. @@ -112,7 +112,7 @@ public function getHeader($name); * concatenated together using a comma. If the header does not appear in * the message, this method MUST return an empty string. */ - public function getHeaderLine($name); + public function getHeaderLine(string $name): string; /** * Return an instance with the provided value replacing the specified header. @@ -129,7 +129,7 @@ public function getHeaderLine($name); * @return static * @throws \InvalidArgumentException for invalid header names or values. */ - public function withHeader($name, $value); + public function withHeader(string $name, $value): MessageInterface; /** * Return an instance with the specified header appended with the given value. @@ -147,7 +147,7 @@ public function withHeader($name, $value); * @return static * @throws \InvalidArgumentException for invalid header names or values. */ - public function withAddedHeader($name, $value); + public function withAddedHeader(string $name, $value): MessageInterface; /** * Return an instance without the specified header. @@ -161,14 +161,14 @@ public function withAddedHeader($name, $value); * @param string $name Case-insensitive header field name to remove. * @return static */ - public function withoutHeader($name); + public function withoutHeader(string $name): MessageInterface; /** * Gets the body of the message. * * @return StreamInterface Returns the body as a stream. */ - public function getBody(); + public function getBody(): StreamInterface; /** * Return an instance with the specified message body. @@ -183,5 +183,5 @@ public function getBody(); * @return static * @throws \InvalidArgumentException When the body is not valid. */ - public function withBody(StreamInterface $body); + public function withBody(StreamInterface $body): MessageInterface; } diff --git a/vendor/psr/http-message/src/RequestInterface.php b/vendor/psr/http-message/src/RequestInterface.php index a96d4fd..33f85e5 100644 --- a/vendor/psr/http-message/src/RequestInterface.php +++ b/vendor/psr/http-message/src/RequestInterface.php @@ -39,7 +39,7 @@ interface RequestInterface extends MessageInterface * * @return string */ - public function getRequestTarget(); + public function getRequestTarget(): string; /** * Return an instance with the specific request-target. @@ -55,17 +55,18 @@ public function getRequestTarget(); * * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various * request-target forms allowed in request messages) - * @param mixed $requestTarget + * @param string $requestTarget * @return static */ - public function withRequestTarget($requestTarget); + public function withRequestTarget(string $requestTarget): RequestInterface; + /** * Retrieves the HTTP method of the request. * * @return string Returns the request method. */ - public function getMethod(); + public function getMethod(): string; /** * Return an instance with the provided HTTP method. @@ -82,7 +83,7 @@ public function getMethod(); * @return static * @throws \InvalidArgumentException for invalid HTTP methods. */ - public function withMethod($method); + public function withMethod(string $method): RequestInterface; /** * Retrieves the URI instance. @@ -93,7 +94,7 @@ public function withMethod($method); * @return UriInterface Returns a UriInterface instance * representing the URI of the request. */ - public function getUri(); + public function getUri(): UriInterface; /** * Returns an instance with the provided URI. @@ -125,5 +126,5 @@ public function getUri(); * @param bool $preserveHost Preserve the original state of the Host header. * @return static */ - public function withUri(UriInterface $uri, $preserveHost = false); + public function withUri(UriInterface $uri, bool $preserveHost = false): RequestInterface; } diff --git a/vendor/psr/http-message/src/ResponseInterface.php b/vendor/psr/http-message/src/ResponseInterface.php index c306514..e9299a9 100644 --- a/vendor/psr/http-message/src/ResponseInterface.php +++ b/vendor/psr/http-message/src/ResponseInterface.php @@ -27,7 +27,7 @@ interface ResponseInterface extends MessageInterface * * @return int Status code. */ - public function getStatusCode(); + public function getStatusCode(): int; /** * Return an instance with the specified status code and, optionally, reason phrase. @@ -49,7 +49,7 @@ public function getStatusCode(); * @return static * @throws \InvalidArgumentException For invalid status code arguments. */ - public function withStatus($code, $reasonPhrase = ''); + public function withStatus(int $code, string $reasonPhrase = ''): ResponseInterface; /** * Gets the response reason phrase associated with the status code. @@ -64,5 +64,5 @@ public function withStatus($code, $reasonPhrase = ''); * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml * @return string Reason phrase; must return an empty string if none present. */ - public function getReasonPhrase(); + public function getReasonPhrase(): string; } diff --git a/vendor/psr/http-message/src/ServerRequestInterface.php b/vendor/psr/http-message/src/ServerRequestInterface.php index 0251234..8625d0e 100644 --- a/vendor/psr/http-message/src/ServerRequestInterface.php +++ b/vendor/psr/http-message/src/ServerRequestInterface.php @@ -51,7 +51,7 @@ interface ServerRequestInterface extends RequestInterface * * @return array */ - public function getServerParams(); + public function getServerParams(): array; /** * Retrieve cookies. @@ -63,7 +63,7 @@ public function getServerParams(); * * @return array */ - public function getCookieParams(); + public function getCookieParams(): array; /** * Return an instance with the specified cookies. @@ -82,7 +82,7 @@ public function getCookieParams(); * @param array $cookies Array of key/value pairs representing cookies. * @return static */ - public function withCookieParams(array $cookies); + public function withCookieParams(array $cookies): ServerRequestInterface; /** * Retrieve query string arguments. @@ -96,7 +96,7 @@ public function withCookieParams(array $cookies); * * @return array */ - public function getQueryParams(); + public function getQueryParams(): array; /** * Return an instance with the specified query string arguments. @@ -120,7 +120,7 @@ public function getQueryParams(); * $_GET. * @return static */ - public function withQueryParams(array $query); + public function withQueryParams(array $query): ServerRequestInterface; /** * Retrieve normalized file upload data. @@ -134,7 +134,7 @@ public function withQueryParams(array $query); * @return array An array tree of UploadedFileInterface instances; an empty * array MUST be returned if no data is present. */ - public function getUploadedFiles(); + public function getUploadedFiles(): array; /** * Create a new instance with the specified uploaded files. @@ -147,7 +147,7 @@ public function getUploadedFiles(); * @return static * @throws \InvalidArgumentException if an invalid structure is provided. */ - public function withUploadedFiles(array $uploadedFiles); + public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface; /** * Retrieve any parameters provided in the request body. @@ -194,7 +194,7 @@ public function getParsedBody(); * @throws \InvalidArgumentException if an unsupported argument type is * provided. */ - public function withParsedBody($data); + public function withParsedBody($data): ServerRequestInterface; /** * Retrieve attributes derived from the request. @@ -207,7 +207,7 @@ public function withParsedBody($data); * * @return array Attributes derived from the request. */ - public function getAttributes(); + public function getAttributes(): array; /** * Retrieve a single derived request attribute. @@ -224,7 +224,7 @@ public function getAttributes(); * @param mixed $default Default value to return if the attribute does not exist. * @return mixed */ - public function getAttribute($name, $default = null); + public function getAttribute(string $name, $default = null); /** * Return an instance with the specified derived request attribute. @@ -241,7 +241,7 @@ public function getAttribute($name, $default = null); * @param mixed $value The value of the attribute. * @return static */ - public function withAttribute($name, $value); + public function withAttribute(string $name, $value): ServerRequestInterface; /** * Return an instance that removes the specified derived request attribute. @@ -257,5 +257,5 @@ public function withAttribute($name, $value); * @param string $name The attribute name. * @return static */ - public function withoutAttribute($name); + public function withoutAttribute(string $name): ServerRequestInterface; } diff --git a/vendor/psr/http-message/src/StreamInterface.php b/vendor/psr/http-message/src/StreamInterface.php index f68f391..a62aabb 100644 --- a/vendor/psr/http-message/src/StreamInterface.php +++ b/vendor/psr/http-message/src/StreamInterface.php @@ -25,14 +25,14 @@ interface StreamInterface * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring * @return string */ - public function __toString(); + public function __toString(): string; /** * Closes the stream and any underlying resources. * * @return void */ - public function close(); + public function close(): void; /** * Separates any underlying resources from the stream. @@ -48,7 +48,7 @@ public function detach(); * * @return int|null Returns the size in bytes if known, or null if unknown. */ - public function getSize(); + public function getSize(): ?int; /** * Returns the current position of the file read/write pointer @@ -56,21 +56,21 @@ public function getSize(); * @return int Position of the file pointer * @throws \RuntimeException on error. */ - public function tell(); + public function tell(): int; /** * Returns true if the stream is at the end of the stream. * * @return bool */ - public function eof(); + public function eof(): bool; /** * Returns whether or not the stream is seekable. * * @return bool */ - public function isSeekable(); + public function isSeekable(): bool; /** * Seek to a position in the stream. @@ -84,7 +84,7 @@ public function isSeekable(); * SEEK_END: Set position to end-of-stream plus offset. * @throws \RuntimeException on failure. */ - public function seek($offset, $whence = SEEK_SET); + public function seek(int $offset, int $whence = SEEK_SET): void; /** * Seek to the beginning of the stream. @@ -96,14 +96,14 @@ public function seek($offset, $whence = SEEK_SET); * @link http://www.php.net/manual/en/function.fseek.php * @throws \RuntimeException on failure. */ - public function rewind(); + public function rewind(): void; /** * Returns whether or not the stream is writable. * * @return bool */ - public function isWritable(); + public function isWritable(): bool; /** * Write data to the stream. @@ -112,14 +112,14 @@ public function isWritable(); * @return int Returns the number of bytes written to the stream. * @throws \RuntimeException on failure. */ - public function write($string); + public function write(string $string): int; /** * Returns whether or not the stream is readable. * * @return bool */ - public function isReadable(); + public function isReadable(): bool; /** * Read data from the stream. @@ -131,7 +131,7 @@ public function isReadable(); * if no bytes are available. * @throws \RuntimeException if an error occurs. */ - public function read($length); + public function read(int $length): string; /** * Returns the remaining contents in a string @@ -140,7 +140,7 @@ public function read($length); * @throws \RuntimeException if unable to read or an error occurs while * reading. */ - public function getContents(); + public function getContents(): string; /** * Get stream metadata as an associative array or retrieve a specific key. @@ -149,10 +149,10 @@ public function getContents(); * stream_get_meta_data() function. * * @link http://php.net/manual/en/function.stream-get-meta-data.php - * @param string $key Specific metadata to retrieve. + * @param string|null $key Specific metadata to retrieve. * @return array|mixed|null Returns an associative array if no key is * provided. Returns a specific key value if a key is provided and the * value is found, or null if the key is not found. */ - public function getMetadata($key = null); + public function getMetadata(?string $key = null); } diff --git a/vendor/psr/http-message/src/UploadedFileInterface.php b/vendor/psr/http-message/src/UploadedFileInterface.php index f8a6901..dd19d65 100644 --- a/vendor/psr/http-message/src/UploadedFileInterface.php +++ b/vendor/psr/http-message/src/UploadedFileInterface.php @@ -28,7 +28,7 @@ interface UploadedFileInterface * @throws \RuntimeException in cases when no stream is available or can be * created. */ - public function getStream(); + public function getStream(): StreamInterface; /** * Move the uploaded file to a new location. @@ -62,7 +62,7 @@ public function getStream(); * @throws \RuntimeException on any error during the move operation, or on * the second or subsequent call to the method. */ - public function moveTo($targetPath); + public function moveTo(string $targetPath): void; /** * Retrieve the file size. @@ -73,7 +73,7 @@ public function moveTo($targetPath); * * @return int|null The file size in bytes or null if unknown. */ - public function getSize(); + public function getSize(): ?int; /** * Retrieve the error associated with the uploaded file. @@ -89,7 +89,7 @@ public function getSize(); * @see http://php.net/manual/en/features.file-upload.errors.php * @return int One of PHP's UPLOAD_ERR_XXX constants. */ - public function getError(); + public function getError(): int; /** * Retrieve the filename sent by the client. @@ -104,7 +104,7 @@ public function getError(); * @return string|null The filename sent by the client or null if none * was provided. */ - public function getClientFilename(); + public function getClientFilename(): ?string; /** * Retrieve the media type sent by the client. @@ -119,5 +119,5 @@ public function getClientFilename(); * @return string|null The media type sent by the client or null if none * was provided. */ - public function getClientMediaType(); + public function getClientMediaType(): ?string; } diff --git a/vendor/psr/http-message/src/UriInterface.php b/vendor/psr/http-message/src/UriInterface.php index 9d7ab9e..15e2cf2 100644 --- a/vendor/psr/http-message/src/UriInterface.php +++ b/vendor/psr/http-message/src/UriInterface.php @@ -1,4 +1,5 @@ <?php + namespace Psr\Http\Message; /** @@ -37,7 +38,7 @@ interface UriInterface * @see https://tools.ietf.org/html/rfc3986#section-3.1 * @return string The URI scheme. */ - public function getScheme(); + public function getScheme(): string; /** * Retrieve the authority component of the URI. @@ -57,7 +58,7 @@ public function getScheme(); * @see https://tools.ietf.org/html/rfc3986#section-3.2 * @return string The URI authority, in "[user-info@]host[:port]" format. */ - public function getAuthority(); + public function getAuthority(): string; /** * Retrieve the user information component of the URI. @@ -74,7 +75,7 @@ public function getAuthority(); * * @return string The URI user information, in "username[:password]" format. */ - public function getUserInfo(); + public function getUserInfo(): string; /** * Retrieve the host component of the URI. @@ -87,7 +88,7 @@ public function getUserInfo(); * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 * @return string The URI host. */ - public function getHost(); + public function getHost(): string; /** * Retrieve the port component of the URI. @@ -104,7 +105,7 @@ public function getHost(); * * @return null|int The URI port. */ - public function getPort(); + public function getPort(): ?int; /** * Retrieve the path component of the URI. @@ -131,7 +132,7 @@ public function getPort(); * @see https://tools.ietf.org/html/rfc3986#section-3.3 * @return string The URI path. */ - public function getPath(); + public function getPath(): string; /** * Retrieve the query string of the URI. @@ -153,7 +154,7 @@ public function getPath(); * @see https://tools.ietf.org/html/rfc3986#section-3.4 * @return string The URI query string. */ - public function getQuery(); + public function getQuery(): string; /** * Retrieve the fragment component of the URI. @@ -171,7 +172,7 @@ public function getQuery(); * @see https://tools.ietf.org/html/rfc3986#section-3.5 * @return string The URI fragment. */ - public function getFragment(); + public function getFragment(): string; /** * Return an instance with the specified scheme. @@ -188,7 +189,7 @@ public function getFragment(); * @return static A new instance with the specified scheme. * @throws \InvalidArgumentException for invalid or unsupported schemes. */ - public function withScheme($scheme); + public function withScheme(string $scheme): UriInterface; /** * Return an instance with the specified user information. @@ -204,7 +205,7 @@ public function withScheme($scheme); * @param null|string $password The password associated with $user. * @return static A new instance with the specified user information. */ - public function withUserInfo($user, $password = null); + public function withUserInfo(string $user, ?string $password = null): UriInterface; /** * Return an instance with the specified host. @@ -218,7 +219,7 @@ public function withUserInfo($user, $password = null); * @return static A new instance with the specified host. * @throws \InvalidArgumentException for invalid hostnames. */ - public function withHost($host); + public function withHost(string $host): UriInterface; /** * Return an instance with the specified port. @@ -237,7 +238,7 @@ public function withHost($host); * @return static A new instance with the specified port. * @throws \InvalidArgumentException for invalid ports. */ - public function withPort($port); + public function withPort(?int $port): UriInterface; /** * Return an instance with the specified path. @@ -261,7 +262,7 @@ public function withPort($port); * @return static A new instance with the specified path. * @throws \InvalidArgumentException for invalid paths. */ - public function withPath($path); + public function withPath(string $path): UriInterface; /** * Return an instance with the specified query string. @@ -278,7 +279,7 @@ public function withPath($path); * @return static A new instance with the specified query string. * @throws \InvalidArgumentException for invalid query strings. */ - public function withQuery($query); + public function withQuery(string $query): UriInterface; /** * Return an instance with the specified URI fragment. @@ -294,7 +295,7 @@ public function withQuery($query); * @param string $fragment The fragment to use with the new instance. * @return static A new instance with the specified fragment. */ - public function withFragment($fragment); + public function withFragment(string $fragment): UriInterface; /** * Return the string representation as a URI reference. @@ -319,5 +320,5 @@ public function withFragment($fragment); * @see http://tools.ietf.org/html/rfc3986#section-4.1 * @return string */ - public function __toString(); + public function __toString(): string; } diff --git a/vendor/psr/log/.gitignore b/vendor/psr/log/.gitignore deleted file mode 100644 index 22d0d82..0000000 --- a/vendor/psr/log/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vendor diff --git a/vendor/psr/log/Psr/Log/AbstractLogger.php b/vendor/psr/log/Psr/Log/AbstractLogger.php index 90e721a..e02f9da 100644 --- a/vendor/psr/log/Psr/Log/AbstractLogger.php +++ b/vendor/psr/log/Psr/Log/AbstractLogger.php @@ -14,8 +14,8 @@ abstract class AbstractLogger implements LoggerInterface /** * System is unusable. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -30,8 +30,8 @@ public function emergency($message, array $context = array()) * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -45,8 +45,8 @@ public function alert($message, array $context = array()) * * Example: Application component unavailable, unexpected exception. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -59,8 +59,8 @@ public function critical($message, array $context = array()) * Runtime errors that do not require immediate action but should typically * be logged and monitored. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -75,8 +75,8 @@ public function error($message, array $context = array()) * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -88,8 +88,8 @@ public function warning($message, array $context = array()) /** * Normal but significant events. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -103,8 +103,8 @@ public function notice($message, array $context = array()) * * Example: User logs in, SQL logs. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -116,8 +116,8 @@ public function info($message, array $context = array()) /** * Detailed debug information. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ diff --git a/vendor/psr/log/Psr/Log/LoggerAwareTrait.php b/vendor/psr/log/Psr/Log/LoggerAwareTrait.php index 639f79b..82bf45c 100644 --- a/vendor/psr/log/Psr/Log/LoggerAwareTrait.php +++ b/vendor/psr/log/Psr/Log/LoggerAwareTrait.php @@ -10,7 +10,7 @@ trait LoggerAwareTrait /** * The logger instance. * - * @var LoggerInterface + * @var LoggerInterface|null */ protected $logger; diff --git a/vendor/psr/log/Psr/Log/LoggerInterface.php b/vendor/psr/log/Psr/Log/LoggerInterface.php index 5ea7243..2206cfd 100644 --- a/vendor/psr/log/Psr/Log/LoggerInterface.php +++ b/vendor/psr/log/Psr/Log/LoggerInterface.php @@ -22,8 +22,8 @@ interface LoggerInterface /** * System is unusable. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -35,8 +35,8 @@ public function emergency($message, array $context = array()); * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -47,8 +47,8 @@ public function alert($message, array $context = array()); * * Example: Application component unavailable, unexpected exception. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -58,8 +58,8 @@ public function critical($message, array $context = array()); * Runtime errors that do not require immediate action but should typically * be logged and monitored. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -71,8 +71,8 @@ public function error($message, array $context = array()); * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -81,8 +81,8 @@ public function warning($message, array $context = array()); /** * Normal but significant events. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -93,8 +93,8 @@ public function notice($message, array $context = array()); * * Example: User logs in, SQL logs. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -103,8 +103,8 @@ public function info($message, array $context = array()); /** * Detailed debug information. * - * @param string $message - * @param array $context + * @param string $message + * @param mixed[] $context * * @return void */ @@ -113,11 +113,13 @@ public function debug($message, array $context = array()); /** * Logs with an arbitrary level. * - * @param mixed $level - * @param string $message - * @param array $context + * @param mixed $level + * @param string $message + * @param mixed[] $context * * @return void + * + * @throws \Psr\Log\InvalidArgumentException */ public function log($level, $message, array $context = array()); } diff --git a/vendor/psr/log/Psr/Log/LoggerTrait.php b/vendor/psr/log/Psr/Log/LoggerTrait.php index 867225d..e392fef 100644 --- a/vendor/psr/log/Psr/Log/LoggerTrait.php +++ b/vendor/psr/log/Psr/Log/LoggerTrait.php @@ -135,6 +135,8 @@ public function debug($message, array $context = array()) * @param array $context * * @return void + * + * @throws \Psr\Log\InvalidArgumentException */ abstract public function log($level, $message, array $context = array()); } diff --git a/vendor/psr/log/Psr/Log/NullLogger.php b/vendor/psr/log/Psr/Log/NullLogger.php index d8cd682..c8f7293 100644 --- a/vendor/psr/log/Psr/Log/NullLogger.php +++ b/vendor/psr/log/Psr/Log/NullLogger.php @@ -20,6 +20,8 @@ class NullLogger extends AbstractLogger * @param array $context * * @return void + * + * @throws \Psr\Log\InvalidArgumentException */ public function log($level, $message, array $context = array()) { diff --git a/vendor/psr/log/Psr/Log/Test/DummyTest.php b/vendor/psr/log/Psr/Log/Test/DummyTest.php new file mode 100644 index 0000000..9638c11 --- /dev/null +++ b/vendor/psr/log/Psr/Log/Test/DummyTest.php @@ -0,0 +1,18 @@ +<?php + +namespace Psr\Log\Test; + +/** + * This class is internal and does not follow the BC promise. + * + * Do NOT use this class in any way. + * + * @internal + */ +class DummyTest +{ + public function __toString() + { + return 'DummyTest'; + } +} diff --git a/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php index a0391a5..e1e5354 100644 --- a/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php +++ b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php @@ -4,6 +4,7 @@ use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; +use PHPUnit\Framework\TestCase; /** * Provides a base test class for ensuring compliance with the LoggerInterface. @@ -11,7 +12,7 @@ * Implementors can extend the class and implement abstract methods to run this * as part of their test suite. */ -abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase +abstract class LoggerInterfaceTest extends TestCase { /** * @return LoggerInterface @@ -101,6 +102,9 @@ public function testObjectCastToString() public function testContextCanContainAnything() { + $closed = fopen('php://memory', 'r'); + fclose($closed); + $context = array( 'bool' => true, 'null' => null, @@ -110,6 +114,7 @@ public function testContextCanContainAnything() 'nested' => array('with object' => new DummyTest), 'object' => new \DateTime, 'resource' => fopen('php://memory', 'r'), + 'closed' => $closed, ); $this->getLogger()->warning('Crazy context data', $context); @@ -131,10 +136,3 @@ public function testContextExceptionKeyCanBeExceptionOrOtherValues() $this->assertEquals($expected, $this->getLogs()); } } - -class DummyTest -{ - public function __toString() - { - } -} diff --git a/vendor/psr/log/Psr/Log/Test/TestLogger.php b/vendor/psr/log/Psr/Log/Test/TestLogger.php new file mode 100644 index 0000000..1be3230 --- /dev/null +++ b/vendor/psr/log/Psr/Log/Test/TestLogger.php @@ -0,0 +1,147 @@ +<?php + +namespace Psr\Log\Test; + +use Psr\Log\AbstractLogger; + +/** + * Used for testing purposes. + * + * It records all records and gives you access to them for verification. + * + * @method bool hasEmergency($record) + * @method bool hasAlert($record) + * @method bool hasCritical($record) + * @method bool hasError($record) + * @method bool hasWarning($record) + * @method bool hasNotice($record) + * @method bool hasInfo($record) + * @method bool hasDebug($record) + * + * @method bool hasEmergencyRecords() + * @method bool hasAlertRecords() + * @method bool hasCriticalRecords() + * @method bool hasErrorRecords() + * @method bool hasWarningRecords() + * @method bool hasNoticeRecords() + * @method bool hasInfoRecords() + * @method bool hasDebugRecords() + * + * @method bool hasEmergencyThatContains($message) + * @method bool hasAlertThatContains($message) + * @method bool hasCriticalThatContains($message) + * @method bool hasErrorThatContains($message) + * @method bool hasWarningThatContains($message) + * @method bool hasNoticeThatContains($message) + * @method bool hasInfoThatContains($message) + * @method bool hasDebugThatContains($message) + * + * @method bool hasEmergencyThatMatches($message) + * @method bool hasAlertThatMatches($message) + * @method bool hasCriticalThatMatches($message) + * @method bool hasErrorThatMatches($message) + * @method bool hasWarningThatMatches($message) + * @method bool hasNoticeThatMatches($message) + * @method bool hasInfoThatMatches($message) + * @method bool hasDebugThatMatches($message) + * + * @method bool hasEmergencyThatPasses($message) + * @method bool hasAlertThatPasses($message) + * @method bool hasCriticalThatPasses($message) + * @method bool hasErrorThatPasses($message) + * @method bool hasWarningThatPasses($message) + * @method bool hasNoticeThatPasses($message) + * @method bool hasInfoThatPasses($message) + * @method bool hasDebugThatPasses($message) + */ +class TestLogger extends AbstractLogger +{ + /** + * @var array + */ + public $records = []; + + public $recordsByLevel = []; + + /** + * @inheritdoc + */ + public function log($level, $message, array $context = []) + { + $record = [ + 'level' => $level, + 'message' => $message, + 'context' => $context, + ]; + + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } + + public function hasRecords($level) + { + return isset($this->recordsByLevel[$level]); + } + + public function hasRecord($record, $level) + { + if (is_string($record)) { + $record = ['message' => $record]; + } + return $this->hasRecordThatPasses(function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + return true; + }, $level); + } + + public function hasRecordThatContains($message, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($message) { + return strpos($rec['message'], $message) !== false; + }, $level); + } + + public function hasRecordThatMatches($regex, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($regex) { + return preg_match($regex, $rec['message']) > 0; + }, $level); + } + + public function hasRecordThatPasses(callable $predicate, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + foreach ($this->recordsByLevel[$level] as $i => $rec) { + if (call_user_func($predicate, $rec, $i)) { + return true; + } + } + return false; + } + + public function __call($method, $args) + { + if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { + $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; + $level = strtolower($matches[2]); + if (method_exists($this, $genericMethod)) { + $args[] = $level; + return call_user_func_array([$this, $genericMethod], $args); + } + } + throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); + } + + public function reset() + { + $this->records = []; + $this->recordsByLevel = []; + } +} diff --git a/vendor/psr/log/README.md b/vendor/psr/log/README.md index 574bc1c..a9f20c4 100644 --- a/vendor/psr/log/README.md +++ b/vendor/psr/log/README.md @@ -7,6 +7,13 @@ This repository holds all interfaces/classes/traits related to Note that this is not a logger of its own. It is merely an interface that describes a logger. See the specification for more details. +Installation +------------ + +```bash +composer require psr/log +``` + Usage ----- @@ -31,6 +38,12 @@ class Foo if ($this->logger) { $this->logger->info('Doing work'); } + + try { + $this->doSomethingElse(); + } catch (Exception $exception) { + $this->logger->error('Oh no!', array('exception' => $exception)); + } // do something useful } diff --git a/vendor/psr/log/composer.json b/vendor/psr/log/composer.json index 87934d7..ca05695 100644 --- a/vendor/psr/log/composer.json +++ b/vendor/psr/log/composer.json @@ -7,7 +7,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "require": { @@ -20,7 +20,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } } } diff --git a/vendor/ralouphie/getallheaders/LICENSE b/vendor/ralouphie/getallheaders/LICENSE new file mode 100644 index 0000000..be5540c --- /dev/null +++ b/vendor/ralouphie/getallheaders/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Ralph Khattar + +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/vendor/ralouphie/getallheaders/README.md b/vendor/ralouphie/getallheaders/README.md new file mode 100644 index 0000000..9430d76 --- /dev/null +++ b/vendor/ralouphie/getallheaders/README.md @@ -0,0 +1,27 @@ +getallheaders +============= + +PHP `getallheaders()` polyfill. Compatible with PHP >= 5.3. + +[![Build Status](https://travis-ci.org/ralouphie/getallheaders.svg?branch=master)](https://travis-ci.org/ralouphie/getallheaders) +[![Coverage Status](https://coveralls.io/repos/ralouphie/getallheaders/badge.png?branch=master)](https://coveralls.io/r/ralouphie/getallheaders?branch=master) +[![Latest Stable Version](https://poser.pugx.org/ralouphie/getallheaders/v/stable.png)](https://packagist.org/packages/ralouphie/getallheaders) +[![Latest Unstable Version](https://poser.pugx.org/ralouphie/getallheaders/v/unstable.png)](https://packagist.org/packages/ralouphie/getallheaders) +[![License](https://poser.pugx.org/ralouphie/getallheaders/license.png)](https://packagist.org/packages/ralouphie/getallheaders) + + +This is a simple polyfill for [`getallheaders()`](http://www.php.net/manual/en/function.getallheaders.php). + +## Install + +For PHP version **`>= 5.6`**: + +``` +composer require ralouphie/getallheaders +``` + +For PHP version **`< 5.6`**: + +``` +composer require ralouphie/getallheaders "^2" +``` diff --git a/vendor/ralouphie/getallheaders/composer.json b/vendor/ralouphie/getallheaders/composer.json new file mode 100644 index 0000000..de8ce62 --- /dev/null +++ b/vendor/ralouphie/getallheaders/composer.json @@ -0,0 +1,26 @@ +{ + "name": "ralouphie/getallheaders", + "description": "A polyfill for getallheaders.", + "license": "MIT", + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^5 || ^6.5", + "php-coveralls/php-coveralls": "^2.1" + }, + "autoload": { + "files": ["src/getallheaders.php"] + }, + "autoload-dev": { + "psr-4": { + "getallheaders\\Tests\\": "tests/" + } + } +} diff --git a/vendor/ralouphie/getallheaders/src/getallheaders.php b/vendor/ralouphie/getallheaders/src/getallheaders.php new file mode 100644 index 0000000..c7285a5 --- /dev/null +++ b/vendor/ralouphie/getallheaders/src/getallheaders.php @@ -0,0 +1,46 @@ +<?php + +if (!function_exists('getallheaders')) { + + /** + * Get all HTTP header key/values as an associative array for the current request. + * + * @return string[string] The HTTP header key/value pairs. + */ + function getallheaders() + { + $headers = array(); + + $copy_server = array( + 'CONTENT_TYPE' => 'Content-Type', + 'CONTENT_LENGTH' => 'Content-Length', + 'CONTENT_MD5' => 'Content-Md5', + ); + + foreach ($_SERVER as $key => $value) { + if (substr($key, 0, 5) === 'HTTP_') { + $key = substr($key, 5); + if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) { + $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key)))); + $headers[$key] = $value; + } + } elseif (isset($copy_server[$key])) { + $headers[$copy_server[$key]] = $value; + } + } + + if (!isset($headers['Authorization'])) { + if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { + $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; + } elseif (isset($_SERVER['PHP_AUTH_USER'])) { + $basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; + $headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass); + } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) { + $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST']; + } + } + + return $headers; + } + +} diff --git a/vendor/squizlabs/php_codesniffer/CodeSniffer.php b/vendor/squizlabs/php_codesniffer/CodeSniffer.php index cdce86c..fa682c6 100644 --- a/vendor/squizlabs/php_codesniffer/CodeSniffer.php +++ b/vendor/squizlabs/php_codesniffer/CodeSniffer.php @@ -73,7 +73,7 @@ class PHP_CodeSniffer * * @var string */ - const VERSION = '2.9.1'; + const VERSION = '2.9.2'; /** * Package stability; either stable, beta or alpha. diff --git a/vendor/squizlabs/php_codesniffer/CodeSniffer/File.php b/vendor/squizlabs/php_codesniffer/CodeSniffer/File.php index 62c3979..17f155b 100644 --- a/vendor/squizlabs/php_codesniffer/CodeSniffer/File.php +++ b/vendor/squizlabs/php_codesniffer/CodeSniffer/File.php @@ -1763,7 +1763,7 @@ private static function _createTokenMap(&$tokens, $tokenizer, $eolChar) } break; default: - continue; + continue 2; }//end switch }//end for @@ -2880,7 +2880,7 @@ public function getMethodParameters($stackPtr) // If it's null, then there must be no parameters for this // method. if ($currVar === null) { - continue; + continue 2; } $vars[$paramCount] = array(); diff --git a/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php b/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php index 2020826..040090e 100644 --- a/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php +++ b/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php @@ -50,7 +50,9 @@ class Generic_Sniffs_CodeAnalysis_EmptyStatementSniff implements PHP_CodeSniffer public function register() { return array( + T_TRY, T_CATCH, + T_FINALLY, T_DO, T_ELSE, T_ELSEIF, @@ -98,7 +100,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) // Get token identifier. $name = strtoupper($token['content']); $error = 'Empty %s statement detected'; - $phpcsFile->addError($error, $stackPtr, 'Detected'.$name, array($name)); + $phpcsFile->addError($error, $stackPtr, 'Detected'.ucfirst(strtolower($name)), array($name)); }//end process() diff --git a/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php b/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php index 6dd3263..5710642 100644 --- a/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php +++ b/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php @@ -47,6 +47,7 @@ public function register() return array( T_TRY, T_CATCH, + T_FINALLY, T_DO, T_WHILE, T_FOR, diff --git a/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php b/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php index 71bedc8..116a1f0 100644 --- a/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php +++ b/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php @@ -384,6 +384,10 @@ private function _validateInlineEmbeddedPhp(PHP_CodeSniffer_File $phpcsFile, $st $trailingSpace = 0; if ($tokens[($closeTag - 1)]['code'] === T_WHITESPACE) { $trailingSpace = strlen($tokens[($closeTag - 1)]['content']); + } else if ($tokens[($closeTag - 1)]['code'] === T_COMMENT + && substr($tokens[($closeTag - 1)]['content'], -1) === ' ' + ) { + $trailingSpace = (strlen($tokens[($closeTag - 1)]['content']) - strlen(rtrim($tokens[($closeTag - 1)]['content']))); } if ($trailingSpace !== 1) { @@ -393,6 +397,8 @@ private function _validateInlineEmbeddedPhp(PHP_CodeSniffer_File $phpcsFile, $st if ($fix === true) { if ($trailingSpace === 0) { $phpcsFile->fixer->addContentBefore($closeTag, ' '); + } else if ($tokens[($closeTag - 1)]['code'] === T_COMMENT) { + $phpcsFile->fixer->replaceToken(($closeTag - 1), rtrim($tokens[($closeTag - 1)]['content']).' '); } else { $phpcsFile->fixer->replaceToken(($closeTag - 1), ' '); } diff --git a/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php b/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php index 102f4af..e1bcf36 100644 --- a/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php +++ b/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php @@ -138,6 +138,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $phpcsFile->fixer->beginChangeset(); $innerContent = substr($workingString, 1, -1); $innerContent = str_replace('\"', '"', $innerContent); + $innerContent = str_replace('\\$', '$', $innerContent); $phpcsFile->fixer->replaceToken($stackPtr, "'$innerContent'"); while ($lastStringToken !== $stackPtr) { $phpcsFile->fixer->replaceToken($lastStringToken, ''); diff --git a/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php b/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php index fb0914a..19202e9 100644 --- a/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php +++ b/vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php @@ -59,6 +59,7 @@ public function register() T_ELSEIF, T_TRY, T_CATCH, + T_FINALLY, ); }//end register() @@ -301,6 +302,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } else if ($tokens[$trailingContent]['code'] !== T_ELSE && $tokens[$trailingContent]['code'] !== T_ELSEIF && $tokens[$trailingContent]['code'] !== T_CATCH + && $tokens[$trailingContent]['code'] !== T_FINALLY && $tokens[$trailingContent]['line'] === ($tokens[$scopeCloser]['line'] + 1) ) { $error = 'No blank line found after control structure'; diff --git a/vendor/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/CSS.php b/vendor/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/CSS.php index 8e4ba35..8656e05 100644 --- a/vendor/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/CSS.php +++ b/vendor/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/CSS.php @@ -390,7 +390,7 @@ public function tokenizeString($string, $eolChar='\n') // Needs to be in the format "url(" for it to be a URL. if ($finalTokens[$x]['code'] !== T_OPEN_PARENTHESIS) { - continue; + continue 2; } // Make sure the content isn't empty. @@ -401,7 +401,7 @@ public function tokenizeString($string, $eolChar='\n') } if ($finalTokens[$y]['code'] === T_CLOSE_PARENTHESIS) { - continue; + continue 2; } if (PHP_CODESNIFFER_VERBOSITY > 1) { diff --git a/vendor/symfony/console/Application.php b/vendor/symfony/console/Application.php index 1d41563..29951e9 100644 --- a/vendor/symfony/console/Application.php +++ b/vendor/symfony/console/Application.php @@ -12,16 +12,24 @@ namespace Symfony\Component\Console; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\CompleteCommand; +use Symfony\Component\Console\Command\DumpCompletionCommand; use Symfony\Component\Console\Command\HelpCommand; +use Symfony\Component\Console\Command\LazyCommand; use Symfony\Component\Console\Command\ListCommand; +use Symfony\Component\Console\Command\SignalableCommandInterface; use Symfony\Component\Console\CommandLoader\CommandLoaderInterface; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Event\ConsoleExceptionEvent; +use Symfony\Component\Console\Event\ConsoleSignalEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\Console\Exception\ExceptionInterface; use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Exception\NamespaceNotFoundException; +use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\DebugFormatterHelper; use Symfony\Component\Console\Helper\FormatterHelper; @@ -36,13 +44,14 @@ use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\StreamableInputInterface; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Debug\ErrorHandler; -use Symfony\Component\Debug\Exception\FatalThrowableError; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Console\SignalRegistry\SignalRegistry; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\ErrorHandler\ErrorHandler; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\Service\ResetInterface; /** * An Application is the container for a collection of commands. @@ -59,9 +68,9 @@ * * @author Fabien Potencier <fabien@symfony.com> */ -class Application +class Application implements ResetInterface { - private $commands = array(); + private $commands = []; private $wantHelps = false; private $runningCommand; private $name; @@ -74,21 +83,26 @@ class Application private $dispatcher; private $terminal; private $defaultCommand; - private $singleCommand; + private $singleCommand = false; private $initialized; + private $signalRegistry; + private $signalsToDispatchEvent = []; - /** - * @param string $name The name of the application - * @param string $version The version of the application - */ - public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') + public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN') { $this->name = $name; $this->version = $version; $this->terminal = new Terminal(); $this->defaultCommand = 'list'; + if (\defined('SIGINT') && SignalRegistry::isSupported()) { + $this->signalRegistry = new SignalRegistry(); + $this->signalsToDispatchEvent = [\SIGINT, \SIGTERM, \SIGUSR1, \SIGUSR2]; + } } + /** + * @final + */ public function setDispatcher(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; @@ -99,6 +113,20 @@ public function setCommandLoader(CommandLoaderInterface $commandLoader) $this->commandLoader = $commandLoader; } + public function getSignalRegistry(): SignalRegistry + { + if (!$this->signalRegistry) { + throw new RuntimeException('Signals are not supported. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.'); + } + + return $this->signalRegistry; + } + + public function setSignalsToDispatchEvent(int ...$signalsToDispatchEvent) + { + $this->signalsToDispatchEvent = $signalsToDispatchEvent; + } + /** * Runs the current application. * @@ -108,8 +136,10 @@ public function setCommandLoader(CommandLoaderInterface $commandLoader) */ public function run(InputInterface $input = null, OutputInterface $output = null) { - putenv('LINES='.$this->terminal->getHeight()); - putenv('COLUMNS='.$this->terminal->getWidth()); + if (\function_exists('putenv')) { + @putenv('LINES='.$this->terminal->getHeight()); + @putenv('COLUMNS='.$this->terminal->getWidth()); + } if (null === $input) { $input = new ArgvInput(); @@ -119,29 +149,22 @@ public function run(InputInterface $input = null, OutputInterface $output = null $output = new ConsoleOutput(); } - $renderException = function ($e) use ($output) { - if (!$e instanceof \Exception) { - $e = class_exists(FatalThrowableError::class) ? new FatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); - } + $renderException = function (\Throwable $e) use ($output) { if ($output instanceof ConsoleOutputInterface) { - $this->renderException($e, $output->getErrorOutput()); + $this->renderThrowable($e, $output->getErrorOutput()); } else { - $this->renderException($e, $output); + $this->renderThrowable($e, $output); } }; if ($phpHandler = set_exception_handler($renderException)) { restore_exception_handler(); if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) { - $debugHandler = true; - } elseif ($debugHandler = $phpHandler[0]->setExceptionHandler($renderException)) { - $phpHandler[0]->setExceptionHandler($debugHandler); + $errorHandler = true; + } elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) { + $phpHandler[0]->setExceptionHandler($errorHandler); } } - if (null !== $this->dispatcher && $this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) { - @trigger_error(sprintf('The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead.'), E_USER_DEPRECATED); - } - $this->configureIO($input, $output); try { @@ -156,7 +179,7 @@ public function run(InputInterface $input = null, OutputInterface $output = null $exitCode = $e->getCode(); if (is_numeric($exitCode)) { $exitCode = (int) $exitCode; - if (0 === $exitCode) { + if ($exitCode <= 0) { $exitCode = 1; } } else { @@ -170,7 +193,7 @@ public function run(InputInterface $input = null, OutputInterface $output = null restore_exception_handler(); } restore_exception_handler(); - } elseif (!$debugHandler) { + } elseif (!$errorHandler) { $finalHandler = $phpHandler[0]->setExceptionHandler(null); if ($finalHandler !== $renderException) { $phpHandler[0]->setExceptionHandler($finalHandler); @@ -196,17 +219,24 @@ public function run(InputInterface $input = null, OutputInterface $output = null */ public function doRun(InputInterface $input, OutputInterface $output) { - if (true === $input->hasParameterOption(array('--version', '-V'), true)) { + if (true === $input->hasParameterOption(['--version', '-V'], true)) { $output->writeln($this->getLongVersion()); return 0; } + try { + // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument. + $input->bind($this->getDefinition()); + } catch (ExceptionInterface $e) { + // Errors must be ignored, full binding/validation happens later when the command is known. + } + $name = $this->getCommandName($input); - if (true === $input->hasParameterOption(array('--help', '-h'), true)) { + if (true === $input->hasParameterOption(['--help', '-h'], true)) { if (!$name) { $name = 'help'; - $input = new ArrayInput(array('command_name' => $this->defaultCommand)); + $input = new ArrayInput(['command_name' => $this->defaultCommand]); } else { $this->wantHelps = true; } @@ -217,31 +247,54 @@ public function doRun(InputInterface $input, OutputInterface $output) $definition = $this->getDefinition(); $definition->setArguments(array_merge( $definition->getArguments(), - array( + [ 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name), - ) + ] )); } try { - $e = $this->runningCommand = null; + $this->runningCommand = null; // the command name MUST be the first element of the input $command = $this->find($name); - } catch (\Exception $e) { } catch (\Throwable $e) { - } - if (null !== $e) { - if (null !== $this->dispatcher) { - $event = new ConsoleErrorEvent($input, $output, $e); - $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); - $e = $event->getError(); + if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== \count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) { + if (null !== $this->dispatcher) { + $event = new ConsoleErrorEvent($input, $output, $e); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); + + if (0 === $event->getExitCode()) { + return 0; + } - if (0 === $event->getExitCode()) { - return 0; + $e = $event->getError(); } + + throw $e; } - throw $e; + $alternative = $alternatives[0]; + + $style = new SymfonyStyle($input, $output); + $output->writeln(''); + $formattedBlock = (new FormatterHelper())->formatBlock(sprintf('Command "%s" is not defined.', $name), 'error', true); + $output->writeln($formattedBlock); + if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) { + if (null !== $this->dispatcher) { + $event = new ConsoleErrorEvent($input, $output, $e); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); + + return $event->getExitCode(); + } + + return 1; + } + + $command = $this->find($alternative); + } + + if ($command instanceof LazyCommand) { + $command = $command->getCommand(); } $this->runningCommand = $command; @@ -251,6 +304,13 @@ public function doRun(InputInterface $input, OutputInterface $output) return $exitCode; } + /** + * {@inheritdoc} + */ + public function reset() + { + } + public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; @@ -259,7 +319,7 @@ public function setHelperSet(HelperSet $helperSet) /** * Get the helper set associated with the command. * - * @return HelperSet The HelperSet instance associated with this command + * @return HelperSet */ public function getHelperSet() { @@ -278,7 +338,7 @@ public function setDefinition(InputDefinition $definition) /** * Gets the InputDefinition related to this Application. * - * @return InputDefinition The InputDefinition instance + * @return InputDefinition */ public function getDefinition() { @@ -296,10 +356,42 @@ public function getDefinition() return $this->definition; } + /** + * Adds suggestions to $suggestions for the current completion input (e.g. option or argument). + */ + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ( + CompletionInput::TYPE_ARGUMENT_VALUE === $input->getCompletionType() + && 'command' === $input->getCompletionName() + ) { + $commandNames = []; + foreach ($this->all() as $name => $command) { + // skip hidden commands and aliased commands as they already get added below + if ($command->isHidden() || $command->getName() !== $name) { + continue; + } + $commandNames[] = $command->getName(); + foreach ($command->getAliases() as $name) { + $commandNames[] = $name; + } + } + $suggestions->suggestValues(array_filter($commandNames)); + + return; + } + + if (CompletionInput::TYPE_OPTION_NAME === $input->getCompletionType()) { + $suggestions->suggestOptions($this->getDefinition()->getOptions()); + + return; + } + } + /** * Gets the help message. * - * @return string A help message + * @return string */ public function getHelp() { @@ -309,7 +401,7 @@ public function getHelp() /** * Gets whether to catch exceptions or not during commands execution. * - * @return bool Whether to catch exceptions or not during commands execution + * @return bool */ public function areExceptionsCaught() { @@ -318,18 +410,16 @@ public function areExceptionsCaught() /** * Sets whether to catch exceptions or not during commands execution. - * - * @param bool $boolean Whether to catch exceptions or not during commands execution */ - public function setCatchExceptions($boolean) + public function setCatchExceptions(bool $boolean) { - $this->catchExceptions = (bool) $boolean; + $this->catchExceptions = $boolean; } /** * Gets whether to automatically exit after a command execution or not. * - * @return bool Whether to automatically exit after a command execution or not + * @return bool */ public function isAutoExitEnabled() { @@ -338,18 +428,16 @@ public function isAutoExitEnabled() /** * Sets whether to automatically exit after a command execution or not. - * - * @param bool $boolean Whether to automatically exit after a command execution or not */ - public function setAutoExit($boolean) + public function setAutoExit(bool $boolean) { - $this->autoExit = (bool) $boolean; + $this->autoExit = $boolean; } /** * Gets the name of the application. * - * @return string The application name + * @return string */ public function getName() { @@ -358,10 +446,8 @@ public function getName() /** * Sets the application name. - * - * @param string $name The application name - */ - public function setName($name) + **/ + public function setName(string $name) { $this->name = $name; } @@ -369,7 +455,7 @@ public function setName($name) /** * Gets the application version. * - * @return string The application version + * @return string */ public function getVersion() { @@ -378,10 +464,8 @@ public function getVersion() /** * Sets the application version. - * - * @param string $version The application version */ - public function setVersion($version) + public function setVersion(string $version) { $this->version = $version; } @@ -389,7 +473,7 @@ public function setVersion($version) /** * Returns the long version of the application. * - * @return string The long application version + * @return string */ public function getLongVersion() { @@ -407,11 +491,9 @@ public function getLongVersion() /** * Registers a new command. * - * @param string $name The command name - * - * @return Command The newly created command + * @return Command */ - public function register($name) + public function register(string $name) { return $this->add(new Command($name)); } @@ -436,7 +518,7 @@ public function addCommands(array $commands) * If a command with the same name already exists, it will be overridden. * If the command is not enabled it will not be added. * - * @return Command|null The registered command if enabled or null + * @return Command|null */ public function add(Command $command) { @@ -447,15 +529,16 @@ public function add(Command $command) if (!$command->isEnabled()) { $command->setApplication(null); - return; + return null; } - if (null === $command->getDefinition()) { - throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', \get_class($command))); + if (!$command instanceof LazyCommand) { + // Will throw if the command is not correctly initialized. + $command->getDefinition(); } if (!$command->getName()) { - throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($command))); + throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_debug_type($command))); } $this->commands[$command->getName()] = $command; @@ -470,13 +553,11 @@ public function add(Command $command) /** * Returns a registered command by name or alias. * - * @param string $name The command name or alias - * - * @return Command A Command object + * @return Command * * @throws CommandNotFoundException When given command name does not exist */ - public function get($name) + public function get(string $name) { $this->init(); @@ -484,6 +565,11 @@ public function get($name) throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); } + // When the command has a different name than the one used at the command loader level + if (!isset($this->commands[$name])) { + throw new CommandNotFoundException(sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name)); + } + $command = $this->commands[$name]; if ($this->wantHelps) { @@ -501,11 +587,9 @@ public function get($name) /** * Returns true if the command exists, false otherwise. * - * @param string $name The command name or alias - * - * @return bool true if the command exists, false otherwise + * @return bool */ - public function has($name) + public function has(string $name) { $this->init(); @@ -517,35 +601,37 @@ public function has($name) * * It does not return the global namespace which always exists. * - * @return string[] An array of namespaces + * @return string[] */ public function getNamespaces() { - $namespaces = array(); + $namespaces = []; foreach ($this->all() as $command) { - $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName())); + if ($command->isHidden()) { + continue; + } + + $namespaces[] = $this->extractAllNamespaces($command->getName()); foreach ($command->getAliases() as $alias) { - $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias)); + $namespaces[] = $this->extractAllNamespaces($alias); } } - return array_values(array_unique(array_filter($namespaces))); + return array_values(array_unique(array_filter(array_merge([], ...$namespaces)))); } /** * Finds a registered namespace by a name or an abbreviation. * - * @param string $namespace A namespace or abbreviation to search for - * - * @return string A registered namespace + * @return string * - * @throws CommandNotFoundException When namespace is incorrect or ambiguous + * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous */ - public function findNamespace($namespace) + public function findNamespace(string $namespace) { $allNamespaces = $this->getNamespaces(); - $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace); + $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $namespace))).'[^:]*'; $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); if (empty($namespaces)) { @@ -561,12 +647,12 @@ public function findNamespace($namespace) $message .= implode("\n ", $alternatives); } - throw new CommandNotFoundException($message, $alternatives); + throw new NamespaceNotFoundException($message, $alternatives); } $exact = \in_array($namespace, $namespaces, true); if (\count($namespaces) > 1 && !$exact) { - throw new CommandNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); + throw new NamespaceNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); } return $exact ? $namespace : reset($namespaces); @@ -578,19 +664,30 @@ public function findNamespace($namespace) * Contrary to get, this command tries to find the best * match if you give it an abbreviation of a name or alias. * - * @param string $name A command name or a command alias - * - * @return Command A Command instance + * @return Command * * @throws CommandNotFoundException When command name is incorrect or ambiguous */ - public function find($name) + public function find(string $name) { $this->init(); - $aliases = array(); + $aliases = []; + + foreach ($this->commands as $command) { + foreach ($command->getAliases() as $alias) { + if (!$this->has($alias)) { + $this->commands[$alias] = $command; + } + } + } + + if ($this->has($name)) { + return $this->get($name); + } + $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); - $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); + $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $name))).'[^:]*'; $commands = preg_grep('{^'.$expr.'}', $allCommands); if (empty($commands)) { @@ -607,6 +704,11 @@ public function find($name) $message = sprintf('Command "%s" is not defined.', $name); if ($alternatives = $this->findAlternatives($name, $allCommands)) { + // remove hidden commands + $alternatives = array_filter($alternatives, function ($name) { + return !$this->get($name)->isHidden(); + }); + if (1 == \count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { @@ -615,42 +717,58 @@ public function find($name) $message .= implode("\n ", $alternatives); } - throw new CommandNotFoundException($message, $alternatives); + throw new CommandNotFoundException($message, array_values($alternatives)); } // filter out aliases for commands which are already on the list if (\count($commands) > 1) { $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; - $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) { - $commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias; + $commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) { + if (!$commandList[$nameOrAlias] instanceof Command) { + $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias); + } + + $commandName = $commandList[$nameOrAlias]->getName(); + $aliases[$nameOrAlias] = $commandName; return $commandName === $nameOrAlias || !\in_array($commandName, $commands); })); } - $exact = \in_array($name, $commands, true) || isset($aliases[$name]); - if (\count($commands) > 1 && !$exact) { + if (\count($commands) > 1) { $usableWidth = $this->terminal->getWidth() - 10; $abbrevs = array_values($commands); $maxLen = 0; foreach ($abbrevs as $abbrev) { - $maxLen = max(Helper::strlen($abbrev), $maxLen); + $maxLen = max(Helper::width($abbrev), $maxLen); } - $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen) { - if (!$commandList[$cmd] instanceof Command) { - return $cmd; + $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen, &$commands) { + if ($commandList[$cmd]->isHidden()) { + unset($commands[array_search($cmd, $commands)]); + + return false; } + $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription(); - return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev; + return Helper::width($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev; }, array_values($commands)); - $suggestions = $this->getAbbreviationSuggestions($abbrevs); - throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $name, $suggestions), array_values($commands)); + if (\count($commands) > 1) { + $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs)); + + throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), array_values($commands)); + } + } + + $command = $this->get(reset($commands)); + + if ($command->isHidden()) { + throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); } - return $this->get($exact ? $name : reset($commands)); + return $command; } /** @@ -658,11 +776,9 @@ public function find($name) * * The array keys are the full names and the values the command instances. * - * @param string $namespace A namespace name - * - * @return Command[] An array of Command instances + * @return Command[] */ - public function all($namespace = null) + public function all(string $namespace = null) { $this->init(); @@ -681,7 +797,7 @@ public function all($namespace = null) return $commands; } - $commands = array(); + $commands = []; foreach ($this->commands as $name => $command) { if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { $commands[$name] = $command; @@ -702,13 +818,11 @@ public function all($namespace = null) /** * Returns an array of possible abbreviations given a set of names. * - * @param array $names An array of names - * - * @return array An array of abbreviations + * @return string[][] */ - public static function getAbbreviations($names) + public static function getAbbreviations(array $names) { - $abbrevs = array(); + $abbrevs = []; foreach ($names as $name) { for ($len = \strlen($name); $len > 0; --$len) { $abbrev = substr($name, 0, $len); @@ -719,55 +833,55 @@ public static function getAbbreviations($names) return $abbrevs; } - /** - * Renders a caught exception. - */ - public function renderException(\Exception $e, OutputInterface $output) + public function renderThrowable(\Throwable $e, OutputInterface $output): void { $output->writeln('', OutputInterface::VERBOSITY_QUIET); - $this->doRenderException($e, $output); + $this->doRenderThrowable($e, $output); if (null !== $this->runningCommand) { - $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET); + $output->writeln(sprintf('<info>%s</info>', OutputFormatter::escape(sprintf($this->runningCommand->getSynopsis(), $this->getName()))), OutputInterface::VERBOSITY_QUIET); $output->writeln('', OutputInterface::VERBOSITY_QUIET); } } - protected function doRenderException(\Exception $e, OutputInterface $output) + protected function doRenderThrowable(\Throwable $e, OutputInterface $output): void { do { $message = trim($e->getMessage()); if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $title = sprintf(' [%s%s] ', \get_class($e), 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); - $len = Helper::strlen($title); + $class = get_debug_type($e); + $title = sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); + $len = Helper::width($title); } else { $len = 0; } - $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX; - // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327 - if (\defined('HHVM_VERSION') && $width > 1 << 31) { - $width = 1 << 31; + if (str_contains($message, "@anonymous\0")) { + $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { + return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; + }, $message); } - $lines = array(); - foreach ('' !== $message ? preg_split('/\r?\n/', $message) : array() as $line) { + + $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX; + $lines = []; + foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) { foreach ($this->splitStringByWidth($line, $width - 4) as $line) { // pre-format lines to get the right string length - $lineLength = Helper::strlen($line) + 4; - $lines[] = array($line, $lineLength); + $lineLength = Helper::width($line) + 4; + $lines[] = [$line, $lineLength]; $len = max($lineLength, $len); } } - $messages = array(); + $messages = []; if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $messages[] = sprintf('<comment>%s</comment>', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); } $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len)); if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title)))); + $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::width($title)))); } foreach ($lines as $line) { $messages[] = sprintf('<error> %s %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1])); @@ -783,14 +897,21 @@ protected function doRenderException(\Exception $e, OutputInterface $output) // exception related properties $trace = $e->getTrace(); + array_unshift($trace, [ + 'function' => '', + 'file' => $e->getFile() ?: 'n/a', + 'line' => $e->getLine() ?: 'n/a', + 'args' => [], + ]); + for ($i = 0, $count = \count($trace); $i < $count; ++$i) { - $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; - $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; - $function = $trace[$i]['function']; - $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; - $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; + $class = $trace[$i]['class'] ?? ''; + $type = $trace[$i]['type'] ?? ''; + $function = $trace[$i]['function'] ?? ''; + $file = $trace[$i]['file'] ?? 'n/a'; + $line = $trace[$i]['line'] ?? 'n/a'; - $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET); + $output->writeln(sprintf(' %s%s at <info>%s:%s</info>', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET); } $output->writeln('', OutputInterface::VERBOSITY_QUIET); @@ -798,110 +919,40 @@ protected function doRenderException(\Exception $e, OutputInterface $output) } while ($e = $e->getPrevious()); } - /** - * Tries to figure out the terminal width in which this application runs. - * - * @return int|null - * - * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. - */ - protected function getTerminalWidth() - { - @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); - - return $this->terminal->getWidth(); - } - - /** - * Tries to figure out the terminal height in which this application runs. - * - * @return int|null - * - * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. - */ - protected function getTerminalHeight() - { - @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); - - return $this->terminal->getHeight(); - } - - /** - * Tries to figure out the terminal dimensions based on the current environment. - * - * @return array Array containing width and height - * - * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. - */ - public function getTerminalDimensions() - { - @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); - - return array($this->terminal->getWidth(), $this->terminal->getHeight()); - } - - /** - * Sets terminal dimensions. - * - * Can be useful to force terminal dimensions for functional tests. - * - * @param int $width The width - * @param int $height The height - * - * @return $this - * - * @deprecated since version 3.2, to be removed in 4.0. Set the COLUMNS and LINES env vars instead. - */ - public function setTerminalDimensions($width, $height) - { - @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Set the COLUMNS and LINES env vars instead.', __METHOD__), E_USER_DEPRECATED); - - putenv('COLUMNS='.$width); - putenv('LINES='.$height); - - return $this; - } - /** * Configures the input and output instances based on the user arguments and options. */ protected function configureIO(InputInterface $input, OutputInterface $output) { - if (true === $input->hasParameterOption(array('--ansi'), true)) { + if (true === $input->hasParameterOption(['--ansi'], true)) { $output->setDecorated(true); - } elseif (true === $input->hasParameterOption(array('--no-ansi'), true)) { + } elseif (true === $input->hasParameterOption(['--no-ansi'], true)) { $output->setDecorated(false); } - if (true === $input->hasParameterOption(array('--no-interaction', '-n'), true)) { + if (true === $input->hasParameterOption(['--no-interaction', '-n'], true)) { $input->setInteractive(false); - } elseif (\function_exists('posix_isatty')) { - $inputStream = null; - - if ($input instanceof StreamableInputInterface) { - $inputStream = $input->getStream(); - } - - // This check ensures that calling QuestionHelper::setInputStream() works - // To be removed in 4.0 (in the same time as QuestionHelper::setInputStream) - if (!$inputStream && $this->getHelperSet()->has('question')) { - $inputStream = $this->getHelperSet()->get('question')->getInputStream(false); - } - - if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) { - $input->setInteractive(false); - } } switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { - case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break; - case 1: $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); break; - case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break; - case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break; - default: $shellVerbosity = 0; break; + case -1: + $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); + break; + case 1: + $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); + break; + case 2: + $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); + break; + case 3: + $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); + break; + default: + $shellVerbosity = 0; + break; } - if (true === $input->hasParameterOption(array('--quiet', '-q'), true)) { + if (true === $input->hasParameterOption(['--quiet', '-q'], true)) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); $shellVerbosity = -1; } else { @@ -921,7 +972,9 @@ protected function configureIO(InputInterface $input, OutputInterface $output) $input->setInteractive(false); } - putenv('SHELL_VERBOSITY='.$shellVerbosity); + if (\function_exists('putenv')) { + @putenv('SHELL_VERBOSITY='.$shellVerbosity); + } $_ENV['SHELL_VERBOSITY'] = $shellVerbosity; $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity; } @@ -942,6 +995,47 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI } } + if ($this->signalsToDispatchEvent) { + $commandSignals = $command instanceof SignalableCommandInterface ? $command->getSubscribedSignals() : []; + + if ($commandSignals || null !== $this->dispatcher) { + if (!$this->signalRegistry) { + throw new RuntimeException('Unable to subscribe to signal events. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.'); + } + + if (Terminal::hasSttyAvailable()) { + $sttyMode = shell_exec('stty -g'); + + foreach ([\SIGINT, \SIGTERM] as $signal) { + $this->signalRegistry->register($signal, static function () use ($sttyMode) { + shell_exec('stty '.$sttyMode); + }); + } + } + } + + if (null !== $this->dispatcher) { + foreach ($this->signalsToDispatchEvent as $signal) { + $event = new ConsoleSignalEvent($command, $input, $output, $signal); + + $this->signalRegistry->register($signal, function ($signal, $hasNext) use ($event) { + $this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL); + + // No more handlers, we try to simulate PHP default behavior + if (!$hasNext) { + if (!\in_array($signal, [\SIGUSR1, \SIGUSR2], true)) { + exit(0); + } + } + }); + } + } + + foreach ($commandSignals as $signal) { + $this->signalRegistry->register($signal, [$command, 'handleSignal']); + } + } + if (null === $this->dispatcher) { return $command->run($input, $output); } @@ -958,28 +1052,16 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI $e = null; try { - $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); + $this->dispatcher->dispatch($event, ConsoleEvents::COMMAND); if ($event->commandShouldRun()) { $exitCode = $command->run($input, $output); } else { $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED; } - } catch (\Exception $e) { } catch (\Throwable $e) { - } - if (null !== $e) { - if ($this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) { - $x = $e instanceof \Exception ? $e : new FatalThrowableError($e); - $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode()); - $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); - - if ($x !== $event->getException()) { - $e = $event->getException(); - } - } $event = new ConsoleErrorEvent($input, $output, $e, $command); - $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); $e = $event->getError(); if (0 === $exitCode = $event->getExitCode()) { @@ -988,7 +1070,7 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI } $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); - $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); + $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE); if (null !== $e) { throw $e; @@ -1000,7 +1082,7 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI /** * Gets the name of the command based on input. * - * @return string The command name + * @return string|null */ protected function getCommandName(InputInterface $input) { @@ -1010,56 +1092,50 @@ protected function getCommandName(InputInterface $input) /** * Gets the default input definition. * - * @return InputDefinition An InputDefinition instance + * @return InputDefinition */ protected function getDefaultInputDefinition() { - return new InputDefinition(array( + return new InputDefinition([ new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), - - new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'), + new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display help for the given command. When no command is given display help for the <info>'.$this->defaultCommand.'</info> command'), new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), - new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'), - new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'), + new InputOption('--ansi', '', InputOption::VALUE_NEGATABLE, 'Force (or disable --no-ansi) ANSI output', null), new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'), - )); + ]); } /** * Gets the default commands that should always be available. * - * @return Command[] An array of default Command instances + * @return Command[] */ protected function getDefaultCommands() { - return array(new HelpCommand(), new ListCommand()); + return [new HelpCommand(), new ListCommand(), new CompleteCommand(), new DumpCompletionCommand()]; } /** * Gets the default helper set with the helpers that should always be available. * - * @return HelperSet A HelperSet instance + * @return HelperSet */ protected function getDefaultHelperSet() { - return new HelperSet(array( + return new HelperSet([ new FormatterHelper(), new DebugFormatterHelper(), new ProcessHelper(), new QuestionHelper(), - )); + ]); } /** * Returns abbreviated suggestions in string format. - * - * @param array $abbrevs Abbreviated suggestions to convert - * - * @return string A formatted string of abbreviated suggestions */ - private function getAbbreviationSuggestions($abbrevs) + private function getAbbreviationSuggestions(array $abbrevs): string { return ' '.implode("\n ", $abbrevs); } @@ -1069,15 +1145,11 @@ private function getAbbreviationSuggestions($abbrevs) * * This method is not part of public API and should not be used directly. * - * @param string $name The full name of the command - * @param string $limit The maximum number of parts of the namespace - * - * @return string The namespace of the command + * @return string */ - public function extractNamespace($name, $limit = null) + public function extractNamespace(string $name, int $limit = null) { - $parts = explode(':', $name); - array_pop($parts); + $parts = explode(':', $name, -1); return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit)); } @@ -1086,17 +1158,14 @@ public function extractNamespace($name, $limit = null) * Finds alternative of $name among $collection, * if nothing is found in $collection, try in $abbrevs. * - * @param string $name The string - * @param iterable $collection The collection - * - * @return string[] A sorted array of similar string + * @return string[] */ - private function findAlternatives($name, $collection) + private function findAlternatives(string $name, iterable $collection): array { $threshold = 1e3; - $alternatives = array(); + $alternatives = []; - $collectionParts = array(); + $collectionParts = []; foreach ($collection as $item) { $collectionParts[$item] = explode(':', $item); } @@ -1112,7 +1181,7 @@ private function findAlternatives($name, $collection) } $lev = levenshtein($subname, $parts[$i]); - if ($lev <= \strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) { + if ($lev <= \strlen($subname) / 3 || '' !== $subname && str_contains($parts[$i], $subname)) { $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; } elseif ($exists) { $alternatives[$collectionName] += $threshold; @@ -1122,13 +1191,13 @@ private function findAlternatives($name, $collection) foreach ($collection as $item) { $lev = levenshtein($name, $item); - if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { + if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) { $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; } } $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); - ksort($alternatives, SORT_NATURAL | SORT_FLAG_CASE); + ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE); return array_keys($alternatives); } @@ -1136,14 +1205,11 @@ private function findAlternatives($name, $collection) /** * Sets the default Command name. * - * @param string $commandName The Command name - * @param bool $isSingleCommand Set to true if there is only one command in this application - * - * @return self + * @return $this */ - public function setDefaultCommand($commandName, $isSingleCommand = false) + public function setDefaultCommand(string $commandName, bool $isSingleCommand = false) { - $this->defaultCommand = $commandName; + $this->defaultCommand = explode('|', ltrim($commandName, '|'))[0]; if ($isSingleCommand) { // Ensure the command exist @@ -1155,7 +1221,15 @@ public function setDefaultCommand($commandName, $isSingleCommand = false) return $this; } - private function splitStringByWidth($string, $width) + /** + * @internal + */ + public function isSingleCommand(): bool + { + return $this->singleCommand; + } + + private function splitStringByWidth(string $string, int $width): array { // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly. // additionally, array_slice() is not enough as some character has doubled width. @@ -1165,17 +1239,23 @@ private function splitStringByWidth($string, $width) } $utf8String = mb_convert_encoding($string, 'utf8', $encoding); - $lines = array(); + $lines = []; $line = ''; - foreach (preg_split('//u', $utf8String) as $char) { - // test if $char could be appended to current line - if (mb_strwidth($line.$char, 'utf8') <= $width) { - $line .= $char; - continue; + + $offset = 0; + while (preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) { + $offset += \strlen($m[0]); + + foreach (preg_split('//u', $m[0]) as $char) { + // test if $char could be appended to current line + if (mb_strwidth($line.$char, 'utf8') <= $width) { + $line .= $char; + continue; + } + // if not, push current line to array and make new line + $lines[] = str_pad($line, $width); + $line = $char; } - // if not, push current line to array and make new line - $lines[] = str_pad($line, $width); - $line = $char; } $lines[] = \count($lines) ? str_pad($line, $width) : $line; @@ -1188,15 +1268,13 @@ private function splitStringByWidth($string, $width) /** * Returns all namespaces of the command name. * - * @param string $name The full name of the command - * - * @return string[] The namespaces of the command + * @return string[] */ - private function extractAllNamespaces($name) + private function extractAllNamespaces(string $name): array { // -1 as third argument is needed to skip the command short name when exploding $parts = explode(':', $name, -1); - $namespaces = array(); + $namespaces = []; foreach ($parts as $part) { if (\count($namespaces)) { diff --git a/vendor/symfony/console/Attribute/AsCommand.php b/vendor/symfony/console/Attribute/AsCommand.php new file mode 100644 index 0000000..b337f54 --- /dev/null +++ b/vendor/symfony/console/Attribute/AsCommand.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Attribute; + +/** + * Service tag to autoconfigure commands. + */ +#[\Attribute(\Attribute::TARGET_CLASS)] +class AsCommand +{ + public function __construct( + public string $name, + public ?string $description = null, + array $aliases = [], + bool $hidden = false, + ) { + if (!$hidden && !$aliases) { + return; + } + + $name = explode('|', $name); + $name = array_merge($name, $aliases); + + if ($hidden && '' !== $name[0]) { + array_unshift($name, ''); + } + + $this->name = implode('|', $name); + } +} diff --git a/vendor/symfony/console/CHANGELOG.md b/vendor/symfony/console/CHANGELOG.md index 946ff1e..6662dd1 100644 --- a/vendor/symfony/console/CHANGELOG.md +++ b/vendor/symfony/console/CHANGELOG.md @@ -1,6 +1,111 @@ CHANGELOG ========= +5.4 +--- + + * Add `TesterTrait::assertCommandIsSuccessful()` to test command + * Deprecate `HelperSet::setCommand()` and `getCommand()` without replacement + +5.3 +--- + + * Add `GithubActionReporter` to render annotations in a Github Action + * Add `InputOption::VALUE_NEGATABLE` flag to handle `--foo`/`--no-foo` options + * Add the `Command::$defaultDescription` static property and the `description` attribute + on the `console.command` tag to allow the `list` command to instantiate commands lazily + * Add option `--short` to the `list` command + * Add support for bright colors + * Add `#[AsCommand]` attribute for declaring commands on PHP 8 + * Add `Helper::width()` and `Helper::length()` + * The `--ansi` and `--no-ansi` options now default to `null`. + +5.2.0 +----- + + * Added `SingleCommandApplication::setAutoExit()` to allow testing via `CommandTester` + * added support for multiline responses to questions through `Question::setMultiline()` + and `Question::isMultiline()` + * Added `SignalRegistry` class to stack signals handlers + * Added support for signals: + * Added `Application::getSignalRegistry()` and `Application::setSignalsToDispatchEvent()` methods + * Added `SignalableCommandInterface` interface + * Added `TableCellStyle` class to customize table cell + * Removed `php ` prefix invocation from help messages. + +5.1.0 +----- + + * `Command::setHidden()` is final since Symfony 5.1 + * Add `SingleCommandApplication` + * Add `Cursor` class + +5.0.0 +----- + + * removed support for finding hidden commands using an abbreviation, use the full name instead + * removed `TableStyle::setCrossingChar()` method in favor of `TableStyle::setDefaultCrossingChar()` + * removed `TableStyle::setHorizontalBorderChar()` method in favor of `TableStyle::setDefaultCrossingChars()` + * removed `TableStyle::getHorizontalBorderChar()` method in favor of `TableStyle::getBorderChars()` + * removed `TableStyle::setVerticalBorderChar()` method in favor of `TableStyle::setVerticalBorderChars()` + * removed `TableStyle::getVerticalBorderChar()` method in favor of `TableStyle::getBorderChars()` + * removed support for returning `null` from `Command::execute()`, return `0` instead + * `ProcessHelper::run()` accepts only `array|Symfony\Component\Process\Process` for its `command` argument + * `Application::setDispatcher` accepts only `Symfony\Contracts\EventDispatcher\EventDispatcherInterface` + for its `dispatcher` argument + * renamed `Application::renderException()` and `Application::doRenderException()` + to `renderThrowable()` and `doRenderThrowable()` respectively. + +4.4.0 +----- + + * deprecated finding hidden commands using an abbreviation, use the full name instead + * added `Question::setTrimmable` default to true to allow the answer to be trimmed + * added method `minSecondsBetweenRedraws()` and `maxSecondsBetweenRedraws()` on `ProgressBar` + * `Application` implements `ResetInterface` + * marked all dispatched event classes as `@final` + * added support for displaying table horizontally + * deprecated returning `null` from `Command::execute()`, return `0` instead + * Deprecated the `Application::renderException()` and `Application::doRenderException()` methods, + use `renderThrowable()` and `doRenderThrowable()` instead. + * added support for the `NO_COLOR` env var (https://no-color.org/) + +4.3.0 +----- + + * added support for hyperlinks + * added `ProgressBar::iterate()` method that simplify updating the progress bar when iterating + * added `Question::setAutocompleterCallback()` to provide a callback function + that dynamically generates suggestions as the user types + +4.2.0 +----- + + * allowed passing commands as `[$process, 'ENV_VAR' => 'value']` to + `ProcessHelper::run()` to pass environment variables + * deprecated passing a command as a string to `ProcessHelper::run()`, + pass it the command as an array of its arguments instead + * made the `ProcessHelper` class final + * added `WrappableOutputFormatterInterface::formatAndWrap()` (implemented in `OutputFormatter`) + * added `capture_stderr_separately` option to `CommandTester::execute()` + +4.1.0 +----- + + * added option to run suggested command if command is not found and only 1 alternative is available + * added option to modify console output and print multiple modifiable sections + * added support for iterable messages in output `write` and `writeln` methods + +4.0.0 +----- + + * `OutputFormatter` throws an exception when unknown options are used + * removed `QuestionHelper::setInputStream()/getInputStream()` + * removed `Application::getTerminalWidth()/getTerminalHeight()` and + `Application::setTerminalDimensions()/getTerminalDimensions()` + * removed `ConsoleExceptionEvent` + * removed `ConsoleEvents::EXCEPTION` + 3.4.0 ----- @@ -16,29 +121,29 @@ CHANGELOG 3.3.0 ----- -* added `ExceptionListener` -* added `AddConsoleCommandPass` (originally in FrameworkBundle) -* [BC BREAK] `Input::getOption()` no longer returns the default value for options - with value optional explicitly passed empty -* added console.error event to catch exceptions thrown by other listeners -* deprecated console.exception event in favor of console.error -* added ability to handle `CommandNotFoundException` through the - `console.error` event -* deprecated default validation in `SymfonyQuestionHelper::ask` + * added `ExceptionListener` + * added `AddConsoleCommandPass` (originally in FrameworkBundle) + * [BC BREAK] `Input::getOption()` no longer returns the default value for options + with value optional explicitly passed empty + * added console.error event to catch exceptions thrown by other listeners + * deprecated console.exception event in favor of console.error + * added ability to handle `CommandNotFoundException` through the + `console.error` event + * deprecated default validation in `SymfonyQuestionHelper::ask` 3.2.0 ------ -* added `setInputs()` method to CommandTester for ease testing of commands expecting inputs -* added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface) -* added StreamableInputInterface -* added LockableTrait + * added `setInputs()` method to CommandTester for ease testing of commands expecting inputs + * added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface) + * added StreamableInputInterface + * added LockableTrait 3.1.0 ----- * added truncate method to FormatterHelper - * added setColumnWidth(s) method to Table + * added setColumnWidth(s) method to Table 2.8.3 ----- diff --git a/vendor/symfony/console/CI/GithubActionReporter.php b/vendor/symfony/console/CI/GithubActionReporter.php new file mode 100644 index 0000000..a15c1ff --- /dev/null +++ b/vendor/symfony/console/CI/GithubActionReporter.php @@ -0,0 +1,99 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\CI; + +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Utility class for Github actions. + * + * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> + */ +class GithubActionReporter +{ + private $output; + + /** + * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85 + */ + private const ESCAPED_DATA = [ + '%' => '%25', + "\r" => '%0D', + "\n" => '%0A', + ]; + + /** + * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L87-L94 + */ + private const ESCAPED_PROPERTIES = [ + '%' => '%25', + "\r" => '%0D', + "\n" => '%0A', + ':' => '%3A', + ',' => '%2C', + ]; + + public function __construct(OutputInterface $output) + { + $this->output = $output; + } + + public static function isGithubActionEnvironment(): bool + { + return false !== getenv('GITHUB_ACTIONS'); + } + + /** + * Output an error using the Github annotations format. + * + * @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 + { + $this->log('error', $message, $file, $line, $col); + } + + /** + * Output a warning using the Github annotations format. + * + * @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 + { + $this->log('warning', $message, $file, $line, $col); + } + + /** + * Output a debug log using the Github annotations format. + * + * @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 + { + $this->log('debug', $message, $file, $line, $col); + } + + 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); + + if (!$file) { + // No file provided, output the message solely: + $this->output->writeln(sprintf('::%s::%s', $type, $message)); + + return; + } + + $this->output->writeln(sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message)); + } +} diff --git a/vendor/symfony/console/Color.php b/vendor/symfony/console/Color.php new file mode 100644 index 0000000..22a4ce9 --- /dev/null +++ b/vendor/symfony/console/Color.php @@ -0,0 +1,180 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * @author Fabien Potencier <fabien@symfony.com> + */ +final class Color +{ + private const COLORS = [ + 'black' => 0, + 'red' => 1, + 'green' => 2, + 'yellow' => 3, + 'blue' => 4, + 'magenta' => 5, + 'cyan' => 6, + 'white' => 7, + 'default' => 9, + ]; + + private const BRIGHT_COLORS = [ + 'gray' => 0, + 'bright-red' => 1, + 'bright-green' => 2, + 'bright-yellow' => 3, + 'bright-blue' => 4, + 'bright-magenta' => 5, + 'bright-cyan' => 6, + 'bright-white' => 7, + ]; + + private const AVAILABLE_OPTIONS = [ + 'bold' => ['set' => 1, 'unset' => 22], + 'underscore' => ['set' => 4, 'unset' => 24], + 'blink' => ['set' => 5, 'unset' => 25], + 'reverse' => ['set' => 7, 'unset' => 27], + 'conceal' => ['set' => 8, 'unset' => 28], + ]; + + private $foreground; + private $background; + private $options = []; + + public function __construct(string $foreground = '', string $background = '', array $options = []) + { + $this->foreground = $this->parseColor($foreground); + $this->background = $this->parseColor($background, true); + + foreach ($options as $option) { + if (!isset(self::AVAILABLE_OPTIONS[$option])) { + throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS)))); + } + + $this->options[$option] = self::AVAILABLE_OPTIONS[$option]; + } + } + + public function apply(string $text): string + { + return $this->set().$text.$this->unset(); + } + + public function set(): string + { + $setCodes = []; + if ('' !== $this->foreground) { + $setCodes[] = $this->foreground; + } + if ('' !== $this->background) { + $setCodes[] = $this->background; + } + foreach ($this->options as $option) { + $setCodes[] = $option['set']; + } + if (0 === \count($setCodes)) { + return ''; + } + + return sprintf("\033[%sm", implode(';', $setCodes)); + } + + public function unset(): string + { + $unsetCodes = []; + if ('' !== $this->foreground) { + $unsetCodes[] = 39; + } + if ('' !== $this->background) { + $unsetCodes[] = 49; + } + foreach ($this->options as $option) { + $unsetCodes[] = $option['unset']; + } + if (0 === \count($unsetCodes)) { + return ''; + } + + return sprintf("\033[%sm", implode(';', $unsetCodes)); + } + + private function parseColor(string $color, bool $background = false): string + { + if ('' === $color) { + return ''; + } + + if ('#' === $color[0]) { + $color = substr($color, 1); + + if (3 === \strlen($color)) { + $color = $color[0].$color[0].$color[1].$color[1].$color[2].$color[2]; + } + + if (6 !== \strlen($color)) { + throw new InvalidArgumentException(sprintf('Invalid "%s" color.', $color)); + } + + return ($background ? '4' : '3').$this->convertHexColorToAnsi(hexdec($color)); + } + + if (isset(self::COLORS[$color])) { + return ($background ? '4' : '3').self::COLORS[$color]; + } + + if (isset(self::BRIGHT_COLORS[$color])) { + return ($background ? '10' : '9').self::BRIGHT_COLORS[$color]; + } + + throw new InvalidArgumentException(sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS))))); + } + + private function convertHexColorToAnsi(int $color): string + { + $r = ($color >> 16) & 255; + $g = ($color >> 8) & 255; + $b = $color & 255; + + // see https://github.com/termstandard/colors/ for more information about true color support + if ('truecolor' !== getenv('COLORTERM')) { + return (string) $this->degradeHexColorToAnsi($r, $g, $b); + } + + return sprintf('8;2;%d;%d;%d', $r, $g, $b); + } + + private function degradeHexColorToAnsi(int $r, int $g, int $b): int + { + if (0 === round($this->getSaturation($r, $g, $b) / 50)) { + return 0; + } + + return (round($b / 255) << 2) | (round($g / 255) << 1) | round($r / 255); + } + + private function getSaturation(int $r, int $g, int $b): int + { + $r = $r / 255; + $g = $g / 255; + $b = $b / 255; + $v = max($r, $g, $b); + + if (0 === $diff = $v - min($r, $g, $b)) { + return 0; + } + + return (int) $diff * 100 / $v; + } +} diff --git a/vendor/symfony/console/Command/Command.php b/vendor/symfony/console/Command/Command.php index e602f40..cfa1836 100644 --- a/vendor/symfony/console/Command/Command.php +++ b/vendor/symfony/console/Command/Command.php @@ -12,6 +12,9 @@ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Application; +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; use Symfony\Component\Console\Exception\ExceptionInterface; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\LogicException; @@ -29,51 +32,93 @@ */ class Command { + // see https://tldp.org/LDP/abs/html/exitcodes.html + public const SUCCESS = 0; + public const FAILURE = 1; + public const INVALID = 2; + /** * @var string|null The default command name */ protected static $defaultName; + /** + * @var string|null The default command description + */ + protected static $defaultDescription; + private $application; private $name; private $processTitle; - private $aliases = array(); + private $aliases = []; private $definition; private $hidden = false; - private $help; - private $description; + private $help = ''; + private $description = ''; + private $fullDefinition; private $ignoreValidationErrors = false; - private $applicationDefinitionMerged = false; - private $applicationDefinitionMergedWithArgs = false; private $code; - private $synopsis = array(); - private $usages = array(); + private $synopsis = []; + private $usages = []; private $helperSet; /** - * @return string|null The default command name or null when no default name is set + * @return string|null */ public static function getDefaultName() { - $class = \get_called_class(); + $class = static::class; + + if (\PHP_VERSION_ID >= 80000 && $attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) { + return $attribute[0]->newInstance()->name; + } + $r = new \ReflectionProperty($class, 'defaultName'); return $class === $r->class ? static::$defaultName : null; } + public static function getDefaultDescription(): ?string + { + $class = static::class; + + if (\PHP_VERSION_ID >= 80000 && $attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) { + return $attribute[0]->newInstance()->description; + } + + $r = new \ReflectionProperty($class, 'defaultDescription'); + + return $class === $r->class ? static::$defaultDescription : null; + } + /** * @param string|null $name The name of the command; passing null means it must be set in configure() * * @throws LogicException When the command name is empty */ - public function __construct($name = null) + public function __construct(string $name = null) { $this->definition = new InputDefinition(); - if (null !== $name || null !== $name = static::getDefaultName()) { + if (null === $name && null !== $name = static::getDefaultName()) { + $aliases = explode('|', $name); + + if ('' === $name = array_shift($aliases)) { + $this->setHidden(true); + $name = array_shift($aliases); + } + + $this->setAliases($aliases); + } + + if (null !== $name) { $this->setName($name); } + if ('' === $this->description) { + $this->setDescription(static::getDefaultDescription() ?? ''); + } + $this->configure(); } @@ -95,6 +140,8 @@ public function setApplication(Application $application = null) } else { $this->helperSet = null; } + + $this->fullDefinition = null; } public function setHelperSet(HelperSet $helperSet) @@ -105,7 +152,7 @@ public function setHelperSet(HelperSet $helperSet) /** * Gets the helper set. * - * @return HelperSet A HelperSet instance + * @return HelperSet|null */ public function getHelperSet() { @@ -115,7 +162,7 @@ public function getHelperSet() /** * Gets the application instance for this command. * - * @return Application An Application instance + * @return Application|null */ public function getApplication() { @@ -125,7 +172,7 @@ public function getApplication() /** * Checks whether the command is enabled or not in the current environment. * - * Override this to check for x or y and return false if the command can not + * Override this to check for x or y and return false if the command cannot * run properly under the current conditions. * * @return bool @@ -150,7 +197,7 @@ protected function configure() * execute() method, you set the code to execute by passing * a Closure to the setCode() method. * - * @return null|int null or 0 if everything went fine, or an error code + * @return int 0 if everything went fine, or an exit code * * @throws LogicException When this abstract method is not implemented * @@ -173,10 +220,14 @@ protected function interact(InputInterface $input, OutputInterface $output) } /** - * Initializes the command just after the input has been validated. + * Initializes the command after the input has been bound and before the input + * is validated. * * This is mainly useful when a lot of commands extends one main command * where some things need to be initialized based on the input arguments and options. + * + * @see InputInterface::bind() + * @see InputInterface::validate() */ protected function initialize(InputInterface $input, OutputInterface $output) { @@ -191,23 +242,19 @@ protected function initialize(InputInterface $input, OutputInterface $output) * * @return int The command exit code * - * @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}. + * @throws ExceptionInterface When input binding fails. Bypass this by calling {@link ignoreValidationErrors()}. * * @see setCode() * @see execute() */ public function run(InputInterface $input, OutputInterface $output) { - // force the creation of the synopsis before the merge with the app definition - $this->getSynopsis(true); - $this->getSynopsis(false); - // add the application arguments and options $this->mergeApplicationDefinition(); // bind the input against the command specific arguments/options try { - $input->bind($this->definition); + $input->bind($this->getDefinition()); } catch (ExceptionInterface $e) { if (!$this->ignoreValidationErrors) { throw $e; @@ -219,7 +266,7 @@ public function run(InputInterface $input, OutputInterface $output) if (null !== $this->processTitle) { if (\function_exists('cli_set_process_title')) { if (!@cli_set_process_title($this->processTitle)) { - if ('Darwin' === PHP_OS) { + if ('Darwin' === \PHP_OS) { $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE); } else { cli_set_process_title($this->processTitle); @@ -246,14 +293,25 @@ public function run(InputInterface $input, OutputInterface $output) $input->validate(); if ($this->code) { - $statusCode = \call_user_func($this->code, $input, $output); + $statusCode = ($this->code)($input, $output); } else { $statusCode = $this->execute($input, $output); + + if (!\is_int($statusCode)) { + throw new \TypeError(sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, get_debug_type($statusCode))); + } } return is_numeric($statusCode) ? (int) $statusCode : 0; } + /** + * Adds suggestions to $suggestions for the current completion input (e.g. option or argument). + */ + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + } + /** * Sets the code to execute when running this command. * @@ -273,14 +331,13 @@ public function setCode(callable $code) if ($code instanceof \Closure) { $r = new \ReflectionFunction($code); if (null === $r->getClosureThis()) { - if (\PHP_VERSION_ID < 70000) { - // Bug in PHP5: https://bugs.php.net/bug.php?id=64761 - // This means that we cannot bind static closures and therefore we must - // ignore any errors here. There is no way to test if the closure is - // bindable. - $code = @\Closure::bind($code, $this); - } else { - $code = \Closure::bind($code, $this); + set_error_handler(static function () {}); + try { + if ($c = \Closure::bind($code, $this)) { + $code = $c; + } + } finally { + restore_error_handler(); } } } @@ -296,24 +353,24 @@ public function setCode(callable $code) * This method is not part of public API and should not be used directly. * * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments + * + * @internal */ - public function mergeApplicationDefinition($mergeArgs = true) + public function mergeApplicationDefinition(bool $mergeArgs = true) { - if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) { + if (null === $this->application) { return; } - $this->definition->addOptions($this->application->getDefinition()->getOptions()); - - if ($mergeArgs) { - $currentArguments = $this->definition->getArguments(); - $this->definition->setArguments($this->application->getDefinition()->getArguments()); - $this->definition->addArguments($currentArguments); - } + $this->fullDefinition = new InputDefinition(); + $this->fullDefinition->setOptions($this->definition->getOptions()); + $this->fullDefinition->addOptions($this->application->getDefinition()->getOptions()); - $this->applicationDefinitionMerged = true; if ($mergeArgs) { - $this->applicationDefinitionMergedWithArgs = true; + $this->fullDefinition->setArguments($this->application->getDefinition()->getArguments()); + $this->fullDefinition->addArguments($this->definition->getArguments()); + } else { + $this->fullDefinition->setArguments($this->definition->getArguments()); } } @@ -332,7 +389,7 @@ public function setDefinition($definition) $this->definition->setDefinition($definition); } - $this->applicationDefinitionMerged = false; + $this->fullDefinition = null; return $this; } @@ -340,11 +397,11 @@ public function setDefinition($definition) /** * Gets the InputDefinition attached to this Command. * - * @return InputDefinition An InputDefinition instance + * @return InputDefinition */ public function getDefinition() { - return $this->definition; + return $this->fullDefinition ?? $this->getNativeDefinition(); } /** @@ -355,26 +412,33 @@ public function getDefinition() * * This method is not part of public API and should not be used directly. * - * @return InputDefinition An InputDefinition instance + * @return InputDefinition */ public function getNativeDefinition() { - return $this->getDefinition(); + if (null === $this->definition) { + throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class)); + } + + return $this->definition; } /** * Adds an argument. * - * @param string $name The argument name - * @param int $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL - * @param string $description A description text - * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) + * @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 */ - public function addArgument($name, $mode = null, $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) { + $this->fullDefinition->addArgument(new InputArgument($name, $mode, $description, $default)); + } return $this; } @@ -382,17 +446,20 @@ public function addArgument($name, $mode = null, $description = '', $default = n /** * Adds an option. * - * @param string $name The option name - * @param string $shortcut The shortcut (can be null) - * @param int $mode The option mode: One of the InputOption::VALUE_* constants - * @param string $description A description text - * @param mixed $default The default value (must be null for InputOption::VALUE_NONE) + * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @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 */ - public function addOption($name, $shortcut = null, $mode = null, $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) { + $this->fullDefinition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); + } return $this; } @@ -405,13 +472,11 @@ public function addOption($name, $shortcut = null, $mode = null, $description = * * $command->setName('foo:bar'); * - * @param string $name The command name - * * @return $this * * @throws InvalidArgumentException When the name is invalid */ - public function setName($name) + public function setName(string $name) { $this->validateName($name); @@ -426,13 +491,9 @@ public function setName($name) * This feature should be used only when creating a long process command, * like a daemon. * - * PHP 5.5+ or the proctitle PECL library is required - * - * @param string $title The process title - * * @return $this */ - public function setProcessTitle($title) + public function setProcessTitle(string $title) { $this->processTitle = $title; @@ -442,7 +503,7 @@ public function setProcessTitle($title) /** * Returns the command name. * - * @return string The command name + * @return string|null */ public function getName() { @@ -451,12 +512,15 @@ public function getName() /** * @param bool $hidden Whether or not the command should be hidden from the list of commands + * The default value will be true in Symfony 6.0 + * + * @return $this * - * @return Command The current instance + * @final since Symfony 5.1 */ - public function setHidden($hidden) + public function setHidden(bool $hidden /* = true */) { - $this->hidden = (bool) $hidden; + $this->hidden = $hidden; return $this; } @@ -472,11 +536,9 @@ public function isHidden() /** * Sets the description for the command. * - * @param string $description The description for the command - * * @return $this */ - public function setDescription($description) + public function setDescription(string $description) { $this->description = $description; @@ -486,7 +548,7 @@ public function setDescription($description) /** * Returns the description for the command. * - * @return string The description for the command + * @return string */ public function getDescription() { @@ -496,11 +558,9 @@ public function getDescription() /** * Sets the help for the command. * - * @param string $help The help for the command - * * @return $this */ - public function setHelp($help) + public function setHelp(string $help) { $this->help = $help; @@ -510,7 +570,7 @@ public function setHelp($help) /** * Returns the help for the command. * - * @return string The help for the command + * @return string */ public function getHelp() { @@ -521,20 +581,21 @@ public function getHelp() * Returns the processed help for the command replacing the %command.name% and * %command.full_name% patterns with the real values dynamically. * - * @return string The processed help for the command + * @return string */ public function getProcessedHelp() { $name = $this->name; + $isSingleCommand = $this->application && $this->application->isSingleCommand(); - $placeholders = array( + $placeholders = [ '%command.name%', '%command.full_name%', - ); - $replacements = array( + ]; + $replacements = [ $name, - $_SERVER['PHP_SELF'].' '.$name, - ); + $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'].' '.$name, + ]; return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription()); } @@ -548,17 +609,16 @@ public function getProcessedHelp() * * @throws InvalidArgumentException When an alias is invalid */ - public function setAliases($aliases) + public function setAliases(iterable $aliases) { - if (!\is_array($aliases) && !$aliases instanceof \Traversable) { - throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable'); - } + $list = []; foreach ($aliases as $alias) { $this->validateName($alias); + $list[] = $alias; } - $this->aliases = $aliases; + $this->aliases = \is_array($aliases) ? $aliases : $list; return $this; } @@ -566,7 +626,7 @@ public function setAliases($aliases) /** * Returns the aliases for the command. * - * @return array An array of aliases for the command + * @return array */ public function getAliases() { @@ -578,9 +638,9 @@ public function getAliases() * * @param bool $short Whether to show the short version of the synopsis (with options folded) or not * - * @return string The synopsis + * @return string */ - public function getSynopsis($short = false) + public function getSynopsis(bool $short = false) { $key = $short ? 'short' : 'long'; @@ -592,15 +652,13 @@ public function getSynopsis($short = false) } /** - * Add a command usage example. - * - * @param string $usage The usage, it'll be prefixed with the command name + * Add a command usage example, it'll be prefixed with the command name. * * @return $this */ - public function addUsage($usage) + public function addUsage(string $usage) { - if (0 !== strpos($usage, $this->name)) { + if (!str_starts_with($usage, $this->name)) { $usage = sprintf('%s %s', $this->name, $usage); } @@ -622,14 +680,12 @@ public function getUsages() /** * Gets a helper instance by name. * - * @param string $name The helper name - * - * @return mixed The helper value + * @return mixed * * @throws LogicException if no HelperSet is defined * @throws InvalidArgumentException if the helper is not defined */ - public function getHelper($name) + public function getHelper(string $name) { if (null === $this->helperSet) { throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name)); @@ -643,11 +699,9 @@ public function getHelper($name) * * It must be non-empty and parts can optionally be separated by ":". * - * @param string $name - * * @throws InvalidArgumentException When the name is invalid */ - private function validateName($name) + private function validateName(string $name) { if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); diff --git a/vendor/symfony/console/Command/CompleteCommand.php b/vendor/symfony/console/Command/CompleteCommand.php new file mode 100644 index 0000000..0e35143 --- /dev/null +++ b/vendor/symfony/console/Command/CompleteCommand.php @@ -0,0 +1,205 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Completion\Output\BashCompletionOutput; +use Symfony\Component\Console\Completion\Output\CompletionOutputInterface; +use Symfony\Component\Console\Exception\CommandNotFoundException; +use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Responsible for providing the values to the shell completion. + * + * @author Wouter de Jong <wouter@wouterj.nl> + */ +final class CompleteCommand extends Command +{ + protected static $defaultName = '|_complete'; + protected static $defaultDescription = 'Internal command to provide shell completion suggestions'; + + private $completionOutputs; + + private $isDebug = false; + + /** + * @param array<string, class-string<CompletionOutputInterface>> $completionOutputs A list of additional completion outputs, with shell name as key and FQCN as value + */ + public function __construct(array $completionOutputs = []) + { + // must be set before the parent constructor, as the property value is used in configure() + $this->completionOutputs = $completionOutputs + ['bash' => BashCompletionOutput::class]; + + parent::__construct(); + } + + protected function configure(): void + { + $this + ->addOption('shell', 's', InputOption::VALUE_REQUIRED, 'The shell type ("'.implode('", "', array_keys($this->completionOutputs)).'")') + ->addOption('input', 'i', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'An array of input tokens (e.g. COMP_WORDS or argv)') + ->addOption('current', 'c', InputOption::VALUE_REQUIRED, 'The index of the "input" array that the cursor is in (e.g. COMP_CWORD)') + ->addOption('symfony', 'S', InputOption::VALUE_REQUIRED, 'The version of the completion script') + ; + } + + protected function initialize(InputInterface $input, OutputInterface $output) + { + $this->isDebug = filter_var(getenv('SYMFONY_COMPLETION_DEBUG'), \FILTER_VALIDATE_BOOLEAN); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + try { + // uncomment when a bugfix or BC break has been introduced in the shell completion scripts + // $version = $input->getOption('symfony'); + // if ($version && version_compare($version, 'x.y', '>=')) { + // $message = sprintf('Completion script version is not supported ("%s" given, ">=x.y" required).', $version); + // $this->log($message); + + // $output->writeln($message.' Install the Symfony completion script again by using the "completion" command.'); + + // return 126; + // } + + $shell = $input->getOption('shell'); + if (!$shell) { + throw new \RuntimeException('The "--shell" option must be set.'); + } + + if (!$completionOutput = $this->completionOutputs[$shell] ?? false) { + throw new \RuntimeException(sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, implode('", "', array_keys($this->completionOutputs)))); + } + + $completionInput = $this->createCompletionInput($input); + $suggestions = new CompletionSuggestions(); + + $this->log([ + '', + '<comment>'.date('Y-m-d H:i:s').'</>', + '<info>Input:</> <comment>("|" indicates the cursor position)</>', + ' '.(string) $completionInput, + '<info>Command:</>', + ' '.(string) implode(' ', $_SERVER['argv']), + '<info>Messages:</>', + ]); + + $command = $this->findCommand($completionInput, $output); + if (null === $command) { + $this->log(' No command found, completing using the Application class.'); + + $this->getApplication()->complete($completionInput, $suggestions); + } elseif ( + $completionInput->mustSuggestArgumentValuesFor('command') + && $command->getName() !== $completionInput->getCompletionValue() + && !\in_array($completionInput->getCompletionValue(), $command->getAliases(), true) + ) { + $this->log(' No command found, completing using the Application class.'); + + // expand shortcut names ("cache:cl<TAB>") into their full name ("cache:clear") + $suggestions->suggestValues(array_filter(array_merge([$command->getName()], $command->getAliases()))); + } else { + $command->mergeApplicationDefinition(); + $completionInput->bind($command->getDefinition()); + + if (CompletionInput::TYPE_OPTION_NAME === $completionInput->getCompletionType()) { + $this->log(' Completing option names for the <comment>'.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).'</> command.'); + + $suggestions->suggestOptions($command->getDefinition()->getOptions()); + } else { + $this->log([ + ' Completing using the <comment>'.\get_class($command instanceof LazyCommand ? $command->getCommand() : $command).'</> class.', + ' Completing <comment>'.$completionInput->getCompletionType().'</> for <comment>'.$completionInput->getCompletionName().'</>', + ]); + if (null !== $compval = $completionInput->getCompletionValue()) { + $this->log(' Current value: <comment>'.$compval.'</>'); + } + + $command->complete($completionInput, $suggestions); + } + } + + /** @var CompletionOutputInterface $completionOutput */ + $completionOutput = new $completionOutput(); + + $this->log('<info>Suggestions:</>'); + if ($options = $suggestions->getOptionSuggestions()) { + $this->log(' --'.implode(' --', array_map(function ($o) { return $o->getName(); }, $options))); + } elseif ($values = $suggestions->getValueSuggestions()) { + $this->log(' '.implode(' ', $values)); + } else { + $this->log(' <comment>No suggestions were provided</>'); + } + + $completionOutput->write($suggestions, $output); + } catch (\Throwable $e) { + $this->log([ + '<error>Error!</error>', + (string) $e, + ]); + + if ($output->isDebug()) { + throw $e; + } + + return 2; + } + + return 0; + } + + private function createCompletionInput(InputInterface $input): CompletionInput + { + $currentIndex = $input->getOption('current'); + if (!$currentIndex || !ctype_digit($currentIndex)) { + throw new \RuntimeException('The "--current" option must be set and it must be an integer.'); + } + + $completionInput = CompletionInput::fromTokens($input->getOption('input'), (int) $currentIndex); + + try { + $completionInput->bind($this->getApplication()->getDefinition()); + } catch (ExceptionInterface $e) { + } + + return $completionInput; + } + + private function findCommand(CompletionInput $completionInput, OutputInterface $output): ?Command + { + try { + $inputName = $completionInput->getFirstArgument(); + if (null === $inputName) { + return null; + } + + return $this->getApplication()->find($inputName); + } catch (CommandNotFoundException $e) { + } + + return null; + } + + private function log($messages): void + { + if (!$this->isDebug) { + return; + } + + $commandName = basename($_SERVER['argv'][0]); + file_put_contents(sys_get_temp_dir().'/sf_'.$commandName.'.log', implode(\PHP_EOL, (array) $messages).\PHP_EOL, \FILE_APPEND); + } +} diff --git a/vendor/symfony/console/Command/DumpCompletionCommand.php b/vendor/symfony/console/Command/DumpCompletionCommand.php new file mode 100644 index 0000000..eaf22be --- /dev/null +++ b/vendor/symfony/console/Command/DumpCompletionCommand.php @@ -0,0 +1,145 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Process\Process; + +/** + * Dumps the completion script for the current shell. + * + * @author Wouter de Jong <wouter@wouterj.nl> + */ +final class DumpCompletionCommand extends Command +{ + protected static $defaultName = 'completion'; + protected static $defaultDescription = 'Dump the shell completion script'; + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestArgumentValuesFor('shell')) { + $suggestions->suggestValues($this->getSupportedShells()); + } + } + + protected function configure() + { + $fullCommand = $_SERVER['PHP_SELF']; + $commandName = basename($fullCommand); + $fullCommand = @realpath($fullCommand) ?: $fullCommand; + + $this + ->setHelp(<<<EOH +The <info>%command.name%</> command dumps the shell completion script required +to use shell autocompletion (currently only bash completion is supported). + +<comment>Static installation +-------------------</> + +Dump the script to a global completion file and restart your shell: + + <info>%command.full_name% bash | sudo tee /etc/bash_completion.d/{$commandName}</> + +Or dump the script to a local file and source it: + + <info>%command.full_name% bash > completion.sh</> + + <comment># source the file whenever you use the project</> + <info>source completion.sh</> + + <comment># or add this line at the end of your "~/.bashrc" file:</> + <info>source /path/to/completion.sh</> + +<comment>Dynamic installation +--------------------</> + +Add this to the end of your shell configuration file (e.g. <info>"~/.bashrc"</>): + + <info>eval "$({$fullCommand} completion bash)"</> +EOH + ) + ->addArgument('shell', InputArgument::OPTIONAL, 'The shell type (e.g. "bash"), the value of the "$SHELL" env var will be used if this is not given') + ->addOption('debug', null, InputOption::VALUE_NONE, 'Tail the completion debug log') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $commandName = basename($_SERVER['argv'][0]); + + if ($input->getOption('debug')) { + $this->tailDebugLog($commandName, $output); + + return 0; + } + + $shell = $input->getArgument('shell') ?? self::guessShell(); + $completionFile = __DIR__.'/../Resources/completion.'.$shell; + if (!file_exists($completionFile)) { + $supportedShells = $this->getSupportedShells(); + + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + if ($shell) { + $output->writeln(sprintf('<error>Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").</>', $shell, implode('", "', $supportedShells))); + } else { + $output->writeln(sprintf('<error>Shell not detected, Symfony shell completion only supports "%s").</>', implode('", "', $supportedShells))); + } + + return 2; + } + + $output->write(str_replace(['{{ COMMAND_NAME }}', '{{ VERSION }}'], [$commandName, $this->getApplication()->getVersion()], file_get_contents($completionFile))); + + return 0; + } + + private static function guessShell(): string + { + return basename($_SERVER['SHELL'] ?? ''); + } + + private function tailDebugLog(string $commandName, OutputInterface $output): void + { + $debugFile = sys_get_temp_dir().'/sf_'.$commandName.'.log'; + if (!file_exists($debugFile)) { + touch($debugFile); + } + $process = new Process(['tail', '-f', $debugFile], null, null, null, 0); + $process->run(function (string $type, string $line) use ($output): void { + $output->write($line); + }); + } + + /** + * @return string[] + */ + 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; + } +} diff --git a/vendor/symfony/console/Command/HelpCommand.php b/vendor/symfony/console/Command/HelpCommand.php index 1e20b00..c66ef46 100644 --- a/vendor/symfony/console/Command/HelpCommand.php +++ b/vendor/symfony/console/Command/HelpCommand.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Console\Command; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Descriptor\ApplicationDescription; use Symfony\Component\Console\Helper\DescriptorHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -35,20 +38,20 @@ protected function configure() $this ->setName('help') - ->setDefinition(array( + ->setDefinition([ new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), - )) - ->setDescription('Displays help for a command') + ]) + ->setDescription('Display help for a command') ->setHelp(<<<'EOF' The <info>%command.name%</info> command displays help for a given command: - <info>php %command.full_name% list</info> + <info>%command.full_name% list</info> You can also output the help in other formats by using the <comment>--format</comment> option: - <info>php %command.full_name% --format=xml list</info> + <info>%command.full_name% --format=xml list</info> To display the list of available commands, please use the <info>list</info> command. EOF @@ -71,11 +74,28 @@ protected function execute(InputInterface $input, OutputInterface $output) } $helper = new DescriptorHelper(); - $helper->describe($output, $this->command, array( + $helper->describe($output, $this->command, [ 'format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), - )); + ]); $this->command = null; + + return 0; + } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestArgumentValuesFor('command_name')) { + $descriptor = new ApplicationDescription($this->getApplication()); + $suggestions->suggestValues(array_keys($descriptor->getCommands())); + + return; + } + + if ($input->mustSuggestOptionValuesFor('format')) { + $helper = new DescriptorHelper(); + $suggestions->suggestValues($helper->getFormats()); + } } } diff --git a/vendor/symfony/console/Command/LazyCommand.php b/vendor/symfony/console/Command/LazyCommand.php new file mode 100644 index 0000000..e576ad0 --- /dev/null +++ b/vendor/symfony/console/Command/LazyCommand.php @@ -0,0 +1,218 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Nicolas Grekas <p@tchwork.com> + */ +final class LazyCommand extends Command +{ + private $command; + private $isEnabled; + + public function __construct(string $name, array $aliases, string $description, bool $isHidden, \Closure $commandFactory, ?bool $isEnabled = true) + { + $this->setName($name) + ->setAliases($aliases) + ->setHidden($isHidden) + ->setDescription($description); + + $this->command = $commandFactory; + $this->isEnabled = $isEnabled; + } + + public function ignoreValidationErrors(): void + { + $this->getCommand()->ignoreValidationErrors(); + } + + public function setApplication(Application $application = null): void + { + if ($this->command instanceof parent) { + $this->command->setApplication($application); + } + + parent::setApplication($application); + } + + public function setHelperSet(HelperSet $helperSet): void + { + if ($this->command instanceof parent) { + $this->command->setHelperSet($helperSet); + } + + parent::setHelperSet($helperSet); + } + + public function isEnabled(): bool + { + return $this->isEnabled ?? $this->getCommand()->isEnabled(); + } + + public function run(InputInterface $input, OutputInterface $output): int + { + return $this->getCommand()->run($input, $output); + } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + $this->getCommand()->complete($input, $suggestions); + } + + /** + * @return $this + */ + public function setCode(callable $code): self + { + $this->getCommand()->setCode($code); + + return $this; + } + + /** + * @internal + */ + public function mergeApplicationDefinition(bool $mergeArgs = true): void + { + $this->getCommand()->mergeApplicationDefinition($mergeArgs); + } + + /** + * @return $this + */ + public function setDefinition($definition): self + { + $this->getCommand()->setDefinition($definition); + + return $this; + } + + public function getDefinition(): InputDefinition + { + return $this->getCommand()->getDefinition(); + } + + public function getNativeDefinition(): InputDefinition + { + return $this->getCommand()->getNativeDefinition(); + } + + /** + * @return $this + */ + public function addArgument(string $name, int $mode = null, string $description = '', $default = null): self + { + $this->getCommand()->addArgument($name, $mode, $description, $default); + + return $this; + } + + /** + * @return $this + */ + public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null): self + { + $this->getCommand()->addOption($name, $shortcut, $mode, $description, $default); + + return $this; + } + + /** + * @return $this + */ + public function setProcessTitle(string $title): self + { + $this->getCommand()->setProcessTitle($title); + + return $this; + } + + /** + * @return $this + */ + public function setHelp(string $help): self + { + $this->getCommand()->setHelp($help); + + return $this; + } + + public function getHelp(): string + { + return $this->getCommand()->getHelp(); + } + + public function getProcessedHelp(): string + { + return $this->getCommand()->getProcessedHelp(); + } + + public function getSynopsis(bool $short = false): string + { + return $this->getCommand()->getSynopsis($short); + } + + /** + * @return $this + */ + public function addUsage(string $usage): self + { + $this->getCommand()->addUsage($usage); + + return $this; + } + + public function getUsages(): array + { + return $this->getCommand()->getUsages(); + } + + /** + * @return mixed + */ + public function getHelper(string $name) + { + return $this->getCommand()->getHelper($name); + } + + public function getCommand(): parent + { + if (!$this->command instanceof \Closure) { + return $this->command; + } + + $command = $this->command = ($this->command)(); + $command->setApplication($this->getApplication()); + + if (null !== $this->getHelperSet()) { + $command->setHelperSet($this->getHelperSet()); + } + + $command->setName($this->getName()) + ->setAliases($this->getAliases()) + ->setHidden($this->isHidden()) + ->setDescription($this->getDescription()); + + // Will throw if the command is not correctly initialized. + $command->getDefinition(); + + return $command; + } +} diff --git a/vendor/symfony/console/Command/ListCommand.php b/vendor/symfony/console/Command/ListCommand.php index 5d93233..f04a4ef 100644 --- a/vendor/symfony/console/Command/ListCommand.php +++ b/vendor/symfony/console/Command/ListCommand.php @@ -11,9 +11,11 @@ namespace Symfony\Component\Console\Command; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Descriptor\ApplicationDescription; use Symfony\Component\Console\Helper\DescriptorHelper; use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -32,59 +34,62 @@ protected function configure() { $this ->setName('list') - ->setDefinition($this->createDefinition()) - ->setDescription('Lists commands') + ->setDefinition([ + new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), + new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), + new InputOption('short', null, InputOption::VALUE_NONE, 'To skip describing commands\' arguments'), + ]) + ->setDescription('List commands') ->setHelp(<<<'EOF' The <info>%command.name%</info> command lists all commands: - <info>php %command.full_name%</info> + <info>%command.full_name%</info> You can also display the commands for a specific namespace: - <info>php %command.full_name% test</info> + <info>%command.full_name% test</info> You can also output the information in other formats by using the <comment>--format</comment> option: - <info>php %command.full_name% --format=xml</info> + <info>%command.full_name% --format=xml</info> It's also possible to get raw list of commands (useful for embedding command runner): - <info>php %command.full_name% --raw</info> + <info>%command.full_name% --raw</info> EOF ) ; } - /** - * {@inheritdoc} - */ - public function getNativeDefinition() - { - return $this->createDefinition(); - } - /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $helper = new DescriptorHelper(); - $helper->describe($output, $this->getApplication(), array( + $helper->describe($output, $this->getApplication(), [ 'format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'namespace' => $input->getArgument('namespace'), - )); + 'short' => $input->getOption('short'), + ]); + + return 0; } - /** - * {@inheritdoc} - */ - private function createDefinition() + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void { - return new InputDefinition(array( - new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), - new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), - )); + if ($input->mustSuggestArgumentValuesFor('namespace')) { + $descriptor = new ApplicationDescription($this->getApplication()); + $suggestions->suggestValues(array_keys($descriptor->getNamespaces())); + + return; + } + + if ($input->mustSuggestOptionValuesFor('format')) { + $helper = new DescriptorHelper(); + $suggestions->suggestValues($helper->getFormats()); + } } } diff --git a/vendor/symfony/console/Command/LockableTrait.php b/vendor/symfony/console/Command/LockableTrait.php index 308ebf2..b1856dc 100644 --- a/vendor/symfony/console/Command/LockableTrait.php +++ b/vendor/symfony/console/Command/LockableTrait.php @@ -12,9 +12,8 @@ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Lock\Factory; -use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\LockInterface; use Symfony\Component\Lock\Store\FlockStore; use Symfony\Component\Lock\Store\SemaphoreStore; @@ -25,31 +24,29 @@ */ trait LockableTrait { - /** @var Lock */ + /** @var LockInterface|null */ private $lock; /** * Locks a command. - * - * @return bool */ - private function lock($name = null, $blocking = false) + private function lock(string $name = null, bool $blocking = false): bool { if (!class_exists(SemaphoreStore::class)) { - throw new RuntimeException('To enable the locking feature you must install the symfony/lock component.'); + throw new LogicException('To enable the locking feature you must install the symfony/lock component.'); } if (null !== $this->lock) { throw new LogicException('A lock is already in place.'); } - if (SemaphoreStore::isSupported($blocking)) { + if (SemaphoreStore::isSupported()) { $store = new SemaphoreStore(); } else { $store = new FlockStore(); } - $this->lock = (new Factory($store))->createLock($name ?: $this->getName()); + $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName()); if (!$this->lock->acquire($blocking)) { $this->lock = null; diff --git a/vendor/symfony/console/Command/SignalableCommandInterface.php b/vendor/symfony/console/Command/SignalableCommandInterface.php new file mode 100644 index 0000000..d439728 --- /dev/null +++ b/vendor/symfony/console/Command/SignalableCommandInterface.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +/** + * Interface for command reacting to signal. + * + * @author Grégoire Pineau <lyrixx@lyrix.info> + */ +interface SignalableCommandInterface +{ + /** + * Returns the list of signals to subscribe. + */ + public function getSubscribedSignals(): array; + + /** + * The method will be called when the application is signaled. + */ + public function handleSignal(int $signal): void; +} diff --git a/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php b/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php index 9462996..0adaf88 100644 --- a/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php +++ b/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php @@ -1,5 +1,14 @@ <?php +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Console\CommandLoader; use Symfony\Component\Console\Command\Command; @@ -13,25 +22,21 @@ interface CommandLoaderInterface /** * Loads a command. * - * @param string $name - * * @return Command * * @throws CommandNotFoundException */ - public function get($name); + public function get(string $name); /** * Checks if a command exists. * - * @param string $name - * * @return bool */ - public function has($name); + public function has(string $name); /** - * @return string[] All registered command names + * @return string[] */ public function getNames(); } diff --git a/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php index 753ad0f..ddccb3d 100644 --- a/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php +++ b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php @@ -1,5 +1,14 @@ <?php +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Console\CommandLoader; use Psr\Container\ContainerInterface; @@ -16,8 +25,7 @@ class ContainerCommandLoader implements CommandLoaderInterface private $commandMap; /** - * @param ContainerInterface $container A container from which to load command services - * @param array $commandMap An array with command names as keys and service ids as values + * @param array $commandMap An array with command names as keys and service ids as values */ public function __construct(ContainerInterface $container, array $commandMap) { @@ -28,7 +36,7 @@ public function __construct(ContainerInterface $container, array $commandMap) /** * {@inheritdoc} */ - public function get($name) + public function get(string $name) { if (!$this->has($name)) { throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); @@ -40,7 +48,7 @@ public function get($name) /** * {@inheritdoc} */ - public function has($name) + public function has(string $name) { return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]); } diff --git a/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php b/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php index d9c2055..7e2db34 100644 --- a/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php +++ b/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php @@ -33,7 +33,7 @@ public function __construct(array $factories) /** * {@inheritdoc} */ - public function has($name) + public function has(string $name) { return isset($this->factories[$name]); } @@ -41,7 +41,7 @@ public function has($name) /** * {@inheritdoc} */ - public function get($name) + public function get(string $name) { if (!isset($this->factories[$name])) { throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); diff --git a/vendor/symfony/console/Completion/CompletionInput.php b/vendor/symfony/console/Completion/CompletionInput.php new file mode 100644 index 0000000..368b945 --- /dev/null +++ b/vendor/symfony/console/Completion/CompletionInput.php @@ -0,0 +1,249 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Completion; + +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * An input specialized for shell completion. + * + * This input allows unfinished option names or values and exposes what kind of + * completion is expected. + * + * @author Wouter de Jong <wouter@wouterj.nl> + */ +final class CompletionInput extends ArgvInput +{ + public const TYPE_ARGUMENT_VALUE = 'argument_value'; + public const TYPE_OPTION_VALUE = 'option_value'; + public const TYPE_OPTION_NAME = 'option_name'; + public const TYPE_NONE = 'none'; + + private $tokens; + private $currentIndex; + private $completionType; + private $completionName = null; + private $completionValue = ''; + + /** + * Converts a terminal string into tokens. + * + * This is required for shell completions without COMP_WORDS support. + */ + public static function fromString(string $inputStr, int $currentIndex): self + { + preg_match_all('/(?<=^|\s)([\'"]?)(.+?)(?<!\\\\)\1(?=$|\s)/', $inputStr, $tokens); + + return self::fromTokens($tokens[0], $currentIndex); + } + + /** + * 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 $currentIndex the index of the cursor (e.g. COMP_CWORD) + */ + public static function fromTokens(array $tokens, int $currentIndex): self + { + $input = new self($tokens); + $input->tokens = $tokens; + $input->currentIndex = $currentIndex; + + return $input; + } + + /** + * {@inheritdoc} + */ + public function bind(InputDefinition $definition): void + { + parent::bind($definition); + + $relevantToken = $this->getRelevantToken(); + if ('-' === $relevantToken[0]) { + // the current token is an input option: complete either option name or option value + [$optionToken, $optionValue] = explode('=', $relevantToken, 2) + ['', '']; + + $option = $this->getOptionFromToken($optionToken); + if (null === $option && !$this->isCursorFree()) { + $this->completionType = self::TYPE_OPTION_NAME; + $this->completionValue = $relevantToken; + + return; + } + + if (null !== $option && $option->acceptValue()) { + $this->completionType = self::TYPE_OPTION_VALUE; + $this->completionName = $option->getName(); + $this->completionValue = $optionValue ?: (!str_starts_with($optionToken, '--') ? substr($optionToken, 2) : ''); + + return; + } + } + + $previousToken = $this->tokens[$this->currentIndex - 1]; + if ('-' === $previousToken[0] && '' !== trim($previousToken, '-')) { + // check if previous option accepted a value + $previousOption = $this->getOptionFromToken($previousToken); + if (null !== $previousOption && $previousOption->acceptValue()) { + $this->completionType = self::TYPE_OPTION_VALUE; + $this->completionName = $previousOption->getName(); + $this->completionValue = $relevantToken; + + return; + } + } + + // complete argument value + $this->completionType = self::TYPE_ARGUMENT_VALUE; + + foreach ($this->definition->getArguments() as $argumentName => $argument) { + if (!isset($this->arguments[$argumentName])) { + break; + } + + $argumentValue = $this->arguments[$argumentName]; + $this->completionName = $argumentName; + if (\is_array($argumentValue)) { + $this->completionValue = $argumentValue ? $argumentValue[array_key_last($argumentValue)] : null; + } else { + $this->completionValue = $argumentValue; + } + } + + if ($this->currentIndex >= \count($this->tokens)) { + if (!isset($this->arguments[$argumentName]) || $this->definition->getArgument($argumentName)->isArray()) { + $this->completionName = $argumentName; + $this->completionValue = ''; + } else { + // we've reached the end + $this->completionType = self::TYPE_NONE; + $this->completionName = null; + $this->completionValue = ''; + } + } + } + + /** + * Returns the type of completion required. + * + * TYPE_ARGUMENT_VALUE when completing the value of an input argument + * TYPE_OPTION_VALUE when completing the value of an input option + * TYPE_OPTION_NAME when completing the name of an input option + * TYPE_NONE when nothing should be completed + * + * @return string One of self::TYPE_* constants. TYPE_OPTION_NAME and TYPE_NONE are already implemented by the Console component + */ + public function getCompletionType(): string + { + return $this->completionType; + } + + /** + * The name of the input option or argument when completing a value. + * + * @return string|null returns null when completing an option name + */ + public function getCompletionName(): ?string + { + return $this->completionName; + } + + /** + * The value already typed by the user (or empty string). + */ + public function getCompletionValue(): string + { + return $this->completionValue; + } + + public function mustSuggestOptionValuesFor(string $optionName): bool + { + return self::TYPE_OPTION_VALUE === $this->getCompletionType() && $optionName === $this->getCompletionName(); + } + + public function mustSuggestArgumentValuesFor(string $argumentName): bool + { + return self::TYPE_ARGUMENT_VALUE === $this->getCompletionType() && $argumentName === $this->getCompletionName(); + } + + protected function parseToken(string $token, bool $parseOptions): bool + { + try { + return parent::parseToken($token, $parseOptions); + } catch (RuntimeException $e) { + // suppress errors, completed input is almost never valid + } + + return $parseOptions; + } + + private function getOptionFromToken(string $optionToken): ?InputOption + { + $optionName = ltrim($optionToken, '-'); + if (!$optionName) { + return null; + } + + if ('-' === ($optionToken[1] ?? ' ')) { + // long option name + return $this->definition->hasOption($optionName) ? $this->definition->getOption($optionName) : null; + } + + // short option name + return $this->definition->hasShortcut($optionName[0]) ? $this->definition->getOptionForShortcut($optionName[0]) : null; + } + + /** + * The token of the cursor, or the last token if the cursor is at the end of the input. + */ + private function getRelevantToken(): string + { + return $this->tokens[$this->isCursorFree() ? $this->currentIndex - 1 : $this->currentIndex]; + } + + /** + * Whether the cursor is "free" (i.e. at the end of the input preceded by a space). + */ + private function isCursorFree(): bool + { + $nrOfTokens = \count($this->tokens); + if ($this->currentIndex > $nrOfTokens) { + throw new \LogicException('Current index is invalid, it must be the number of input tokens or one more.'); + } + + return $this->currentIndex >= $nrOfTokens; + } + + public function __toString() + { + $str = ''; + foreach ($this->tokens as $i => $token) { + $str .= $token; + + if ($this->currentIndex === $i) { + $str .= '|'; + } + + $str .= ' '; + } + + if ($this->currentIndex > $i) { + $str .= '|'; + } + + return rtrim($str); + } +} diff --git a/vendor/symfony/console/Completion/CompletionSuggestions.php b/vendor/symfony/console/Completion/CompletionSuggestions.php new file mode 100644 index 0000000..d8905e5 --- /dev/null +++ b/vendor/symfony/console/Completion/CompletionSuggestions.php @@ -0,0 +1,99 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Completion; + +use Symfony\Component\Console\Input\InputOption; + +/** + * Stores all completion suggestions for the current input. + * + * @author Wouter de Jong <wouter@wouterj.nl> + */ +final class CompletionSuggestions +{ + private $valueSuggestions = []; + private $optionSuggestions = []; + + /** + * Add a suggested value for an input option or argument. + * + * @param string|Suggestion $value + * + * @return $this + */ + public function suggestValue($value): self + { + $this->valueSuggestions[] = !$value instanceof Suggestion ? new Suggestion($value) : $value; + + return $this; + } + + /** + * Add multiple suggested values at once for an input option or argument. + * + * @param list<string|Suggestion> $values + * + * @return $this + */ + public function suggestValues(array $values): self + { + foreach ($values as $value) { + $this->suggestValue($value); + } + + return $this; + } + + /** + * Add a suggestion for an input option name. + * + * @return $this + */ + public function suggestOption(InputOption $option): self + { + $this->optionSuggestions[] = $option; + + return $this; + } + + /** + * Add multiple suggestions for input option names at once. + * + * @param InputOption[] $options + * + * @return $this + */ + public function suggestOptions(array $options): self + { + foreach ($options as $option) { + $this->suggestOption($option); + } + + return $this; + } + + /** + * @return InputOption[] + */ + public function getOptionSuggestions(): array + { + return $this->optionSuggestions; + } + + /** + * @return Suggestion[] + */ + public function getValueSuggestions(): array + { + return $this->valueSuggestions; + } +} diff --git a/vendor/symfony/console/Completion/Output/BashCompletionOutput.php b/vendor/symfony/console/Completion/Output/BashCompletionOutput.php new file mode 100644 index 0000000..c6f76eb --- /dev/null +++ b/vendor/symfony/console/Completion/Output/BashCompletionOutput.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Completion\Output; + +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Wouter de Jong <wouter@wouterj.nl> + */ +class BashCompletionOutput implements CompletionOutputInterface +{ + public function write(CompletionSuggestions $suggestions, OutputInterface $output): void + { + $values = $suggestions->getValueSuggestions(); + foreach ($suggestions->getOptionSuggestions() as $option) { + $values[] = '--'.$option->getName(); + if ($option->isNegatable()) { + $values[] = '--no-'.$option->getName(); + } + } + $output->writeln(implode("\n", $values)); + } +} diff --git a/vendor/symfony/console/Completion/Output/CompletionOutputInterface.php b/vendor/symfony/console/Completion/Output/CompletionOutputInterface.php new file mode 100644 index 0000000..659e596 --- /dev/null +++ b/vendor/symfony/console/Completion/Output/CompletionOutputInterface.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Completion\Output; + +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Transforms the {@see CompletionSuggestions} object into output readable by the shell completion. + * + * @author Wouter de Jong <wouter@wouterj.nl> + */ +interface CompletionOutputInterface +{ + public function write(CompletionSuggestions $suggestions, OutputInterface $output): void; +} diff --git a/vendor/symfony/console/Completion/Suggestion.php b/vendor/symfony/console/Completion/Suggestion.php new file mode 100644 index 0000000..6c7bc4d --- /dev/null +++ b/vendor/symfony/console/Completion/Suggestion.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Completion; + +/** + * Represents a single suggested value. + * + * @author Wouter de Jong <wouter@wouterj.nl> + */ +class Suggestion +{ + private $value; + + public function __construct(string $value) + { + $this->value = $value; + } + + public function getValue(): string + { + return $this->value; + } + + public function __toString(): string + { + return $this->getValue(); + } +} diff --git a/vendor/symfony/console/ConsoleEvents.php b/vendor/symfony/console/ConsoleEvents.php index bf6cab9..6ae8f32 100644 --- a/vendor/symfony/console/ConsoleEvents.php +++ b/vendor/symfony/console/ConsoleEvents.php @@ -11,6 +11,11 @@ namespace Symfony\Component\Console; +use Symfony\Component\Console\Event\ConsoleCommandEvent; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleSignalEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; + /** * Contains all events dispatched by an Application. * @@ -21,32 +26,27 @@ final class ConsoleEvents /** * The COMMAND event allows you to attach listeners before any command is * executed by the console. It also allows you to modify the command, input and output - * before they are handled to the command. + * before they are handed to the command. * * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent") */ - const COMMAND = 'console.command'; + public const COMMAND = 'console.command'; /** - * The TERMINATE event allows you to attach listeners after a command is - * executed by the console. + * The SIGNAL event allows you to perform some actions + * after the command execution was interrupted. * - * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent") + * @Event("Symfony\Component\Console\Event\ConsoleSignalEvent") */ - const TERMINATE = 'console.terminate'; + public const SIGNAL = 'console.signal'; /** - * The EXCEPTION event occurs when an uncaught exception appears - * while executing Command#run(). - * - * This event allows you to deal with the exception or - * to modify the thrown exception. - * - * @Event("Symfony\Component\Console\Event\ConsoleExceptionEvent") + * The TERMINATE event allows you to attach listeners after a command is + * executed by the console. * - * @deprecated The console.exception event is deprecated since version 3.3 and will be removed in 4.0. Use the console.error event instead. + * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent") */ - const EXCEPTION = 'console.exception'; + public const TERMINATE = 'console.terminate'; /** * The ERROR event occurs when an uncaught exception or error appears. @@ -56,5 +56,17 @@ final class ConsoleEvents * * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent") */ - const ERROR = 'console.error'; + public const ERROR = 'console.error'; + + /** + * Event aliases. + * + * These aliases can be consumed by RegisterListenersPass. + */ + public const ALIASES = [ + ConsoleCommandEvent::class => self::COMMAND, + ConsoleErrorEvent::class => self::ERROR, + ConsoleSignalEvent::class => self::SIGNAL, + ConsoleTerminateEvent::class => self::TERMINATE, + ]; } diff --git a/vendor/symfony/console/Cursor.php b/vendor/symfony/console/Cursor.php new file mode 100644 index 0000000..0c4dafb --- /dev/null +++ b/vendor/symfony/console/Cursor.php @@ -0,0 +1,207 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Pierre du Plessis <pdples@gmail.com> + */ +final class Cursor +{ + private $output; + private $input; + + /** + * @param resource|null $input + */ + public function __construct(OutputInterface $output, $input = null) + { + $this->output = $output; + $this->input = $input ?? (\defined('STDIN') ? \STDIN : fopen('php://input', 'r+')); + } + + /** + * @return $this + */ + public function moveUp(int $lines = 1): self + { + $this->output->write(sprintf("\x1b[%dA", $lines)); + + return $this; + } + + /** + * @return $this + */ + public function moveDown(int $lines = 1): self + { + $this->output->write(sprintf("\x1b[%dB", $lines)); + + return $this; + } + + /** + * @return $this + */ + public function moveRight(int $columns = 1): self + { + $this->output->write(sprintf("\x1b[%dC", $columns)); + + return $this; + } + + /** + * @return $this + */ + public function moveLeft(int $columns = 1): self + { + $this->output->write(sprintf("\x1b[%dD", $columns)); + + return $this; + } + + /** + * @return $this + */ + public function moveToColumn(int $column): self + { + $this->output->write(sprintf("\x1b[%dG", $column)); + + return $this; + } + + /** + * @return $this + */ + public function moveToPosition(int $column, int $row): self + { + $this->output->write(sprintf("\x1b[%d;%dH", $row + 1, $column)); + + return $this; + } + + /** + * @return $this + */ + public function savePosition(): self + { + $this->output->write("\x1b7"); + + return $this; + } + + /** + * @return $this + */ + public function restorePosition(): self + { + $this->output->write("\x1b8"); + + return $this; + } + + /** + * @return $this + */ + public function hide(): self + { + $this->output->write("\x1b[?25l"); + + return $this; + } + + /** + * @return $this + */ + public function show(): self + { + $this->output->write("\x1b[?25h\x1b[?0c"); + + return $this; + } + + /** + * Clears all the output from the current line. + * + * @return $this + */ + public function clearLine(): self + { + $this->output->write("\x1b[2K"); + + return $this; + } + + /** + * Clears all the output from the current line after the current position. + */ + public function clearLineAfter(): self + { + $this->output->write("\x1b[K"); + + return $this; + } + + /** + * Clears all the output from the cursors' current position to the end of the screen. + * + * @return $this + */ + public function clearOutput(): self + { + $this->output->write("\x1b[0J"); + + return $this; + } + + /** + * Clears the entire screen. + * + * @return $this + */ + public function clearScreen(): self + { + $this->output->write("\x1b[2J"); + + return $this; + } + + /** + * Returns the current cursor position as x,y coordinates. + */ + public function getCurrentPosition(): array + { + static $isTtySupported; + + if (null === $isTtySupported && \function_exists('proc_open')) { + $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes); + } + + if (!$isTtySupported) { + return [1, 1]; + } + + $sttyMode = shell_exec('stty -g'); + shell_exec('stty -icanon -echo'); + + @fwrite($this->input, "\033[6n"); + + $code = trim(fread($this->input, 1024)); + + shell_exec(sprintf('stty %s', $sttyMode)); + + sscanf($code, "\033[%d;%dR", $row, $col); + + return [$col, $row]; + } +} diff --git a/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php index 39d53ef..1fbb212 100644 --- a/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php +++ b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php @@ -12,11 +12,14 @@ namespace Symfony\Component\Console\DependencyInjection; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\LazyCommand; use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\TypedReference; /** @@ -28,29 +31,35 @@ class AddConsoleCommandPass implements CompilerPassInterface { private $commandLoaderServiceId; private $commandTag; + private $noPreloadTag; + private $privateTagName; - public function __construct($commandLoaderServiceId = 'console.command_loader', $commandTag = 'console.command') + public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command', string $noPreloadTag = 'container.no_preload', string $privateTagName = 'container.private') { + if (0 < \func_num_args()) { + trigger_deprecation('symfony/console', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); + } + $this->commandLoaderServiceId = $commandLoaderServiceId; $this->commandTag = $commandTag; + $this->noPreloadTag = $noPreloadTag; + $this->privateTagName = $privateTagName; } public function process(ContainerBuilder $container) { $commandServices = $container->findTaggedServiceIds($this->commandTag, true); - $lazyCommandMap = array(); - $lazyCommandRefs = array(); - $serviceIds = array(); - $lazyServiceIds = array(); + $lazyCommandMap = []; + $lazyCommandRefs = []; + $serviceIds = []; foreach ($commandServices as $id => $tags) { $definition = $container->getDefinition($id); + $definition->addTag($this->noPreloadTag); $class = $container->getParameterBag()->resolveValue($definition->getClass()); - $commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class)); - if (isset($tags[0]['command'])) { - $commandName = $tags[0]['command']; + $aliases = $tags[0]['command']; } else { if (!$r = $container->getReflectionClass($class)) { throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); @@ -58,49 +67,82 @@ public function process(ContainerBuilder $container) if (!$r->isSubclassOf(Command::class)) { throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class)); } - $commandName = $class::getDefaultName(); + $aliases = str_replace('%', '%%', $class::getDefaultName() ?? ''); + } + + $aliases = explode('|', $aliases ?? ''); + $commandName = array_shift($aliases); + + if ($isHidden = '' === $commandName) { + $commandName = array_shift($aliases); } if (null === $commandName) { - if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) { - $commandId = $commandId.'_'.$id; - } - if (!$definition->isPublic() || $definition->isPrivate()) { + if (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag($this->privateTagName)) { + $commandId = 'console.command.public_alias.'.$id; $container->setAlias($commandId, $id)->setPublic(true); $id = $commandId; } - $serviceIds[$commandId] = $id; + $serviceIds[] = $id; continue; } - $serviceIds[$commandId] = $id; - $lazyServiceIds[$id] = true; + $description = $tags[0]['description'] ?? null; + unset($tags[0]); $lazyCommandMap[$commandName] = $id; $lazyCommandRefs[$id] = new TypedReference($id, $class); - $aliases = array(); + + foreach ($aliases as $alias) { + $lazyCommandMap[$alias] = $id; + } foreach ($tags as $tag) { if (isset($tag['command'])) { $aliases[] = $tag['command']; $lazyCommandMap[$tag['command']] = $id; } + + $description = $description ?? $tag['description'] ?? null; } - $definition->addMethodCall('setName', array($commandName)); + $definition->addMethodCall('setName', [$commandName]); if ($aliases) { - $definition->addMethodCall('setAliases', array($aliases)); + $definition->addMethodCall('setAliases', [$aliases]); + } + + if ($isHidden) { + $definition->addMethodCall('setHidden', [true]); + } + + if (!$description) { + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + if (!$r->isSubclassOf(Command::class)) { + throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class)); + } + $description = str_replace('%', '%%', $class::getDefaultDescription() ?? ''); + } + + if ($description) { + $definition->addMethodCall('setDescription', [$description]); + + $container->register('.'.$id.'.lazy', LazyCommand::class) + ->setArguments([$commandName, $aliases, $description, $isHidden, new ServiceClosureArgument($lazyCommandRefs[$id])]); + + $lazyCommandRefs[$id] = new Reference('.'.$id.'.lazy'); } } $container ->register($this->commandLoaderServiceId, ContainerCommandLoader::class) ->setPublic(true) - ->setArguments(array(ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap)); + ->addTag($this->noPreloadTag) + ->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]); $container->setParameter('console.command.ids', $serviceIds); - $container->setParameter('console.lazy_command.ids', $lazyServiceIds); } } diff --git a/vendor/symfony/console/Descriptor/ApplicationDescription.php b/vendor/symfony/console/Descriptor/ApplicationDescription.php index ef4c673..2a3acc9 100644 --- a/vendor/symfony/console/Descriptor/ApplicationDescription.php +++ b/vendor/symfony/console/Descriptor/ApplicationDescription.php @@ -22,7 +22,7 @@ */ class ApplicationDescription { - const GLOBAL_NAMESPACE = '_global'; + public const GLOBAL_NAMESPACE = '_global'; private $application; private $namespace; @@ -34,31 +34,23 @@ class ApplicationDescription private $namespaces; /** - * @var Command[] + * @var array<string, Command> */ private $commands; /** - * @var Command[] + * @var array<string, Command> */ private $aliases; - /** - * @param Application $application - * @param string|null $namespace - * @param bool $showHidden - */ - public function __construct(Application $application, $namespace = null, $showHidden = false) + public function __construct(Application $application, string $namespace = null, bool $showHidden = false) { $this->application = $application; $this->namespace = $namespace; $this->showHidden = $showHidden; } - /** - * @return array - */ - public function getNamespaces() + public function getNamespaces(): array { if (null === $this->namespaces) { $this->inspectApplication(); @@ -70,7 +62,7 @@ public function getNamespaces() /** * @return Command[] */ - public function getCommands() + public function getCommands(): array { if (null === $this->commands) { $this->inspectApplication(); @@ -80,29 +72,25 @@ public function getCommands() } /** - * @param string $name - * - * @return Command - * * @throws CommandNotFoundException */ - public function getCommand($name) + public function getCommand(string $name): Command { if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { - throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name)); + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); } - return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; + return $this->commands[$name] ?? $this->aliases[$name]; } private function inspectApplication() { - $this->commands = array(); - $this->namespaces = array(); + $this->commands = []; + $this->namespaces = []; $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); foreach ($this->sortCommands($all) as $namespace => $commands) { - $names = array(); + $names = []; /** @var Command $command */ foreach ($commands as $name => $command) { @@ -119,34 +107,37 @@ private function inspectApplication() $names[] = $name; } - $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names); + $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names]; } } - /** - * @return array - */ - private function sortCommands(array $commands) + private function sortCommands(array $commands): array { - $namespacedCommands = array(); - $globalCommands = array(); + $namespacedCommands = []; + $globalCommands = []; + $sortedCommands = []; foreach ($commands as $name => $command) { $key = $this->application->extractNamespace($name, 1); - if (!$key) { - $globalCommands['_global'][$name] = $command; + if (\in_array($key, ['', self::GLOBAL_NAMESPACE], true)) { + $globalCommands[$name] = $command; } else { $namespacedCommands[$key][$name] = $command; } } - ksort($namespacedCommands); - $namespacedCommands = array_merge($globalCommands, $namespacedCommands); - foreach ($namespacedCommands as &$commandsSet) { - ksort($commandsSet); + if ($globalCommands) { + ksort($globalCommands); + $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands; + } + + if ($namespacedCommands) { + ksort($namespacedCommands, \SORT_STRING); + foreach ($namespacedCommands as $key => $commandsSet) { + ksort($commandsSet); + $sortedCommands[$key] = $commandsSet; + } } - // unset reference to keep scope clear - unset($commandsSet); - return $namespacedCommands; + return $sortedCommands; } } diff --git a/vendor/symfony/console/Descriptor/Descriptor.php b/vendor/symfony/console/Descriptor/Descriptor.php index 151d84f..a364830 100644 --- a/vendor/symfony/console/Descriptor/Descriptor.php +++ b/vendor/symfony/console/Descriptor/Descriptor.php @@ -34,7 +34,7 @@ abstract class Descriptor implements DescriptorInterface /** * {@inheritdoc} */ - public function describe(OutputInterface $output, $object, array $options = array()) + public function describe(OutputInterface $output, object $object, array $options = []) { $this->output = $output; @@ -55,53 +55,40 @@ public function describe(OutputInterface $output, $object, array $options = arra $this->describeApplication($object, $options); break; default: - throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', \get_class($object))); + throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_debug_type($object))); } } /** * Writes content to output. - * - * @param string $content - * @param bool $decorated */ - protected function write($content, $decorated = false) + protected function write(string $content, bool $decorated = false) { $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); } /** * Describes an InputArgument instance. - * - * @return string|mixed */ - abstract protected function describeInputArgument(InputArgument $argument, array $options = array()); + abstract protected function describeInputArgument(InputArgument $argument, array $options = []); /** * Describes an InputOption instance. - * - * @return string|mixed */ - abstract protected function describeInputOption(InputOption $option, array $options = array()); + abstract protected function describeInputOption(InputOption $option, array $options = []); /** * Describes an InputDefinition instance. - * - * @return string|mixed */ - abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array()); + abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []); /** * Describes a Command instance. - * - * @return string|mixed */ - abstract protected function describeCommand(Command $command, array $options = array()); + abstract protected function describeCommand(Command $command, array $options = []); /** * Describes an Application instance. - * - * @return string|mixed */ - abstract protected function describeApplication(Application $application, array $options = array()); + abstract protected function describeApplication(Application $application, array $options = []); } diff --git a/vendor/symfony/console/Descriptor/DescriptorInterface.php b/vendor/symfony/console/Descriptor/DescriptorInterface.php index 5d3339a..ebea303 100644 --- a/vendor/symfony/console/Descriptor/DescriptorInterface.php +++ b/vendor/symfony/console/Descriptor/DescriptorInterface.php @@ -20,12 +20,5 @@ */ interface DescriptorInterface { - /** - * Describes an object if supported. - * - * @param OutputInterface $output - * @param object $object - * @param array $options - */ - public function describe(OutputInterface $output, $object, array $options = array()); + public function describe(OutputInterface $output, object $object, array $options = []); } diff --git a/vendor/symfony/console/Descriptor/JsonDescriptor.php b/vendor/symfony/console/Descriptor/JsonDescriptor.php index f60323b..1d28659 100644 --- a/vendor/symfony/console/Descriptor/JsonDescriptor.php +++ b/vendor/symfony/console/Descriptor/JsonDescriptor.php @@ -29,7 +29,7 @@ class JsonDescriptor extends Descriptor /** * {@inheritdoc} */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) + protected function describeInputArgument(InputArgument $argument, array $options = []) { $this->writeData($this->getInputArgumentData($argument), $options); } @@ -37,15 +37,18 @@ protected function describeInputArgument(InputArgument $argument, array $options /** * {@inheritdoc} */ - protected function describeInputOption(InputOption $option, array $options = array()) + protected function describeInputOption(InputOption $option, array $options = []) { $this->writeData($this->getInputOptionData($option), $options); + if ($option->isNegatable()) { + $this->writeData($this->getInputOptionData($option, true), $options); + } } /** * {@inheritdoc} */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) + protected function describeInputDefinition(InputDefinition $definition, array $options = []) { $this->writeData($this->getInputDefinitionData($definition), $options); } @@ -53,25 +56,25 @@ protected function describeInputDefinition(InputDefinition $definition, array $o /** * {@inheritdoc} */ - protected function describeCommand(Command $command, array $options = array()) + protected function describeCommand(Command $command, array $options = []) { - $this->writeData($this->getCommandData($command), $options); + $this->writeData($this->getCommandData($command, $options['short'] ?? false), $options); } /** * {@inheritdoc} */ - protected function describeApplication(Application $application, array $options = array()) + protected function describeApplication(Application $application, array $options = []) { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $describedNamespace = $options['namespace'] ?? null; $description = new ApplicationDescription($application, $describedNamespace, true); - $commands = array(); + $commands = []; foreach ($description->getCommands() as $command) { - $commands[] = $this->getCommandData($command); + $commands[] = $this->getCommandData($command, $options['short'] ?? false); } - $data = array(); + $data = []; if ('UNKNOWN' !== $application->getName()) { $data['application']['name'] = $application->getName(); if ('UNKNOWN' !== $application->getVersion()) { @@ -92,77 +95,87 @@ protected function describeApplication(Application $application, array $options /** * Writes data as json. - * - * @return array|string */ private function writeData(array $data, array $options) { - $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0)); + $flags = $options['json_encoding'] ?? 0; + + $this->write(json_encode($data, $flags)); } - /** - * @return array - */ - private function getInputArgumentData(InputArgument $argument) + private function getInputArgumentData(InputArgument $argument): array { - return array( + return [ 'name' => $argument->getName(), 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), - 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), - ); + 'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), + ]; } - /** - * @return array - */ - private function getInputOptionData(InputOption $option) + private function getInputOptionData(InputOption $option, bool $negated = false): array { - return array( + return $negated ? [ + 'name' => '--no-'.$option->getName(), + 'shortcut' => '', + 'accept_value' => false, + 'is_value_required' => false, + 'is_multiple' => false, + 'description' => 'Negate the "--'.$option->getName().'" option', + 'default' => false, + ] : [ 'name' => '--'.$option->getName(), 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', 'accept_value' => $option->acceptValue(), 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), - 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(), - ); + 'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault(), + ]; } - /** - * @return array - */ - private function getInputDefinitionData(InputDefinition $definition) + private function getInputDefinitionData(InputDefinition $definition): array { - $inputArguments = array(); + $inputArguments = []; foreach ($definition->getArguments() as $name => $argument) { $inputArguments[$name] = $this->getInputArgumentData($argument); } - $inputOptions = array(); + $inputOptions = []; foreach ($definition->getOptions() as $name => $option) { $inputOptions[$name] = $this->getInputOptionData($option); + if ($option->isNegatable()) { + $inputOptions['no-'.$name] = $this->getInputOptionData($option, true); + } } - return array('arguments' => $inputArguments, 'options' => $inputOptions); + return ['arguments' => $inputArguments, 'options' => $inputOptions]; } - /** - * @return array - */ - private function getCommandData(Command $command) + private function getCommandData(Command $command, bool $short = false): array { - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - return array( + $data = [ 'name' => $command->getName(), - 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()), 'description' => $command->getDescription(), - 'help' => $command->getProcessedHelp(), - 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()), - 'hidden' => $command->isHidden(), - ); + ]; + + if ($short) { + $data += [ + 'usage' => $command->getAliases(), + ]; + } else { + $command->mergeApplicationDefinition(false); + + $data += [ + 'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), + 'help' => $command->getProcessedHelp(), + 'definition' => $this->getInputDefinitionData($command->getDefinition()), + ]; + } + + $data['hidden'] = $command->isHidden(); + + return $data; } } diff --git a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php index 6d8399f..21ceca6 100644 --- a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php +++ b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php @@ -31,7 +31,7 @@ class MarkdownDescriptor extends Descriptor /** * {@inheritdoc} */ - public function describe(OutputInterface $output, $object, array $options = array()) + public function describe(OutputInterface $output, object $object, array $options = []) { $decorated = $output->isDecorated(); $output->setDecorated(false); @@ -44,7 +44,7 @@ public function describe(OutputInterface $output, $object, array $options = arra /** * {@inheritdoc} */ - protected function write($content, $decorated = true) + protected function write(string $content, bool $decorated = true) { parent::write($content, $decorated); } @@ -52,7 +52,7 @@ protected function write($content, $decorated = true) /** * {@inheritdoc} */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) + protected function describeInputArgument(InputArgument $argument, array $options = []) { $this->write( '#### `'.($argument->getName() ?: '<none>')."`\n\n" @@ -66,9 +66,12 @@ protected function describeInputArgument(InputArgument $argument, array $options /** * {@inheritdoc} */ - protected function describeInputOption(InputOption $option, array $options = array()) + protected function describeInputOption(InputOption $option, array $options = []) { $name = '--'.$option->getName(); + if ($option->isNegatable()) { + $name .= '|--no-'.$option->getName(); + } if ($option->getShortcut()) { $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).''; } @@ -79,6 +82,7 @@ protected function describeInputOption(InputOption $option, array $options = arr .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" + .'* Is negatable: '.($option->isNegatable() ? 'yes' : 'no')."\n" .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' ); } @@ -86,13 +90,15 @@ protected function describeInputOption(InputOption $option, array $options = arr /** * {@inheritdoc} */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) + protected function describeInputDefinition(InputDefinition $definition, array $options = []) { if ($showArguments = \count($definition->getArguments()) > 0) { $this->write('### Arguments'); foreach ($definition->getArguments() as $argument) { $this->write("\n\n"); - $this->write($this->describeInputArgument($argument)); + if (null !== $describeInputArgument = $this->describeInputArgument($argument)) { + $this->write($describeInputArgument); + } } } @@ -104,7 +110,9 @@ protected function describeInputDefinition(InputDefinition $definition, array $o $this->write('### Options'); foreach ($definition->getOptions() as $option) { $this->write("\n\n"); - $this->write($this->describeInputOption($option)); + if (null !== $describeInputOption = $this->describeInputOption($option)) { + $this->write($describeInputOption); + } } } } @@ -112,17 +120,30 @@ protected function describeInputDefinition(InputDefinition $definition, array $o /** * {@inheritdoc} */ - protected function describeCommand(Command $command, array $options = array()) + protected function describeCommand(Command $command, array $options = []) { - $command->getSynopsis(); + if ($options['short'] ?? false) { + $this->write( + '`'.$command->getName()."`\n" + .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n" + .($command->getDescription() ? $command->getDescription()."\n\n" : '') + .'### Usage'."\n\n" + .array_reduce($command->getAliases(), function ($carry, $usage) { + return $carry.'* `'.$usage.'`'."\n"; + }) + ); + + return; + } + $command->mergeApplicationDefinition(false); $this->write( '`'.$command->getName()."`\n" - .str_repeat('-', Helper::strlen($command->getName()) + 2)."\n\n" + .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n" .($command->getDescription() ? $command->getDescription()."\n\n" : '') .'### Usage'."\n\n" - .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) { + .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) { return $carry.'* `'.$usage.'`'."\n"; }) ); @@ -132,22 +153,23 @@ protected function describeCommand(Command $command, array $options = array()) $this->write($help); } - if ($command->getNativeDefinition()) { + $definition = $command->getDefinition(); + if ($definition->getOptions() || $definition->getArguments()) { $this->write("\n\n"); - $this->describeInputDefinition($command->getNativeDefinition()); + $this->describeInputDefinition($definition); } } /** * {@inheritdoc} */ - protected function describeApplication(Application $application, array $options = array()) + protected function describeApplication(Application $application, array $options = []) { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $describedNamespace = $options['namespace'] ?? null; $description = new ApplicationDescription($application, $describedNamespace); $title = $this->getApplicationTitle($application); - $this->write($title."\n".str_repeat('=', Helper::strlen($title))); + $this->write($title."\n".str_repeat('=', Helper::width($title))); foreach ($description->getNamespaces() as $namespace) { if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { @@ -163,11 +185,13 @@ protected function describeApplication(Application $application, array $options foreach ($description->getCommands() as $command) { $this->write("\n\n"); - $this->write($this->describeCommand($command)); + if (null !== $describeCommand = $this->describeCommand($command, $options)) { + $this->write($describeCommand); + } } } - private function getApplicationTitle(Application $application) + private function getApplicationTitle(Application $application): string { if ('UNKNOWN' !== $application->getName()) { if ('UNKNOWN' !== $application->getVersion()) { diff --git a/vendor/symfony/console/Descriptor/TextDescriptor.php b/vendor/symfony/console/Descriptor/TextDescriptor.php index 04dd225..fbb140a 100644 --- a/vendor/symfony/console/Descriptor/TextDescriptor.php +++ b/vendor/symfony/console/Descriptor/TextDescriptor.php @@ -31,7 +31,7 @@ class TextDescriptor extends Descriptor /** * {@inheritdoc} */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) + protected function describeInputArgument(InputArgument $argument, array $options = []) { if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault())); @@ -39,7 +39,7 @@ protected function describeInputArgument(InputArgument $argument, array $options $default = ''; } - $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName()); + $totalWidth = $options['total_width'] ?? Helper::width($argument->getName()); $spacingWidth = $totalWidth - \strlen($argument->getName()); $this->writeText(sprintf(' <info>%s</info> %s%s%s', @@ -54,7 +54,7 @@ protected function describeInputArgument(InputArgument $argument, array $options /** * {@inheritdoc} */ - protected function describeInputOption(InputOption $option, array $options = array()) + protected function describeInputOption(InputOption $option, array $options = []) { if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault())); @@ -71,13 +71,13 @@ protected function describeInputOption(InputOption $option, array $options = arr } } - $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option)); + $totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]); $synopsis = sprintf('%s%s', $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', - sprintf('--%s%s', $option->getName(), $value) + sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value) ); - $spacingWidth = $totalWidth - Helper::strlen($synopsis); + $spacingWidth = $totalWidth - Helper::width($synopsis); $this->writeText(sprintf(' <info>%s</info> %s%s%s%s', $synopsis, @@ -92,18 +92,18 @@ protected function describeInputOption(InputOption $option, array $options = arr /** * {@inheritdoc} */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) + protected function describeInputDefinition(InputDefinition $definition, array $options = []) { $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); foreach ($definition->getArguments() as $argument) { - $totalWidth = max($totalWidth, Helper::strlen($argument->getName())); + $totalWidth = max($totalWidth, Helper::width($argument->getName())); } if ($definition->getArguments()) { $this->writeText('<comment>Arguments:</comment>', $options); $this->writeText("\n"); foreach ($definition->getArguments() as $argument) { - $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth))); + $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth])); $this->writeText("\n"); } } @@ -113,20 +113,20 @@ protected function describeInputDefinition(InputDefinition $definition, array $o } if ($definition->getOptions()) { - $laterOptions = array(); + $laterOptions = []; $this->writeText('<comment>Options:</comment>', $options); foreach ($definition->getOptions() as $option) { - if (\strlen($option->getShortcut()) > 1) { + if (\strlen($option->getShortcut() ?? '') > 1) { $laterOptions[] = $option; continue; } $this->writeText("\n"); - $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth))); + $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); } foreach ($laterOptions as $option) { $this->writeText("\n"); - $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth))); + $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); } } } @@ -134,27 +134,33 @@ protected function describeInputDefinition(InputDefinition $definition, array $o /** * {@inheritdoc} */ - protected function describeCommand(Command $command, array $options = array()) + protected function describeCommand(Command $command, array $options = []) { - $command->getSynopsis(true); - $command->getSynopsis(false); $command->mergeApplicationDefinition(false); + if ($description = $command->getDescription()) { + $this->writeText('<comment>Description:</comment>', $options); + $this->writeText("\n"); + $this->writeText(' '.$description); + $this->writeText("\n\n"); + } + $this->writeText('<comment>Usage:</comment>', $options); - foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) { + foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) { $this->writeText("\n"); $this->writeText(' '.OutputFormatter::escape($usage), $options); } $this->writeText("\n"); - $definition = $command->getNativeDefinition(); + $definition = $command->getDefinition(); if ($definition->getOptions() || $definition->getArguments()) { $this->writeText("\n"); $this->describeInputDefinition($definition, $options); $this->writeText("\n"); } - if ($help = $command->getProcessedHelp()) { + $help = $command->getProcessedHelp(); + if ($help && $help !== $description) { $this->writeText("\n"); $this->writeText('<comment>Help:</comment>', $options); $this->writeText("\n"); @@ -166,9 +172,9 @@ protected function describeCommand(Command $command, array $options = array()) /** * {@inheritdoc} */ - protected function describeApplication(Application $application, array $options = array()) + protected function describeApplication(Application $application, array $options = []) { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $describedNamespace = $options['namespace'] ?? null; $description = new ApplicationDescription($application, $describedNamespace); if (isset($options['raw_text']) && $options['raw_text']) { @@ -202,9 +208,9 @@ protected function describeApplication(Application $application, array $options } // calculate max. width based on available commands per namespace - $width = $this->getColumnWidth(\call_user_func_array('array_merge', array_map(function ($namespace) use ($commands) { + $width = $this->getColumnWidth(array_merge(...array_values(array_map(function ($namespace) use ($commands) { return array_intersect($namespace['commands'], array_keys($commands)); - }, $namespaces))); + }, array_values($namespaces))))); if ($describedNamespace) { $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options); @@ -228,7 +234,7 @@ protected function describeApplication(Application $application, array $options foreach ($namespace['commands'] as $name) { $this->writeText("\n"); - $spacingWidth = $width - Helper::strlen($name); + $spacingWidth = $width - Helper::width($name); $command = $commands[$name]; $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : ''; $this->writeText(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); @@ -242,7 +248,7 @@ protected function describeApplication(Application $application, array $options /** * {@inheritdoc} */ - private function writeText($content, array $options = array()) + private function writeText(string $content, array $options = []) { $this->write( isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, @@ -252,10 +258,8 @@ private function writeText($content, array $options = array()) /** * Formats command aliases to show them in the command description. - * - * @return string */ - private function getCommandAliasesText(Command $command) + private function getCommandAliasesText(Command $command): string { $text = ''; $aliases = $command->getAliases(); @@ -271,12 +275,10 @@ private function getCommandAliasesText(Command $command) * Formats input option/argument default value. * * @param mixed $default - * - * @return string */ - private function formatDefaultValue($default) + private function formatDefaultValue($default): string { - if (INF === $default) { + if (\INF === $default) { return 'INF'; } @@ -290,26 +292,24 @@ private function formatDefaultValue($default) } } - return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); + return str_replace('\\\\', '\\', json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); } /** - * @param (Command|string)[] $commands - * - * @return int + * @param array<Command|string> $commands */ - private function getColumnWidth(array $commands) + private function getColumnWidth(array $commands): int { - $widths = array(); + $widths = []; foreach ($commands as $command) { if ($command instanceof Command) { - $widths[] = Helper::strlen($command->getName()); + $widths[] = Helper::width($command->getName()); foreach ($command->getAliases() as $alias) { - $widths[] = Helper::strlen($alias); + $widths[] = Helper::width($alias); } } else { - $widths[] = Helper::strlen($command); + $widths[] = Helper::width($command); } } @@ -318,18 +318,17 @@ private function getColumnWidth(array $commands) /** * @param InputOption[] $options - * - * @return int */ - private function calculateTotalWidthForOptions(array $options) + private function calculateTotalWidthForOptions(array $options): int { $totalWidth = 0; foreach ($options as $option) { // "-" + shortcut + ", --" + name - $nameLength = 1 + max(Helper::strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName()); - - if ($option->acceptValue()) { - $valueLength = 1 + Helper::strlen($option->getName()); // = + value + $nameLength = 1 + max(Helper::width($option->getShortcut()), 1) + 4 + Helper::width($option->getName()); + if ($option->isNegatable()) { + $nameLength += 6 + Helper::width($option->getName()); // |--no- + name + } elseif ($option->acceptValue()) { + $valueLength = 1 + Helper::width($option->getName()); // = + value $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ] $nameLength += $valueLength; diff --git a/vendor/symfony/console/Descriptor/XmlDescriptor.php b/vendor/symfony/console/Descriptor/XmlDescriptor.php index 1a12a1d..4f7cd8b 100644 --- a/vendor/symfony/console/Descriptor/XmlDescriptor.php +++ b/vendor/symfony/console/Descriptor/XmlDescriptor.php @@ -26,10 +26,7 @@ */ class XmlDescriptor extends Descriptor { - /** - * @return \DOMDocument - */ - public function getInputDefinitionDocument(InputDefinition $definition) + public function getInputDefinitionDocument(InputDefinition $definition): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($definitionXML = $dom->createElement('definition')); @@ -47,46 +44,42 @@ public function getInputDefinitionDocument(InputDefinition $definition) return $dom; } - /** - * @return \DOMDocument - */ - public function getCommandDocument(Command $command) + public function getCommandDocument(Command $command, bool $short = false): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($commandXML = $dom->createElement('command')); - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - $commandXML->setAttribute('id', $command->getName()); $commandXML->setAttribute('name', $command->getName()); $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0); $commandXML->appendChild($usagesXML = $dom->createElement('usages')); - foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) { - $usagesXML->appendChild($dom->createElement('usage', $usage)); - } - $commandXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); - $commandXML->appendChild($helpXML = $dom->createElement('help')); - $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); + if ($short) { + foreach ($command->getAliases() as $usage) { + $usagesXML->appendChild($dom->createElement('usage', $usage)); + } + } else { + $command->mergeApplicationDefinition(false); + + foreach (array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) { + $usagesXML->appendChild($dom->createElement('usage', $usage)); + } - $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition()); - $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); + $commandXML->appendChild($helpXML = $dom->createElement('help')); + $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); + + $definitionXML = $this->getInputDefinitionDocument($command->getDefinition()); + $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); + } return $dom; } - /** - * @param Application $application - * @param string|null $namespace - * - * @return \DOMDocument - */ - public function getApplicationDocument(Application $application, $namespace = null) + 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')); @@ -107,7 +100,7 @@ public function getApplicationDocument(Application $application, $namespace = nu } foreach ($description->getCommands() as $command) { - $this->appendDocument($commandsXML, $this->getCommandDocument($command)); + $this->appendDocument($commandsXML, $this->getCommandDocument($command, $short)); } if (!$namespace) { @@ -130,7 +123,7 @@ public function getApplicationDocument(Application $application, $namespace = nu /** * {@inheritdoc} */ - protected function describeInputArgument(InputArgument $argument, array $options = array()) + protected function describeInputArgument(InputArgument $argument, array $options = []) { $this->writeDocument($this->getInputArgumentDocument($argument)); } @@ -138,7 +131,7 @@ protected function describeInputArgument(InputArgument $argument, array $options /** * {@inheritdoc} */ - protected function describeInputOption(InputOption $option, array $options = array()) + protected function describeInputOption(InputOption $option, array $options = []) { $this->writeDocument($this->getInputOptionDocument($option)); } @@ -146,7 +139,7 @@ protected function describeInputOption(InputOption $option, array $options = arr /** * {@inheritdoc} */ - protected function describeInputDefinition(InputDefinition $definition, array $options = array()) + protected function describeInputDefinition(InputDefinition $definition, array $options = []) { $this->writeDocument($this->getInputDefinitionDocument($definition)); } @@ -154,17 +147,17 @@ protected function describeInputDefinition(InputDefinition $definition, array $o /** * {@inheritdoc} */ - protected function describeCommand(Command $command, array $options = array()) + protected function describeCommand(Command $command, array $options = []) { - $this->writeDocument($this->getCommandDocument($command)); + $this->writeDocument($this->getCommandDocument($command, $options['short'] ?? false)); } /** * {@inheritdoc} */ - protected function describeApplication(Application $application, array $options = array()) + protected function describeApplication(Application $application, array $options = []) { - $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null)); + $this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null, $options['short'] ?? false)); } /** @@ -179,8 +172,6 @@ private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) /** * Writes DOM document. - * - * @return \DOMDocument|string */ private function writeDocument(\DOMDocument $dom) { @@ -188,10 +179,7 @@ private function writeDocument(\DOMDocument $dom) $this->write($dom->saveXML()); } - /** - * @return \DOMDocument - */ - private function getInputArgumentDocument(InputArgument $argument) + private function getInputArgumentDocument(InputArgument $argument): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); @@ -203,7 +191,7 @@ private function getInputArgumentDocument(InputArgument $argument) $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); - $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array())); + $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [var_export($argument->getDefault(), true)] : ($argument->getDefault() ? [$argument->getDefault()] : [])); foreach ($defaults as $default) { $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); $defaultXML->appendChild($dom->createTextNode($default)); @@ -212,16 +200,13 @@ private function getInputArgumentDocument(InputArgument $argument) return $dom; } - /** - * @return \DOMDocument - */ - private function getInputOptionDocument(InputOption $option) + private function getInputOptionDocument(InputOption $option): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($objectXML = $dom->createElement('option')); $objectXML->setAttribute('name', '--'.$option->getName()); - $pos = strpos($option->getShortcut(), '|'); + $pos = strpos($option->getShortcut() ?? '', '|'); if (false !== $pos) { $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut())); @@ -235,7 +220,7 @@ private function getInputOptionDocument(InputOption $option) $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); if ($option->acceptValue()) { - $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array())); + $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), true)] : ($option->getDefault() ? [$option->getDefault()] : [])); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); if (!empty($defaults)) { @@ -246,6 +231,17 @@ private function getInputOptionDocument(InputOption $option) } } + if ($option->isNegatable()) { + $dom->appendChild($objectXML = $dom->createElement('option')); + $objectXML->setAttribute('name', '--no-'.$option->getName()); + $objectXML->setAttribute('shortcut', ''); + $objectXML->setAttribute('accept_value', 0); + $objectXML->setAttribute('is_value_required', 0); + $objectXML->setAttribute('is_multiple', 0); + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode('Negate the "--'.$option->getName().'" option')); + } + return $dom; } } diff --git a/vendor/symfony/console/Event/ConsoleCommandEvent.php b/vendor/symfony/console/Event/ConsoleCommandEvent.php index 2f517c1..08bd18f 100644 --- a/vendor/symfony/console/Event/ConsoleCommandEvent.php +++ b/vendor/symfony/console/Event/ConsoleCommandEvent.php @@ -16,12 +16,12 @@ * * @author Fabien Potencier <fabien@symfony.com> */ -class ConsoleCommandEvent extends ConsoleEvent +final class ConsoleCommandEvent extends ConsoleEvent { /** * The return code for skipped commands, this will also be passed into the terminate event. */ - const RETURN_CODE_DISABLED = 113; + public const RETURN_CODE_DISABLED = 113; /** * Indicates if the command should be run or skipped. @@ -30,30 +30,21 @@ class ConsoleCommandEvent extends ConsoleEvent /** * Disables the command, so it won't be run. - * - * @return bool */ - public function disableCommand() + public function disableCommand(): bool { return $this->commandShouldRun = false; } - /** - * Enables the command. - * - * @return bool - */ - public function enableCommand() + public function enableCommand(): bool { return $this->commandShouldRun = true; } /** * Returns true if the command is runnable, false otherwise. - * - * @return bool */ - public function commandShouldRun() + public function commandShouldRun(): bool { return $this->commandShouldRun; } diff --git a/vendor/symfony/console/Event/ConsoleErrorEvent.php b/vendor/symfony/console/Event/ConsoleErrorEvent.php index 51a5f56..57d9b38 100644 --- a/vendor/symfony/console/Event/ConsoleErrorEvent.php +++ b/vendor/symfony/console/Event/ConsoleErrorEvent.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -26,58 +25,34 @@ final class ConsoleErrorEvent extends ConsoleEvent private $error; private $exitCode; - public function __construct(InputInterface $input, OutputInterface $output, $error, Command $command = null) + public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null) { parent::__construct($command, $input, $output); - $this->setError($error); + $this->error = $error; } - /** - * Returns the thrown error/exception. - * - * @return \Throwable - */ - public function getError() + public function getError(): \Throwable { return $this->error; } - /** - * Replaces the thrown error/exception. - * - * @param \Throwable $error - */ - public function setError($error) + public function setError(\Throwable $error): void { - if (!$error instanceof \Throwable && !$error instanceof \Exception) { - throw new InvalidArgumentException(sprintf('The error passed to ConsoleErrorEvent must be an instance of \Throwable or \Exception, "%s" was passed instead.', \is_object($error) ? \get_class($error) : \gettype($error))); - } - $this->error = $error; } - /** - * Sets the exit code. - * - * @param int $exitCode The command exit code - */ - public function setExitCode($exitCode) + public function setExitCode(int $exitCode): void { - $this->exitCode = (int) $exitCode; + $this->exitCode = $exitCode; $r = new \ReflectionProperty($this->error, 'code'); $r->setAccessible(true); $r->setValue($this->error, $this->exitCode); } - /** - * Gets the exit code. - * - * @return int The command exit code - */ - public function getExitCode() + public function getExitCode(): int { - return null !== $this->exitCode ? $this->exitCode : (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1); + return $this->exitCode ?? (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1); } } diff --git a/vendor/symfony/console/Event/ConsoleEvent.php b/vendor/symfony/console/Event/ConsoleEvent.php index 5440da2..be7937d 100644 --- a/vendor/symfony/console/Event/ConsoleEvent.php +++ b/vendor/symfony/console/Event/ConsoleEvent.php @@ -14,7 +14,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; /** * Allows to inspect input and output of a command. @@ -28,7 +28,7 @@ class ConsoleEvent extends Event private $input; private $output; - public function __construct(Command $command = null, InputInterface $input, OutputInterface $output) + public function __construct(?Command $command, InputInterface $input, OutputInterface $output) { $this->command = $command; $this->input = $input; @@ -38,7 +38,7 @@ public function __construct(Command $command = null, InputInterface $input, Outp /** * Gets the command that is executed. * - * @return Command|null A Command instance + * @return Command|null */ public function getCommand() { @@ -48,7 +48,7 @@ public function getCommand() /** * Gets the input instance. * - * @return InputInterface An InputInterface instance + * @return InputInterface */ public function getInput() { @@ -58,7 +58,7 @@ public function getInput() /** * Gets the output instance. * - * @return OutputInterface An OutputInterface instance + * @return OutputInterface */ public function getOutput() { diff --git a/vendor/symfony/console/Event/ConsoleExceptionEvent.php b/vendor/symfony/console/Event/ConsoleExceptionEvent.php deleted file mode 100644 index 0adfaf9..0000000 --- a/vendor/symfony/console/Event/ConsoleExceptionEvent.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -@trigger_error(sprintf('The "%s" class is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ConsoleErrorEvent instead.', ConsoleExceptionEvent::class), E_USER_DEPRECATED); - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Allows to handle exception thrown in a command. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @deprecated since version 3.3, to be removed in 4.0. Use ConsoleErrorEvent instead. - */ -class ConsoleExceptionEvent extends ConsoleEvent -{ - private $exception; - private $exitCode; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode) - { - parent::__construct($command, $input, $output); - - $this->setException($exception); - $this->exitCode = (int) $exitCode; - } - - /** - * Returns the thrown exception. - * - * @return \Exception The thrown exception - */ - public function getException() - { - return $this->exception; - } - - /** - * Replaces the thrown exception. - * - * This exception will be thrown if no response is set in the event. - * - * @param \Exception $exception The thrown exception - */ - public function setException(\Exception $exception) - { - $this->exception = $exception; - } - - /** - * Gets the exit code. - * - * @return int The command exit code - */ - public function getExitCode() - { - return $this->exitCode; - } -} diff --git a/vendor/symfony/console/Event/ConsoleSignalEvent.php b/vendor/symfony/console/Event/ConsoleSignalEvent.php new file mode 100644 index 0000000..ef13ed2 --- /dev/null +++ b/vendor/symfony/console/Event/ConsoleSignalEvent.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author marie <marie@users.noreply.github.com> + */ +final class ConsoleSignalEvent extends ConsoleEvent +{ + private $handlingSignal; + + public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal) + { + parent::__construct($command, $input, $output); + $this->handlingSignal = $handlingSignal; + } + + public function getHandlingSignal(): int + { + return $this->handlingSignal; + } +} diff --git a/vendor/symfony/console/Event/ConsoleTerminateEvent.php b/vendor/symfony/console/Event/ConsoleTerminateEvent.php index b6a5d7c..190038d 100644 --- a/vendor/symfony/console/Event/ConsoleTerminateEvent.php +++ b/vendor/symfony/console/Event/ConsoleTerminateEvent.php @@ -20,38 +20,23 @@ * * @author Francesco Levorato <git@flevour.net> */ -class ConsoleTerminateEvent extends ConsoleEvent +final class ConsoleTerminateEvent extends ConsoleEvent { - /** - * The exit code of the command. - * - * @var int - */ private $exitCode; - public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode) + public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $exitCode) { parent::__construct($command, $input, $output); $this->setExitCode($exitCode); } - /** - * Sets the exit code. - * - * @param int $exitCode The command exit code - */ - public function setExitCode($exitCode) + public function setExitCode(int $exitCode): void { - $this->exitCode = (int) $exitCode; + $this->exitCode = $exitCode; } - /** - * Gets the exit code. - * - * @return int The command exit code - */ - public function getExitCode() + public function getExitCode(): int { return $this->exitCode; } diff --git a/vendor/symfony/console/EventListener/ErrorListener.php b/vendor/symfony/console/EventListener/ErrorListener.php index 909d6ea..897d985 100644 --- a/vendor/symfony/console/EventListener/ErrorListener.php +++ b/vendor/symfony/console/EventListener/ErrorListener.php @@ -40,10 +40,12 @@ public function onConsoleError(ConsoleErrorEvent $event) $error = $event->getError(); if (!$inputString = $this->getInputString($event)) { - return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('exception' => $error, 'message' => $error->getMessage())); + $this->logger->critical('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]); + + return; } - $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('exception' => $error, 'command' => $inputString, 'message' => $error->getMessage())); + $this->logger->critical('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]); } public function onConsoleTerminate(ConsoleTerminateEvent $event) @@ -59,28 +61,30 @@ public function onConsoleTerminate(ConsoleTerminateEvent $event) } if (!$inputString = $this->getInputString($event)) { - return $this->logger->debug('The console exited with code "{code}"', array('code' => $exitCode)); + $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]); + + return; } - $this->logger->debug('Command "{command}" exited with code "{code}"', array('command' => $inputString, 'code' => $exitCode)); + $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]); } public static function getSubscribedEvents() { - return array( - ConsoleEvents::ERROR => array('onConsoleError', -128), - ConsoleEvents::TERMINATE => array('onConsoleTerminate', -128), - ); + return [ + ConsoleEvents::ERROR => ['onConsoleError', -128], + ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128], + ]; } - private static function getInputString(ConsoleEvent $event) + private static function getInputString(ConsoleEvent $event): ?string { $commandName = $event->getCommand() ? $event->getCommand()->getName() : null; $input = $event->getInput(); if (method_exists($input, '__toString')) { if ($commandName) { - return str_replace(array("'$commandName'", "\"$commandName\""), $commandName, (string) $input); + return str_replace(["'$commandName'", "\"$commandName\""], $commandName, (string) $input); } return (string) $input; diff --git a/vendor/symfony/console/Exception/CommandNotFoundException.php b/vendor/symfony/console/Exception/CommandNotFoundException.php index cb7d113..910ae19 100644 --- a/vendor/symfony/console/Exception/CommandNotFoundException.php +++ b/vendor/symfony/console/Exception/CommandNotFoundException.php @@ -21,12 +21,12 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce private $alternatives; /** - * @param string $message Exception message to throw - * @param array $alternatives List of similar defined names - * @param int $code Exception code - * @param \Exception $previous Previous exception used for the exception chaining + * @param string $message Exception message to throw + * @param string[] $alternatives List of similar defined names + * @param int $code Exception code + * @param \Throwable|null $previous Previous exception used for the exception chaining */ - public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null) + public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null) { parent::__construct($message, $code, $previous); @@ -34,7 +34,7 @@ public function __construct($message, array $alternatives = array(), $code = 0, } /** - * @return array A list of similar defined names + * @return string[] */ public function getAlternatives() { diff --git a/vendor/symfony/console/Exception/ExceptionInterface.php b/vendor/symfony/console/Exception/ExceptionInterface.php index 491cc4c..1624e13 100644 --- a/vendor/symfony/console/Exception/ExceptionInterface.php +++ b/vendor/symfony/console/Exception/ExceptionInterface.php @@ -16,6 +16,6 @@ * * @author Jérôme Tamarelle <jerome@tamarelle.net> */ -interface ExceptionInterface +interface ExceptionInterface extends \Throwable { } diff --git a/vendor/symfony/console/Exception/InvalidOptionException.php b/vendor/symfony/console/Exception/InvalidOptionException.php index b2eec61..5cf6279 100644 --- a/vendor/symfony/console/Exception/InvalidOptionException.php +++ b/vendor/symfony/console/Exception/InvalidOptionException.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Console\Exception; /** - * Represents an incorrect option name typed in the console. + * Represents an incorrect option name or value typed in the console. * * @author Jérôme Tamarelle <jerome@tamarelle.net> */ diff --git a/vendor/symfony/console/Exception/MissingInputException.php b/vendor/symfony/console/Exception/MissingInputException.php new file mode 100644 index 0000000..04f02ad --- /dev/null +++ b/vendor/symfony/console/Exception/MissingInputException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * Represents failure to read input from stdin. + * + * @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com> + */ +class MissingInputException extends RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/console/Exception/NamespaceNotFoundException.php b/vendor/symfony/console/Exception/NamespaceNotFoundException.php new file mode 100644 index 0000000..dd16e45 --- /dev/null +++ b/vendor/symfony/console/Exception/NamespaceNotFoundException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * Represents an incorrect namespace typed in the console. + * + * @author Pierre du Plessis <pdples@gmail.com> + */ +class NamespaceNotFoundException extends CommandNotFoundException +{ +} diff --git a/vendor/symfony/console/Formatter/NullOutputFormatter.php b/vendor/symfony/console/Formatter/NullOutputFormatter.php new file mode 100644 index 0000000..d770e14 --- /dev/null +++ b/vendor/symfony/console/Formatter/NullOutputFormatter.php @@ -0,0 +1,69 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +/** + * @author Tien Xuan Vo <tien.xuan.vo@gmail.com> + */ +final class NullOutputFormatter implements OutputFormatterInterface +{ + private $style; + + /** + * {@inheritdoc} + */ + public function format(?string $message): ?string + { + return null; + } + + /** + * {@inheritdoc} + */ + public function getStyle(string $name): OutputFormatterStyleInterface + { + // to comply with the interface we must return a OutputFormatterStyleInterface + return $this->style ?? $this->style = new NullOutputFormatterStyle(); + } + + /** + * {@inheritdoc} + */ + public function hasStyle(string $name): bool + { + return false; + } + + /** + * {@inheritdoc} + */ + public function isDecorated(): bool + { + return false; + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated): void + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function setStyle(string $name, OutputFormatterStyleInterface $style): void + { + // do nothing + } +} diff --git a/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php b/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php new file mode 100644 index 0000000..9232510 --- /dev/null +++ b/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +/** + * @author Tien Xuan Vo <tien.xuan.vo@gmail.com> + */ +final class NullOutputFormatterStyle implements OutputFormatterStyleInterface +{ + /** + * {@inheritdoc} + */ + public function apply(string $text): string + { + return $text; + } + + /** + * {@inheritdoc} + */ + public function setBackground(string $color = null): void + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function setForeground(string $color = null): void + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function setOption(string $option): void + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function setOptions(array $options): void + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function unsetOption(string $option): void + { + // do nothing + } +} diff --git a/vendor/symfony/console/Formatter/OutputFormatter.php b/vendor/symfony/console/Formatter/OutputFormatter.php index 57b95eb..603e5dc 100644 --- a/vendor/symfony/console/Formatter/OutputFormatter.php +++ b/vendor/symfony/console/Formatter/OutputFormatter.php @@ -17,23 +17,30 @@ * Formatter class for console output. * * @author Konstantin Kudryashov <ever.zet@gmail.com> + * @author Roland Franssen <franssen.roland@gmail.com> */ -class OutputFormatter implements OutputFormatterInterface +class OutputFormatter implements WrappableOutputFormatterInterface { private $decorated; - private $styles = array(); + private $styles = []; private $styleStack; + public function __clone() + { + $this->styleStack = clone $this->styleStack; + foreach ($this->styles as $key => $value) { + $this->styles[$key] = clone $value; + } + } + /** - * Escapes "<" special char in given text. - * - * @param string $text Text to escape + * Escapes "<" and ">" special chars in given text. * - * @return string Escaped text + * @return string */ - public static function escape($text) + public static function escape(string $text) { - $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text); + $text = preg_replace('/([^\\\\]|^)([<>])/', '$1\\\\$2', $text); return self::escapeTrailingBackslash($text); } @@ -41,15 +48,11 @@ public static function escape($text) /** * Escapes trailing "\" in given text. * - * @param string $text Text to escape - * - * @return string Escaped text - * * @internal */ - public static function escapeTrailingBackslash($text) + public static function escapeTrailingBackslash(string $text): string { - if ('\\' === substr($text, -1)) { + if (str_ends_with($text, '\\')) { $len = \strlen($text); $text = rtrim($text, '\\'); $text = str_replace("\0", '', $text); @@ -62,12 +65,11 @@ public static function escapeTrailingBackslash($text) /** * Initializes console output formatter. * - * @param bool $decorated Whether this formatter should actually decorate strings - * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances + * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances */ - public function __construct($decorated = false, array $styles = array()) + public function __construct(bool $decorated = false, array $styles = []) { - $this->decorated = (bool) $decorated; + $this->decorated = $decorated; $this->setStyle('error', new OutputFormatterStyle('white', 'red')); $this->setStyle('info', new OutputFormatterStyle('green')); @@ -84,9 +86,9 @@ public function __construct($decorated = false, array $styles = array()) /** * {@inheritdoc} */ - public function setDecorated($decorated) + public function setDecorated(bool $decorated) { - $this->decorated = (bool) $decorated; + $this->decorated = $decorated; } /** @@ -100,7 +102,7 @@ public function isDecorated() /** * {@inheritdoc} */ - public function setStyle($name, OutputFormatterStyleInterface $style) + public function setStyle(string $name, OutputFormatterStyleInterface $style) { $this->styles[strtolower($name)] = $style; } @@ -108,7 +110,7 @@ public function setStyle($name, OutputFormatterStyleInterface $style) /** * {@inheritdoc} */ - public function hasStyle($name) + public function hasStyle(string $name) { return isset($this->styles[strtolower($name)]); } @@ -116,10 +118,10 @@ public function hasStyle($name) /** * {@inheritdoc} */ - public function getStyle($name) + public function getStyle(string $name) { if (!$this->hasStyle($name)) { - throw new InvalidArgumentException(sprintf('Undefined style: %s', $name)); + throw new InvalidArgumentException(sprintf('Undefined style: "%s".', $name)); } return $this->styles[strtolower($name)]; @@ -128,13 +130,26 @@ public function getStyle($name) /** * {@inheritdoc} */ - public function format($message) + public function format(?string $message) + { + return $this->formatAndWrap($message, 0); + } + + /** + * {@inheritdoc} + */ + public function formatAndWrap(?string $message, int $width) { - $message = (string) $message; + if (null === $message) { + return ''; + } + $offset = 0; $output = ''; - $tagRegex = '[a-z][a-z0-9,_=;-]*+'; - preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE); + $openTagRegex = '[a-z](?:[^\\\\<>]*+ | \\\\.)*'; + $closeTagRegex = '[a-z][^<>]*+'; + $currentLineLength = 0; + preg_match_all("#<(($openTagRegex) | /($closeTagRegex)?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE); foreach ($matches[0] as $i => $match) { $pos = $match[1]; $text = $match[0]; @@ -144,21 +159,21 @@ public function format($message) } // add the text up to the next tag - $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset)); + $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); $offset = $pos + \strlen($text); // opening tag? if ($open = '/' != $text[1]) { $tag = $matches[1][$i][0]; } else { - $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : ''; + $tag = $matches[3][$i][0] ?? ''; } if (!$open && !$tag) { // </> $this->styleStack->pop(); - } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) { - $output .= $this->applyCurrentStyle($text); + } elseif (null === $style = $this->createStyleFromString($tag)) { + $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength); } elseif ($open) { $this->styleStack->push($style); } else { @@ -166,13 +181,9 @@ public function format($message) } } - $output .= $this->applyCurrentStyle(substr($message, $offset)); + $output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength); - if (false !== strpos($output, "\0")) { - return strtr($output, array("\0" => '\\', '\\<' => '<')); - } - - return str_replace('\\<', '<', $output); + return strtr($output, ["\0" => '\\', '\\<' => '<', '\\>' => '>']); } /** @@ -185,43 +196,37 @@ public function getStyleStack() /** * Tries to create new style instance from string. - * - * @param string $string - * - * @return OutputFormatterStyle|false false if string is not format string */ - private function createStyleFromString($string) + private function createStyleFromString(string $string): ?OutputFormatterStyleInterface { if (isset($this->styles[$string])) { return $this->styles[$string]; } - if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, PREG_SET_ORDER)) { - return false; + if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, \PREG_SET_ORDER)) { + return null; } $style = new OutputFormatterStyle(); foreach ($matches as $match) { array_shift($match); + $match[0] = strtolower($match[0]); if ('fg' == $match[0]) { - $style->setForeground($match[1]); + $style->setForeground(strtolower($match[1])); } elseif ('bg' == $match[0]) { - $style->setBackground($match[1]); + $style->setBackground(strtolower($match[1])); + } elseif ('href' === $match[0]) { + $url = preg_replace('{\\\\([<>])}', '$1', $match[1]); + $style->setHref($url); } elseif ('options' === $match[0]) { - preg_match_all('([^,;]+)', $match[1], $options); + preg_match_all('([^,;]+)', strtolower($match[1]), $options); $options = array_shift($options); foreach ($options as $option) { - try { - $style->setOption($option); - } catch (\InvalidArgumentException $e) { - @trigger_error(sprintf('Unknown style options are deprecated since Symfony 3.2 and will be removed in 4.0. Exception "%s".', $e->getMessage()), E_USER_DEPRECATED); - - return false; - } + $style->setOption($option); } } else { - return false; + return null; } } @@ -230,13 +235,51 @@ private function createStyleFromString($string) /** * Applies current style from stack to text, if must be applied. - * - * @param string $text Input text - * - * @return string Styled text */ - private function applyCurrentStyle($text) + private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength): string { - return $this->isDecorated() && \strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text; + if ('' === $text) { + return ''; + } + + if (!$width) { + return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text; + } + + if (!$currentLineLength && '' !== $current) { + $text = ltrim($text); + } + + if ($currentLineLength) { + $prefix = substr($text, 0, $i = $width - $currentLineLength)."\n"; + $text = substr($text, $i); + } else { + $prefix = ''; + } + + preg_match('~(\\n)$~', $text, $matches); + $text = $prefix.preg_replace('~([^\\n]{'.$width.'})\\ *~', "\$1\n", $text); + $text = rtrim($text, "\n").($matches[1] ?? ''); + + if (!$currentLineLength && '' !== $current && "\n" !== substr($current, -1)) { + $text = "\n".$text; + } + + $lines = explode("\n", $text); + + foreach ($lines as $line) { + $currentLineLength += \strlen($line); + if ($width <= $currentLineLength) { + $currentLineLength = 0; + } + } + + if ($this->isDecorated()) { + foreach ($lines as $i => $line) { + $lines[$i] = $this->styleStack->getCurrent()->apply($line); + } + } + + return implode("\n", $lines); } } diff --git a/vendor/symfony/console/Formatter/OutputFormatterInterface.php b/vendor/symfony/console/Formatter/OutputFormatterInterface.php index 281e240..0b5f839 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterInterface.php +++ b/vendor/symfony/console/Formatter/OutputFormatterInterface.php @@ -20,52 +20,41 @@ interface OutputFormatterInterface { /** * Sets the decorated flag. - * - * @param bool $decorated Whether to decorate the messages or not */ - public function setDecorated($decorated); + public function setDecorated(bool $decorated); /** - * Gets the decorated flag. + * Whether the output will decorate messages. * - * @return bool true if the output will decorate messages, false otherwise + * @return bool */ public function isDecorated(); /** * Sets a new style. - * - * @param string $name The style name - * @param OutputFormatterStyleInterface $style The style instance */ - public function setStyle($name, OutputFormatterStyleInterface $style); + public function setStyle(string $name, OutputFormatterStyleInterface $style); /** * Checks if output formatter has style with specified name. * - * @param string $name - * * @return bool */ - public function hasStyle($name); + public function hasStyle(string $name); /** * Gets style options from style with specified name. * - * @param string $name - * * @return OutputFormatterStyleInterface * * @throws \InvalidArgumentException When style isn't defined */ - public function getStyle($name); + public function getStyle(string $name); /** * Formats a message according to the given styles. * - * @param string $message The message to style - * - * @return string The styled message + * @return string|null */ - public function format($message); + public function format(?string $message); } diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/vendor/symfony/console/Formatter/OutputFormatterStyle.php index 1f4e0ca..8370ba0 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyle.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyle.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Console\Formatter; -use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Color; /** * Formatter style class for defining styles. @@ -20,155 +20,65 @@ */ class OutputFormatterStyle implements OutputFormatterStyleInterface { - private static $availableForegroundColors = array( - 'black' => array('set' => 30, 'unset' => 39), - 'red' => array('set' => 31, 'unset' => 39), - 'green' => array('set' => 32, 'unset' => 39), - 'yellow' => array('set' => 33, 'unset' => 39), - 'blue' => array('set' => 34, 'unset' => 39), - 'magenta' => array('set' => 35, 'unset' => 39), - 'cyan' => array('set' => 36, 'unset' => 39), - 'white' => array('set' => 37, 'unset' => 39), - 'default' => array('set' => 39, 'unset' => 39), - ); - private static $availableBackgroundColors = array( - 'black' => array('set' => 40, 'unset' => 49), - 'red' => array('set' => 41, 'unset' => 49), - 'green' => array('set' => 42, 'unset' => 49), - 'yellow' => array('set' => 43, 'unset' => 49), - 'blue' => array('set' => 44, 'unset' => 49), - 'magenta' => array('set' => 45, 'unset' => 49), - 'cyan' => array('set' => 46, 'unset' => 49), - 'white' => array('set' => 47, 'unset' => 49), - 'default' => array('set' => 49, 'unset' => 49), - ); - private static $availableOptions = array( - 'bold' => array('set' => 1, 'unset' => 22), - 'underscore' => array('set' => 4, 'unset' => 24), - 'blink' => array('set' => 5, 'unset' => 25), - 'reverse' => array('set' => 7, 'unset' => 27), - 'conceal' => array('set' => 8, 'unset' => 28), - ); - + private $color; private $foreground; private $background; - private $options = array(); + private $options; + private $href; + private $handlesHrefGracefully; /** * Initializes output formatter style. * * @param string|null $foreground The style foreground color name * @param string|null $background The style background color name - * @param array $options The style options */ - public function __construct($foreground = null, $background = null, array $options = array()) + public function __construct(string $foreground = null, string $background = null, array $options = []) { - if (null !== $foreground) { - $this->setForeground($foreground); - } - if (null !== $background) { - $this->setBackground($background); - } - if (\count($options)) { - $this->setOptions($options); - } + $this->color = new Color($this->foreground = $foreground ?: '', $this->background = $background ?: '', $this->options = $options); } /** - * Sets style foreground color. - * - * @param string|null $color The color name - * - * @throws InvalidArgumentException When the color name isn't defined + * {@inheritdoc} */ - public function setForeground($color = null) + public function setForeground(string $color = null) { - if (null === $color) { - $this->foreground = null; - - return; - } - - if (!isset(static::$availableForegroundColors[$color])) { - throw new InvalidArgumentException(sprintf( - 'Invalid foreground color specified: "%s". Expected one of (%s)', - $color, - implode(', ', array_keys(static::$availableForegroundColors)) - )); - } - - $this->foreground = static::$availableForegroundColors[$color]; + $this->color = new Color($this->foreground = $color ?: '', $this->background, $this->options); } /** - * Sets style background color. - * - * @param string|null $color The color name - * - * @throws InvalidArgumentException When the color name isn't defined + * {@inheritdoc} */ - public function setBackground($color = null) + public function setBackground(string $color = null) { - if (null === $color) { - $this->background = null; - - return; - } - - if (!isset(static::$availableBackgroundColors[$color])) { - throw new InvalidArgumentException(sprintf( - 'Invalid background color specified: "%s". Expected one of (%s)', - $color, - implode(', ', array_keys(static::$availableBackgroundColors)) - )); - } + $this->color = new Color($this->foreground, $this->background = $color ?: '', $this->options); + } - $this->background = static::$availableBackgroundColors[$color]; + public function setHref(string $url): void + { + $this->href = $url; } /** - * Sets some specific style option. - * - * @param string $option The option name - * - * @throws InvalidArgumentException When the option name isn't defined + * {@inheritdoc} */ - public function setOption($option) + public function setOption(string $option) { - if (!isset(static::$availableOptions[$option])) { - throw new InvalidArgumentException(sprintf( - 'Invalid option specified: "%s". Expected one of (%s)', - $option, - implode(', ', array_keys(static::$availableOptions)) - )); - } - - if (!\in_array(static::$availableOptions[$option], $this->options)) { - $this->options[] = static::$availableOptions[$option]; - } + $this->options[] = $option; + $this->color = new Color($this->foreground, $this->background, $this->options); } /** - * Unsets some specific style option. - * - * @param string $option The option name - * - * @throws InvalidArgumentException When the option name isn't defined + * {@inheritdoc} */ - public function unsetOption($option) + public function unsetOption(string $option) { - if (!isset(static::$availableOptions[$option])) { - throw new InvalidArgumentException(sprintf( - 'Invalid option specified: "%s". Expected one of (%s)', - $option, - implode(', ', array_keys(static::$availableOptions)) - )); - } - - $pos = array_search(static::$availableOptions[$option], $this->options); + $pos = array_search($option, $this->options); if (false !== $pos) { unset($this->options[$pos]); } + + $this->color = new Color($this->foreground, $this->background, $this->options); } /** @@ -176,44 +86,24 @@ public function unsetOption($option) */ public function setOptions(array $options) { - $this->options = array(); - - foreach ($options as $option) { - $this->setOption($option); - } + $this->color = new Color($this->foreground, $this->background, $this->options = $options); } /** - * Applies the style to a given text. - * - * @param string $text The text to style - * - * @return string + * {@inheritdoc} */ - public function apply($text) + public function apply(string $text) { - $setCodes = array(); - $unsetCodes = array(); - - if (null !== $this->foreground) { - $setCodes[] = $this->foreground['set']; - $unsetCodes[] = $this->foreground['unset']; - } - if (null !== $this->background) { - $setCodes[] = $this->background['set']; - $unsetCodes[] = $this->background['unset']; - } - if (\count($this->options)) { - foreach ($this->options as $option) { - $setCodes[] = $option['set']; - $unsetCodes[] = $option['unset']; - } + if (null === $this->handlesHrefGracefully) { + $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') + && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100) + && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']); } - if (0 === \count($setCodes)) { - return $text; + if (null !== $this->href && $this->handlesHrefGracefully) { + $text = "\033]8;;$this->href\033\\$text\033]8;;\033\\"; } - return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes)); + return $this->color->apply($text); } } diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php index 4c7dc41..b30560d 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php @@ -20,31 +20,23 @@ interface OutputFormatterStyleInterface { /** * Sets style foreground color. - * - * @param string $color The color name */ - public function setForeground($color = null); + public function setForeground(string $color = null); /** * Sets style background color. - * - * @param string $color The color name */ - public function setBackground($color = null); + public function setBackground(string $color = null); /** * Sets some specific style option. - * - * @param string $option The option name */ - public function setOption($option); + public function setOption(string $option); /** * Unsets some specific style option. - * - * @param string $option The option name */ - public function unsetOption($option); + public function unsetOption(string $option); /** * Sets multiple style options at once. @@ -54,9 +46,7 @@ public function setOptions(array $options); /** * Applies the style to a given text. * - * @param string $text The text to style - * * @return string */ - public function apply($text); + public function apply(string $text); } diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php index 9e7283c..fc48dc0 100644 --- a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php +++ b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php @@ -12,11 +12,12 @@ namespace Symfony\Component\Console\Formatter; use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Contracts\Service\ResetInterface; /** * @author Jean-François Simon <contact@jfsimon.fr> */ -class OutputFormatterStyleStack +class OutputFormatterStyleStack implements ResetInterface { /** * @var OutputFormatterStyleInterface[] @@ -27,7 +28,7 @@ class OutputFormatterStyleStack public function __construct(OutputFormatterStyleInterface $emptyStyle = null) { - $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); + $this->emptyStyle = $emptyStyle ?? new OutputFormatterStyle(); $this->reset(); } @@ -36,7 +37,7 @@ public function __construct(OutputFormatterStyleInterface $emptyStyle = null) */ public function reset() { - $this->styles = array(); + $this->styles = []; } /** diff --git a/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php b/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php new file mode 100644 index 0000000..42319ee --- /dev/null +++ b/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +/** + * Formatter interface for console output that supports word wrapping. + * + * @author Roland Franssen <franssen.roland@gmail.com> + */ +interface WrappableOutputFormatterInterface extends OutputFormatterInterface +{ + /** + * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping). + */ + public function formatAndWrap(?string $message, int $width); +} diff --git a/vendor/symfony/console/Helper/DebugFormatterHelper.php b/vendor/symfony/console/Helper/DebugFormatterHelper.php index f5393ed..e258ba0 100644 --- a/vendor/symfony/console/Helper/DebugFormatterHelper.php +++ b/vendor/symfony/console/Helper/DebugFormatterHelper.php @@ -20,22 +20,18 @@ */ class DebugFormatterHelper extends Helper { - private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default'); - private $started = array(); + private const COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default']; + private $started = []; private $count = -1; /** * Starts a debug formatting session. * - * @param string $id The id of the formatting session - * @param string $message The message to display - * @param string $prefix The prefix to use - * * @return string */ - public function start($id, $message, $prefix = 'RUN') + public function start(string $id, string $message, string $prefix = 'RUN') { - $this->started[$id] = array('border' => ++$this->count % \count($this->colors)); + $this->started[$id] = ['border' => ++$this->count % \count(self::COLORS)]; return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message); } @@ -43,15 +39,9 @@ public function start($id, $message, $prefix = 'RUN') /** * Adds progress to a formatting session. * - * @param string $id The id of the formatting session - * @param string $buffer The message to display - * @param bool $error Whether to consider the buffer as error - * @param string $prefix The prefix for output - * @param string $errorPrefix The prefix for error output - * * @return string */ - public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR') + public function progress(string $id, string $buffer, bool $error = false, string $prefix = 'OUT', string $errorPrefix = 'ERR') { $message = ''; @@ -85,14 +75,9 @@ public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPr /** * Stops a formatting session. * - * @param string $id The id of the formatting session - * @param string $message The message to display - * @param bool $successful Whether to consider the result as success - * @param string $prefix The prefix for the end output - * * @return string */ - public function stop($id, $message, $successful, $prefix = 'RES') + public function stop(string $id, string $message, bool $successful, string $prefix = 'RES') { $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : ''; @@ -107,14 +92,9 @@ public function stop($id, $message, $successful, $prefix = 'RES') return $message; } - /** - * @param string $id The id of the formatting session - * - * @return string - */ - private function getBorder($id) + private function getBorder(string $id): string { - return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]); + return sprintf('<bg=%s> </>', self::COLORS[$this->started[$id]['border']]); } /** diff --git a/vendor/symfony/console/Helper/DescriptorHelper.php b/vendor/symfony/console/Helper/DescriptorHelper.php index 54d3b1a..af85e9c 100644 --- a/vendor/symfony/console/Helper/DescriptorHelper.php +++ b/vendor/symfony/console/Helper/DescriptorHelper.php @@ -29,7 +29,7 @@ class DescriptorHelper extends Helper /** * @var DescriptorInterface[] */ - private $descriptors = array(); + private $descriptors = []; public function __construct() { @@ -48,18 +48,14 @@ public function __construct() * * format: string, the output format name * * raw_text: boolean, sets output type as raw * - * @param OutputInterface $output - * @param object $object - * @param array $options - * * @throws InvalidArgumentException when the given format is not supported */ - public function describe(OutputInterface $output, $object, array $options = array()) + public function describe(OutputInterface $output, ?object $object, array $options = []) { - $options = array_merge(array( + $options = array_merge([ 'raw_text' => false, 'format' => 'txt', - ), $options); + ], $options); if (!isset($this->descriptors[$options['format']])) { throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); @@ -72,12 +68,9 @@ public function describe(OutputInterface $output, $object, array $options = arra /** * Registers a descriptor. * - * @param string $format - * @param DescriptorInterface $descriptor - * * @return $this */ - public function register($format, DescriptorInterface $descriptor) + public function register(string $format, DescriptorInterface $descriptor) { $this->descriptors[$format] = $descriptor; @@ -91,4 +84,9 @@ public function getName() { return 'descriptor'; } + + public function getFormats(): array + { + return array_keys($this->descriptors); + } } diff --git a/vendor/symfony/console/Helper/Dumper.php b/vendor/symfony/console/Helper/Dumper.php new file mode 100644 index 0000000..b013b6c --- /dev/null +++ b/vendor/symfony/console/Helper/Dumper.php @@ -0,0 +1,64 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\VarDumper\Cloner\ClonerInterface; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; + +/** + * @author Roland Franssen <franssen.roland@gmail.com> + */ +final class Dumper +{ + private $output; + private $dumper; + private $cloner; + private $handler; + + public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null) + { + $this->output = $output; + $this->dumper = $dumper; + $this->cloner = $cloner; + + if (class_exists(CliDumper::class)) { + $this->handler = function ($var): string { + $dumper = $this->dumper ?? $this->dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR); + $dumper->setColors($this->output->isDecorated()); + + return rtrim($dumper->dump(($this->cloner ?? $this->cloner = new VarCloner())->cloneVar($var)->withRefHandles(false), true)); + }; + } else { + $this->handler = function ($var): string { + switch (true) { + case null === $var: + return 'null'; + case true === $var: + return 'true'; + case false === $var: + return 'false'; + case \is_string($var): + return '"'.$var.'"'; + default: + return rtrim(print_r($var, true)); + } + }; + } + } + + public function __invoke($var): string + { + return ($this->handler)($var); + } +} diff --git a/vendor/symfony/console/Helper/FormatterHelper.php b/vendor/symfony/console/Helper/FormatterHelper.php index 79ab284..92d8dc7 100644 --- a/vendor/symfony/console/Helper/FormatterHelper.php +++ b/vendor/symfony/console/Helper/FormatterHelper.php @@ -23,13 +23,9 @@ class FormatterHelper extends Helper /** * Formats a message within a section. * - * @param string $section The section name - * @param string $message The message - * @param string $style The style to apply to the section - * - * @return string The format section + * @return string */ - public function formatSection($section, $message, $style = 'info') + public function formatSection(string $section, string $message, string $style = 'info') { return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message); } @@ -38,28 +34,26 @@ public function formatSection($section, $message, $style = 'info') * Formats a message as a block of text. * * @param string|array $messages The message to write in the block - * @param string $style The style to apply to the whole block - * @param bool $large Whether to return a large block * - * @return string The formatter message + * @return string */ - public function formatBlock($messages, $style, $large = false) + public function formatBlock($messages, string $style, bool $large = false) { if (!\is_array($messages)) { - $messages = array($messages); + $messages = [$messages]; } $len = 0; - $lines = array(); + $lines = []; foreach ($messages as $message) { $message = OutputFormatter::escape($message); $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); - $len = max($this->strlen($message) + ($large ? 4 : 2), $len); + $len = max(self::width($message) + ($large ? 4 : 2), $len); } - $messages = $large ? array(str_repeat(' ', $len)) : array(); + $messages = $large ? [str_repeat(' ', $len)] : []; for ($i = 0; isset($lines[$i]); ++$i) { - $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i])); + $messages[] = $lines[$i].str_repeat(' ', $len - self::width($lines[$i])); } if ($large) { $messages[] = str_repeat(' ', $len); @@ -75,25 +69,17 @@ public function formatBlock($messages, $style, $large = false) /** * Truncates a message to the given length. * - * @param string $message - * @param int $length - * @param string $suffix - * * @return string */ - public function truncate($message, $length, $suffix = '...') + public function truncate(string $message, int $length, string $suffix = '...') { - $computedLength = $length - $this->strlen($suffix); + $computedLength = $length - self::width($suffix); - if ($computedLength > $this->strlen($message)) { + if ($computedLength > self::width($message)) { return $message; } - if (false === $encoding = mb_detect_encoding($message, null, true)) { - return substr($message, 0, $length).$suffix; - } - - return mb_substr($message, 0, $length, $encoding).$suffix; + return self::substr($message, 0, $length).$suffix; } /** diff --git a/vendor/symfony/console/Helper/Helper.php b/vendor/symfony/console/Helper/Helper.php index 5090185..c7d3e25 100644 --- a/vendor/symfony/console/Helper/Helper.php +++ b/vendor/symfony/console/Helper/Helper.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Formatter\OutputFormatterInterface; +use Symfony\Component\String\UnicodeString; /** * Helper is the base class for all helper classes. @@ -41,12 +42,29 @@ public function getHelperSet() /** * Returns the length of a string, using mb_strwidth if it is available. * - * @param string $string The string to check its length + * @deprecated since Symfony 5.3 * - * @return int The length of the string + * @return int */ - public static function strlen($string) + public static function strlen(?string $string) { + trigger_deprecation('symfony/console', '5.3', 'Method "%s()" is deprecated and will be removed in Symfony 6.0. Use Helper::width() or Helper::length() instead.', __METHOD__); + + return self::width($string); + } + + /** + * Returns the width of a string, using mb_strwidth if it is available. + * The width is how many characters positions the string will use. + */ + public static function width(?string $string): int + { + $string ?? $string = ''; + + if (preg_match('//u', $string)) { + return (new UnicodeString($string))->width(false); + } + if (false === $encoding = mb_detect_encoding($string, null, true)) { return \strlen($string); } @@ -54,17 +72,34 @@ public static function strlen($string) return mb_strwidth($string, $encoding); } + /** + * Returns the length of a string, using mb_strlen if it is available. + * The length is related to how many bytes the string will use. + */ + public static function length(?string $string): int + { + $string ?? $string = ''; + + if (preg_match('//u', $string)) { + return (new UnicodeString($string))->length(); + } + + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return \strlen($string); + } + + return mb_strlen($string, $encoding); + } + /** * Returns the subset of a string, using mb_substr if it is available. * - * @param string $string String to subset - * @param int $from Start offset - * @param int|null $length Length to read - * - * @return string The string subset + * @return string */ - public static function substr($string, $from, $length = null) + public static function substr(?string $string, int $from, int $length = null) { + $string ?? $string = ''; + if (false === $encoding = mb_detect_encoding($string, null, true)) { return substr($string, $from, $length); } @@ -74,17 +109,17 @@ public static function substr($string, $from, $length = null) public static function formatTime($secs) { - static $timeFormats = array( - array(0, '< 1 sec'), - array(1, '1 sec'), - array(2, 'secs', 1), - array(60, '1 min'), - array(120, 'mins', 60), - array(3600, '1 hr'), - array(7200, 'hrs', 3600), - array(86400, '1 day'), - array(172800, 'days', 86400), - ); + static $timeFormats = [ + [0, '< 1 sec'], + [1, '1 sec'], + [2, 'secs', 1], + [60, '1 min'], + [120, 'mins', 60], + [3600, '1 hr'], + [7200, 'hrs', 3600], + [86400, '1 day'], + [172800, 'days', 86400], + ]; foreach ($timeFormats as $index => $format) { if ($secs >= $format[0]) { @@ -101,7 +136,7 @@ public static function formatTime($secs) } } - public static function formatMemory($memory) + public static function formatMemory(int $memory) { if ($memory >= 1024 * 1024 * 1024) { return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024); @@ -118,19 +153,26 @@ public static function formatMemory($memory) return sprintf('%d B', $memory); } - public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string) + /** + * @deprecated since Symfony 5.3 + */ + public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, ?string $string) { - return self::strlen(self::removeDecoration($formatter, $string)); + trigger_deprecation('symfony/console', '5.3', 'Method "%s()" is deprecated and will be removed in Symfony 6.0. Use Helper::removeDecoration() instead.', __METHOD__); + + return self::width(self::removeDecoration($formatter, $string)); } - public static function removeDecoration(OutputFormatterInterface $formatter, $string) + public static function removeDecoration(OutputFormatterInterface $formatter, ?string $string) { $isDecorated = $formatter->isDecorated(); $formatter->setDecorated(false); // remove <...> formatting - $string = $formatter->format($string); + $string = $formatter->format($string ?? ''); // remove already formatted characters - $string = preg_replace("/\033\[[^m]*m/", '', $string); + $string = preg_replace("/\033\[[^m]*m/", '', $string ?? ''); + // remove terminal hyperlinks + $string = preg_replace('/\\033]8;[^;]*;[^\\033]*\\033\\\\/', '', $string ?? ''); $formatter->setDecorated($isDecorated); return $string; diff --git a/vendor/symfony/console/Helper/HelperInterface.php b/vendor/symfony/console/Helper/HelperInterface.php index 1ce8235..fc952b4 100644 --- a/vendor/symfony/console/Helper/HelperInterface.php +++ b/vendor/symfony/console/Helper/HelperInterface.php @@ -26,14 +26,14 @@ public function setHelperSet(HelperSet $helperSet = null); /** * Gets the helper set associated with this helper. * - * @return HelperSet A HelperSet instance + * @return HelperSet|null */ public function getHelperSet(); /** * Returns the canonical name of this helper. * - * @return string The canonical name + * @return string */ public function getName(); } diff --git a/vendor/symfony/console/Helper/HelperSet.php b/vendor/symfony/console/Helper/HelperSet.php index 4c44b05..719762d 100644 --- a/vendor/symfony/console/Helper/HelperSet.php +++ b/vendor/symfony/console/Helper/HelperSet.php @@ -18,32 +18,26 @@ * HelperSet represents a set of helpers to be used with a command. * * @author Fabien Potencier <fabien@symfony.com> + * + * @implements \IteratorAggregate<string, Helper> */ class HelperSet implements \IteratorAggregate { - /** - * @var Helper[] - */ - private $helpers = array(); + /** @var array<string, Helper> */ + private $helpers = []; private $command; /** * @param Helper[] $helpers An array of helper */ - public function __construct(array $helpers = array()) + public function __construct(array $helpers = []) { foreach ($helpers as $alias => $helper) { $this->set($helper, \is_int($alias) ? null : $alias); } } - /** - * Sets a helper. - * - * @param HelperInterface $helper The helper instance - * @param string $alias An alias - */ - public function set(HelperInterface $helper, $alias = null) + public function set(HelperInterface $helper, string $alias = null) { $this->helpers[$helper->getName()] = $helper; if (null !== $alias) { @@ -56,11 +50,9 @@ public function set(HelperInterface $helper, $alias = null) /** * Returns true if the helper if defined. * - * @param string $name The helper name - * - * @return bool true if the helper is defined, false otherwise + * @return bool */ - public function has($name) + public function has(string $name) { return isset($this->helpers[$name]); } @@ -68,13 +60,11 @@ public function has($name) /** * Gets a helper value. * - * @param string $name The helper name - * - * @return HelperInterface The helper instance + * @return HelperInterface * * @throws InvalidArgumentException if the helper is not defined */ - public function get($name) + public function get(string $name) { if (!$this->has($name)) { throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); @@ -83,24 +73,34 @@ public function get($name) return $this->helpers[$name]; } + /** + * @deprecated since Symfony 5.4 + */ public function setCommand(Command $command = null) { + trigger_deprecation('symfony/console', '5.4', 'Method "%s()" is deprecated.', __METHOD__); + $this->command = $command; } /** * Gets the command associated with this helper set. * - * @return Command A Command instance + * @return Command + * + * @deprecated since Symfony 5.4 */ public function getCommand() { + trigger_deprecation('symfony/console', '5.4', 'Method "%s()" is deprecated.', __METHOD__); + return $this->command; } /** - * @return Helper[] + * @return \Traversable<string, Helper> */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->helpers); diff --git a/vendor/symfony/console/Helper/ProcessHelper.php b/vendor/symfony/console/Helper/ProcessHelper.php index 666f114..4ea3d72 100644 --- a/vendor/symfony/console/Helper/ProcessHelper.php +++ b/vendor/symfony/console/Helper/ProcessHelper.php @@ -20,23 +20,24 @@ * The ProcessHelper class provides helpers to run external processes. * * @author Fabien Potencier <fabien@symfony.com> + * + * @final */ class ProcessHelper extends Helper { /** * Runs an external process. * - * @param OutputInterface $output An OutputInterface instance - * @param string|array|Process $cmd An instance of Process or an array of arguments to escape and run or a command to run - * @param string|null $error An error message that must be displayed if something went wrong - * @param callable|null $callback A PHP callback to run whenever there is some - * output available on STDOUT or STDERR - * @param int $verbosity The threshold for verbosity - * - * @return Process The process that ran + * @param array|Process $cmd An instance of Process or an array of the command and arguments + * @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, $error = null, callable $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE) + 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".'); + } + if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); } @@ -44,9 +45,21 @@ public function run(OutputInterface $output, $cmd, $error = null, callable $call $formatter = $this->getHelperSet()->get('debug_formatter'); if ($cmd instanceof Process) { - $process = $cmd; - } else { + $cmd = [$cmd]; + } + + if (!\is_array($cmd)) { + throw new \TypeError(sprintf('The "command" argument of "%s()" must be an array or a "%s" instance, "%s" given.', __METHOD__, Process::class, get_debug_type($cmd))); + } + + if (\is_string($cmd[0] ?? null)) { $process = new Process($cmd); + $cmd = []; + } elseif (($cmd[0] ?? null) instanceof Process) { + $process = $cmd[0]; + unset($cmd[0]); + } else { + throw new \InvalidArgumentException(sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__)); } if ($verbosity <= $output->getVerbosity()) { @@ -57,7 +70,7 @@ public function run(OutputInterface $output, $cmd, $error = null, callable $call $callback = $this->wrapCallback($output, $process, $callback); } - $process->run($callback); + $process->run($callback, $cmd); if ($verbosity <= $output->getVerbosity()) { $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode()); @@ -77,19 +90,15 @@ public function run(OutputInterface $output, $cmd, $error = null, callable $call * This is identical to run() except that an exception is thrown if the process * exits with a non-zero exit code. * - * @param OutputInterface $output An OutputInterface instance - * @param string|Process $cmd An instance of Process or a command to run - * @param string|null $error An error message that must be displayed if something went wrong - * @param callable|null $callback A PHP callback to run whenever there is some - * output available on STDOUT or STDERR - * - * @return Process The process that ran + * @param array|Process $cmd An instance of Process or a command to run + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR * * @throws ProcessFailedException * * @see run() */ - public function mustRun(OutputInterface $output, $cmd, $error = null, callable $callback = null) + public function mustRun(OutputInterface $output, $cmd, string $error = null, callable $callback = null): Process { $process = $this->run($output, $cmd, $error, $callback); @@ -102,14 +111,8 @@ public function mustRun(OutputInterface $output, $cmd, $error = null, callable $ /** * Wraps a Process callback to add debugging output. - * - * @param OutputInterface $output An OutputInterface interface - * @param Process $process The Process - * @param callable|null $callback A PHP callable - * - * @return callable */ - public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null) + public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null): callable { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); @@ -121,12 +124,12 @@ public function wrapCallback(OutputInterface $output, Process $process, callable $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type)); if (null !== $callback) { - \call_user_func($callback, $type, $buffer); + $callback($type, $buffer); } }; } - private function escapeString($str) + private function escapeString(string $str): string { return str_replace('<', '\\<', $str); } @@ -134,7 +137,7 @@ private function escapeString($str) /** * {@inheritdoc} */ - public function getName() + public function getName(): string { return 'process'; } diff --git a/vendor/symfony/console/Helper/ProgressBar.php b/vendor/symfony/console/Helper/ProgressBar.php index bea03e3..eb6aacb 100644 --- a/vendor/symfony/console/Helper/ProgressBar.php +++ b/vendor/symfony/console/Helper/ProgressBar.php @@ -11,8 +11,10 @@ namespace Symfony\Component\Console\Helper; +use Symfony\Component\Console\Cursor; use Symfony\Component\Console\Exception\LogicException; use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Terminal; @@ -24,6 +26,16 @@ */ final class ProgressBar { + public const FORMAT_VERBOSE = 'verbose'; + public const FORMAT_VERY_VERBOSE = 'very_verbose'; + public const FORMAT_DEBUG = 'debug'; + public const FORMAT_NORMAL = 'normal'; + + private const FORMAT_VERBOSE_NOMAX = 'verbose_nomax'; + private const FORMAT_VERY_VERBOSE_NOMAX = 'very_verbose_nomax'; + private const FORMAT_DEBUG_NOMAX = 'debug_nomax'; + private const FORMAT_NORMAL_NOMAX = 'normal_nomax'; + private $barWidth = 28; private $barChar; private $emptyBarChar = '-'; @@ -31,26 +43,29 @@ final class ProgressBar private $format; private $internalFormat; private $redrawFreq = 1; + private $writeCount; + private $lastWriteTime; + private $minSecondsBetweenRedraws = 0; + private $maxSecondsBetweenRedraws = 1; private $output; private $step = 0; private $max; private $startTime; private $stepWidth; private $percent = 0.0; - private $formatLineCount; - private $messages = array(); + private $messages = []; private $overwrite = true; private $terminal; - private $firstRun = true; + private $previousMessage; + private $cursor; private static $formatters; private static $formats; /** - * @param OutputInterface $output An OutputInterface instance - * @param int $max Maximum steps (0 if unknown) + * @param int $max Maximum steps (0 if unknown) */ - public function __construct(OutputInterface $output, $max = 0) + public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 1 / 25) { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); @@ -60,15 +75,21 @@ public function __construct(OutputInterface $output, $max = 0) $this->setMaxSteps($max); $this->terminal = new Terminal(); + if (0 < $minSecondsBetweenRedraws) { + $this->redrawFreq = null; + $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws; + } + if (!$this->output->isDecorated()) { // disable overwrite when output does not support ANSI codes. $this->overwrite = false; // set a reasonable redraw frequency so output isn't flooded - $this->setRedrawFrequency($max / 10); + $this->redrawFreq = null; } $this->startTime = time(); + $this->cursor = new Cursor($output); } /** @@ -79,7 +100,7 @@ public function __construct(OutputInterface $output, $max = 0) * @param string $name The placeholder name (including the delimiter char like %) * @param callable $callable A PHP callable */ - public static function setPlaceholderFormatterDefinition($name, callable $callable) + public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); @@ -92,16 +113,14 @@ public static function setPlaceholderFormatterDefinition($name, callable $callab * Gets the placeholder formatter for a given name. * * @param string $name The placeholder name (including the delimiter char like %) - * - * @return callable|null A PHP callable */ - public static function getPlaceholderFormatterDefinition($name) + public static function getPlaceholderFormatterDefinition(string $name): ?callable { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } - return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; + return self::$formatters[$name] ?? null; } /** @@ -112,7 +131,7 @@ public static function getPlaceholderFormatterDefinition($name) * @param string $name The format name * @param string $format A format string */ - public static function setFormatDefinition($name, $format) + public static function setFormatDefinition(string $name, string $format): void { if (!self::$formats) { self::$formats = self::initFormats(); @@ -125,16 +144,14 @@ public static function setFormatDefinition($name, $format) * Gets the format for a given name. * * @param string $name The format name - * - * @return string|null A format string */ - public static function getFormatDefinition($name) + public static function getFormatDefinition(string $name): ?string { if (!self::$formats) { self::$formats = self::initFormats(); } - return isset(self::$formats[$name]) ? self::$formats[$name] : null; + return self::$formats[$name] ?? null; } /** @@ -147,156 +164,105 @@ public static function getFormatDefinition($name) * @param string $message The text to associate with the placeholder * @param string $name The name of the placeholder */ - public function setMessage($message, $name = 'message') + public function setMessage(string $message, string $name = 'message') { $this->messages[$name] = $message; } - public function getMessage($name = 'message') + public function getMessage(string $name = 'message') { return $this->messages[$name]; } - /** - * Gets the progress bar start time. - * - * @return int The progress bar start time - */ - public function getStartTime() + public function getStartTime(): int { return $this->startTime; } - /** - * Gets the progress bar maximal steps. - * - * @return int The progress bar max steps - */ - public function getMaxSteps() + public function getMaxSteps(): int { return $this->max; } - /** - * Gets the current step position. - * - * @return int The progress bar step - */ - public function getProgress() + public function getProgress(): int { return $this->step; } - /** - * Gets the progress bar step width. - * - * @return int The progress bar step width - */ - private function getStepWidth() + private function getStepWidth(): int { return $this->stepWidth; } - /** - * Gets the current progress bar percent. - * - * @return float The current progress bar percent - */ - public function getProgressPercent() + public function getProgressPercent(): float { return $this->percent; } - /** - * Sets the progress bar width. - * - * @param int $size The progress bar size - */ - public function setBarWidth($size) + public function getBarOffset(): float { - $this->barWidth = max(1, (int) $size); + return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth); } - /** - * Gets the progress bar width. - * - * @return int The progress bar size - */ - public function getBarWidth() + public function getEstimated(): float + { + if (!$this->step) { + return 0; + } + + return round((time() - $this->startTime) / $this->step * $this->max); + } + + public function getRemaining(): float + { + if (!$this->step) { + return 0; + } + + return round((time() - $this->startTime) / $this->step * ($this->max - $this->step)); + } + + public function setBarWidth(int $size) + { + $this->barWidth = max(1, $size); + } + + public function getBarWidth(): int { return $this->barWidth; } - /** - * Sets the bar character. - * - * @param string $char A character - */ - public function setBarCharacter($char) + public function setBarCharacter(string $char) { $this->barChar = $char; } - /** - * Gets the bar character. - * - * @return string A character - */ - public function getBarCharacter() + public function getBarCharacter(): string { - if (null === $this->barChar) { - return $this->max ? '=' : $this->emptyBarChar; - } - - return $this->barChar; + return $this->barChar ?? ($this->max ? '=' : $this->emptyBarChar); } - /** - * Sets the empty bar character. - * - * @param string $char A character - */ - public function setEmptyBarCharacter($char) + public function setEmptyBarCharacter(string $char) { $this->emptyBarChar = $char; } - /** - * Gets the empty bar character. - * - * @return string A character - */ - public function getEmptyBarCharacter() + public function getEmptyBarCharacter(): string { return $this->emptyBarChar; } - /** - * Sets the progress bar character. - * - * @param string $char A character - */ - public function setProgressCharacter($char) + public function setProgressCharacter(string $char) { $this->progressChar = $char; } - /** - * Gets the progress bar character. - * - * @return string A character - */ - public function getProgressCharacter() + public function getProgressCharacter(): string { return $this->progressChar; } - /** - * Sets the progress bar format. - * - * @param string $format The format - */ - public function setFormat($format) + public function setFormat(string $format) { $this->format = null; $this->internalFormat = $format; @@ -305,11 +271,39 @@ public function setFormat($format) /** * Sets the redraw frequency. * - * @param int|float $freq The frequency in steps + * @param int|null $freq The frequency in steps */ - public function setRedrawFrequency($freq) + public function setRedrawFrequency(?int $freq) + { + $this->redrawFreq = null !== $freq ? max(1, $freq) : null; + } + + public function minSecondsBetweenRedraws(float $seconds): void + { + $this->minSecondsBetweenRedraws = $seconds; + } + + public function maxSecondsBetweenRedraws(float $seconds): void { - $this->redrawFreq = max((int) $freq, 1); + $this->maxSecondsBetweenRedraws = $seconds; + } + + /** + * Returns an iterator that will automatically update the progress bar when iterated. + * + * @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 + { + $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0)); + + foreach ($iterable as $key => $value) { + yield $key => $value; + + $this->advance(); + } + + $this->finish(); } /** @@ -317,7 +311,7 @@ public function setRedrawFrequency($freq) * * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged */ - public function start($max = null) + public function start(int $max = null) { $this->startTime = time(); $this->step = 0; @@ -335,49 +329,63 @@ public function start($max = null) * * @param int $step Number of steps to advance */ - public function advance($step = 1) + public function advance(int $step = 1) { $this->setProgress($this->step + $step); } /** * Sets whether to overwrite the progressbar, false for new line. - * - * @param bool $overwrite */ - public function setOverwrite($overwrite) + public function setOverwrite(bool $overwrite) { - $this->overwrite = (bool) $overwrite; + $this->overwrite = $overwrite; } - /** - * Sets the current progress. - * - * @param int $step The current progress - */ - public function setProgress($step) + public function setProgress(int $step) { - $step = (int) $step; - if ($this->max && $step > $this->max) { $this->max = $step; } elseif ($step < 0) { $step = 0; } - $prevPeriod = (int) ($this->step / $this->redrawFreq); - $currPeriod = (int) ($step / $this->redrawFreq); + $redrawFreq = $this->redrawFreq ?? (($this->max ?: 10) / 10); + $prevPeriod = (int) ($this->step / $redrawFreq); + $currPeriod = (int) ($step / $redrawFreq); $this->step = $step; $this->percent = $this->max ? (float) $this->step / $this->max : 0; - if ($prevPeriod !== $currPeriod || $this->max === $step) { + $timeInterval = microtime(true) - $this->lastWriteTime; + + // Draw regardless of other limits + if ($this->max === $step) { + $this->display(); + + return; + } + + // Throttling + if ($timeInterval < $this->minSecondsBetweenRedraws) { + return; + } + + // Draw each step period, but not too late + if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) { $this->display(); } } + public function setMaxSteps(int $max) + { + $this->format = null; + $this->max = max(0, $max); + $this->stepWidth = $this->max ? Helper::width((string) $this->max) : 4; + } + /** * Finishes the progress output. */ - public function finish() + public function finish(): void { if (!$this->max) { $this->max = $this->step; @@ -394,7 +402,7 @@ public function finish() /** * Outputs the current progress string. */ - public function display() + public function display(): void { if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { return; @@ -414,7 +422,7 @@ public function display() * while a progress bar is running. * Call display() to show the progress bar again. */ - public function clear() + public function clear(): void { if (!$this->overwrite) { return; @@ -427,12 +435,7 @@ public function clear() $this->overwrite(''); } - /** - * Sets the progress bar format. - * - * @param string $format The format - */ - private function setRealFormat($format) + private function setRealFormat(string $format) { // try to use the _nomax variant if available if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) { @@ -442,148 +445,137 @@ private function setRealFormat($format) } else { $this->format = $format; } - - $this->formatLineCount = substr_count($this->format, "\n"); - } - - /** - * Sets the progress bar maximal steps. - * - * @param int $max The progress bar max steps - */ - private function setMaxSteps($max) - { - $this->max = max(0, (int) $max); - $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4; } /** * Overwrites a previous message to the output. - * - * @param string $message The message */ - private function overwrite($message) + private function overwrite(string $message): void { - if ($this->overwrite) { - if (!$this->firstRun) { - // Move the cursor to the beginning of the line - $this->output->write("\x0D"); + if ($this->previousMessage === $message) { + return; + } - // Erase the line - $this->output->write("\x1B[2K"); + $originalMessage = $message; - // Erase previous lines - if ($this->formatLineCount > 0) { - $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount)); + if ($this->overwrite) { + if (null !== $this->previousMessage) { + if ($this->output instanceof ConsoleSectionOutput) { + $messageLines = explode("\n", $this->previousMessage); + $lineCount = \count($messageLines); + foreach ($messageLines as $messageLine) { + $messageLineLength = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $messageLine)); + if ($messageLineLength > $this->terminal->getWidth()) { + $lineCount += floor($messageLineLength / $this->terminal->getWidth()); + } + } + $this->output->clear($lineCount); + } else { + $lineCount = substr_count($this->previousMessage, "\n"); + for ($i = 0; $i < $lineCount; ++$i) { + $this->cursor->moveToColumn(1); + $this->cursor->clearLine(); + $this->cursor->moveUp(); + } + + $this->cursor->moveToColumn(1); + $this->cursor->clearLine(); } } } elseif ($this->step > 0) { - $this->output->writeln(''); + $message = \PHP_EOL.$message; } - $this->firstRun = false; + $this->previousMessage = $originalMessage; + $this->lastWriteTime = microtime(true); $this->output->write($message); + ++$this->writeCount; } - private function determineBestFormat() + private function determineBestFormat(): string { switch ($this->output->getVerbosity()) { // OutputInterface::VERBOSITY_QUIET: display is disabled anyway case OutputInterface::VERBOSITY_VERBOSE: - return $this->max ? 'verbose' : 'verbose_nomax'; + return $this->max ? self::FORMAT_VERBOSE : self::FORMAT_VERBOSE_NOMAX; case OutputInterface::VERBOSITY_VERY_VERBOSE: - return $this->max ? 'very_verbose' : 'very_verbose_nomax'; + return $this->max ? self::FORMAT_VERY_VERBOSE : self::FORMAT_VERY_VERBOSE_NOMAX; case OutputInterface::VERBOSITY_DEBUG: - return $this->max ? 'debug' : 'debug_nomax'; + return $this->max ? self::FORMAT_DEBUG : self::FORMAT_DEBUG_NOMAX; default: - return $this->max ? 'normal' : 'normal_nomax'; + return $this->max ? self::FORMAT_NORMAL : self::FORMAT_NORMAL_NOMAX; } } - private static function initPlaceholderFormatters() + private static function initPlaceholderFormatters(): array { - return array( - 'bar' => function (ProgressBar $bar, OutputInterface $output) { - $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth()); + return [ + 'bar' => function (self $bar, OutputInterface $output) { + $completeBars = $bar->getBarOffset(); $display = str_repeat($bar->getBarCharacter(), $completeBars); if ($completeBars < $bar->getBarWidth()) { - $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter()); + $emptyBars = $bar->getBarWidth() - $completeBars - Helper::length(Helper::removeDecoration($output->getFormatter(), $bar->getProgressCharacter())); $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars); } return $display; }, - 'elapsed' => function (ProgressBar $bar) { + 'elapsed' => function (self $bar) { return Helper::formatTime(time() - $bar->getStartTime()); }, - 'remaining' => function (ProgressBar $bar) { + 'remaining' => function (self $bar) { if (!$bar->getMaxSteps()) { throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); } - if (!$bar->getProgress()) { - $remaining = 0; - } else { - $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress())); - } - - return Helper::formatTime($remaining); + return Helper::formatTime($bar->getRemaining()); }, - 'estimated' => function (ProgressBar $bar) { + 'estimated' => function (self $bar) { if (!$bar->getMaxSteps()) { throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); } - if (!$bar->getProgress()) { - $estimated = 0; - } else { - $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps()); - } - - return Helper::formatTime($estimated); + return Helper::formatTime($bar->getEstimated()); }, - 'memory' => function (ProgressBar $bar) { + 'memory' => function (self $bar) { return Helper::formatMemory(memory_get_usage(true)); }, - 'current' => function (ProgressBar $bar) { - return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT); + 'current' => function (self $bar) { + return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT); }, - 'max' => function (ProgressBar $bar) { + 'max' => function (self $bar) { return $bar->getMaxSteps(); }, - 'percent' => function (ProgressBar $bar) { + 'percent' => function (self $bar) { return floor($bar->getProgressPercent() * 100); }, - ); + ]; } - private static function initFormats() + private static function initFormats(): array { - return array( - 'normal' => ' %current%/%max% [%bar%] %percent:3s%%', - 'normal_nomax' => ' %current% [%bar%]', + return [ + self::FORMAT_NORMAL => ' %current%/%max% [%bar%] %percent:3s%%', + self::FORMAT_NORMAL_NOMAX => ' %current% [%bar%]', - 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', - 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', + self::FORMAT_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', + self::FORMAT_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%', - 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', - 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', + self::FORMAT_VERY_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', + self::FORMAT_VERY_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%', - 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', - 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%', - ); + self::FORMAT_DEBUG => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', + self::FORMAT_DEBUG_NOMAX => ' %current% [%bar%] %elapsed:6s% %memory:6s%', + ]; } - /** - * @return string - */ - private function buildLine() + private function buildLine(): string { $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i"; $callback = function ($matches) { if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) { - $text = \call_user_func($formatter, $this, $this->output); + $text = $formatter($this, $this->output); } elseif (isset($this->messages[$matches[1]])) { $text = $this->messages[$matches[1]]; } else { @@ -600,7 +592,7 @@ private function buildLine() // gets string length for each sub line with multiline format $linesLength = array_map(function ($subLine) { - return Helper::strlenWithoutDecoration($this->output->getFormatter(), rtrim($subLine, "\r")); + return Helper::width(Helper::removeDecoration($this->output->getFormatter(), rtrim($subLine, "\r"))); }, explode("\n", $line)); $linesWidth = max($linesLength); diff --git a/vendor/symfony/console/Helper/ProgressIndicator.php b/vendor/symfony/console/Helper/ProgressIndicator.php index 9de766a..3482343 100644 --- a/vendor/symfony/console/Helper/ProgressIndicator.php +++ b/vendor/symfony/console/Helper/ProgressIndicator.php @@ -20,6 +20,17 @@ */ class ProgressIndicator { + private const FORMATS = [ + 'normal' => ' %indicator% %message%', + 'normal_no_ansi' => ' %message%', + + 'verbose' => ' %indicator% %message% (%elapsed:6s%)', + 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', + + 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', + 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)', + ]; + private $output; private $startTime; private $format; @@ -30,16 +41,16 @@ class ProgressIndicator private $indicatorUpdateTime; private $started = false; + /** + * @var array<string, callable> + */ private static $formatters; - private static $formats; /** - * @param OutputInterface $output - * @param string|null $format Indicator format - * @param int $indicatorChangeInterval Change interval in milliseconds - * @param array|null $indicatorValues Animated indicator characters + * @param int $indicatorChangeInterval Change interval in milliseconds + * @param array|null $indicatorValues Animated indicator characters */ - public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null) + public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null) { $this->output = $output; @@ -48,7 +59,7 @@ public function __construct(OutputInterface $output, $format = null, $indicatorC } if (null === $indicatorValues) { - $indicatorValues = array('-', '\\', '|', '/'); + $indicatorValues = ['-', '\\', '|', '/']; } $indicatorValues = array_values($indicatorValues); @@ -65,10 +76,8 @@ public function __construct(OutputInterface $output, $format = null, $indicatorC /** * Sets the current indicator message. - * - * @param string|null $message */ - public function setMessage($message) + public function setMessage(?string $message) { $this->message = $message; @@ -77,10 +86,8 @@ public function setMessage($message) /** * Starts the indicator output. - * - * @param $message */ - public function start($message) + public function start(string $message) { if ($this->started) { throw new LogicException('Progress indicator already started.'); @@ -125,7 +132,7 @@ public function advance() * * @param $message */ - public function finish($message) + public function finish(string $message) { if (!$this->started) { throw new LogicException('Progress indicator has not yet been started.'); @@ -140,28 +147,19 @@ public function finish($message) /** * Gets the format for a given name. * - * @param string $name The format name - * - * @return string|null A format string + * @return string|null */ - public static function getFormatDefinition($name) + public static function getFormatDefinition(string $name) { - if (!self::$formats) { - self::$formats = self::initFormats(); - } - - return isset(self::$formats[$name]) ? self::$formats[$name] : null; + return self::FORMATS[$name] ?? null; } /** * Sets a placeholder formatter for a given name. * * This method also allow you to override an existing placeholder. - * - * @param string $name The placeholder name (including the delimiter char like %) - * @param callable $callable A PHP callable */ - public static function setPlaceholderFormatterDefinition($name, $callable) + public static function setPlaceholderFormatterDefinition(string $name, callable $callable) { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); @@ -171,19 +169,17 @@ public static function setPlaceholderFormatterDefinition($name, $callable) } /** - * Gets the placeholder formatter for a given name. - * - * @param string $name The placeholder name (including the delimiter char like %) + * Gets the placeholder formatter for a given name (including the delimiter char like %). * - * @return callable|null A PHP callable + * @return callable|null */ - public static function getPlaceholderFormatterDefinition($name) + public static function getPlaceholderFormatterDefinition(string $name) { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } - return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; + return self::$formatters[$name] ?? null; } private function display() @@ -192,18 +188,16 @@ private function display() return; } - $self = $this; - - $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) { - if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) { - return \call_user_func($formatter, $self); + $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) { + if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) { + return $formatter($this); } return $matches[0]; - }, $this->format)); + }, $this->format ?? '')); } - private function determineBestFormat() + private function determineBestFormat(): string { switch ($this->output->getVerbosity()) { // OutputInterface::VERBOSITY_QUIET: display is disabled anyway @@ -219,10 +213,8 @@ private function determineBestFormat() /** * Overwrites a previous message to the output. - * - * @param string $message The message */ - private function overwrite($message) + private function overwrite(string $message) { if ($this->output->isDecorated()) { $this->output->write("\x0D\x1B[2K"); @@ -232,40 +224,26 @@ private function overwrite($message) } } - private function getCurrentTimeInMilliseconds() + private function getCurrentTimeInMilliseconds(): float { return round(microtime(true) * 1000); } - private static function initPlaceholderFormatters() + private static function initPlaceholderFormatters(): array { - return array( - 'indicator' => function (ProgressIndicator $indicator) { + return [ + 'indicator' => function (self $indicator) { return $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)]; }, - 'message' => function (ProgressIndicator $indicator) { + 'message' => function (self $indicator) { return $indicator->message; }, - 'elapsed' => function (ProgressIndicator $indicator) { + 'elapsed' => function (self $indicator) { return Helper::formatTime(time() - $indicator->startTime); }, 'memory' => function () { return Helper::formatMemory(memory_get_usage(true)); }, - ); - } - - private static function initFormats() - { - return array( - 'normal' => ' %indicator% %message%', - 'normal_no_ansi' => ' %message%', - - 'verbose' => ' %indicator% %message% (%elapsed:6s%)', - 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', - - 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', - 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)', - ); + ]; } } diff --git a/vendor/symfony/console/Helper/QuestionHelper.php b/vendor/symfony/console/Helper/QuestionHelper.php index d9fca30..e236be9 100644 --- a/vendor/symfony/console/Helper/QuestionHelper.php +++ b/vendor/symfony/console/Helper/QuestionHelper.php @@ -11,16 +11,21 @@ namespace Symfony\Component\Console\Helper; -use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Cursor; +use Symfony\Component\Console\Exception\MissingInputException; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\StreamableInputInterface; use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; + +use function Symfony\Component\String\s; /** * The QuestionHelper class provides helpers to interact with the user. @@ -29,9 +34,13 @@ */ class QuestionHelper extends Helper { + /** + * @var resource|null + */ private $inputStream; - private static $shell; - private static $stty; + + private static $stty = true; + private static $stdinIsInteractive; /** * Asks a question to the user. @@ -47,68 +56,32 @@ public function ask(InputInterface $input, OutputInterface $output, Question $qu } if (!$input->isInteractive()) { - if ($question instanceof ChoiceQuestion) { - $choices = $question->getChoices(); - - return $choices[$question->getDefault()]; - } - - return $question->getDefault(); + return $this->getDefaultAnswer($question); } if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) { $this->inputStream = $stream; } - if (!$question->getValidator()) { - return $this->doAsk($output, $question); - } - - $interviewer = function () use ($output, $question) { - return $this->doAsk($output, $question); - }; + try { + if (!$question->getValidator()) { + return $this->doAsk($output, $question); + } - return $this->validateAttempts($interviewer, $output, $question); - } + $interviewer = function () use ($output, $question) { + return $this->doAsk($output, $question); + }; - /** - * Sets the input stream to read from when interacting with the user. - * - * This is mainly useful for testing purpose. - * - * @deprecated since version 3.2, to be removed in 4.0. Use - * StreamableInputInterface::setStream() instead. - * - * @param resource $stream The input stream - * - * @throws InvalidArgumentException In case the stream is not a resource - */ - public function setInputStream($stream) - { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.2 and will be removed in 4.0. Use %s::setStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED); + return $this->validateAttempts($interviewer, $output, $question); + } catch (MissingInputException $exception) { + $input->setInteractive(false); - if (!\is_resource($stream)) { - throw new InvalidArgumentException('Input stream must be a valid resource.'); - } - - $this->inputStream = $stream; - } + if (null === $fallbackOutput = $this->getDefaultAnswer($question)) { + throw $exception; + } - /** - * Returns the helper's input stream. - * - * @deprecated since version 3.2, to be removed in 4.0. Use - * StreamableInputInterface::getStream() instead. - * - * @return resource - */ - public function getInputStream() - { - if (0 === \func_num_args() || func_get_arg(0)) { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.2 and will be removed in 4.0. Use %s::getStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED); + return $fallbackOutput; } - - return $this->inputStream; } /** @@ -130,7 +103,7 @@ public static function disableStty() /** * Asks the question to the user. * - * @return bool|mixed|null|string + * @return mixed * * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ @@ -138,14 +111,15 @@ private function doAsk(OutputInterface $output, Question $question) { $this->writePrompt($output, $question); - $inputStream = $this->inputStream ?: STDIN; - $autocomplete = $question->getAutocompleterValues(); + $inputStream = $this->inputStream ?: \STDIN; + $autocomplete = $question->getAutocompleterCallback(); - if (null === $autocomplete || !$this->hasSttyAvailable()) { + if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) { $ret = false; if ($question->isHidden()) { try { - $ret = trim($this->getHiddenResponse($output, $inputStream)); + $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable()); + $ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse; } catch (RuntimeException $e) { if (!$question->isHiddenFallback()) { throw $e; @@ -154,14 +128,32 @@ private function doAsk(OutputInterface $output, Question $question) } if (false === $ret) { - $ret = fgets($inputStream, 4096); + $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 RuntimeException('Aborted'); + throw new MissingInputException('Aborted.'); + } + if ($question->isTrimmable()) { + $ret = trim($ret); } - $ret = trim($ret); } } else { - $ret = trim($this->autocomplete($output, $question, $inputStream, \is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false))); + $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete); + $ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete; + } + + if ($output instanceof ConsoleSectionOutput) { + $output->addContent($ret); } $ret = \strlen($ret) > 0 ? $ret : $question->getDefault(); @@ -173,6 +165,36 @@ private function doAsk(OutputInterface $output, Question $question) return $ret; } + /** + * @return mixed + */ + private function getDefaultAnswer(Question $question) + { + $default = $question->getDefault(); + + if (null === $default) { + return $default; + } + + if ($validator = $question->getValidator()) { + return \call_user_func($question->getValidator(), $default); + } elseif ($question instanceof ChoiceQuestion) { + $choices = $question->getChoices(); + + if (!$question->isMultiselect()) { + return $choices[$default] ?? $default; + } + + $default = explode(',', $default); + foreach ($default as $k => $v) { + $v = $question->isTrimmable() ? trim($v) : $v; + $default[$k] = $choices[$v] ?? $v; + } + } + + return $default; + } + /** * Outputs the question prompt. */ @@ -181,15 +203,9 @@ protected function writePrompt(OutputInterface $output, Question $question) $message = $question->getQuestion(); if ($question instanceof ChoiceQuestion) { - $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices()))); - - $messages = (array) $question->getQuestion(); - foreach ($question->getChoices() as $key => $value) { - $width = $maxWidth - $this->strlen($key); - $messages[] = ' [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value; - } - - $output->writeln($messages); + $output->writeln(array_merge([ + $question->getQuestion(), + ], $this->formatChoiceQuestionChoices($question, 'info'))); $message = $question->getPrompt(); } @@ -197,6 +213,24 @@ protected function writePrompt(OutputInterface $output, Question $question) $output->write($message); } + /** + * @return string[] + */ + protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string $tag) + { + $messages = []; + + $maxWidth = max(array_map([__CLASS__, 'width'], array_keys($choices = $question->getChoices()))); + + foreach ($choices as $key => $value) { + $padding = str_repeat(' ', $maxWidth - self::width($key)); + + $messages[] = sprintf(" [<$tag>%s$padding</$tag>] %s", $key, $value); + } + + return $messages; + } + /** * Outputs an error message. */ @@ -214,23 +248,24 @@ protected function writeError(OutputInterface $output, \Exception $error) /** * Autocompletes a question. * - * @param OutputInterface $output - * @param Question $question - * @param resource $inputStream - * @param array $autocomplete - * - * @return string + * @param resource $inputStream */ - private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete) + private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string { + $cursor = new Cursor($output, $inputStream); + + $fullChoice = ''; $ret = ''; $i = 0; $ofs = -1; - $matches = $autocomplete; + $matches = $autocomplete($ret); $numMatches = \count($matches); $sttyMode = shell_exec('stty -g'); + $isStdin = 'php://stdin' === (stream_get_meta_data($inputStream)['uri'] ?? null); + $r = [$inputStream]; + $w = []; // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) shell_exec('stty -icanon -echo'); @@ -240,26 +275,34 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu // Read a keypress while (!feof($inputStream)) { + while ($isStdin && 0 === @stream_select($r, $w, $w, 0, 100)) { + // Give signal handlers a chance to run + $r = [$inputStream]; + } $c = fread($inputStream, 1); - // Backspace Character - if ("\177" === $c) { + // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false. + if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) { + shell_exec('stty '.$sttyMode); + throw new MissingInputException('Aborted.'); + } elseif ("\177" === $c) { // Backspace Character if (0 === $numMatches && 0 !== $i) { --$i; - // Move cursor backwards - $output->write("\033[1D"); + $cursor->moveLeft(s($fullChoice)->slice(-1)->width(false)); + + $fullChoice = self::substr($fullChoice, 0, $i); } if (0 === $i) { $ofs = -1; - $matches = $autocomplete; + $matches = $autocomplete($ret); $numMatches = \count($matches); } else { $numMatches = 0; } // Pop the last character off the end of our string - $ret = substr($ret, 0, $i); + $ret = self::substr($ret, 0, $i); } elseif ("\033" === $c) { // Did we read an escape sequence? $c .= fread($inputStream, 2); @@ -280,10 +323,21 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu } elseif (\ord($c) < 32) { if ("\t" === $c || "\n" === $c) { if ($numMatches > 0 && -1 !== $ofs) { - $ret = $matches[$ofs]; + $ret = (string) $matches[$ofs]; // Echo out remaining chars for current match - $output->write(substr($ret, $i)); - $i = \strlen($ret); + $remainingCharacters = substr($ret, \strlen(trim($this->mostRecentlyEnteredValue($fullChoice)))); + $output->write($remainingCharacters); + $fullChoice .= $remainingCharacters; + $i = (false === $encoding = mb_detect_encoding($fullChoice, null, true)) ? \strlen($fullChoice) : mb_strlen($fullChoice, $encoding); + + $matches = array_filter( + $autocomplete($ret), + function ($match) use ($ret) { + return '' === $ret || str_starts_with($match, $ret); + } + ); + $numMatches = \count($matches); + $ofs = -1; } if ("\n" === $c) { @@ -296,51 +350,73 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu continue; } else { + if ("\x80" <= $c) { + $c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]); + } + $output->write($c); $ret .= $c; + $fullChoice .= $c; ++$i; + $tempRet = $ret; + + if ($question instanceof ChoiceQuestion && $question->isMultiselect()) { + $tempRet = $this->mostRecentlyEnteredValue($fullChoice); + } + $numMatches = 0; $ofs = 0; - foreach ($autocomplete as $value) { + foreach ($autocomplete($ret) as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) - if (0 === strpos($value, $ret)) { + if (str_starts_with($value, $tempRet)) { $matches[$numMatches++] = $value; } } } - // Erase characters from cursor to end of line - $output->write("\033[K"); + $cursor->clearLineAfter(); if ($numMatches > 0 && -1 !== $ofs) { - // Save cursor position - $output->write("\0337"); - // Write highlighted text - $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $i)).'</hl>'); - // Restore cursor position - $output->write("\0338"); + $cursor->savePosition(); + // Write highlighted text, complete the partially entered response + $charactersEntered = \strlen(trim($this->mostRecentlyEnteredValue($fullChoice))); + $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)).'</hl>'); + $cursor->restorePosition(); } } // Reset stty so it behaves normally again - shell_exec(sprintf('stty %s', $sttyMode)); + shell_exec('stty '.$sttyMode); - return $ret; + return $fullChoice; + } + + private function mostRecentlyEnteredValue(string $entered): string + { + // Determine the most recent value that the user entered + if (!str_contains($entered, ',')) { + return $entered; + } + + $choices = explode(',', $entered); + if ('' !== $lastChoice = trim($choices[\count($choices) - 1])) { + return $lastChoice; + } + + return $entered; } /** * Gets a hidden response from user. * - * @param OutputInterface $output An Output instance - * @param resource $inputStream The handler resource - * - * @return string The answer + * @param resource $inputStream The handler resource + * @param bool $trimmable Is the answer trimmable * * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ - private function getHiddenResponse(OutputInterface $output, $inputStream) + private function getHiddenResponse(OutputInterface $output, $inputStream, bool $trimmable = true): string { if ('\\' === \DIRECTORY_SEPARATOR) { $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; @@ -352,7 +428,8 @@ private function getHiddenResponse(OutputInterface $output, $inputStream) $exe = $tmpExe; } - $value = rtrim(shell_exec($exe)); + $sExec = shell_exec('"'.$exe.'"'); + $value = $trimmable ? rtrim($sExec) : $sExec; $output->writeln(''); if (isset($tmpExe)) { @@ -362,41 +439,34 @@ private function getHiddenResponse(OutputInterface $output, $inputStream) return $value; } - if ($this->hasSttyAvailable()) { + if (self::$stty && Terminal::hasSttyAvailable()) { $sttyMode = shell_exec('stty -g'); - shell_exec('stty -echo'); - $value = fgets($inputStream, 4096); - shell_exec(sprintf('stty %s', $sttyMode)); - - if (false === $value) { - throw new RuntimeException('Aborted'); - } + } elseif ($this->isInteractiveInput($inputStream)) { + throw new RuntimeException('Unable to hide the response.'); + } - $value = trim($value); - $output->writeln(''); + $value = fgets($inputStream, 4096); - return $value; + if (self::$stty && Terminal::hasSttyAvailable()) { + shell_exec('stty '.$sttyMode); } - if (false !== $shell = $this->getShell()) { - $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword'; - $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); - $value = rtrim(shell_exec($command)); - $output->writeln(''); - - return $value; + if (false === $value) { + throw new MissingInputException('Aborted.'); + } + if ($trimmable) { + $value = trim($value); } + $output->writeln(''); - throw new RuntimeException('Unable to hide the response.'); + return $value; } /** * Validates an attempt. * - * @param callable $interviewer A callable that will ask for a question and return the result - * @param OutputInterface $output An Output instance - * @param Question $question A Question instance + * @param callable $interviewer A callable that will ask for a question and return the result * * @return mixed The validated response * @@ -406,13 +476,14 @@ private function validateAttempts(callable $interviewer, OutputInterface $output { $error = null; $attempts = $question->getMaxAttempts(); + while (null === $attempts || $attempts--) { if (null !== $error) { $this->writeError($output, $error); } try { - return \call_user_func($question->getValidator(), $interviewer()); + return $question->getValidator()($interviewer()); } catch (RuntimeException $e) { throw $e; } catch (\Exception $error) { @@ -422,46 +493,133 @@ private function validateAttempts(callable $interviewer, OutputInterface $output throw $error; } + private function isInteractiveInput($inputStream): bool + { + if ('php://stdin' !== (stream_get_meta_data($inputStream)['uri'] ?? null)) { + return false; + } + + if (null !== self::$stdinIsInteractive) { + return self::$stdinIsInteractive; + } + + 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('shell_exec')) { + return self::$stdinIsInteractive = true; + } + + return self::$stdinIsInteractive = (bool) shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null')); + } + /** - * Returns a valid unix shell. + * Reads one or more lines of input and returns what is read. * - * @return string|bool The valid shell name, false in case no valid shell is found + * @param resource $inputStream The handler resource + * @param Question $question The question being asked + * + * @return string|false The input received, false in case input could not be read */ - private function getShell() + private function readInput($inputStream, Question $question) { - if (null !== self::$shell) { - return self::$shell; + if (!$question->isMultiline()) { + $cp = $this->setIOCodepage(); + $ret = fgets($inputStream, 4096); + + return $this->resetIOCodepage($cp, $ret); } - self::$shell = false; + $multiLineStreamReader = $this->cloneInputStream($inputStream); + if (null === $multiLineStreamReader) { + return false; + } - if (file_exists('/usr/bin/env')) { - // handle other OSs with bash/zsh/ksh/csh if available to hide the answer - $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; - foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) { - if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { - self::$shell = $sh; - break; - } + $ret = ''; + $cp = $this->setIOCodepage(); + while (false !== ($char = fgetc($multiLineStreamReader))) { + if (\PHP_EOL === "{$ret}{$char}") { + break; + } + $ret .= $char; + } + + return $this->resetIOCodepage($cp, $ret); + } + + /** + * Sets console I/O to the host code page. + * + * @return int Previous code page in IBM/EBCDIC format + */ + private function setIOCodepage(): int + { + if (\function_exists('sapi_windows_cp_set')) { + $cp = sapi_windows_cp_get(); + sapi_windows_cp_set(sapi_windows_cp_get('oem')); + + return $cp; + } + + return 0; + } + + /** + * Sets console I/O to the specified code page and converts the user input. + * + * @param string|false $input + * + * @return string|false + */ + private function resetIOCodepage(int $cp, $input) + { + if (0 !== $cp) { + sapi_windows_cp_set($cp); + + if (false !== $input && '' !== $input) { + $input = sapi_windows_cp_conv(sapi_windows_cp_get('oem'), $cp, $input); } } - return self::$shell; + return $input; } /** - * Returns whether Stty is available or not. + * Clones an input stream in order to act on one instance of the same + * stream without affecting the other instance. * - * @return bool + * @param resource $inputStream The handler resource + * + * @return resource|null The cloned resource, null in case it could not be cloned */ - private function hasSttyAvailable() + private function cloneInputStream($inputStream) { - if (null !== self::$stty) { - return self::$stty; + $streamMetaData = stream_get_meta_data($inputStream); + $seekable = $streamMetaData['seekable'] ?? false; + $mode = $streamMetaData['mode'] ?? 'rb'; + $uri = $streamMetaData['uri'] ?? null; + + if (null === $uri) { + return null; } - exec('stty 2>&1', $output, $exitcode); + $cloneStream = fopen($uri, $mode); + + // For seekable and writable streams, add all the same data to the + // cloned stream and then seek to the same offset. + if (true === $seekable && !\in_array($mode, ['r', 'rb', 'rt'])) { + $offset = ftell($inputStream); + rewind($inputStream); + stream_copy_to_stream($inputStream, $cloneStream); + fseek($inputStream, $offset); + fseek($cloneStream, $offset); + } - return self::$stty = 0 === $exitcode; + return $cloneStream; } } diff --git a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php index 75f4ee5..01f94ab 100644 --- a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php +++ b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php @@ -11,9 +11,7 @@ namespace Symfony\Component\Console\Helper; -use Symfony\Component\Console\Exception\LogicException; use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; @@ -27,32 +25,6 @@ */ class SymfonyQuestionHelper extends QuestionHelper { - /** - * {@inheritdoc} - * - * To be removed in 4.0 - */ - public function ask(InputInterface $input, OutputInterface $output, Question $question) - { - $validator = $question->getValidator(); - $question->setValidator(function ($value) use ($validator) { - if (null !== $validator) { - $value = $validator($value); - } else { - // make required - if (!\is_array($value) && !\is_bool($value) && 0 === \strlen($value)) { - @trigger_error('The default question validator is deprecated since Symfony 3.3 and will not be used anymore in version 4.0. Set a custom question validator if needed.', E_USER_DEPRECATED); - - throw new LogicException('A value is required.'); - } - } - - return $value; - }); - - return parent::ask($input, $output, $question); - } - /** * {@inheritdoc} */ @@ -61,6 +33,10 @@ protected function writePrompt(OutputInterface $output, Question $question) $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion()); $default = $question->getDefault(); + if ($question->isMultiline()) { + $text .= sprintf(' (press %s to continue)', $this->getEofShortcut()); + } + switch (true) { case null === $default: $text = sprintf(' <info>%s</info>:', $text); @@ -86,7 +62,7 @@ protected function writePrompt(OutputInterface $output, Question $question) case $question instanceof ChoiceQuestion: $choices = $question->getChoices(); - $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default])); + $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default] ?? $default)); break; @@ -96,15 +72,15 @@ protected function writePrompt(OutputInterface $output, Question $question) $output->writeln($text); + $prompt = ' > '; + if ($question instanceof ChoiceQuestion) { - $width = max(array_map('strlen', array_keys($question->getChoices()))); + $output->writeln($this->formatChoiceQuestionChoices($question, 'comment')); - foreach ($question->getChoices() as $key => $value) { - $output->writeln(sprintf(" [<comment>%-${width}s</comment>] %s", $key, $value)); - } + $prompt = $question->getPrompt(); } - $output->write(' > '); + $output->write($prompt); } /** @@ -121,4 +97,13 @@ protected function writeError(OutputInterface $output, \Exception $error) parent::writeError($output, $error); } + + private function getEofShortcut(): string + { + if ('Windows' === \PHP_OS_FAMILY) { + return '<comment>Ctrl+Z</comment> then <comment>Enter</comment>'; + } + + return '<comment>Ctrl+D</comment>'; + } } diff --git a/vendor/symfony/console/Helper/Table.php b/vendor/symfony/console/Helper/Table.php index 48e89da..5c3447a 100644 --- a/vendor/symfony/console/Helper/Table.php +++ b/vendor/symfony/console/Helper/Table.php @@ -12,6 +12,10 @@ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; use Symfony\Component\Console\Output\OutputInterface; /** @@ -21,23 +25,35 @@ * @author Саша Стаменковић <umpirsky@gmail.com> * @author Abdellatif Ait boudad <a.aitboudad@gmail.com> * @author Max Grigorian <maxakawizard@gmail.com> + * @author Dany Maillard <danymaillard93b@gmail.com> */ class Table { + private const SEPARATOR_TOP = 0; + private const SEPARATOR_TOP_BOTTOM = 1; + private const SEPARATOR_MID = 2; + private const SEPARATOR_BOTTOM = 3; + private const BORDER_OUTSIDE = 0; + private const BORDER_INSIDE = 1; + + private $headerTitle; + private $footerTitle; + /** * Table headers. */ - private $headers = array(); + private $headers = []; /** * Table rows. */ - private $rows = array(); + private $rows = []; + private $horizontal = false; /** * Column widths cache. */ - private $effectiveColumnWidths = array(); + private $effectiveColumnWidths = []; /** * Number of columns cache. @@ -59,17 +75,23 @@ class Table /** * @var array */ - private $columnStyles = array(); + private $columnStyles = []; /** * User set column widths. * * @var array */ - private $columnWidths = array(); + private $columnWidths = []; + private $columnMaxWidths = []; + /** + * @var array<string, TableStyle>|null + */ private static $styles; + private $rendered = false; + public function __construct(OutputInterface $output) { $this->output = $output; @@ -83,11 +105,8 @@ public function __construct(OutputInterface $output) /** * Sets a style definition. - * - * @param string $name The style name - * @param TableStyle $style A TableStyle instance */ - public static function setStyleDefinition($name, TableStyle $style) + public static function setStyleDefinition(string $name, TableStyle $style) { if (!self::$styles) { self::$styles = self::initStyles(); @@ -99,11 +118,9 @@ public static function setStyleDefinition($name, TableStyle $style) /** * Gets a style definition by name. * - * @param string $name The style name - * * @return TableStyle */ - public static function getStyleDefinition($name) + public static function getStyleDefinition(string $name) { if (!self::$styles) { self::$styles = self::initStyles(); @@ -143,15 +160,12 @@ public function getStyle() /** * Sets table column style. * - * @param int $columnIndex Column index - * @param TableStyle|string $name The style name or a TableStyle instance + * @param TableStyle|string $name The style name or a TableStyle instance * * @return $this */ - public function setColumnStyle($columnIndex, $name) + public function setColumnStyle(int $columnIndex, $name) { - $columnIndex = (int) $columnIndex; - $this->columnStyles[$columnIndex] = $this->resolveStyle($name); return $this; @@ -162,30 +176,21 @@ public function setColumnStyle($columnIndex, $name) * * If style was not set, it returns the global table style. * - * @param int $columnIndex Column index - * * @return TableStyle */ - public function getColumnStyle($columnIndex) + public function getColumnStyle(int $columnIndex) { - if (isset($this->columnStyles[$columnIndex])) { - return $this->columnStyles[$columnIndex]; - } - - return $this->getStyle(); + return $this->columnStyles[$columnIndex] ?? $this->getStyle(); } /** * Sets the minimum width of a column. * - * @param int $columnIndex Column index - * @param int $width Minimum column width in characters - * * @return $this */ - public function setColumnWidth($columnIndex, $width) + public function setColumnWidth(int $columnIndex, int $width) { - $this->columnWidths[(int) $columnIndex] = (int) $width; + $this->columnWidths[$columnIndex] = $width; return $this; } @@ -193,13 +198,11 @@ public function setColumnWidth($columnIndex, $width) /** * Sets the minimum width of all columns. * - * @param array $widths - * * @return $this */ public function setColumnWidths(array $widths) { - $this->columnWidths = array(); + $this->columnWidths = []; foreach ($widths as $index => $width) { $this->setColumnWidth($index, $width); } @@ -207,11 +210,33 @@ public function setColumnWidths(array $widths) return $this; } + /** + * Sets the maximum width of a column. + * + * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while + * formatted strings are preserved. + * + * @return $this + */ + public function setColumnMaxWidth(int $columnIndex, int $width): self + { + if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) { + throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, get_debug_type($this->output->getFormatter()))); + } + + $this->columnMaxWidths[$columnIndex] = $width; + + return $this; + } + + /** + * @return $this + */ public function setHeaders(array $headers) { $headers = array_values($headers); if (!empty($headers) && !\is_array($headers[0])) { - $headers = array($headers); + $headers = [$headers]; } $this->headers = $headers; @@ -221,11 +246,14 @@ public function setHeaders(array $headers) public function setRows(array $rows) { - $this->rows = array(); + $this->rows = []; return $this->addRows($rows); } + /** + * @return $this + */ public function addRows(array $rows) { foreach ($rows as $row) { @@ -235,6 +263,9 @@ public function addRows(array $rows) return $this; } + /** + * @return $this + */ public function addRow($row) { if ($row instanceof TableSeparator) { @@ -252,6 +283,30 @@ public function addRow($row) return $this; } + /** + * Adds a row to the table, and re-renders the table. + * + * @return $this + */ + public function appendRow($row): self + { + if (!$this->output instanceof ConsoleSectionOutput) { + throw new RuntimeException(sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__)); + } + + if ($this->rendered) { + $this->output->clear($this->calculateRowCount()); + } + + $this->addRow($row); + $this->render(); + + return $this; + } + + /** + * @return $this + */ public function setRow($column, array $row) { $this->rows[$column] = $row; @@ -259,67 +314,186 @@ public function setRow($column, array $row) return $this; } + /** + * @return $this + */ + public function setHeaderTitle(?string $title): self + { + $this->headerTitle = $title; + + return $this; + } + + /** + * @return $this + */ + public function setFooterTitle(?string $title): self + { + $this->footerTitle = $title; + + return $this; + } + + /** + * @return $this + */ + public function setHorizontal(bool $horizontal = true): self + { + $this->horizontal = $horizontal; + + return $this; + } + /** * Renders table to output. * * Example: - * <code> - * +---------------+-----------------------+------------------+ - * | ISBN | Title | Author | - * +---------------+-----------------------+------------------+ - * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | - * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | - * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | - * +---------------+-----------------------+------------------+ - * </code> + * + * +---------------+-----------------------+------------------+ + * | ISBN | Title | Author | + * +---------------+-----------------------+------------------+ + * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | + * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | + * +---------------+-----------------------+------------------+ */ public function render() { - $this->calculateNumberOfColumns(); - $rows = $this->buildTableRows($this->rows); - $headers = $this->buildTableRows($this->headers); - - $this->calculateColumnsWidth(array_merge($headers, $rows)); - - $this->renderRowSeparator(); - if (!empty($headers)) { - foreach ($headers as $header) { - $this->renderRow($header, $this->style->getCellHeaderFormat()); - $this->renderRowSeparator(); + $divider = new TableSeparator(); + if ($this->horizontal) { + $rows = []; + foreach ($this->headers[0] ?? [] as $i => $header) { + $rows[$i] = [$header]; + foreach ($this->rows as $row) { + if ($row instanceof TableSeparator) { + continue; + } + if (isset($row[$i])) { + $rows[$i][] = $row[$i]; + } elseif ($rows[$i][0] instanceof TableCell && $rows[$i][0]->getColspan() >= 2) { + // Noop, there is a "title" + } else { + $rows[$i][] = null; + } + } } + } else { + $rows = array_merge($this->headers, [$divider], $this->rows); } - foreach ($rows as $row) { - if ($row instanceof TableSeparator) { - $this->renderRowSeparator(); - } else { - $this->renderRow($row, $this->style->getCellRowFormat()); + + $this->calculateNumberOfColumns($rows); + + $rowGroups = $this->buildTableRows($rows); + $this->calculateColumnsWidth($rowGroups); + + $isHeader = !$this->horizontal; + $isFirstRow = $this->horizontal; + $hasTitle = (bool) $this->headerTitle; + + foreach ($rowGroups as $rowGroup) { + $isHeaderSeparatorRendered = false; + + foreach ($rowGroup as $row) { + if ($divider === $row) { + $isHeader = false; + $isFirstRow = true; + + continue; + } + + if ($row instanceof TableSeparator) { + $this->renderRowSeparator(); + + continue; + } + + if (!$row) { + continue; + } + + if ($isHeader && !$isHeaderSeparatorRendered) { + $this->renderRowSeparator( + $isHeader ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM, + $hasTitle ? $this->headerTitle : null, + $hasTitle ? $this->style->getHeaderTitleFormat() : null + ); + $hasTitle = false; + $isHeaderSeparatorRendered = true; + } + + if ($isFirstRow) { + $this->renderRowSeparator( + $isHeader ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM, + $hasTitle ? $this->headerTitle : null, + $hasTitle ? $this->style->getHeaderTitleFormat() : null + ); + $isFirstRow = false; + $hasTitle = false; + } + + if ($this->horizontal) { + $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat()); + } else { + $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat()); + } } } - if (!empty($rows)) { - $this->renderRowSeparator(); - } + $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat()); $this->cleanup(); + $this->rendered = true; } /** * Renders horizontal header separator. * - * Example: <code>+-----+-----------+-------+</code> + * Example: + * + * +-----+-----------+-------+ */ - private function renderRowSeparator() + private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null) { if (0 === $count = $this->numberOfColumns) { return; } - if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) { + $borders = $this->style->getBorderChars(); + if (!$borders[0] && !$borders[2] && !$this->style->getCrossingChar()) { return; } - $markup = $this->style->getCrossingChar(); + $crossings = $this->style->getCrossingChars(); + if (self::SEPARATOR_MID === $type) { + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[2], $crossings[8], $crossings[0], $crossings[4]]; + } elseif (self::SEPARATOR_TOP === $type) { + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[1], $crossings[2], $crossings[3]]; + } elseif (self::SEPARATOR_TOP_BOTTOM === $type) { + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[9], $crossings[10], $crossings[11]]; + } else { + [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[7], $crossings[6], $crossings[5]]; + } + + $markup = $leftChar; for ($column = 0; $column < $count; ++$column) { - $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->effectiveColumnWidths[$column]).$this->style->getCrossingChar(); + $markup .= str_repeat($horizontal, $this->effectiveColumnWidths[$column]); + $markup .= $column === $count - 1 ? $rightChar : $midChar; + } + + if (null !== $title) { + $titleLength = Helper::width(Helper::removeDecoration($formatter = $this->output->getFormatter(), $formattedTitle = sprintf($titleFormat, $title))); + $markupLength = Helper::width($markup); + if ($titleLength > $limit = $markupLength - 4) { + $titleLength = $limit; + $formatLength = Helper::width(Helper::removeDecoration($formatter, sprintf($titleFormat, ''))); + $formattedTitle = sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...'); + } + + $titleStart = intdiv($markupLength - $titleLength, 2); + if (false === mb_detect_encoding($markup, null, true)) { + $markup = substr_replace($markup, $formattedTitle, $titleStart, $titleLength); + } else { + $markup = mb_substr($markup, 0, $titleStart).$formattedTitle.mb_substr($markup, $titleStart + $titleLength); + } } $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup)); @@ -328,43 +502,42 @@ private function renderRowSeparator() /** * Renders vertical column separator. */ - private function renderColumnSeparator() + private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE): string { - return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()); + $borders = $this->style->getBorderChars(); + + return sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]); } /** * Renders table row. * - * Example: <code>| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |</code> + * Example: * - * @param array $row - * @param string $cellFormat + * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | */ - private function renderRow(array $row, $cellFormat) - { - if (empty($row)) { - return; - } - - $rowContent = $this->renderColumnSeparator(); - foreach ($this->getRowColumns($row) as $column) { - $rowContent .= $this->renderCell($row, $column, $cellFormat); - $rowContent .= $this->renderColumnSeparator(); + private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) + { + $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); + $columns = $this->getRowColumns($row); + $last = \count($columns) - 1; + foreach ($columns as $i => $column) { + if ($firstCellFormat && 0 === $i) { + $rowContent .= $this->renderCell($row, $column, $firstCellFormat); + } else { + $rowContent .= $this->renderCell($row, $column, $cellFormat); + } + $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE); } $this->output->writeln($rowContent); } /** * Renders table cell with padding. - * - * @param array $row - * @param int $column - * @param string $cellFormat */ - private function renderCell(array $row, $column, $cellFormat) + private function renderCell(array $row, int $column, string $cellFormat): string { - $cell = isset($row[$column]) ? $row[$column] : ''; + $cell = $row[$column] ?? ''; $width = $this->effectiveColumnWidths[$column]; if ($cell instanceof TableCell && $cell->getColspan() > 1) { // add the width of the following columns(numbers of colspan). @@ -381,26 +554,45 @@ private function renderCell(array $row, $column, $cellFormat) $style = $this->getColumnStyle($column); if ($cell instanceof TableSeparator) { - return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width)); + return sprintf($style->getBorderFormat(), str_repeat($style->getBorderChars()[2], $width)); } - $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); + $width += Helper::length($cell) - Helper::length(Helper::removeDecoration($this->output->getFormatter(), $cell)); $content = sprintf($style->getCellRowContentFormat(), $cell); - return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType())); + $padType = $style->getPadType(); + if ($cell instanceof TableCell && $cell->getStyle() instanceof TableCellStyle) { + $isNotStyledByTag = !preg_match('/^<(\w+|(\w+=[\w,]+;?)*)>.+<\/(\w+|(\w+=\w+;?)*)?>$/', $cell); + if ($isNotStyledByTag) { + $cellFormat = $cell->getStyle()->getCellFormat(); + if (!\is_string($cellFormat)) { + $tag = http_build_query($cell->getStyle()->getTagOptions(), '', ';'); + $cellFormat = '<'.$tag.'>%s</>'; + } + + if (strstr($content, '</>')) { + $content = str_replace('</>', '', $content); + $width -= 3; + } + if (strstr($content, '<fg=default;bg=default>')) { + $content = str_replace('<fg=default;bg=default>', '', $content); + $width -= \strlen('<fg=default;bg=default>'); + } + } + + $padType = $cell->getStyle()->getPadByAlign(); + } + + return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $padType)); } /** * Calculate number of columns for this table. */ - private function calculateNumberOfColumns() + private function calculateNumberOfColumns(array $rows) { - if (null !== $this->numberOfColumns) { - return; - } - - $columns = array(0); - foreach (array_merge($this->headers, $this->rows) as $row) { + $columns = [0]; + foreach ($rows as $row) { if ($row instanceof TableSeparator) { continue; } @@ -411,75 +603,100 @@ private function calculateNumberOfColumns() $this->numberOfColumns = max($columns); } - private function buildTableRows($rows) + private function buildTableRows(array $rows): TableRows { - $unmergedRows = array(); + /** @var WrappableOutputFormatterInterface $formatter */ + $formatter = $this->output->getFormatter(); + $unmergedRows = []; for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) { $rows = $this->fillNextRows($rows, $rowKey); // Remove any new line breaks and replace it with a new line foreach ($rows[$rowKey] as $column => $cell) { - if (!strstr($cell, "\n")) { + $colspan = $cell instanceof TableCell ? $cell->getColspan() : 1; + + if (isset($this->columnMaxWidths[$column]) && Helper::width(Helper::removeDecoration($formatter, $cell)) > $this->columnMaxWidths[$column]) { + $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan); + } + if (!strstr($cell ?? '', "\n")) { continue; } - $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $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("\n", str_replace("\n", "<fg=default;bg=default></>\n", $cell)); foreach ($lines as $lineKey => $line) { - if ($cell instanceof TableCell) { - $line = new TableCell($line, array('colspan' => $cell->getColspan())); + if ($colspan > 1) { + $line = new TableCell($line, ['colspan' => $colspan]); } if (0 === $lineKey) { $rows[$rowKey][$column] = $line; } else { + if (!\array_key_exists($rowKey, $unmergedRows) || !\array_key_exists($lineKey, $unmergedRows[$rowKey])) { + $unmergedRows[$rowKey][$lineKey] = $this->copyRow($rows, $rowKey); + } $unmergedRows[$rowKey][$lineKey][$column] = $line; } } } } - $tableRows = array(); - foreach ($rows as $rowKey => $row) { - $tableRows[] = $this->fillCells($row); - if (isset($unmergedRows[$rowKey])) { - $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]); + return new TableRows(function () use ($rows, $unmergedRows): \Traversable { + foreach ($rows as $rowKey => $row) { + $rowGroup = [$row instanceof TableSeparator ? $row : $this->fillCells($row)]; + + if (isset($unmergedRows[$rowKey])) { + foreach ($unmergedRows[$rowKey] as $row) { + $rowGroup[] = $row instanceof TableSeparator ? $row : $this->fillCells($row); + } + } + yield $rowGroup; } + }); + } + + private function calculateRowCount(): int + { + $numberOfRows = \count(iterator_to_array($this->buildTableRows(array_merge($this->headers, [new TableSeparator()], $this->rows)))); + + if ($this->headers) { + ++$numberOfRows; // Add row for header separator } - return $tableRows; + if (\count($this->rows) > 0) { + ++$numberOfRows; // Add row for footer separator + } + + return $numberOfRows; } /** * fill rows that contains rowspan > 1. * - * @param array $rows - * @param int $line - * - * @return array - * * @throws InvalidArgumentException */ - private function fillNextRows(array $rows, $line) + private function fillNextRows(array $rows, int $line): array { - $unmergedRows = array(); + $unmergedRows = []; foreach ($rows[$line] as $column => $cell) { - if (null !== $cell && !$cell instanceof TableCell && !is_scalar($cell) && !(\is_object($cell) && method_exists($cell, '__toString'))) { - throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing __toString, %s given.', \gettype($cell))); + if (null !== $cell && !$cell instanceof TableCell && !\is_scalar($cell) && !(\is_object($cell) && method_exists($cell, '__toString'))) { + throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', get_debug_type($cell))); } if ($cell instanceof TableCell && $cell->getRowspan() > 1) { $nbLines = $cell->getRowspan() - 1; - $lines = array($cell); + $lines = [$cell]; if (strstr($cell, "\n")) { $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell)); $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; - $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan())); + $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]); unset($lines[0]); } // create a two dimensional array (rowspan x colspan) - $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows); + $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows); foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { - $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : ''; - $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan())); + $value = $lines[$unmergedRowKey - $line] ?? ''; + $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]); if ($nbLines === $unmergedRowKey - $line) { break; } @@ -492,7 +709,7 @@ private function fillNextRows(array $rows, $line) if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) { foreach ($unmergedRow as $cellKey => $cell) { // insert cell into row at cellKey position - array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell)); + array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]); } } else { $row = $this->copyRow($rows, $unmergedRowKey - 1); @@ -501,7 +718,7 @@ private function fillNextRows(array $rows, $line) $row[$column] = $unmergedRow[$column]; } } - array_splice($rows, $unmergedRowKey, 0, array($row)); + array_splice($rows, $unmergedRowKey, 0, [$row]); } } @@ -510,12 +727,11 @@ private function fillNextRows(array $rows, $line) /** * fill cells for a row that contains colspan > 1. - * - * @return array */ - private function fillCells($row) + private function fillCells(iterable $row) { - $newRow = array(); + $newRow = []; + foreach ($row as $column => $cell) { $newRow[] = $cell; if ($cell instanceof TableCell && $cell->getColspan() > 1) { @@ -529,19 +745,13 @@ private function fillCells($row) return $newRow ?: $row; } - /** - * @param array $rows - * @param int $line - * - * @return array - */ - private function copyRow(array $rows, $line) + private function copyRow(array $rows, int $line): array { $row = $rows[$line]; foreach ($row as $cellKey => $cellValue) { $row[$cellKey] = ''; if ($cellValue instanceof TableCell) { - $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan())); + $row[$cellKey] = new TableCell('', ['colspan' => $cellValue->getColspan()]); } } @@ -550,10 +760,8 @@ private function copyRow(array $rows, $line) /** * Gets number of columns by row. - * - * @return int */ - private function getNumberOfColumns(array $row) + private function getNumberOfColumns(array $row): int { $columns = \count($row); foreach ($row as $column) { @@ -565,10 +773,8 @@ private function getNumberOfColumns(array $row) /** * Gets list of columns for the given row. - * - * @return array */ - private function getRowColumns(array $row) + private function getRowColumns(array $row): array { $columns = range(0, $this->numberOfColumns - 1); foreach ($row as $cellKey => $cell) { @@ -584,65 +790,55 @@ private function getRowColumns(array $row) /** * Calculates columns widths. */ - private function calculateColumnsWidth(array $rows) + private function calculateColumnsWidth(iterable $groups) { for ($column = 0; $column < $this->numberOfColumns; ++$column) { - $lengths = array(); - foreach ($rows as $row) { - if ($row instanceof TableSeparator) { - continue; - } + $lengths = []; + foreach ($groups as $group) { + foreach ($group as $row) { + if ($row instanceof TableSeparator) { + continue; + } - foreach ($row as $i => $cell) { - if ($cell instanceof TableCell) { - $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); - $textLength = Helper::strlen($textContent); - if ($textLength > 0) { - $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan())); - foreach ($contentColumns as $position => $content) { - $row[$i + $position] = $content; + foreach ($row as $i => $cell) { + if ($cell instanceof TableCell) { + $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); + $textLength = Helper::width($textContent); + if ($textLength > 0) { + $contentColumns = mb_str_split($textContent, ceil($textLength / $cell->getColspan())); + foreach ($contentColumns as $position => $content) { + $row[$i + $position] = $content; + } } } } - } - $lengths[] = $this->getCellWidth($row, $column); + $lengths[] = $this->getCellWidth($row, $column); + } } - $this->effectiveColumnWidths[$column] = max($lengths) + \strlen($this->style->getCellRowContentFormat()) - 2; + $this->effectiveColumnWidths[$column] = max($lengths) + Helper::width($this->style->getCellRowContentFormat()) - 2; } } - /** - * Gets column width. - * - * @return int - */ - private function getColumnSeparatorWidth() + private function getColumnSeparatorWidth(): int { - return \strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar())); + return Helper::width(sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3])); } - /** - * Gets cell width. - * - * @param array $row - * @param int $column - * - * @return int - */ - private function getCellWidth(array $row, $column) + private function getCellWidth(array $row, int $column): int { $cellWidth = 0; if (isset($row[$column])) { $cell = $row[$column]; - $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); + $cellWidth = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $cell)); } - $columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0; + $columnWidth = $this->columnWidths[$column] ?? 0; + $cellWidth = max($cellWidth, $columnWidth); - return max($cellWidth, $columnWidth); + return isset($this->columnMaxWidths[$column]) ? min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth; } /** @@ -650,44 +846,61 @@ private function getCellWidth(array $row, $column) */ private function cleanup() { - $this->effectiveColumnWidths = array(); + $this->effectiveColumnWidths = []; $this->numberOfColumns = null; } - private static function initStyles() + /** + * @return array<string, TableStyle> + */ + private static function initStyles(): array { $borderless = new TableStyle(); $borderless - ->setHorizontalBorderChar('=') - ->setVerticalBorderChar(' ') - ->setCrossingChar(' ') + ->setHorizontalBorderChars('=') + ->setVerticalBorderChars(' ') + ->setDefaultCrossingChar(' ') ; $compact = new TableStyle(); $compact - ->setHorizontalBorderChar('') - ->setVerticalBorderChar(' ') - ->setCrossingChar('') - ->setCellRowContentFormat('%s') + ->setHorizontalBorderChars('') + ->setVerticalBorderChars('') + ->setDefaultCrossingChar('') + ->setCellRowContentFormat('%s ') ; $styleGuide = new TableStyle(); $styleGuide - ->setHorizontalBorderChar('-') - ->setVerticalBorderChar(' ') - ->setCrossingChar(' ') + ->setHorizontalBorderChars('-') + ->setVerticalBorderChars(' ') + ->setDefaultCrossingChar(' ') ->setCellHeaderFormat('%s') ; - return array( + $box = (new TableStyle()) + ->setHorizontalBorderChars('─') + ->setVerticalBorderChars('│') + ->setCrossingChars('┼', '┌', '┬', '┐', '┤', '┘', '┴', '└', '├') + ; + + $boxDouble = (new TableStyle()) + ->setHorizontalBorderChars('═', '─') + ->setVerticalBorderChars('║', '│') + ->setCrossingChars('┼', '╔', '╤', '╗', '╢', '╝', '╧', '╚', '╟', '╠', '╪', '╣') + ; + + return [ 'default' => new TableStyle(), 'borderless' => $borderless, 'compact' => $compact, 'symfony-style-guide' => $styleGuide, - ); + 'box' => $box, + 'box-double' => $boxDouble, + ]; } - private function resolveStyle($name) + private function resolveStyle($name): TableStyle { if ($name instanceof TableStyle) { return $name; diff --git a/vendor/symfony/console/Helper/TableCell.php b/vendor/symfony/console/Helper/TableCell.php index fb6c9fd..1a7bc6e 100644 --- a/vendor/symfony/console/Helper/TableCell.php +++ b/vendor/symfony/console/Helper/TableCell.php @@ -19,21 +19,14 @@ class TableCell { private $value; - private $options = array( + private $options = [ 'rowspan' => 1, 'colspan' => 1, - ); + 'style' => null, + ]; - /** - * @param string $value - * @param array $options - */ - public function __construct($value = '', array $options = array()) + public function __construct(string $value = '', array $options = []) { - if (is_numeric($value) && !\is_string($value)) { - $value = (string) $value; - } - $this->value = $value; // check option names @@ -41,6 +34,10 @@ public function __construct($value = '', array $options = array()) throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff))); } + if (isset($options['style']) && !$options['style'] instanceof TableCellStyle) { + throw new InvalidArgumentException('The style option must be an instance of "TableCellStyle".'); + } + $this->options = array_merge($this->options, $options); } @@ -73,4 +70,9 @@ public function getRowspan() { return (int) $this->options['rowspan']; } + + public function getStyle(): ?TableCellStyle + { + return $this->options['style']; + } } diff --git a/vendor/symfony/console/Helper/TableCellStyle.php b/vendor/symfony/console/Helper/TableCellStyle.php new file mode 100644 index 0000000..19cd0ff --- /dev/null +++ b/vendor/symfony/console/Helper/TableCellStyle.php @@ -0,0 +1,89 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * @author Yewhen Khoptynskyi <khoptynskyi@gmail.com> + */ +class TableCellStyle +{ + public const DEFAULT_ALIGN = 'left'; + + private const TAG_OPTIONS = [ + 'fg', + 'bg', + 'options', + ]; + + private const ALIGN_MAP = [ + 'left' => \STR_PAD_RIGHT, + 'center' => \STR_PAD_BOTH, + 'right' => \STR_PAD_LEFT, + ]; + + private $options = [ + 'fg' => 'default', + 'bg' => 'default', + 'options' => null, + 'align' => self::DEFAULT_ALIGN, + 'cellFormat' => null, + ]; + + public function __construct(array $options = []) + { + if ($diff = array_diff(array_keys($options), array_keys($this->options))) { + throw new InvalidArgumentException(sprintf('The TableCellStyle does not support the following options: \'%s\'.', implode('\', \'', $diff))); + } + + if (isset($options['align']) && !\array_key_exists($options['align'], self::ALIGN_MAP)) { + throw new InvalidArgumentException(sprintf('Wrong align value. Value must be following: \'%s\'.', implode('\', \'', array_keys(self::ALIGN_MAP)))); + } + + $this->options = array_merge($this->options, $options); + } + + public function getOptions(): array + { + return $this->options; + } + + /** + * Gets options we need for tag for example fg, bg. + * + * @return string[] + */ + public function getTagOptions() + { + return array_filter( + $this->getOptions(), + function ($key) { + return \in_array($key, self::TAG_OPTIONS) && isset($this->options[$key]); + }, + \ARRAY_FILTER_USE_KEY + ); + } + + /** + * @return int + */ + public function getPadByAlign() + { + return self::ALIGN_MAP[$this->getOptions()['align']]; + } + + public function getCellFormat(): ?string + { + return $this->getOptions()['cellFormat']; + } +} diff --git a/vendor/symfony/console/Helper/TableRows.php b/vendor/symfony/console/Helper/TableRows.php new file mode 100644 index 0000000..cbc07d2 --- /dev/null +++ b/vendor/symfony/console/Helper/TableRows.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +/** + * @internal + */ +class TableRows implements \IteratorAggregate +{ + private $generator; + + public function __construct(\Closure $generator) + { + $this->generator = $generator; + } + + public function getIterator(): \Traversable + { + return ($this->generator)(); + } +} diff --git a/vendor/symfony/console/Helper/TableSeparator.php b/vendor/symfony/console/Helper/TableSeparator.php index c7b8dc9..e541c53 100644 --- a/vendor/symfony/console/Helper/TableSeparator.php +++ b/vendor/symfony/console/Helper/TableSeparator.php @@ -18,7 +18,7 @@ */ class TableSeparator extends TableCell { - public function __construct(array $options = array()) + public function __construct(array $options = []) { parent::__construct('', $options); } diff --git a/vendor/symfony/console/Helper/TableStyle.php b/vendor/symfony/console/Helper/TableStyle.php index 117e311..dfc41e6 100644 --- a/vendor/symfony/console/Helper/TableStyle.php +++ b/vendor/symfony/console/Helper/TableStyle.php @@ -19,30 +19,44 @@ * * @author Fabien Potencier <fabien@symfony.com> * @author Саша Стаменковић <umpirsky@gmail.com> + * @author Dany Maillard <danymaillard93b@gmail.com> */ class TableStyle { private $paddingChar = ' '; - private $horizontalBorderChar = '-'; - private $verticalBorderChar = '|'; + private $horizontalOutsideBorderChar = '-'; + private $horizontalInsideBorderChar = '-'; + private $verticalOutsideBorderChar = '|'; + private $verticalInsideBorderChar = '|'; private $crossingChar = '+'; + private $crossingTopRightChar = '+'; + private $crossingTopMidChar = '+'; + private $crossingTopLeftChar = '+'; + private $crossingMidRightChar = '+'; + private $crossingBottomRightChar = '+'; + private $crossingBottomMidChar = '+'; + private $crossingBottomLeftChar = '+'; + private $crossingMidLeftChar = '+'; + private $crossingTopLeftBottomChar = '+'; + private $crossingTopMidBottomChar = '+'; + private $crossingTopRightBottomChar = '+'; + private $headerTitleFormat = '<fg=black;bg=white;options=bold> %s </>'; + private $footerTitleFormat = '<fg=black;bg=white;options=bold> %s </>'; private $cellHeaderFormat = '<info>%s</info>'; private $cellRowFormat = '%s'; private $cellRowContentFormat = ' %s '; private $borderFormat = '%s'; - private $padType = STR_PAD_RIGHT; + private $padType = \STR_PAD_RIGHT; /** * Sets padding character, used for cell padding. * - * @param string $paddingChar - * * @return $this */ - public function setPaddingChar($paddingChar) + public function setPaddingChar(string $paddingChar) { if (!$paddingChar) { - throw new LogicException('The padding char must not be empty'); + throw new LogicException('The padding char must not be empty.'); } $this->paddingChar = $paddingChar; @@ -61,71 +75,132 @@ public function getPaddingChar() } /** - * Sets horizontal border character. + * Sets horizontal border characters. * - * @param string $horizontalBorderChar + * <code> + * ╔═══════════════╤══════════════════════════╤══════════════════╗ + * 1 ISBN 2 Title │ Author ║ + * ╠═══════════════╪══════════════════════════╪══════════════════╣ + * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ + * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ + * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ + * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ + * ╚═══════════════╧══════════════════════════╧══════════════════╝ + * </code> * * @return $this */ - public function setHorizontalBorderChar($horizontalBorderChar) + public function setHorizontalBorderChars(string $outside, string $inside = null): self { - $this->horizontalBorderChar = $horizontalBorderChar; + $this->horizontalOutsideBorderChar = $outside; + $this->horizontalInsideBorderChar = $inside ?? $outside; return $this; } /** - * Gets horizontal border character. + * Sets vertical border characters. * - * @return string - */ - public function getHorizontalBorderChar() - { - return $this->horizontalBorderChar; - } - - /** - * Sets vertical border character. - * - * @param string $verticalBorderChar + * <code> + * ╔═══════════════╤══════════════════════════╤══════════════════╗ + * ║ ISBN │ Title │ Author ║ + * ╠═══════1═══════╪══════════════════════════╪══════════════════╣ + * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ + * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ + * ╟───────2───────┼──────────────────────────┼──────────────────╢ + * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ + * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ + * ╚═══════════════╧══════════════════════════╧══════════════════╝ + * </code> * * @return $this */ - public function setVerticalBorderChar($verticalBorderChar) + public function setVerticalBorderChars(string $outside, string $inside = null): self { - $this->verticalBorderChar = $verticalBorderChar; + $this->verticalOutsideBorderChar = $outside; + $this->verticalInsideBorderChar = $inside ?? $outside; return $this; } /** - * Gets vertical border character. + * Gets border characters. * - * @return string + * @internal */ - public function getVerticalBorderChar() + public function getBorderChars(): array { - return $this->verticalBorderChar; + return [ + $this->horizontalOutsideBorderChar, + $this->verticalOutsideBorderChar, + $this->horizontalInsideBorderChar, + $this->verticalInsideBorderChar, + ]; } /** - * Sets crossing character. + * Sets crossing characters. + * + * Example: + * <code> + * 1═══════════════2══════════════════════════2══════════════════3 + * ║ ISBN │ Title │ Author ║ + * 8'══════════════0'═════════════════════════0'═════════════════4' + * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ + * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ + * 8───────────────0──────────────────────────0──────────────────4 + * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ + * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ + * 7═══════════════6══════════════════════════6══════════════════5 + * </code> * - * @param string $crossingChar + * @param string $cross Crossing char (see #0 of example) + * @param string $topLeft Top left char (see #1 of example) + * @param string $topMid Top mid char (see #2 of example) + * @param string $topRight Top right char (see #3 of example) + * @param string $midRight Mid right char (see #4 of example) + * @param string $bottomRight Bottom right char (see #5 of example) + * @param string $bottomMid Bottom mid char (see #6 of example) + * @param string $bottomLeft Bottom left char (see #7 of example) + * @param string $midLeft Mid left char (see #8 of example) + * @param string|null $topLeftBottom Top left bottom char (see #8' of example), equals to $midLeft if null + * @param string|null $topMidBottom Top mid bottom char (see #0' of example), equals to $cross if null + * @param string|null $topRightBottom Top right bottom char (see #4' of example), equals to $midRight if null * * @return $this */ - public function setCrossingChar($crossingChar) + 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 = $crossingChar; + $this->crossingChar = $cross; + $this->crossingTopLeftChar = $topLeft; + $this->crossingTopMidChar = $topMid; + $this->crossingTopRightChar = $topRight; + $this->crossingMidRightChar = $midRight; + $this->crossingBottomRightChar = $bottomRight; + $this->crossingBottomMidChar = $bottomMid; + $this->crossingBottomLeftChar = $bottomLeft; + $this->crossingMidLeftChar = $midLeft; + $this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft; + $this->crossingTopMidBottomChar = $topMidBottom ?? $cross; + $this->crossingTopRightBottomChar = $topRightBottom ?? $midRight; return $this; } + /** + * Sets default crossing character used for each cross. + * + * @see {@link setCrossingChars()} for setting each crossing individually. + */ + public function setDefaultCrossingChar(string $char): self + { + return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char); + } + /** * Gets crossing character. * - * @return string $crossingChar + * @return string */ public function getCrossingChar() { @@ -133,13 +208,34 @@ public function getCrossingChar() } /** - * Sets header cell format. + * Gets crossing characters. * - * @param string $cellHeaderFormat + * @internal + */ + public function getCrossingChars(): array + { + return [ + $this->crossingChar, + $this->crossingTopLeftChar, + $this->crossingTopMidChar, + $this->crossingTopRightChar, + $this->crossingMidRightChar, + $this->crossingBottomRightChar, + $this->crossingBottomMidChar, + $this->crossingBottomLeftChar, + $this->crossingMidLeftChar, + $this->crossingTopLeftBottomChar, + $this->crossingTopMidBottomChar, + $this->crossingTopRightBottomChar, + ]; + } + + /** + * Sets header cell format. * * @return $this */ - public function setCellHeaderFormat($cellHeaderFormat) + public function setCellHeaderFormat(string $cellHeaderFormat) { $this->cellHeaderFormat = $cellHeaderFormat; @@ -159,11 +255,9 @@ public function getCellHeaderFormat() /** * Sets row cell format. * - * @param string $cellRowFormat - * * @return $this */ - public function setCellRowFormat($cellRowFormat) + public function setCellRowFormat(string $cellRowFormat) { $this->cellRowFormat = $cellRowFormat; @@ -183,11 +277,9 @@ public function getCellRowFormat() /** * Sets row cell content format. * - * @param string $cellRowContentFormat - * * @return $this */ - public function setCellRowContentFormat($cellRowContentFormat) + public function setCellRowContentFormat(string $cellRowContentFormat) { $this->cellRowContentFormat = $cellRowContentFormat; @@ -207,11 +299,9 @@ public function getCellRowContentFormat() /** * Sets table border format. * - * @param string $borderFormat - * * @return $this */ - public function setBorderFormat($borderFormat) + public function setBorderFormat(string $borderFormat) { $this->borderFormat = $borderFormat; @@ -231,13 +321,11 @@ public function getBorderFormat() /** * Sets cell padding type. * - * @param int $padType STR_PAD_* - * * @return $this */ - public function setPadType($padType) + public function setPadType(int $padType) { - if (!\in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) { + if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], true)) { throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).'); } @@ -255,4 +343,34 @@ public function getPadType() { return $this->padType; } + + public function getHeaderTitleFormat(): string + { + return $this->headerTitleFormat; + } + + /** + * @return $this + */ + public function setHeaderTitleFormat(string $format): self + { + $this->headerTitleFormat = $format; + + return $this; + } + + public function getFooterTitleFormat(): string + { + return $this->footerTitleFormat; + } + + /** + * @return $this + */ + public function setFooterTitleFormat(string $format): self + { + $this->footerTitleFormat = $format; + + return $this; + } } diff --git a/vendor/symfony/console/Input/ArgvInput.php b/vendor/symfony/console/Input/ArgvInput.php index 2133772..675b9ef 100644 --- a/vendor/symfony/console/Input/ArgvInput.php +++ b/vendor/symfony/console/Input/ArgvInput.php @@ -43,15 +43,9 @@ class ArgvInput extends Input private $tokens; private $parsed; - /** - * @param array|null $argv An array of parameters from the CLI (in the argv format) - * @param InputDefinition|null $definition A InputDefinition instance - */ public function __construct(array $argv = null, InputDefinition $definition = null) { - if (null === $argv) { - $argv = $_SERVER['argv']; - } + $argv = $argv ?? $_SERVER['argv'] ?? []; // strip the application name array_shift($argv); @@ -74,26 +68,31 @@ protected function parse() $parseOptions = true; $this->parsed = $this->tokens; while (null !== $token = array_shift($this->parsed)) { - if ($parseOptions && '' == $token) { - $this->parseArgument($token); - } elseif ($parseOptions && '--' == $token) { - $parseOptions = false; - } elseif ($parseOptions && 0 === strpos($token, '--')) { - $this->parseLongOption($token); - } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { - $this->parseShortOption($token); - } else { - $this->parseArgument($token); - } + $parseOptions = $this->parseToken($token, $parseOptions); + } + } + + protected function parseToken(string $token, bool $parseOptions): bool + { + if ($parseOptions && '' == $token) { + $this->parseArgument($token); + } elseif ($parseOptions && '--' == $token) { + return false; + } elseif ($parseOptions && str_starts_with($token, '--')) { + $this->parseLongOption($token); + } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { + $this->parseShortOption($token); + } else { + $this->parseArgument($token); } + + return $parseOptions; } /** * Parses a short option. - * - * @param string $token The current token */ - private function parseShortOption($token) + private function parseShortOption(string $token) { $name = substr($token, 1); @@ -112,16 +111,15 @@ private function parseShortOption($token) /** * Parses a short option set. * - * @param string $name The current token - * * @throws RuntimeException When option given doesn't exist */ - private function parseShortOptionSet($name) + private function parseShortOptionSet(string $name) { $len = \strlen($name); for ($i = 0; $i < $len; ++$i) { if (!$this->definition->hasShortcut($name[$i])) { - throw new RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i])); + $encoding = mb_detect_encoding($name, null, true); + throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding))); } $option = $this->definition->getOptionForShortcut($name[$i]); @@ -137,20 +135,13 @@ private function parseShortOptionSet($name) /** * Parses a long option. - * - * @param string $token The current token */ - private function parseLongOption($token) + private function parseLongOption(string $token) { $name = substr($token, 2); if (false !== $pos = strpos($name, '=')) { - if (0 === \strlen($value = substr($name, $pos + 1))) { - // if no value after "=" then substr() returns "" since php7 only, false before - // see http://php.net/manual/fr/migration70.incompatible.php#119151 - if (\PHP_VERSION_ID < 70000 && false === $value) { - $value = ''; - } + if ('' === $value = substr($name, $pos + 1)) { array_unshift($this->parsed, $value); } $this->addLongOption(substr($name, 0, $pos), $value); @@ -162,18 +153,16 @@ private function parseLongOption($token) /** * Parses an argument. * - * @param string $token The current token - * * @throws RuntimeException When too many arguments are given */ - private function parseArgument($token) + private function parseArgument(string $token) { $c = \count($this->arguments); // if input is expecting another argument, add it if ($this->definition->hasArgument($c)) { $arg = $this->definition->getArgument($c); - $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token; + $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token; // if last argument isArray(), append token to last argument } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { @@ -183,23 +172,34 @@ private function parseArgument($token) // unexpected argument } else { $all = $this->definition->getArguments(); + $symfonyCommandName = null; + if (($inputArgument = $all[$key = array_key_first($all)] ?? null) && 'command' === $inputArgument->getName()) { + $symfonyCommandName = $this->arguments['command'] ?? null; + unset($all[$key]); + } + if (\count($all)) { - throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)))); + if ($symfonyCommandName) { + $message = sprintf('Too many arguments to "%s" command, expected arguments "%s".', $symfonyCommandName, implode('" "', array_keys($all))); + } else { + $message = sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))); + } + } elseif ($symfonyCommandName) { + $message = sprintf('No arguments expected for "%s" command, got "%s".', $symfonyCommandName, $token); + } else { + $message = sprintf('No arguments expected, got "%s".', $token); } - throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token)); + throw new RuntimeException($message); } } /** * Adds a short option value. * - * @param string $shortcut The short option key - * @param mixed $value The value for the option - * * @throws RuntimeException When option given doesn't exist */ - private function addShortOption($shortcut, $value) + private function addShortOption(string $shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); @@ -211,15 +211,22 @@ private function addShortOption($shortcut, $value) /** * Adds a long option value. * - * @param string $name The long option key - * @param mixed $value The value for the option - * * @throws RuntimeException When option given doesn't exist */ - private function addLongOption($name, $value) + private function addLongOption(string $name, $value) { if (!$this->definition->hasOption($name)) { - throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name)); + if (!$this->definition->hasNegation($name)) { + throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name)); + } + + $optionName = $this->definition->negationToName($name); + if (null !== $value) { + throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); + } + $this->options[$optionName] = false; + + return; } $option = $this->definition->getOption($name); @@ -228,11 +235,11 @@ private function addLongOption($name, $value) throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); } - if (\in_array($value, array('', null), true) && $option->acceptValue() && \count($this->parsed)) { + if (\in_array($value, ['', null], true) && $option->acceptValue() && \count($this->parsed)) { // if option accepts an optional or mandatory argument // let's see if there is one provided $next = array_shift($this->parsed); - if ((isset($next[0]) && '-' !== $next[0]) || \in_array($next, array('', null), true)) { + if ((isset($next[0]) && '-' !== $next[0]) || \in_array($next, ['', null], true)) { $value = $next; } else { array_unshift($this->parsed, $next); @@ -261,19 +268,40 @@ private function addLongOption($name, $value) */ public function getFirstArgument() { - foreach ($this->tokens as $token) { + $isOption = false; + foreach ($this->tokens as $i => $token) { if ($token && '-' === $token[0]) { + if (str_contains($token, '=') || !isset($this->tokens[$i + 1])) { + continue; + } + + // If it's a long option, consider that everything after "--" is the option name. + // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator) + $name = '-' === $token[1] ? substr($token, 2) : substr($token, -1); + if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) { + // noop + } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) { + $isOption = true; + } + + continue; + } + + if ($isOption) { + $isOption = false; continue; } return $token; } + + return null; } /** * {@inheritdoc} */ - public function hasParameterOption($values, $onlyParams = false) + public function hasParameterOption($values, bool $onlyParams = false) { $values = (array) $values; @@ -285,8 +313,8 @@ public function hasParameterOption($values, $onlyParams = false) // Options with values: // For long options, test for '--option=' at beginning // For short options, test for '-o' at beginning - $leading = 0 === strpos($value, '--') ? $value.'=' : $value; - if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) { + $leading = str_starts_with($value, '--') ? $value.'=' : $value; + if ($token === $value || '' !== $leading && str_starts_with($token, $leading)) { return true; } } @@ -298,7 +326,7 @@ public function hasParameterOption($values, $onlyParams = false) /** * {@inheritdoc} */ - public function getParameterOption($values, $default = false, $onlyParams = false) + public function getParameterOption($values, $default = false, bool $onlyParams = false) { $values = (array) $values; $tokens = $this->tokens; @@ -316,8 +344,8 @@ public function getParameterOption($values, $default = false, $onlyParams = fals // Options with values: // For long options, test for '--option=' at beginning // For short options, test for '-o' at beginning - $leading = 0 === strpos($value, '--') ? $value.'=' : $value; - if ('' !== $leading && 0 === strpos($token, $leading)) { + $leading = str_starts_with($value, '--') ? $value.'=' : $value; + if ('' !== $leading && str_starts_with($token, $leading)) { return substr($token, \strlen($leading)); } } diff --git a/vendor/symfony/console/Input/ArrayInput.php b/vendor/symfony/console/Input/ArrayInput.php index 8b6917f..c651614 100644 --- a/vendor/symfony/console/Input/ArrayInput.php +++ b/vendor/symfony/console/Input/ArrayInput.php @@ -19,7 +19,7 @@ * * Usage: * - * $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar')); + * $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']); * * @author Fabien Potencier <fabien@symfony.com> */ @@ -39,19 +39,21 @@ public function __construct(array $parameters, InputDefinition $definition = nul */ public function getFirstArgument() { - foreach ($this->parameters as $key => $value) { - if ($key && '-' === $key[0]) { + foreach ($this->parameters as $param => $value) { + if ($param && \is_string($param) && '-' === $param[0]) { continue; } return $value; } + + return null; } /** * {@inheritdoc} */ - public function hasParameterOption($values, $onlyParams = false) + public function hasParameterOption($values, bool $onlyParams = false) { $values = (array) $values; @@ -75,7 +77,7 @@ public function hasParameterOption($values, $onlyParams = false) /** * {@inheritdoc} */ - public function getParameterOption($values, $default = false, $onlyParams = false) + public function getParameterOption($values, $default = false, bool $onlyParams = false) { $values = (array) $values; @@ -103,18 +105,19 @@ public function getParameterOption($values, $default = false, $onlyParams = fals */ public function __toString() { - $params = array(); + $params = []; foreach ($this->parameters as $param => $val) { - if ($param && '-' === $param[0]) { + if ($param && \is_string($param) && '-' === $param[0]) { + $glue = ('-' === $param[1]) ? '=' : ' '; if (\is_array($val)) { foreach ($val as $v) { - $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : ''); + $params[] = $param.('' != $v ? $glue.$this->escapeToken($v) : ''); } } else { - $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); + $params[] = $param.('' != $val ? $glue.$this->escapeToken($val) : ''); } } else { - $params[] = \is_array($val) ? implode(' ', array_map(array($this, 'escapeToken'), $val)) : $this->escapeToken($val); + $params[] = \is_array($val) ? implode(' ', array_map([$this, 'escapeToken'], $val)) : $this->escapeToken($val); } } @@ -130,9 +133,9 @@ protected function parse() if ('--' === $key) { return; } - if (0 === strpos($key, '--')) { + if (str_starts_with($key, '--')) { $this->addLongOption(substr($key, 2), $value); - } elseif ('-' === $key[0]) { + } elseif (str_starts_with($key, '-')) { $this->addShortOption(substr($key, 1), $value); } else { $this->addArgument($key, $value); @@ -143,12 +146,9 @@ protected function parse() /** * Adds a short option value. * - * @param string $shortcut The short option key - * @param mixed $value The value for the option - * * @throws InvalidOptionException When option given doesn't exist */ - private function addShortOption($shortcut, $value) + private function addShortOption(string $shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut)); @@ -160,16 +160,20 @@ private function addShortOption($shortcut, $value) /** * Adds a long option value. * - * @param string $name The long option key - * @param mixed $value The value for the option - * * @throws InvalidOptionException When option given doesn't exist * @throws InvalidOptionException When a required value is missing */ - private function addLongOption($name, $value) + private function addLongOption(string $name, $value) { if (!$this->definition->hasOption($name)) { - throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name)); + if (!$this->definition->hasNegation($name)) { + throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name)); + } + + $optionName = $this->definition->negationToName($name); + $this->options[$optionName] = false; + + return; } $option = $this->definition->getOption($name); @@ -190,8 +194,8 @@ private function addLongOption($name, $value) /** * Adds an argument value. * - * @param string $name The argument name - * @param mixed $value The value for the argument + * @param string|int $name The argument name + * @param mixed $value The value for the argument * * @throws InvalidArgumentException When argument given doesn't exist */ diff --git a/vendor/symfony/console/Input/Input.php b/vendor/symfony/console/Input/Input.php index fa5644d..d37460e 100644 --- a/vendor/symfony/console/Input/Input.php +++ b/vendor/symfony/console/Input/Input.php @@ -29,8 +29,8 @@ abstract class Input implements InputInterface, StreamableInputInterface { protected $definition; protected $stream; - protected $options = array(); - protected $arguments = array(); + protected $options = []; + protected $arguments = []; protected $interactive = true; public function __construct(InputDefinition $definition = null) @@ -48,8 +48,8 @@ public function __construct(InputDefinition $definition = null) */ public function bind(InputDefinition $definition) { - $this->arguments = array(); - $this->options = array(); + $this->arguments = []; + $this->options = []; $this->definition = $definition; $this->parse(); @@ -69,7 +69,7 @@ public function validate() $givenArguments = $this->arguments; $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) { - return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired(); + return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired(); }); if (\count($missingArguments) > 0) { @@ -88,9 +88,9 @@ public function isInteractive() /** * {@inheritdoc} */ - public function setInteractive($interactive) + public function setInteractive(bool $interactive) { - $this->interactive = (bool) $interactive; + $this->interactive = $interactive; } /** @@ -104,19 +104,19 @@ public function getArguments() /** * {@inheritdoc} */ - public function getArgument($name) + public function getArgument(string $name) { if (!$this->definition->hasArgument($name)) { throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } - return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); + return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault(); } /** * {@inheritdoc} */ - public function setArgument($name, $value) + public function setArgument(string $name, $value) { if (!$this->definition->hasArgument($name)) { throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); @@ -128,7 +128,7 @@ public function setArgument($name, $value) /** * {@inheritdoc} */ - public function hasArgument($name) + public function hasArgument(string $name) { return $this->definition->hasArgument($name); } @@ -144,21 +144,33 @@ public function getOptions() /** * {@inheritdoc} */ - public function getOption($name) + public function getOption(string $name) { + if ($this->definition->hasNegation($name)) { + if (null === $value = $this->getOption($this->definition->negationToName($name))) { + return $value; + } + + return !$value; + } + if (!$this->definition->hasOption($name)) { throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); } - return array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); + return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); } /** * {@inheritdoc} */ - public function setOption($name, $value) + public function setOption(string $name, $value) { - if (!$this->definition->hasOption($name)) { + if ($this->definition->hasNegation($name)) { + $this->options[$this->definition->negationToName($name)] = !$value; + + return; + } elseif (!$this->definition->hasOption($name)) { throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); } @@ -168,19 +180,17 @@ public function setOption($name, $value) /** * {@inheritdoc} */ - public function hasOption($name) + public function hasOption(string $name) { - return $this->definition->hasOption($name); + return $this->definition->hasOption($name) || $this->definition->hasNegation($name); } /** * Escapes a token through escapeshellarg if it contains unsafe chars. * - * @param string $token - * * @return string */ - public function escapeToken($token) + public function escapeToken(string $token) { return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); } diff --git a/vendor/symfony/console/Input/InputArgument.php b/vendor/symfony/console/Input/InputArgument.php index d4c5e35..8a64f7a 100644 --- a/vendor/symfony/console/Input/InputArgument.php +++ b/vendor/symfony/console/Input/InputArgument.php @@ -21,9 +21,9 @@ */ class InputArgument { - const REQUIRED = 1; - const OPTIONAL = 2; - const IS_ARRAY = 4; + public const REQUIRED = 1; + public const OPTIONAL = 2; + public const IS_ARRAY = 4; private $name; private $mode; @@ -31,18 +31,18 @@ class InputArgument private $description; /** - * @param string $name The argument name - * @param int $mode The argument mode: self::REQUIRED or self::OPTIONAL - * @param string $description A description text - * @param mixed $default The default value (for self::OPTIONAL mode only) + * @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 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($name, $mode = null, $description = '', $default = null) + public function __construct(string $name, int $mode = null, string $description = '', $default = null) { if (null === $mode) { $mode = self::OPTIONAL; - } elseif (!\is_int($mode) || $mode > 7 || $mode < 1) { + } elseif ($mode > 7 || $mode < 1) { throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); } @@ -56,7 +56,7 @@ public function __construct($name, $mode = null, $description = '', $default = n /** * Returns the argument name. * - * @return string The argument name + * @return string */ public function getName() { @@ -86,19 +86,19 @@ public function isArray() /** * Sets the default value. * - * @param mixed $default The default value + * @param string|bool|int|float|array|null $default * * @throws LogicException When incorrect default value is given */ public function setDefault($default = null) { - if (self::REQUIRED === $this->mode && null !== $default) { + if ($this->isRequired() && null !== $default) { throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.'); } if ($this->isArray()) { if (null === $default) { - $default = array(); + $default = []; } elseif (!\is_array($default)) { throw new LogicException('A default value for an array argument must be an array.'); } @@ -110,7 +110,7 @@ public function setDefault($default = null) /** * Returns the default value. * - * @return mixed The default value + * @return string|bool|int|float|array|null */ public function getDefault() { @@ -120,7 +120,7 @@ public function getDefault() /** * Returns the description text. * - * @return string The description text + * @return string */ public function getDescription() { diff --git a/vendor/symfony/console/Input/InputAwareInterface.php b/vendor/symfony/console/Input/InputAwareInterface.php index d0f11e9..5a288de 100644 --- a/vendor/symfony/console/Input/InputAwareInterface.php +++ b/vendor/symfony/console/Input/InputAwareInterface.php @@ -21,8 +21,6 @@ interface InputAwareInterface { /** * Sets the Console Input. - * - * @param InputInterface */ public function setInput(InputInterface $input); } diff --git a/vendor/symfony/console/Input/InputDefinition.php b/vendor/symfony/console/Input/InputDefinition.php index 940cbf3..11f704f 100644 --- a/vendor/symfony/console/Input/InputDefinition.php +++ b/vendor/symfony/console/Input/InputDefinition.php @@ -19,10 +19,10 @@ * * Usage: * - * $definition = new InputDefinition(array( - * new InputArgument('name', InputArgument::REQUIRED), - * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), - * )); + * $definition = new InputDefinition([ + * new InputArgument('name', InputArgument::REQUIRED), + * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), + * ]); * * @author Fabien Potencier <fabien@symfony.com> */ @@ -30,15 +30,16 @@ class InputDefinition { private $arguments; private $requiredCount; - private $hasAnArrayArgument = false; - private $hasOptional; + private $lastArrayArgument; + private $lastOptionalArgument; private $options; + private $negations; private $shortcuts; /** * @param array $definition An array of InputArgument and InputOption instance */ - public function __construct(array $definition = array()) + public function __construct(array $definition = []) { $this->setDefinition($definition); } @@ -48,8 +49,8 @@ public function __construct(array $definition = array()) */ public function setDefinition(array $definition) { - $arguments = array(); - $options = array(); + $arguments = []; + $options = []; foreach ($definition as $item) { if ($item instanceof InputOption) { $options[] = $item; @@ -67,12 +68,12 @@ public function setDefinition(array $definition) * * @param InputArgument[] $arguments An array of InputArgument objects */ - public function setArguments($arguments = array()) + public function setArguments(array $arguments = []) { - $this->arguments = array(); + $this->arguments = []; $this->requiredCount = 0; - $this->hasOptional = false; - $this->hasAnArrayArgument = false; + $this->lastOptionalArgument = null; + $this->lastArrayArgument = null; $this->addArguments($arguments); } @@ -81,7 +82,7 @@ public function setArguments($arguments = array()) * * @param InputArgument[] $arguments An array of InputArgument objects */ - public function addArguments($arguments = array()) + public function addArguments(?array $arguments = []) { if (null !== $arguments) { foreach ($arguments as $argument) { @@ -99,22 +100,22 @@ public function addArgument(InputArgument $argument) throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName())); } - if ($this->hasAnArrayArgument) { - throw new LogicException('Cannot add an argument after an array argument.'); + if (null !== $this->lastArrayArgument) { + throw new LogicException(sprintf('Cannot add a required argument "%s" after an array argument "%s".', $argument->getName(), $this->lastArrayArgument->getName())); } - if ($argument->isRequired() && $this->hasOptional) { - throw new LogicException('Cannot add a required argument after an optional one.'); + if ($argument->isRequired() && null !== $this->lastOptionalArgument) { + throw new LogicException(sprintf('Cannot add a required argument "%s" after an optional one "%s".', $argument->getName(), $this->lastOptionalArgument->getName())); } if ($argument->isArray()) { - $this->hasAnArrayArgument = true; + $this->lastArrayArgument = $argument; } if ($argument->isRequired()) { ++$this->requiredCount; } else { - $this->hasOptional = true; + $this->lastOptionalArgument = $argument; } $this->arguments[$argument->getName()] = $argument; @@ -125,7 +126,7 @@ public function addArgument(InputArgument $argument) * * @param string|int $name The InputArgument name or position * - * @return InputArgument An InputArgument object + * @return InputArgument * * @throws InvalidArgumentException When argument given doesn't exist */ @@ -145,7 +146,7 @@ public function getArgument($name) * * @param string|int $name The InputArgument name or position * - * @return bool true if the InputArgument object exists, false otherwise + * @return bool */ public function hasArgument($name) { @@ -157,7 +158,7 @@ public function hasArgument($name) /** * Gets the array of InputArgument objects. * - * @return InputArgument[] An array of InputArgument objects + * @return InputArgument[] */ public function getArguments() { @@ -167,17 +168,17 @@ public function getArguments() /** * Returns the number of InputArguments. * - * @return int The number of InputArguments + * @return int */ public function getArgumentCount() { - return $this->hasAnArrayArgument ? PHP_INT_MAX : \count($this->arguments); + return null !== $this->lastArrayArgument ? \PHP_INT_MAX : \count($this->arguments); } /** * Returns the number of required InputArguments. * - * @return int The number of required InputArguments + * @return int */ public function getArgumentRequiredCount() { @@ -185,13 +186,11 @@ public function getArgumentRequiredCount() } /** - * Gets the default values. - * - * @return array An array of default values + * @return array<string|bool|int|float|array|null> */ public function getArgumentDefaults() { - $values = array(); + $values = []; foreach ($this->arguments as $argument) { $values[$argument->getName()] = $argument->getDefault(); } @@ -204,10 +203,11 @@ public function getArgumentDefaults() * * @param InputOption[] $options An array of InputOption objects */ - public function setOptions($options = array()) + public function setOptions(array $options = []) { - $this->options = array(); - $this->shortcuts = array(); + $this->options = []; + $this->shortcuts = []; + $this->negations = []; $this->addOptions($options); } @@ -216,7 +216,7 @@ public function setOptions($options = array()) * * @param InputOption[] $options An array of InputOption objects */ - public function addOptions($options = array()) + public function addOptions(array $options = []) { foreach ($options as $option) { $this->addOption($option); @@ -231,6 +231,9 @@ public function addOption(InputOption $option) if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName())); } + if (isset($this->negations[$option->getName()])) { + throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName())); + } if ($option->getShortcut()) { foreach (explode('|', $option->getShortcut()) as $shortcut) { @@ -246,18 +249,24 @@ public function addOption(InputOption $option) $this->shortcuts[$shortcut] = $option->getName(); } } + + if ($option->isNegatable()) { + $negatedName = 'no-'.$option->getName(); + if (isset($this->options[$negatedName])) { + throw new LogicException(sprintf('An option named "%s" already exists.', $negatedName)); + } + $this->negations[$negatedName] = $option->getName(); + } } /** * Returns an InputOption by name. * - * @param string $name The InputOption name - * - * @return InputOption A InputOption object + * @return InputOption * * @throws InvalidArgumentException When option given doesn't exist */ - public function getOption($name) + public function getOption(string $name) { if (!$this->hasOption($name)) { throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); @@ -272,11 +281,9 @@ public function getOption($name) * This method can't be used to check if the user included the option when * executing the command (use getOption() instead). * - * @param string $name The InputOption name - * - * @return bool true if the InputOption object exists, false otherwise + * @return bool */ - public function hasOption($name) + public function hasOption(string $name) { return isset($this->options[$name]); } @@ -284,7 +291,7 @@ public function hasOption($name) /** * Gets the array of InputOption objects. * - * @return InputOption[] An array of InputOption objects + * @return InputOption[] */ public function getOptions() { @@ -294,35 +301,37 @@ public function getOptions() /** * Returns true if an InputOption object exists by shortcut. * - * @param string $name The InputOption shortcut - * - * @return bool true if the InputOption object exists, false otherwise + * @return bool */ - public function hasShortcut($name) + public function hasShortcut(string $name) { return isset($this->shortcuts[$name]); } + /** + * Returns true if an InputOption object exists by negated name. + */ + public function hasNegation(string $name): bool + { + return isset($this->negations[$name]); + } + /** * Gets an InputOption by shortcut. * - * @param string $shortcut The Shortcut name - * - * @return InputOption An InputOption object + * @return InputOption */ - public function getOptionForShortcut($shortcut) + public function getOptionForShortcut(string $shortcut) { return $this->getOption($this->shortcutToName($shortcut)); } /** - * Gets an array of default values. - * - * @return array An array of all default values + * @return array<string|bool|int|float|array|null> */ public function getOptionDefaults() { - $values = array(); + $values = []; foreach ($this->options as $option) { $values[$option->getName()] = $option->getDefault(); } @@ -333,13 +342,11 @@ public function getOptionDefaults() /** * Returns the InputOption name given a shortcut. * - * @param string $shortcut The shortcut - * - * @return string The InputOption name - * * @throws InvalidArgumentException When option given does not exist + * + * @internal */ - private function shortcutToName($shortcut) + public function shortcutToName(string $shortcut): string { if (!isset($this->shortcuts[$shortcut])) { throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); @@ -349,15 +356,29 @@ private function shortcutToName($shortcut) } /** - * Gets the synopsis. + * Returns the InputOption name given a negation. * - * @param bool $short Whether to return the short version (with options folded) or not + * @throws InvalidArgumentException When option given does not exist + * + * @internal + */ + public function negationToName(string $negation): string + { + if (!isset($this->negations[$negation])) { + throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $negation)); + } + + return $this->negations[$negation]; + } + + /** + * Gets the synopsis. * - * @return string The synopsis + * @return string */ - public function getSynopsis($short = false) + public function getSynopsis(bool $short = false) { - $elements = array(); + $elements = []; if ($short && $this->getOptions()) { $elements[] = '[options]'; @@ -374,7 +395,8 @@ public function getSynopsis($short = false) } $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; - $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value); + $negation = $option->isNegatable() ? sprintf('|--no-%s', $option->getName()) : ''; + $elements[] = sprintf('[%s--%s%s%s]', $shortcut, $option->getName(), $value, $negation); } } @@ -382,21 +404,21 @@ public function getSynopsis($short = false) $elements[] = '[--]'; } + $tail = ''; foreach ($this->getArguments() as $argument) { $element = '<'.$argument->getName().'>'; - if (!$argument->isRequired()) { - $element = '['.$element.']'; - } elseif ($argument->isArray()) { - $element = $element.' ('.$element.')'; - } - if ($argument->isArray()) { $element .= '...'; } + if (!$argument->isRequired()) { + $element = '['.$element; + $tail .= ']'; + } + $elements[] = $element; } - return implode(' ', $elements); + return implode(' ', $elements).$tail; } } diff --git a/vendor/symfony/console/Input/InputInterface.php b/vendor/symfony/console/Input/InputInterface.php index 43810f7..628b603 100644 --- a/vendor/symfony/console/Input/InputInterface.php +++ b/vendor/symfony/console/Input/InputInterface.php @@ -24,7 +24,7 @@ interface InputInterface /** * Returns the first argument from the raw parameters (not parsed). * - * @return string|null The value of the first argument or null otherwise + * @return string|null */ public function getFirstArgument(); @@ -39,9 +39,9 @@ public function getFirstArgument(); * @param string|array $values The values to look for in the raw parameters (can be an array) * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal * - * @return bool true if the value is contained in the raw parameters + * @return bool */ - public function hasParameterOption($values, $onlyParams = false); + public function hasParameterOption($values, bool $onlyParams = false); /** * Returns the value of a raw option (not parsed). @@ -51,16 +51,18 @@ public function hasParameterOption($values, $onlyParams = false); * Does not necessarily return the correct result for short options * when multiple flags are combined in the same option. * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal + * @param string|array $values The value(s) to look for in the raw parameters (can be an array) + * @param string|bool|int|float|array|null $default The default value to return if no result is found + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal * - * @return mixed The option value + * @return mixed */ - public function getParameterOption($values, $default = false, $onlyParams = false); + public function getParameterOption($values, $default = false, bool $onlyParams = false); /** * Binds the current Input instance with the given arguments and options. + * + * @throws RuntimeException */ public function bind(InputDefinition $definition); @@ -74,76 +76,66 @@ public function validate(); /** * Returns all the given arguments merged with the default values. * - * @return array + * @return array<string|bool|int|float|array|null> */ public function getArguments(); /** * Returns the argument value for a given argument name. * - * @param string $name The argument name - * - * @return mixed The argument value + * @return mixed * * @throws InvalidArgumentException When argument given doesn't exist */ - public function getArgument($name); + public function getArgument(string $name); /** * Sets an argument value by name. * - * @param string $name The argument name - * @param string $value The argument value + * @param mixed $value The argument value * * @throws InvalidArgumentException When argument given doesn't exist */ - public function setArgument($name, $value); + public function setArgument(string $name, $value); /** * Returns true if an InputArgument object exists by name or position. * - * @param string|int $name The InputArgument name or position - * - * @return bool true if the InputArgument object exists, false otherwise + * @return bool */ - public function hasArgument($name); + public function hasArgument(string $name); /** * Returns all the given options merged with the default values. * - * @return array + * @return array<string|bool|int|float|array|null> */ public function getOptions(); /** * Returns the option value for a given option name. * - * @param string $name The option name - * - * @return mixed The option value + * @return mixed * * @throws InvalidArgumentException When option given doesn't exist */ - public function getOption($name); + public function getOption(string $name); /** * Sets an option value by name. * - * @param string $name The option name - * @param string|bool $value The option value + * @param mixed $value The option value * * @throws InvalidArgumentException When option given doesn't exist */ - public function setOption($name, $value); + public function setOption(string $name, $value); /** * Returns true if an InputOption object exists by name. * - * @param string $name The InputOption name - * - * @return bool true if the InputOption object exists, false otherwise + * @return bool */ - public function hasOption($name); + public function hasOption(string $name); /** * Is this input means interactive? @@ -154,8 +146,6 @@ public function isInteractive(); /** * Sets the input interactivity. - * - * @param bool $interactive If the input should be interactive */ - public function setInteractive($interactive); + public function setInteractive(bool $interactive); } diff --git a/vendor/symfony/console/Input/InputOption.php b/vendor/symfony/console/Input/InputOption.php index 9567876..2bec34f 100644 --- a/vendor/symfony/console/Input/InputOption.php +++ b/vendor/symfony/console/Input/InputOption.php @@ -21,10 +21,30 @@ */ class InputOption { - const VALUE_NONE = 1; - const VALUE_REQUIRED = 2; - const VALUE_OPTIONAL = 4; - const VALUE_IS_ARRAY = 8; + /** + * Do not accept input for the option (e.g. --yell). This is the default behavior of options. + */ + public const VALUE_NONE = 1; + + /** + * A value must be passed when the option is used (e.g. --iterations=5 or -i5). + */ + public const VALUE_REQUIRED = 2; + + /** + * The option may or may not have a value (e.g. --yell or --yell=loud). + */ + public const VALUE_OPTIONAL = 4; + + /** + * The option accepts multiple values (e.g. --dir=/foo --dir=/bar). + */ + public const VALUE_IS_ARRAY = 8; + + /** + * The option may have either positive or negative value (e.g. --ansi or --no-ansi). + */ + public const VALUE_NEGATABLE = 16; private $name; private $shortcut; @@ -33,17 +53,15 @@ class InputOption private $description; /** - * @param string $name The option name - * @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts - * @param int $mode The option mode: One of the VALUE_* constants - * @param string $description A description text - * @param mixed $default The default value (must be null for self::VALUE_NONE) + * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param int|null $mode The option mode: One of the VALUE_* constants + * @param string|bool|int|float|array|null $default The default value (must be null for self::VALUE_NONE) * * @throws InvalidArgumentException If option mode is invalid or incompatible */ - public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null) + public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) { - if (0 === strpos($name, '--')) { + if (str_starts_with($name, '--')) { $name = substr($name, 2); } @@ -70,7 +88,7 @@ public function __construct($name, $shortcut = null, $mode = null, $description if (null === $mode) { $mode = self::VALUE_NONE; - } elseif (!\is_int($mode) || $mode > 15 || $mode < 1) { + } elseif ($mode >= (self::VALUE_NEGATABLE << 1) || $mode < 1) { throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); } @@ -82,6 +100,9 @@ public function __construct($name, $shortcut = null, $mode = null, $description if ($this->isArray() && !$this->acceptValue()) { throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); } + if ($this->isNegatable() && $this->acceptValue()) { + throw new InvalidArgumentException('Impossible to have an option mode VALUE_NEGATABLE if the option also accepts a value.'); + } $this->setDefault($default); } @@ -89,7 +110,7 @@ public function __construct($name, $shortcut = null, $mode = null, $description /** * Returns the option shortcut. * - * @return string The shortcut + * @return string|null */ public function getShortcut() { @@ -99,7 +120,7 @@ public function getShortcut() /** * Returns the option name. * - * @return string The name + * @return string */ public function getName() { @@ -146,12 +167,13 @@ public function isArray() return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); } + public function isNegatable(): bool + { + return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode); + } + /** - * Sets the default value. - * - * @param mixed $default The default value - * - * @throws LogicException When incorrect default value is given + * @param string|bool|int|float|array|null $default */ public function setDefault($default = null) { @@ -161,19 +183,19 @@ public function setDefault($default = null) if ($this->isArray()) { if (null === $default) { - $default = array(); + $default = []; } elseif (!\is_array($default)) { throw new LogicException('A default value for an array option must be an array.'); } } - $this->default = $this->acceptValue() ? $default : false; + $this->default = $this->acceptValue() || $this->isNegatable() ? $default : false; } /** * Returns the default value. * - * @return mixed The default value + * @return string|bool|int|float|array|null */ public function getDefault() { @@ -183,7 +205,7 @@ public function getDefault() /** * Returns the description text. * - * @return string The description text + * @return string */ public function getDescription() { @@ -200,6 +222,7 @@ public function equals(self $option) return $option->getName() === $this->getName() && $option->getShortcut() === $this->getShortcut() && $option->getDefault() === $this->getDefault() + && $option->isNegatable() === $this->isNegatable() && $option->isArray() === $this->isArray() && $option->isValueRequired() === $this->isValueRequired() && $option->isValueOptional() === $this->isValueOptional() diff --git a/vendor/symfony/console/Input/StringInput.php b/vendor/symfony/console/Input/StringInput.php index eb39ad6..56bb66c 100644 --- a/vendor/symfony/console/Input/StringInput.php +++ b/vendor/symfony/console/Input/StringInput.php @@ -24,15 +24,16 @@ */ class StringInput extends ArgvInput { - const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)'; - const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')'; + public const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)'; + public const REGEX_UNQUOTED_STRING = '([^\s\\\\]+?)'; + public const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')'; /** * @param string $input A string representing the parameters from the CLI */ - public function __construct($input) + public function __construct(string $input) { - parent::__construct(array()); + parent::__construct([]); $this->setTokens($this->tokenize($input)); } @@ -40,33 +41,44 @@ public function __construct($input) /** * Tokenizes a string. * - * @param string $input The input to tokenize - * - * @return array An array of tokens - * * @throws InvalidArgumentException When unable to parse input (should never happen) */ - private function tokenize($input) + private function tokenize(string $input): array { - $tokens = array(); + $tokens = []; $length = \strlen($input); $cursor = 0; + $token = null; while ($cursor < $length) { - if (preg_match('/\s+/A', $input, $match, null, $cursor)) { - } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { - $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, \strlen($match[3]) - 2))); - } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) { - $tokens[] = stripcslashes(substr($match[0], 1, \strlen($match[0]) - 2)); - } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) { - $tokens[] = stripcslashes($match[1]); + if ('\\' === $input[$cursor]) { + $token .= $input[++$cursor] ?? ''; + ++$cursor; + continue; + } + + if (preg_match('/\s+/A', $input, $match, 0, $cursor)) { + if (null !== $token) { + $tokens[] = $token; + $token = null; + } + } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, 0, $cursor)) { + $token .= $match[1].$match[2].stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', substr($match[3], 1, -1))); + } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, 0, $cursor)) { + $token .= stripcslashes(substr($match[0], 1, -1)); + } elseif (preg_match('/'.self::REGEX_UNQUOTED_STRING.'/A', $input, $match, 0, $cursor)) { + $token .= $match[1]; } else { // should never happen - throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); + throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ...".', substr($input, $cursor, 10))); } $cursor += \strlen($match[0]); } + if (null !== $token) { + $tokens[] = $token; + } + return $tokens; } } diff --git a/vendor/symfony/console/LICENSE b/vendor/symfony/console/LICENSE index 21d7fb9..0138f8f 100644 --- a/vendor/symfony/console/LICENSE +++ b/vendor/symfony/console/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/console/Logger/ConsoleLogger.php b/vendor/symfony/console/Logger/ConsoleLogger.php index ea7f9bf..4a10fa1 100644 --- a/vendor/symfony/console/Logger/ConsoleLogger.php +++ b/vendor/symfony/console/Logger/ConsoleLogger.php @@ -22,15 +22,15 @@ * * @author Kévin Dunglas <dunglas@gmail.com> * - * @see http://www.php-fig.org/psr/psr-3/ + * @see https://www.php-fig.org/psr/psr-3/ */ class ConsoleLogger extends AbstractLogger { - const INFO = 'info'; - const ERROR = 'error'; + public const INFO = 'info'; + public const ERROR = 'error'; private $output; - private $verbosityLevelMap = array( + private $verbosityLevelMap = [ LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, @@ -39,8 +39,8 @@ class ConsoleLogger extends AbstractLogger LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE, LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG, - ); - private $formatLevelMap = array( + ]; + private $formatLevelMap = [ LogLevel::EMERGENCY => self::ERROR, LogLevel::ALERT => self::ERROR, LogLevel::CRITICAL => self::ERROR, @@ -49,10 +49,10 @@ class ConsoleLogger extends AbstractLogger LogLevel::NOTICE => self::INFO, LogLevel::INFO => self::INFO, LogLevel::DEBUG => self::INFO, - ); + ]; private $errored = false; - public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array()) + public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = []) { $this->output = $output; $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap; @@ -61,8 +61,10 @@ public function __construct(OutputInterface $output, array $verbosityLevelMap = /** * {@inheritdoc} + * + * @return void */ - public function log($level, $message, array $context = array()) + public function log($level, $message, array $context = []) { if (!isset($this->verbosityLevelMap[$level])) { throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); @@ -99,21 +101,16 @@ public function hasErrored() * Interpolates context values into the message placeholders. * * @author PHP Framework Interoperability Group - * - * @param string $message - * @param array $context - * - * @return string */ - private function interpolate($message, array $context) + private function interpolate(string $message, array $context): string { - if (false === strpos($message, '{')) { + if (!str_contains($message, '{')) { return $message; } - $replacements = array(); + $replacements = []; foreach ($context as $key => $val) { - if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { + if (null === $val || \is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { $replacements["{{$key}}"] = $val; } elseif ($val instanceof \DateTimeInterface) { $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); diff --git a/vendor/symfony/console/Output/BufferedOutput.php b/vendor/symfony/console/Output/BufferedOutput.php index 8afc893..d37c6e3 100644 --- a/vendor/symfony/console/Output/BufferedOutput.php +++ b/vendor/symfony/console/Output/BufferedOutput.php @@ -34,12 +34,12 @@ public function fetch() /** * {@inheritdoc} */ - protected function doWrite($message, $newline) + protected function doWrite(string $message, bool $newline) { $this->buffer .= $message; if ($newline) { - $this->buffer .= PHP_EOL; + $this->buffer .= \PHP_EOL; } } } diff --git a/vendor/symfony/console/Output/ConsoleOutput.php b/vendor/symfony/console/Output/ConsoleOutput.php index 3cb0fb1..f19f9eb 100644 --- a/vendor/symfony/console/Output/ConsoleOutput.php +++ b/vendor/symfony/console/Output/ConsoleOutput.php @@ -30,16 +30,24 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface { private $stderr; + private $consoleSectionOutputs = []; /** * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) */ - public function __construct($verbosity = self::VERBOSITY_NORMAL, $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); + if (null === $formatter) { + // for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter. + $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated); + + return; + } + $actualDecorated = $this->isDecorated(); $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); @@ -48,10 +56,18 @@ public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = nu } } + /** + * Creates a new output section. + */ + public function section(): ConsoleSectionOutput + { + return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter()); + } + /** * {@inheritdoc} */ - public function setDecorated($decorated) + public function setDecorated(bool $decorated) { parent::setDecorated($decorated); $this->stderr->setDecorated($decorated); @@ -69,7 +85,7 @@ public function setFormatter(OutputFormatterInterface $formatter) /** * {@inheritdoc} */ - public function setVerbosity($level) + public function setVerbosity(int $level) { parent::setVerbosity($level); $this->stderr->setVerbosity($level); @@ -116,16 +132,14 @@ protected function hasStderrSupport() /** * Checks if current executing environment is IBM iSeries (OS400), which * doesn't properly convert character-encodings between ASCII to EBCDIC. - * - * @return bool */ - private function isRunningOS400() + private function isRunningOS400(): bool { - $checks = array( + $checks = [ \function_exists('php_uname') ? php_uname('s') : '', getenv('OSTYPE'), - PHP_OS, - ); + \PHP_OS, + ]; return false !== stripos(implode(';', $checks), 'OS400'); } @@ -139,7 +153,8 @@ private function openOutputStream() return fopen('php://output', 'w'); } - return @fopen('php://stdout', 'w') ?: fopen('php://output', 'w'); + // Use STDOUT when possible to prevent from opening too many file descriptors + return \defined('STDOUT') ? \STDOUT : (@fopen('php://stdout', 'w') ?: fopen('php://output', 'w')); } /** @@ -147,6 +162,11 @@ private function openOutputStream() */ private function openErrorStream() { - return fopen($this->hasStderrSupport() ? 'php://stderr' : 'php://output', 'w'); + if (!$this->hasStderrSupport()) { + return fopen('php://output', 'w'); + } + + // Use STDERR when possible to prevent from opening too many file descriptors + return \defined('STDERR') ? \STDERR : (@fopen('php://stderr', 'w') ?: fopen('php://output', 'w')); } } diff --git a/vendor/symfony/console/Output/ConsoleOutputInterface.php b/vendor/symfony/console/Output/ConsoleOutputInterface.php index b44ea7e..6b6635f 100644 --- a/vendor/symfony/console/Output/ConsoleOutputInterface.php +++ b/vendor/symfony/console/Output/ConsoleOutputInterface.php @@ -13,7 +13,7 @@ /** * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. - * This adds information about stderr output stream. + * This adds information about stderr and section output stream. * * @author Dariusz Górecki <darek.krk@gmail.com> */ @@ -27,4 +27,6 @@ interface ConsoleOutputInterface extends OutputInterface public function getErrorOutput(); public function setErrorOutput(OutputInterface $error); + + public function section(): ConsoleSectionOutput; } diff --git a/vendor/symfony/console/Output/ConsoleSectionOutput.php b/vendor/symfony/console/Output/ConsoleSectionOutput.php new file mode 100644 index 0000000..8f16497 --- /dev/null +++ b/vendor/symfony/console/Output/ConsoleSectionOutput.php @@ -0,0 +1,143 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Terminal; + +/** + * @author Pierre du Plessis <pdples@gmail.com> + * @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com> + */ +class ConsoleSectionOutput extends StreamOutput +{ + private $content = []; + private $lines = 0; + private $sections; + private $terminal; + + /** + * @param resource $stream + * @param ConsoleSectionOutput[] $sections + */ + public function __construct($stream, array &$sections, int $verbosity, bool $decorated, OutputFormatterInterface $formatter) + { + parent::__construct($stream, $verbosity, $decorated, $formatter); + array_unshift($sections, $this); + $this->sections = &$sections; + $this->terminal = new Terminal(); + } + + /** + * Clears previous output for this section. + * + * @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) + { + if (empty($this->content) || !$this->isDecorated()) { + return; + } + + if ($lines) { + array_splice($this->content, -($lines * 2)); // Multiply lines by 2 to cater for each new line added between content + } else { + $lines = $this->lines; + $this->content = []; + } + + $this->lines -= $lines; + + parent::doWrite($this->popStreamContentUntilCurrentSection($lines), false); + } + + /** + * Overwrites the previous output with a new message. + * + * @param array|string $message + */ + public function overwrite($message) + { + $this->clear(); + $this->writeln($message); + } + + public function getContent(): string + { + return implode('', $this->content); + } + + /** + * @internal + */ + public function addContent(string $input) + { + foreach (explode(\PHP_EOL, $input) as $lineContent) { + $this->lines += ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1; + $this->content[] = $lineContent; + $this->content[] = \PHP_EOL; + } + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $message, bool $newline) + { + if (!$this->isDecorated()) { + parent::doWrite($message, $newline); + + return; + } + + $erasedContent = $this->popStreamContentUntilCurrentSection(); + + $this->addContent($message); + + parent::doWrite($message, true); + parent::doWrite($erasedContent, false); + } + + /** + * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits + * current section. Then it erases content it crawled through. Optionally, it erases part of current section too. + */ + private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFromCurrentSection = 0): string + { + $numberOfLinesToClear = $numberOfLinesToClearFromCurrentSection; + $erasedContent = []; + + foreach ($this->sections as $section) { + if ($section === $this) { + break; + } + + $numberOfLinesToClear += $section->lines; + $erasedContent[] = $section->getContent(); + } + + if ($numberOfLinesToClear > 0) { + // move cursor up n lines + parent::doWrite(sprintf("\x1b[%dA", $numberOfLinesToClear), false); + // erase to end of screen + parent::doWrite("\x1b[0J", false); + } + + return implode('', array_reverse($erasedContent)); + } + + private function getDisplayLength(string $text): int + { + return Helper::width(Helper::removeDecoration($this->getFormatter(), str_replace("\t", ' ', $text))); + } +} diff --git a/vendor/symfony/console/Output/NullOutput.php b/vendor/symfony/console/Output/NullOutput.php index 218f285..3bbe63e 100644 --- a/vendor/symfony/console/Output/NullOutput.php +++ b/vendor/symfony/console/Output/NullOutput.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Console\Output; -use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\NullOutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** @@ -24,6 +24,8 @@ */ class NullOutput implements OutputInterface { + private $formatter; + /** * {@inheritdoc} */ @@ -37,14 +39,17 @@ public function setFormatter(OutputFormatterInterface $formatter) */ public function getFormatter() { + if ($this->formatter) { + return $this->formatter; + } // to comply with the interface we must return a OutputFormatterInterface - return new OutputFormatter(); + return $this->formatter = new NullOutputFormatter(); } /** * {@inheritdoc} */ - public function setDecorated($decorated) + public function setDecorated(bool $decorated) { // do nothing } @@ -60,7 +65,7 @@ public function isDecorated() /** * {@inheritdoc} */ - public function setVerbosity($level) + public function setVerbosity(int $level) { // do nothing } @@ -108,7 +113,7 @@ public function isDebug() /** * {@inheritdoc} */ - public function writeln($messages, $options = self::OUTPUT_NORMAL) + public function writeln($messages, int $options = self::OUTPUT_NORMAL) { // do nothing } @@ -116,7 +121,7 @@ public function writeln($messages, $options = self::OUTPUT_NORMAL) /** * {@inheritdoc} */ - public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL) + public function write($messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) { // do nothing } diff --git a/vendor/symfony/console/Output/Output.php b/vendor/symfony/console/Output/Output.php index c3856cc..d7c5fb2 100644 --- a/vendor/symfony/console/Output/Output.php +++ b/vendor/symfony/console/Output/Output.php @@ -33,14 +33,14 @@ abstract class Output implements OutputInterface private $formatter; /** - * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) + * @param int|null $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool $decorated Whether to decorate messages * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) */ - public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null) + public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) { - $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; - $this->formatter = $formatter ?: new OutputFormatter(); + $this->verbosity = $verbosity ?? self::VERBOSITY_NORMAL; + $this->formatter = $formatter ?? new OutputFormatter(); $this->formatter->setDecorated($decorated); } @@ -63,7 +63,7 @@ public function getFormatter() /** * {@inheritdoc} */ - public function setDecorated($decorated) + public function setDecorated(bool $decorated) { $this->formatter->setDecorated($decorated); } @@ -79,9 +79,9 @@ public function isDecorated() /** * {@inheritdoc} */ - public function setVerbosity($level) + public function setVerbosity(int $level) { - $this->verbosity = (int) $level; + $this->verbosity = $level; } /** @@ -127,7 +127,7 @@ public function isDebug() /** * {@inheritdoc} */ - public function writeln($messages, $options = self::OUTPUT_NORMAL) + public function writeln($messages, int $options = self::OUTPUT_NORMAL) { $this->write($messages, true, $options); } @@ -135,9 +135,11 @@ public function writeln($messages, $options = self::OUTPUT_NORMAL) /** * {@inheritdoc} */ - public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL) + public function write($messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) { - $messages = (array) $messages; + if (!is_iterable($messages)) { + $messages = [$messages]; + } $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN; $type = $types & $options ?: self::OUTPUT_NORMAL; @@ -161,15 +163,12 @@ public function write($messages, $newline = false, $options = self::OUTPUT_NORMA break; } - $this->doWrite($message, $newline); + $this->doWrite($message ?? '', $newline); } } /** * Writes a message to the output. - * - * @param string $message A message to write to the output - * @param bool $newline Whether to add a newline or not */ - abstract protected function doWrite($message, $newline); + abstract protected function doWrite(string $message, bool $newline); } diff --git a/vendor/symfony/console/Output/OutputInterface.php b/vendor/symfony/console/Output/OutputInterface.php index ad785a4..55caab8 100644 --- a/vendor/symfony/console/Output/OutputInterface.php +++ b/vendor/symfony/console/Output/OutputInterface.php @@ -20,86 +20,82 @@ */ interface OutputInterface { - const VERBOSITY_QUIET = 16; - const VERBOSITY_NORMAL = 32; - const VERBOSITY_VERBOSE = 64; - const VERBOSITY_VERY_VERBOSE = 128; - const VERBOSITY_DEBUG = 256; + public const VERBOSITY_QUIET = 16; + public const VERBOSITY_NORMAL = 32; + public const VERBOSITY_VERBOSE = 64; + public const VERBOSITY_VERY_VERBOSE = 128; + public const VERBOSITY_DEBUG = 256; - const OUTPUT_NORMAL = 1; - const OUTPUT_RAW = 2; - const OUTPUT_PLAIN = 4; + public const OUTPUT_NORMAL = 1; + public const OUTPUT_RAW = 2; + public const OUTPUT_PLAIN = 4; /** * Writes a message to the output. * - * @param string|array $messages The message as an array of strings or a single string - * @param bool $newline Whether to add a newline - * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL + * @param string|iterable $messages The message as an iterable of strings or a single string + * @param bool $newline Whether to add a newline + * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL */ - public function write($messages, $newline = false, $options = 0); + public function write($messages, bool $newline = false, int $options = 0); /** * Writes a message to the output and adds a newline at the end. * - * @param string|array $messages The message as an array of strings or a single string - * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL + * @param string|iterable $messages The message as an iterable of strings or a single string + * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL */ - public function writeln($messages, $options = 0); + public function writeln($messages, int $options = 0); /** * Sets the verbosity of the output. - * - * @param int $level The level of verbosity (one of the VERBOSITY constants) */ - public function setVerbosity($level); + public function setVerbosity(int $level); /** * Gets the current verbosity of the output. * - * @return int The current level of verbosity (one of the VERBOSITY constants) + * @return int */ public function getVerbosity(); /** * Returns whether verbosity is quiet (-q). * - * @return bool true if verbosity is set to VERBOSITY_QUIET, false otherwise + * @return bool */ public function isQuiet(); /** * Returns whether verbosity is verbose (-v). * - * @return bool true if verbosity is set to VERBOSITY_VERBOSE, false otherwise + * @return bool */ public function isVerbose(); /** * Returns whether verbosity is very verbose (-vv). * - * @return bool true if verbosity is set to VERBOSITY_VERY_VERBOSE, false otherwise + * @return bool */ public function isVeryVerbose(); /** * Returns whether verbosity is debug (-vvv). * - * @return bool true if verbosity is set to VERBOSITY_DEBUG, false otherwise + * @return bool */ public function isDebug(); /** * Sets the decorated flag. - * - * @param bool $decorated Whether to decorate the messages */ - public function setDecorated($decorated); + public function setDecorated(bool $decorated); /** * Gets the decorated flag. * - * @return bool true if the output will decorate messages, false otherwise + * @return bool */ public function isDecorated(); diff --git a/vendor/symfony/console/Output/StreamOutput.php b/vendor/symfony/console/Output/StreamOutput.php index 20f4508..7f55518 100644 --- a/vendor/symfony/console/Output/StreamOutput.php +++ b/vendor/symfony/console/Output/StreamOutput.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** @@ -20,11 +19,11 @@ * * Usage: * - * $output = new StreamOutput(fopen('php://stdout', 'w')); + * $output = new StreamOutput(fopen('php://stdout', 'w')); * * As `StreamOutput` can use any stream, you can also use a file: * - * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); + * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); * * @author Fabien Potencier <fabien@symfony.com> */ @@ -40,7 +39,7 @@ class StreamOutput extends Output * * @throws InvalidArgumentException When first argument is not a real stream */ - public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $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.'); @@ -58,7 +57,7 @@ public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decor /** * Gets the stream attached to this StreamOutput instance. * - * @return resource A stream resource + * @return resource */ public function getStream() { @@ -68,13 +67,14 @@ public function getStream() /** * {@inheritdoc} */ - protected function doWrite($message, $newline) + protected function doWrite(string $message, bool $newline) { - if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) { - // should never happen - throw new RuntimeException('Unable to write output.'); + if ($newline) { + $message .= \PHP_EOL; } + @fwrite($this->stream, $message); + fflush($this->stream); } @@ -93,6 +93,11 @@ protected function doWrite($message, $newline) */ protected function hasColorSupport() { + // Follow https://no-color.org/ + if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) { + return false; + } + if ('Hyper' === getenv('TERM_PROGRAM')) { return true; } @@ -105,16 +110,6 @@ protected function hasColorSupport() || 'xterm' === getenv('TERM'); } - if (\function_exists('stream_isatty')) { - return @stream_isatty($this->stream); - } - - if (\function_exists('posix_isatty')) { - return @posix_isatty($this->stream); - } - - $stat = @fstat($this->stream); - // Check if formatted mode is S_IFCHR - return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; + return stream_isatty($this->stream); } } diff --git a/vendor/symfony/console/Output/TrimmedBufferOutput.php b/vendor/symfony/console/Output/TrimmedBufferOutput.php new file mode 100644 index 0000000..3f4d375 --- /dev/null +++ b/vendor/symfony/console/Output/TrimmedBufferOutput.php @@ -0,0 +1,63 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * A BufferedOutput that keeps only the last N chars. + * + * @author Jérémy Derussé <jeremy@derusse.com> + */ +class TrimmedBufferOutput extends Output +{ + private $maxLength; + private $buffer = ''; + + 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)); + } + + parent::__construct($verbosity, $decorated, $formatter); + $this->maxLength = $maxLength; + } + + /** + * Empties buffer and returns its content. + * + * @return string + */ + public function fetch() + { + $content = $this->buffer; + $this->buffer = ''; + + return $content; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $message, bool $newline) + { + $this->buffer .= $message; + + if ($newline) { + $this->buffer .= \PHP_EOL; + } + + $this->buffer = substr($this->buffer, 0 - $this->maxLength); + } +} diff --git a/vendor/symfony/console/Question/ChoiceQuestion.php b/vendor/symfony/console/Question/ChoiceQuestion.php index 0a45d74..bf1f904 100644 --- a/vendor/symfony/console/Question/ChoiceQuestion.php +++ b/vendor/symfony/console/Question/ChoiceQuestion.php @@ -30,7 +30,7 @@ class ChoiceQuestion extends Question * @param array $choices The list of available choices * @param mixed $default The default answer to return */ - public function __construct($question, array $choices, $default = null) + public function __construct(string $question, array $choices, $default = null) { if (!$choices) { throw new \LogicException('Choice question must have at least 1 choice available.'); @@ -58,11 +58,9 @@ public function getChoices() * * When multiselect is set to true, multiple choices can be answered. * - * @param bool $multiselect - * * @return $this */ - public function setMultiselect($multiselect) + public function setMultiselect(bool $multiselect) { $this->multiselect = $multiselect; $this->setValidator($this->getDefaultValidator()); @@ -93,11 +91,9 @@ public function getPrompt() /** * Sets the prompt for choices. * - * @param string $prompt - * * @return $this */ - public function setPrompt($prompt) + public function setPrompt(string $prompt) { $this->prompt = $prompt; @@ -109,11 +105,9 @@ public function setPrompt($prompt) * * The error message has a string placeholder (%s) for the invalid value. * - * @param string $errorMessage - * * @return $this */ - public function setErrorMessage($errorMessage) + public function setErrorMessage(string $errorMessage) { $this->errorMessage = $errorMessage; $this->setValidator($this->getDefaultValidator()); @@ -121,12 +115,7 @@ public function setErrorMessage($errorMessage) return $this; } - /** - * Returns the default answer validator. - * - * @return callable - */ - private function getDefaultValidator() + private function getDefaultValidator(): callable { $choices = $this->choices; $errorMessage = $this->errorMessage; @@ -134,22 +123,26 @@ private function getDefaultValidator() $isAssoc = $this->isAssoc($choices); return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) { - // Collapse all spaces. - $selectedChoices = str_replace(' ', '', $selected); - if ($multiselect) { // Check for a separated comma values - if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) { + if (!preg_match('/^[^,]+(?:,[^,]+)*$/', (string) $selected, $matches)) { throw new InvalidArgumentException(sprintf($errorMessage, $selected)); } - $selectedChoices = explode(',', $selectedChoices); + + $selectedChoices = explode(',', (string) $selected); } else { - $selectedChoices = array($selected); + $selectedChoices = [$selected]; + } + + if ($this->isTrimmable()) { + foreach ($selectedChoices as $k => $v) { + $selectedChoices[$k] = trim((string) $v); + } } - $multiselectChoices = array(); + $multiselectChoices = []; foreach ($selectedChoices as $value) { - $results = array(); + $results = []; foreach ($choices as $key => $choice) { if ($choice === $value) { $results[] = $key; @@ -157,7 +150,7 @@ private function getDefaultValidator() } if (\count($results) > 1) { - throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results))); + throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of "%s".', implode('" or "', $results))); } $result = array_search($value, $choices); @@ -176,7 +169,8 @@ private function getDefaultValidator() throw new InvalidArgumentException(sprintf($errorMessage, $value)); } - $multiselectChoices[] = (string) $result; + // For associative choices, consistently return the key as string: + $multiselectChoices[] = $isAssoc ? (string) $result : $result; } if ($multiselect) { diff --git a/vendor/symfony/console/Question/ConfirmationQuestion.php b/vendor/symfony/console/Question/ConfirmationQuestion.php index 150ab27..4228521 100644 --- a/vendor/symfony/console/Question/ConfirmationQuestion.php +++ b/vendor/symfony/console/Question/ConfirmationQuestion.php @@ -25,9 +25,9 @@ class ConfirmationQuestion extends Question * @param bool $default The default answer to return, true or false * @param string $trueAnswerRegex A regex to match the "yes" answer */ - public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i') + public function __construct(string $question, bool $default = true, string $trueAnswerRegex = '/^y/i') { - parent::__construct($question, (bool) $default); + parent::__construct($question, $default); $this->trueAnswerRegex = $trueAnswerRegex; $this->setNormalizer($this->getDefaultNormalizer()); @@ -35,10 +35,8 @@ public function __construct($question, $default = true, $trueAnswerRegex = '/^y/ /** * Returns the default answer normalizer. - * - * @return callable */ - private function getDefaultNormalizer() + private function getDefaultNormalizer(): callable { $default = $this->getDefault(); $regex = $this->trueAnswerRegex; @@ -53,7 +51,7 @@ private function getDefaultNormalizer() return $answer && $answerIsTrue; } - return !$answer || $answerIsTrue; + return '' === $answer || $answerIsTrue; }; } } diff --git a/vendor/symfony/console/Question/Question.php b/vendor/symfony/console/Question/Question.php index 2ca95ac..3a73f04 100644 --- a/vendor/symfony/console/Question/Question.php +++ b/vendor/symfony/console/Question/Question.php @@ -25,16 +25,18 @@ class Question private $attempts; private $hidden = false; private $hiddenFallback = true; - private $autocompleterValues; + private $autocompleterCallback; private $validator; private $default; private $normalizer; + private $trimmable = true; + private $multiline = false; /** - * @param string $question The question to ask to the user - * @param mixed $default The default answer to return if the user enters nothing + * @param string $question The question to ask to the user + * @param string|bool|int|float|null $default The default answer to return if the user enters nothing */ - public function __construct($question, $default = null) + public function __construct(string $question, $default = null) { $this->question = $question; $this->default = $default; @@ -53,13 +55,33 @@ public function getQuestion() /** * Returns the default answer. * - * @return mixed + * @return string|bool|int|float|null */ public function getDefault() { return $this->default; } + /** + * Returns whether the user response accepts newline characters. + */ + public function isMultiline(): bool + { + return $this->multiline; + } + + /** + * Sets whether the user response should accept newline characters. + * + * @return $this + */ + public function setMultiline(bool $multiline): self + { + $this->multiline = $multiline; + + return $this; + } + /** * Returns whether the user response must be hidden. * @@ -73,25 +95,23 @@ public function isHidden() /** * Sets whether the user response must be hidden or not. * - * @param bool $hidden - * * @return $this * * @throws LogicException In case the autocompleter is also used */ - public function setHidden($hidden) + public function setHidden(bool $hidden) { - if ($this->autocompleterValues) { + if ($this->autocompleterCallback) { throw new LogicException('A hidden question cannot use the autocompleter.'); } - $this->hidden = (bool) $hidden; + $this->hidden = $hidden; return $this; } /** - * In case the response can not be hidden, whether to fallback on non-hidden question or not. + * In case the response cannot be hidden, whether to fallback on non-hidden question or not. * * @return bool */ @@ -101,15 +121,13 @@ public function isHiddenFallback() } /** - * Sets whether to fallback on non-hidden question if the response can not be hidden. - * - * @param bool $fallback + * Sets whether to fallback on non-hidden question if the response cannot be hidden. * * @return $this */ - public function setHiddenFallback($fallback) + public function setHiddenFallback(bool $fallback) { - $this->hiddenFallback = (bool) $fallback; + $this->hiddenFallback = $fallback; return $this; } @@ -117,38 +135,64 @@ public function setHiddenFallback($fallback) /** * Gets values for the autocompleter. * - * @return null|iterable + * @return iterable|null */ public function getAutocompleterValues() { - return $this->autocompleterValues; + $callback = $this->getAutocompleterCallback(); + + return $callback ? $callback('') : null; } /** * Sets values for the autocompleter. * - * @param null|iterable $values - * * @return $this * - * @throws InvalidArgumentException * @throws LogicException */ - public function setAutocompleterValues($values) + public function setAutocompleterValues(?iterable $values) { if (\is_array($values)) { $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values); - } - if (null !== $values && !\is_array($values) && !$values instanceof \Traversable) { - throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.'); + $callback = static function () use ($values) { + return $values; + }; + } elseif ($values instanceof \Traversable) { + $valueCache = null; + $callback = static function () use ($values, &$valueCache) { + return $valueCache ?? $valueCache = iterator_to_array($values, false); + }; + } else { + $callback = null; } - if ($this->hidden) { + return $this->setAutocompleterCallback($callback); + } + + /** + * Gets the callback function used for the autocompleter. + */ + public function getAutocompleterCallback(): ?callable + { + return $this->autocompleterCallback; + } + + /** + * Sets the callback function used for the autocompleter. + * + * The callback is passed the user input as argument and should return an iterable of corresponding suggestions. + * + * @return $this + */ + public function setAutocompleterCallback(callable $callback = null): self + { + if ($this->hidden && null !== $callback) { throw new LogicException('A hidden question cannot use the autocompleter.'); } - $this->autocompleterValues = $values; + $this->autocompleterCallback = $callback; return $this; } @@ -156,8 +200,6 @@ public function setAutocompleterValues($values) /** * Sets a validator for the question. * - * @param null|callable $validator - * * @return $this */ public function setValidator(callable $validator = null) @@ -170,7 +212,7 @@ public function setValidator(callable $validator = null) /** * Gets the validator for the question. * - * @return null|callable + * @return callable|null */ public function getValidator() { @@ -182,13 +224,11 @@ public function getValidator() * * Null means an unlimited number of attempts. * - * @param null|int $attempts - * * @return $this * * @throws InvalidArgumentException in case the number of attempts is invalid */ - public function setMaxAttempts($attempts) + public function setMaxAttempts(?int $attempts) { if (null !== $attempts && $attempts < 1) { throw new InvalidArgumentException('Maximum number of attempts must be a positive value.'); @@ -204,7 +244,7 @@ public function setMaxAttempts($attempts) * * Null means an unlimited number of attempts. * - * @return null|int + * @return int|null */ public function getMaxAttempts() { @@ -216,8 +256,6 @@ public function getMaxAttempts() * * The normalizer can be a callable (a string), a closure or a class implementing __invoke. * - * @param callable $normalizer - * * @return $this */ public function setNormalizer(callable $normalizer) @@ -232,15 +270,30 @@ public function setNormalizer(callable $normalizer) * * The normalizer can ba a callable (a string), a closure or a class implementing __invoke. * - * @return callable + * @return callable|null */ public function getNormalizer() { return $this->normalizer; } - protected function isAssoc($array) + protected function isAssoc(array $array) { return (bool) \count(array_filter(array_keys($array), 'is_string')); } + + public function isTrimmable(): bool + { + return $this->trimmable; + } + + /** + * @return $this + */ + public function setTrimmable(bool $trimmable): self + { + $this->trimmable = $trimmable; + + return $this; + } } diff --git a/vendor/symfony/console/README.md b/vendor/symfony/console/README.md index 664a37c..c4c1299 100644 --- a/vendor/symfony/console/README.md +++ b/vendor/symfony/console/README.md @@ -4,17 +4,33 @@ Console Component The Console component eases the creation of beautiful and testable command line interfaces. +Sponsor +------- + +The Console component for Symfony 5.4/6.0 is [backed][1] by [Les-Tilleuls.coop][2]. + +Les-Tilleuls.coop is a team of 50+ Symfony experts who can help you design, develop and +fix your projects. We provide a wide range of professional services including development, +consulting, coaching, training and audits. We also are highly skilled in JS, Go and DevOps. +We are a worker cooperative! + +Help Symfony by [sponsoring][3] its development! + Resources --------- - * [Documentation](https://symfony.com/doc/current/components/console/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) + * [Documentation](https://symfony.com/doc/current/components/console.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) Credits ------- `Resources/bin/hiddeninput.exe` is a third party binary provided within this component. Find sources and license at https://github.com/Seldaek/hidden-input. + +[1]: https://symfony.com/backers +[2]: https://les-tilleuls.coop +[3]: https://symfony.com/sponsor diff --git a/vendor/symfony/console/Resources/completion.bash b/vendor/symfony/console/Resources/completion.bash new file mode 100644 index 0000000..64b87cc --- /dev/null +++ b/vendor/symfony/console/Resources/completion.bash @@ -0,0 +1,84 @@ +# This file is part of the Symfony package. +# +# (c) Fabien Potencier <fabien@symfony.com> +# +# For the full copyright and license information, please view +# https://symfony.com/doc/current/contributing/code/license.html + +_sf_{{ COMMAND_NAME }}() { + # Use newline as only separator to allow space in completion values + IFS=$'\n' + local sf_cmd="${COMP_WORDS[0]}" + + # for an alias, get the real script behind it + sf_cmd_type=$(type -t $sf_cmd) + if [[ $sf_cmd_type == "alias" ]]; then + sf_cmd=$(alias $sf_cmd | sed -E "s/alias $sf_cmd='(.*)'/\1/") + elif [[ $sf_cmd_type == "file" ]]; then + sf_cmd=$(type -p $sf_cmd) + fi + + if [[ $sf_cmd_type != "function" && ! -x $sf_cmd ]]; then + return 1 + fi + + local cur prev words cword + _get_comp_words_by_ref -n := cur prev words cword + + local completecmd=("$sf_cmd" "_complete" "--no-interaction" "-sbash" "-c$cword" "-S{{ VERSION }}") + for w in ${words[@]}; do + w=$(printf -- '%b' "$w") + # remove quotes from typed values + quote="${w:0:1}" + if [ "$quote" == \' ]; then + w="${w%\'}" + w="${w#\'}" + elif [ "$quote" == \" ]; then + w="${w%\"}" + w="${w#\"}" + fi + # empty values are ignored + if [ ! -z "$w" ]; then + completecmd+=("-i$w") + fi + done + + local sfcomplete + if sfcomplete=$(${completecmd[@]} 2>&1); then + local quote suggestions + quote=${cur:0:1} + + # Use single quotes by default if suggestions contains backslash (FQCN) + if [ "$quote" == '' ] && [[ "$sfcomplete" =~ \\ ]]; then + quote=\' + fi + + if [ "$quote" == \' ]; then + # single quotes: no additional escaping (does not accept ' in values) + suggestions=$(for s in $sfcomplete; do printf $'%q%q%q\n' "$quote" "$s" "$quote"; done) + elif [ "$quote" == \" ]; then + # double quotes: double escaping for \ $ ` " + suggestions=$(for s in $sfcomplete; do + s=${s//\\/\\\\} + s=${s//\$/\\\$} + s=${s//\`/\\\`} + s=${s//\"/\\\"} + printf $'%q%q%q\n' "$quote" "$s" "$quote"; + done) + else + # no quotes: double escaping + suggestions=$(for s in $sfcomplete; do printf $'%q\n' $(printf '%q' "$s"); done) + fi + COMPREPLY=($(IFS=$'\n' compgen -W "$suggestions" -- $(printf -- "%q" "$cur"))) + __ltrim_colon_completions "$cur" + else + if [[ "$sfcomplete" != *"Command \"_complete\" is not defined."* ]]; then + >&2 echo + >&2 echo $sfcomplete + fi + + return 1 + fi +} + +complete -F _sf_{{ COMMAND_NAME }} {{ COMMAND_NAME }} diff --git a/vendor/symfony/console/SignalRegistry/SignalRegistry.php b/vendor/symfony/console/SignalRegistry/SignalRegistry.php new file mode 100644 index 0000000..6bee24a --- /dev/null +++ b/vendor/symfony/console/SignalRegistry/SignalRegistry.php @@ -0,0 +1,65 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\SignalRegistry; + +final class SignalRegistry +{ + private $signalHandlers = []; + + public function __construct() + { + if (\function_exists('pcntl_async_signals')) { + pcntl_async_signals(true); + } + } + + public function register(int $signal, callable $signalHandler): void + { + if (!isset($this->signalHandlers[$signal])) { + $previousCallback = pcntl_signal_get_handler($signal); + + if (\is_callable($previousCallback)) { + $this->signalHandlers[$signal][] = $previousCallback; + } + } + + $this->signalHandlers[$signal][] = $signalHandler; + + pcntl_signal($signal, [$this, 'handle']); + } + + public static function isSupported(): bool + { + if (!\function_exists('pcntl_signal')) { + return false; + } + + if (\in_array('pcntl_signal', explode(',', \ini_get('disable_functions')))) { + return false; + } + + return true; + } + + /** + * @internal + */ + public function handle(int $signal): void + { + $count = \count($this->signalHandlers[$signal]); + + foreach ($this->signalHandlers[$signal] as $i => $signalHandler) { + $hasNext = $i !== $count - 1; + $signalHandler($signal, $hasNext); + } + } +} diff --git a/vendor/symfony/console/SingleCommandApplication.php b/vendor/symfony/console/SingleCommandApplication.php new file mode 100644 index 0000000..e93c182 --- /dev/null +++ b/vendor/symfony/console/SingleCommandApplication.php @@ -0,0 +1,72 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Grégoire Pineau <lyrixx@lyrixx.info> + */ +class SingleCommandApplication extends Command +{ + private $version = 'UNKNOWN'; + private $autoExit = true; + private $running = false; + + /** + * @return $this + */ + public function setVersion(string $version): self + { + $this->version = $version; + + return $this; + } + + /** + * @final + * + * @return $this + */ + public function setAutoExit(bool $autoExit): self + { + $this->autoExit = $autoExit; + + return $this; + } + + public function run(InputInterface $input = null, OutputInterface $output = null): int + { + if ($this->running) { + return parent::run($input, $output); + } + + // We use the command name as the application name + $application = new Application($this->getName() ?: 'UNKNOWN', $this->version); + $application->setAutoExit($this->autoExit); + // Fix the usage of the command displayed with "--help" + $this->setName($_SERVER['argv'][0]); + $application->add($this); + $application->setDefaultCommand($this->getName(), true); + + $this->running = true; + try { + $ret = $application->run($input, $output); + } finally { + $this->running = false; + } + + return $ret ?? 1; + } +} diff --git a/vendor/symfony/console/Style/OutputStyle.php b/vendor/symfony/console/Style/OutputStyle.php index b1262b5..67a98ff 100644 --- a/vendor/symfony/console/Style/OutputStyle.php +++ b/vendor/symfony/console/Style/OutputStyle.php @@ -33,17 +33,15 @@ public function __construct(OutputInterface $output) /** * {@inheritdoc} */ - public function newLine($count = 1) + public function newLine(int $count = 1) { - $this->output->write(str_repeat(PHP_EOL, $count)); + $this->output->write(str_repeat(\PHP_EOL, $count)); } /** - * @param int $max - * * @return ProgressBar */ - public function createProgressBar($max = 0) + public function createProgressBar(int $max = 0) { return new ProgressBar($this->output, $max); } @@ -51,7 +49,7 @@ public function createProgressBar($max = 0) /** * {@inheritdoc} */ - public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) + public function write($messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) { $this->output->write($messages, $newline, $type); } @@ -59,7 +57,7 @@ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) /** * {@inheritdoc} */ - public function writeln($messages, $type = self::OUTPUT_NORMAL) + public function writeln($messages, int $type = self::OUTPUT_NORMAL) { $this->output->writeln($messages, $type); } @@ -67,7 +65,7 @@ public function writeln($messages, $type = self::OUTPUT_NORMAL) /** * {@inheritdoc} */ - public function setVerbosity($level) + public function setVerbosity(int $level) { $this->output->setVerbosity($level); } @@ -83,7 +81,7 @@ public function getVerbosity() /** * {@inheritdoc} */ - public function setDecorated($decorated) + public function setDecorated(bool $decorated) { $this->output->setDecorated($decorated); } diff --git a/vendor/symfony/console/Style/StyleInterface.php b/vendor/symfony/console/Style/StyleInterface.php index 475c268..38d23b7 100644 --- a/vendor/symfony/console/Style/StyleInterface.php +++ b/vendor/symfony/console/Style/StyleInterface.php @@ -20,17 +20,13 @@ interface StyleInterface { /** * Formats a command title. - * - * @param string $message */ - public function title($message); + public function title(string $message); /** * Formats a section title. - * - * @param string $message */ - public function section($message); + public function section(string $message); /** * Formats a list. @@ -87,65 +83,47 @@ public function table(array $headers, array $rows); /** * Asks a question. * - * @param string $question - * @param string|null $default - * @param callable|null $validator - * * @return mixed */ - public function ask($question, $default = null, $validator = null); + public function ask(string $question, string $default = null, callable $validator = null); /** * Asks a question with the user input hidden. * - * @param string $question - * @param callable|null $validator - * * @return mixed */ - public function askHidden($question, $validator = null); + public function askHidden(string $question, callable $validator = null); /** * Asks for confirmation. * - * @param string $question - * @param bool $default - * * @return bool */ - public function confirm($question, $default = true); + public function confirm(string $question, bool $default = true); /** * Asks a choice question. * - * @param string $question - * @param array $choices * @param string|int|null $default * * @return mixed */ - public function choice($question, array $choices, $default = null); + public function choice(string $question, array $choices, $default = null); /** * Add newline(s). - * - * @param int $count The number of newlines */ - public function newLine($count = 1); + public function newLine(int $count = 1); /** * Starts the progress output. - * - * @param int $max Maximum steps (0 if unknown) */ - public function progressStart($max = 0); + public function progressStart(int $max = 0); /** * Advances the progress output X steps. - * - * @param int $step Number of steps to advance */ - public function progressAdvance($step = 1); + public function progressAdvance(int $step = 1); /** * Finishes the progress output. diff --git a/vendor/symfony/console/Style/SymfonyStyle.php b/vendor/symfony/console/Style/SymfonyStyle.php index e74ab66..e3c5ac8 100644 --- a/vendor/symfony/console/Style/SymfonyStyle.php +++ b/vendor/symfony/console/Style/SymfonyStyle.php @@ -11,15 +11,19 @@ namespace Symfony\Component\Console\Style; +use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\SymfonyQuestionHelper; use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableCell; +use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\BufferedOutput; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\TrimmedBufferOutput; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\Question; @@ -32,9 +36,10 @@ */ class SymfonyStyle extends OutputStyle { - const MAX_LINE_LENGTH = 120; + public const MAX_LINE_LENGTH = 120; private $input; + private $output; private $questionHelper; private $progressBar; private $lineLength; @@ -43,27 +48,22 @@ class SymfonyStyle extends OutputStyle public function __construct(InputInterface $input, OutputInterface $output) { $this->input = $input; - $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter()); + $this->bufferedOutput = new TrimmedBufferOutput(\DIRECTORY_SEPARATOR === '\\' ? 4 : 2, $output->getVerbosity(), false, clone $output->getFormatter()); // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not. $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH; $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH); - parent::__construct($output); + parent::__construct($this->output = $output); } /** * Formats a message as a block of text. * * @param string|array $messages The message to write in the block - * @param string|null $type The block type (added in [] on first line) - * @param string|null $style The style to apply to the whole block - * @param string $prefix The prefix for the block - * @param bool $padding Whether to add vertical padding - * @param bool $escape Whether to escape the message */ - public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $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) : array($messages); + $messages = \is_array($messages) ? array_values($messages) : [$messages]; $this->autoPrependBlock(); $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape)); @@ -73,26 +73,26 @@ public function block($messages, $type = null, $style = null, $prefix = ' ', $pa /** * {@inheritdoc} */ - public function title($message) + public function title(string $message) { $this->autoPrependBlock(); - $this->writeln(array( + $this->writeln([ sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), - sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))), - )); + sprintf('<comment>%s</>', str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))), + ]); $this->newLine(); } /** * {@inheritdoc} */ - public function section($message) + public function section(string $message) { $this->autoPrependBlock(); - $this->writeln(array( + $this->writeln([ sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), - sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))), - )); + sprintf('<comment>%s</>', str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))), + ]); $this->newLine(); } @@ -117,7 +117,7 @@ public function text($message) { $this->autoPrependText(); - $messages = \is_array($message) ? array_values($message) : array($message); + $messages = \is_array($message) ? array_values($message) : [$message]; foreach ($messages as $message) { $this->writeln(sprintf(' %s', $message)); } @@ -154,7 +154,7 @@ public function error($message) */ public function warning($message) { - $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true); + $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', true); } /** @@ -165,6 +165,16 @@ public function note($message) $this->block($message, 'NOTE', 'fg=yellow', ' ! '); } + /** + * Formats an info message. + * + * @param string|array $message + */ + public function info($message) + { + $this->block($message, 'INFO', 'fg=green', ' ', true); + } + /** * {@inheritdoc} */ @@ -178,22 +188,69 @@ public function caution($message) */ public function table(array $headers, array $rows) { - $style = clone Table::getStyleDefinition('symfony-style-guide'); - $style->setCellHeaderFormat('<info>%s</info>'); + $this->createTable() + ->setHeaders($headers) + ->setRows($rows) + ->render() + ; + + $this->newLine(); + } - $table = new Table($this); - $table->setHeaders($headers); - $table->setRows($rows); - $table->setStyle($style); + /** + * Formats a horizontal table. + */ + public function horizontalTable(array $headers, array $rows) + { + $this->createTable() + ->setHorizontal(true) + ->setHeaders($headers) + ->setRows($rows) + ->render() + ; - $table->render(); $this->newLine(); } + /** + * Formats a list of key/value horizontally. + * + * Each row can be one of: + * * 'A title' + * * ['key' => 'value'] + * * new TableSeparator() + * + * @param string|array|TableSeparator ...$list + */ + public function definitionList(...$list) + { + $headers = []; + $row = []; + foreach ($list as $value) { + if ($value instanceof TableSeparator) { + $headers[] = $value; + $row[] = $value; + continue; + } + if (\is_string($value)) { + $headers[] = new TableCell($value, ['colspan' => 2]); + $row[] = null; + continue; + } + if (!\is_array($value)) { + throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.'); + } + $headers[] = key($value); + $row[] = current($value); + } + + $this->horizontalTable($headers, [$row]); + } + /** * {@inheritdoc} */ - public function ask($question, $default = null, $validator = null) + public function ask(string $question, string $default = null, callable $validator = null) { $question = new Question($question, $default); $question->setValidator($validator); @@ -204,7 +261,7 @@ public function ask($question, $default = null, $validator = null) /** * {@inheritdoc} */ - public function askHidden($question, $validator = null) + public function askHidden(string $question, callable $validator = null) { $question = new Question($question); @@ -217,7 +274,7 @@ public function askHidden($question, $validator = null) /** * {@inheritdoc} */ - public function confirm($question, $default = true) + public function confirm(string $question, bool $default = true) { return $this->askQuestion(new ConfirmationQuestion($question, $default)); } @@ -225,11 +282,11 @@ public function confirm($question, $default = true) /** * {@inheritdoc} */ - public function choice($question, array $choices, $default = null) + public function choice(string $question, array $choices, $default = null) { if (null !== $default) { $values = array_flip($choices); - $default = $values[$default]; + $default = $values[$default] ?? $default; } return $this->askQuestion(new ChoiceQuestion($question, $choices, $default)); @@ -238,7 +295,7 @@ public function choice($question, array $choices, $default = null) /** * {@inheritdoc} */ - public function progressStart($max = 0) + public function progressStart(int $max = 0) { $this->progressBar = $this->createProgressBar($max); $this->progressBar->start(); @@ -247,7 +304,7 @@ public function progressStart($max = 0) /** * {@inheritdoc} */ - public function progressAdvance($step = 1) + public function progressAdvance(int $step = 1) { $this->getProgressBar()->advance($step); } @@ -265,7 +322,7 @@ public function progressFinish() /** * {@inheritdoc} */ - public function createProgressBar($max = 0) + public function createProgressBar(int $max = 0) { $progressBar = parent::createProgressBar($max); @@ -278,6 +335,16 @@ public function createProgressBar($max = 0) return $progressBar; } + /** + * @see ProgressBar::iterate() + */ + public function progressIterate(iterable $iterable, int $max = null): iterable + { + yield from $this->createProgressBar()->iterate($iterable, $max); + + $this->newLine(2); + } + /** * @return mixed */ @@ -304,25 +371,37 @@ public function askQuestion(Question $question) /** * {@inheritdoc} */ - public function writeln($messages, $type = self::OUTPUT_NORMAL) + public function writeln($messages, int $type = self::OUTPUT_NORMAL) { - parent::writeln($messages, $type); - $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type); + if (!is_iterable($messages)) { + $messages = [$messages]; + } + + foreach ($messages as $message) { + parent::writeln($message, $type); + $this->writeBuffer($message, true, $type); + } } /** * {@inheritdoc} */ - public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) + public function write($messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) { - parent::write($messages, $newline, $type); - $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type); + if (!is_iterable($messages)) { + $messages = [$messages]; + } + + foreach ($messages as $message) { + parent::write($message, $newline, $type); + $this->writeBuffer($message, $newline, $type); + } } /** * {@inheritdoc} */ - public function newLine($count = 1) + public function newLine(int $count = 1) { parent::newLine($count); $this->bufferedOutput->write(str_repeat("\n", $count)); @@ -338,10 +417,16 @@ public function getErrorStyle() return new self($this->input, $this->getErrorOutput()); } - /** - * @return ProgressBar - */ - private function getProgressBar() + public function createTable(): Table + { + $output = $this->output instanceof ConsoleOutputInterface ? $this->output->section() : $this->output; + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('<info>%s</info>'); + + return (new Table($output))->setStyle($style); + } + + private function getProgressBar(): ProgressBar { if (!$this->progressBar) { throw new RuntimeException('The ProgressBar is not started.'); @@ -350,40 +435,39 @@ private function getProgressBar() return $this->progressBar; } - private function autoPrependBlock() + private function autoPrependBlock(): void { - $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); + $chars = substr(str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); if (!isset($chars[0])) { - return $this->newLine(); //empty history, so we should start with a new line. + $this->newLine(); // empty history, so we should start with a new line. + + return; } - //Prepend new line for each non LF chars (This means no blank line was output before) + // Prepend new line for each non LF chars (This means no blank line was output before) $this->newLine(2 - substr_count($chars, "\n")); } - private function autoPrependText() + private function autoPrependText(): void { $fetched = $this->bufferedOutput->fetch(); - //Prepend new line if last char isn't EOL: - if ("\n" !== substr($fetched, -1)) { + // Prepend new line if last char isn't EOL: + if (!str_ends_with($fetched, "\n")) { $this->newLine(); } } - private function reduceBuffer($messages) + private function writeBuffer(string $message, bool $newLine, int $type): void { - // We need to know if the two last chars are PHP_EOL - // Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer - return array_map(function ($value) { - return substr($value, -4); - }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages)); + // We need to know if the last chars are PHP_EOL + $this->bufferedOutput->write($message, $newLine, $type); } - private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false) + private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array { $indentLength = 0; - $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix); - $lines = array(); + $prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix)); + $lines = []; if (null !== $type) { $type = sprintf('[%s] ', $type); @@ -397,7 +481,12 @@ private function createBlock($messages, $type = null, $style = null, $prefix = ' $message = OutputFormatter::escape($message); } - $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true))); + $decorationLength = Helper::width($message) - Helper::width(Helper::removeDecoration($this->getFormatter(), $message)); + $messageLineLength = min($this->lineLength - $prefixLength - $indentLength + $decorationLength, $this->lineLength); + $messageLines = explode(\PHP_EOL, wordwrap($message, $messageLineLength, \PHP_EOL, true)); + foreach ($messageLines as $messageLine) { + $lines[] = $messageLine; + } if (\count($messages) > 1 && $key < \count($messages) - 1) { $lines[] = ''; @@ -417,7 +506,7 @@ private function createBlock($messages, $type = null, $style = null, $prefix = ' } $line = $prefix.$line; - $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line)); + $line .= str_repeat(' ', max($this->lineLength - Helper::width(Helper::removeDecoration($this->getFormatter(), $line)), 0)); if ($style) { $line = sprintf('<%s>%s</>', $style, $line); diff --git a/vendor/symfony/console/Terminal.php b/vendor/symfony/console/Terminal.php index 3930ca0..b91e8af 100644 --- a/vendor/symfony/console/Terminal.php +++ b/vendor/symfony/console/Terminal.php @@ -15,6 +15,7 @@ class Terminal { private static $width; private static $height; + private static $stty; /** * Gets the terminal width. @@ -54,20 +55,60 @@ public function getHeight() return self::$height ?: 50; } + /** + * @internal + */ + public static function hasSttyAvailable(): bool + { + if (null !== self::$stty) { + return self::$stty; + } + + // skip check if shell_exec function is disabled + if (!\function_exists('shell_exec')) { + return false; + } + + return self::$stty = (bool) shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null')); + } + private static function initDimensions() { if ('\\' === \DIRECTORY_SEPARATOR) { - if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) { + $ansicon = getenv('ANSICON'); + if (false !== $ansicon && preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim($ansicon), $matches)) { // extract [w, H] from "wxh (WxH)" // or [w, h] from "wxh" self::$width = (int) $matches[1]; self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; + } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { + // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash) + // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT + self::initDimensionsUsingStty(); } elseif (null !== $dimensions = self::getConsoleMode()) { // extract [w, h] from "wxh" self::$width = (int) $dimensions[0]; self::$height = (int) $dimensions[1]; } - } elseif ($sttyString = self::getSttyColumns()) { + } else { + self::initDimensionsUsingStty(); + } + } + + /** + * Returns whether STDOUT has vt100 support (some Windows 10+ configurations). + */ + private static function hasVt100Support(): bool + { + return \function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'w')); + } + + /** + * Initializes dimensions using the output of an stty columns line. + */ + private static function initDimensionsUsingStty() + { + if ($sttyString = self::getSttyColumns()) { if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { // extract [w, h] from "rows h; columns w;" self::$width = (int) $matches[2]; @@ -85,53 +126,52 @@ private static function initDimensions() * * @return int[]|null An array composed of the width and the height or null if it could not be parsed */ - private static function getConsoleMode() + private static function getConsoleMode(): ?array { - if (!\function_exists('proc_open')) { - return; - } + $info = self::readFromProcess('mode CON'); - $descriptorspec = array( - 1 => array('pipe', 'w'), - 2 => array('pipe', 'w'), - ); - $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); - if (\is_resource($process)) { - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); - - if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { - return array((int) $matches[2], (int) $matches[1]); - } + if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { + return null; } + + return [(int) $matches[2], (int) $matches[1]]; } /** * Runs and parses stty -a if it's available, suppressing any error output. - * - * @return string|null */ - private static function getSttyColumns() + private static function getSttyColumns(): ?string + { + return self::readFromProcess('stty -a | grep columns'); + } + + private static function readFromProcess(string $command): ?string { if (!\function_exists('proc_open')) { - return; + return null; } - $descriptorspec = array( - 1 => array('pipe', 'w'), - 2 => array('pipe', 'w'), - ); + $descriptorspec = [ + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; - $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); - if (\is_resource($process)) { - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); + $cp = \function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0; - return $info; + $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); + if (!\is_resource($process)) { + return null; } + + $info = stream_get_contents($pipes[1]); + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + + if ($cp) { + sapi_windows_cp_set($cp); + } + + return $info; } } diff --git a/vendor/symfony/console/Tester/ApplicationTester.php b/vendor/symfony/console/Tester/ApplicationTester.php index c0f8c72..3a262e8 100644 --- a/vendor/symfony/console/Tester/ApplicationTester.php +++ b/vendor/symfony/console/Tester/ApplicationTester.php @@ -13,10 +13,6 @@ use Symfony\Component\Console\Application; use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\StreamOutput; /** * Eases the testing of console applications. @@ -30,14 +26,9 @@ */ class ApplicationTester { + use TesterTrait; + private $application; - private $input; - private $statusCode; - /** - * @var OutputInterface - */ - private $output; - private $captureStreamsIndependently = false; public function __construct(Application $application) { @@ -54,123 +45,41 @@ public function __construct(Application $application) * * verbosity: Sets the output verbosity flag * * capture_stderr_separately: Make output of stdOut and stdErr separately available * - * @param array $input An array of arguments and options - * @param array $options An array of options - * * @return int The command exit code */ - public function run(array $input, $options = array()) + public function run(array $input, array $options = []) { - $this->input = new ArrayInput($input); - if (isset($options['interactive'])) { - $this->input->setInteractive($options['interactive']); - } + $prevShellVerbosity = getenv('SHELL_VERBOSITY'); - $this->captureStreamsIndependently = array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; - if (!$this->captureStreamsIndependently) { - $this->output = new StreamOutput(fopen('php://memory', 'w', false)); - if (isset($options['decorated'])) { - $this->output->setDecorated($options['decorated']); - } - if (isset($options['verbosity'])) { - $this->output->setVerbosity($options['verbosity']); + try { + $this->input = new ArrayInput($input); + if (isset($options['interactive'])) { + $this->input->setInteractive($options['interactive']); } - } else { - $this->output = new ConsoleOutput( - isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL, - isset($options['decorated']) ? $options['decorated'] : null - ); - - $errorOutput = new StreamOutput(fopen('php://memory', 'w', false)); - $errorOutput->setFormatter($this->output->getFormatter()); - $errorOutput->setVerbosity($this->output->getVerbosity()); - $errorOutput->setDecorated($this->output->isDecorated()); - - $reflectedOutput = new \ReflectionObject($this->output); - $strErrProperty = $reflectedOutput->getProperty('stderr'); - $strErrProperty->setAccessible(true); - $strErrProperty->setValue($this->output, $errorOutput); - - $reflectedParent = $reflectedOutput->getParentClass(); - $streamProperty = $reflectedParent->getProperty('stream'); - $streamProperty->setAccessible(true); - $streamProperty->setValue($this->output, fopen('php://memory', 'w', false)); - } - - return $this->statusCode = $this->application->run($this->input, $this->output); - } - - /** - * Gets the display returned by the last execution of the application. - * - * @param bool $normalize Whether to normalize end of lines to \n or not - * - * @return string The display - */ - public function getDisplay($normalize = false) - { - rewind($this->output->getStream()); - - $display = stream_get_contents($this->output->getStream()); - - if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); - } - - return $display; - } - - /** - * Gets the output written to STDERR by the application. - * - * @param bool $normalize Whether to normalize end of lines to \n or not - * - * @return string - */ - public function getErrorOutput($normalize = false) - { - if (!$this->captureStreamsIndependently) { - throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.'); - } - rewind($this->output->getErrorOutput()->getStream()); - - $display = stream_get_contents($this->output->getErrorOutput()->getStream()); + if ($this->inputs) { + $this->input->setStream(self::createStream($this->inputs)); + } - if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); + $this->initOutput($options); + + return $this->statusCode = $this->application->run($this->input, $this->output); + } finally { + // SHELL_VERBOSITY is set by Application::configureIO so we need to unset/reset it + // to its previous value to avoid one test's verbosity to spread to the following tests + if (false === $prevShellVerbosity) { + if (\function_exists('putenv')) { + @putenv('SHELL_VERBOSITY'); + } + unset($_ENV['SHELL_VERBOSITY']); + unset($_SERVER['SHELL_VERBOSITY']); + } else { + if (\function_exists('putenv')) { + @putenv('SHELL_VERBOSITY='.$prevShellVerbosity); + } + $_ENV['SHELL_VERBOSITY'] = $prevShellVerbosity; + $_SERVER['SHELL_VERBOSITY'] = $prevShellVerbosity; + } } - - return $display; - } - - /** - * Gets the input instance used by the last execution of the application. - * - * @return InputInterface The current input instance - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance used by the last execution of the application. - * - * @return OutputInterface The current output instance - */ - public function getOutput() - { - return $this->output; - } - - /** - * Gets the status code returned by the last execution of the application. - * - * @return int The status code - */ - public function getStatusCode() - { - return $this->statusCode; } } diff --git a/vendor/symfony/console/Tester/CommandCompletionTester.php b/vendor/symfony/console/Tester/CommandCompletionTester.php new file mode 100644 index 0000000..ade7327 --- /dev/null +++ b/vendor/symfony/console/Tester/CommandCompletionTester.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tester; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; + +/** + * Eases the testing of command completion. + * + * @author Jérôme Tamarelle <jerome@tamarelle.net> + */ +class CommandCompletionTester +{ + private $command; + + public function __construct(Command $command) + { + $this->command = $command; + } + + /** + * Create completion suggestions from input tokens. + */ + public function complete(array $input): array + { + $currentIndex = \count($input); + if ('' === end($input)) { + array_pop($input); + } + array_unshift($input, $this->command->getName()); + + $completionInput = CompletionInput::fromTokens($input, $currentIndex); + $completionInput->bind($this->command->getDefinition()); + $suggestions = new CompletionSuggestions(); + + $this->command->complete($completionInput, $suggestions); + + $options = []; + foreach ($suggestions->getOptionSuggestions() as $option) { + $options[] = '--'.$option->getName(); + } + + return array_map('strval', array_merge($options, $suggestions->getValueSuggestions())); + } +} diff --git a/vendor/symfony/console/Tester/CommandTester.php b/vendor/symfony/console/Tester/CommandTester.php index 131ca9b..6c15c25 100644 --- a/vendor/symfony/console/Tester/CommandTester.php +++ b/vendor/symfony/console/Tester/CommandTester.php @@ -13,9 +13,6 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\StreamOutput; /** * Eases the testing of console commands. @@ -25,11 +22,9 @@ */ class CommandTester { + use TesterTrait; + private $command; - private $input; - private $output; - private $inputs = array(); - private $statusCode; public function __construct(Command $command) { @@ -41,16 +36,17 @@ public function __construct(Command $command) * * Available execution options: * - * * interactive: Sets the input interactive flag - * * decorated: Sets the output decorated flag - * * verbosity: Sets the output verbosity flag + * * interactive: Sets the input interactive flag + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * * capture_stderr_separately: Make output of stdOut and stdErr separately available * * @param array $input An array of command arguments and options * @param array $options An array of execution options * * @return int The command exit code */ - public function execute(array $input, array $options = array()) + public function execute(array $input, array $options = []) { // set the command name automatically if the application requires // this argument and no command name was passed @@ -58,99 +54,23 @@ public function execute(array $input, array $options = array()) && (null !== $application = $this->command->getApplication()) && $application->getDefinition()->hasArgument('command') ) { - $input = array_merge(array('command' => $this->command->getName()), $input); + $input = array_merge(['command' => $this->command->getName()], $input); } $this->input = new ArrayInput($input); - if ($this->inputs) { - $this->input->setStream(self::createStream($this->inputs)); - } + // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN. + $this->input->setStream(self::createStream($this->inputs)); if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); } - $this->output = new StreamOutput(fopen('php://memory', 'w', false)); - $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false); - if (isset($options['verbosity'])) { - $this->output->setVerbosity($options['verbosity']); + if (!isset($options['decorated'])) { + $options['decorated'] = false; } - return $this->statusCode = $this->command->run($this->input, $this->output); - } - - /** - * Gets the display returned by the last execution of the command. - * - * @param bool $normalize Whether to normalize end of lines to \n or not - * - * @return string The display - */ - public function getDisplay($normalize = false) - { - rewind($this->output->getStream()); - - $display = stream_get_contents($this->output->getStream()); + $this->initOutput($options); - if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); - } - - return $display; - } - - /** - * Gets the input instance used by the last execution of the command. - * - * @return InputInterface The current input instance - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance used by the last execution of the command. - * - * @return OutputInterface The current output instance - */ - public function getOutput() - { - return $this->output; - } - - /** - * Gets the status code returned by the last execution of the application. - * - * @return int The status code - */ - public function getStatusCode() - { - return $this->statusCode; - } - - /** - * Sets the user inputs. - * - * @param array $inputs An array of strings representing each input - * passed to the command input stream - * - * @return CommandTester - */ - public function setInputs(array $inputs) - { - $this->inputs = $inputs; - - return $this; - } - - private static function createStream(array $inputs) - { - $stream = fopen('php://memory', 'r+', false); - - fwrite($stream, implode(PHP_EOL, $inputs)); - rewind($stream); - - return $stream; + return $this->statusCode = $this->command->run($this->input, $this->output); } } diff --git a/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php b/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php new file mode 100644 index 0000000..a473242 --- /dev/null +++ b/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tester\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\Console\Command\Command; + +final class CommandIsSuccessful extends Constraint +{ + /** + * {@inheritdoc} + */ + public function toString(): string + { + return 'is successful'; + } + + /** + * {@inheritdoc} + */ + protected function matches($other): bool + { + return Command::SUCCESS === $other; + } + + /** + * {@inheritdoc} + */ + protected function failureDescription($other): string + { + return 'the command '.$this->toString(); + } + + /** + * {@inheritdoc} + */ + protected function additionalFailureDescription($other): string + { + $mapping = [ + Command::FAILURE => 'Command failed.', + Command::INVALID => 'Command was invalid.', + ]; + + return $mapping[$other] ?? sprintf('Command returned exit status %d.', $other); + } +} diff --git a/vendor/symfony/console/Tester/TesterTrait.php b/vendor/symfony/console/Tester/TesterTrait.php new file mode 100644 index 0000000..f454bbf --- /dev/null +++ b/vendor/symfony/console/Tester/TesterTrait.php @@ -0,0 +1,197 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tester; + +use PHPUnit\Framework\Assert; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\StreamOutput; +use Symfony\Component\Console\Tester\Constraint\CommandIsSuccessful; + +/** + * @author Amrouche Hamza <hamza.simperfit@gmail.com> + */ +trait TesterTrait +{ + /** @var StreamOutput */ + private $output; + private $inputs = []; + private $captureStreamsIndependently = false; + /** @var InputInterface */ + private $input; + /** @var int */ + private $statusCode; + + /** + * 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 + */ + public function getDisplay(bool $normalize = false) + { + if (null === $this->output) { + throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?'); + } + + rewind($this->output->getStream()); + + $display = stream_get_contents($this->output->getStream()); + + if ($normalize) { + $display = str_replace(\PHP_EOL, "\n", $display); + } + + return $display; + } + + /** + * Gets the output written to STDERR by the application. + * + * @param bool $normalize Whether to normalize end of lines to \n or not + * + * @return string + */ + public function getErrorOutput(bool $normalize = false) + { + if (!$this->captureStreamsIndependently) { + throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.'); + } + + rewind($this->output->getErrorOutput()->getStream()); + + $display = stream_get_contents($this->output->getErrorOutput()->getStream()); + + if ($normalize) { + $display = str_replace(\PHP_EOL, "\n", $display); + } + + return $display; + } + + /** + * Gets the input instance used by the last execution of the command or application. + * + * @return InputInterface + */ + public function getInput() + { + return $this->input; + } + + /** + * Gets the output instance used by the last execution of the command or application. + * + * @return OutputInterface + */ + public function getOutput() + { + return $this->output; + } + + /** + * 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 + */ + public function getStatusCode() + { + if (null === $this->statusCode) { + throw new \RuntimeException('Status code not initialized, did you execute the command before requesting the status code?'); + } + + return $this->statusCode; + } + + public function assertCommandIsSuccessful(string $message = ''): void + { + Assert::assertThat($this->statusCode, new CommandIsSuccessful(), $message); + } + + /** + * Sets the user inputs. + * + * @param array $inputs An array of strings representing each input + * passed to the command input stream + * + * @return $this + */ + public function setInputs(array $inputs) + { + $this->inputs = $inputs; + + return $this; + } + + /** + * Initializes the output property. + * + * Available options: + * + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * * capture_stderr_separately: Make output of stdOut and stdErr separately available + */ + private function initOutput(array $options) + { + $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; + if (!$this->captureStreamsIndependently) { + $this->output = new StreamOutput(fopen('php://memory', 'w', false)); + if (isset($options['decorated'])) { + $this->output->setDecorated($options['decorated']); + } + if (isset($options['verbosity'])) { + $this->output->setVerbosity($options['verbosity']); + } + } else { + $this->output = new ConsoleOutput( + $options['verbosity'] ?? ConsoleOutput::VERBOSITY_NORMAL, + $options['decorated'] ?? null + ); + + $errorOutput = new StreamOutput(fopen('php://memory', 'w', false)); + $errorOutput->setFormatter($this->output->getFormatter()); + $errorOutput->setVerbosity($this->output->getVerbosity()); + $errorOutput->setDecorated($this->output->isDecorated()); + + $reflectedOutput = new \ReflectionObject($this->output); + $strErrProperty = $reflectedOutput->getProperty('stderr'); + $strErrProperty->setAccessible(true); + $strErrProperty->setValue($this->output, $errorOutput); + + $reflectedParent = $reflectedOutput->getParentClass(); + $streamProperty = $reflectedParent->getProperty('stream'); + $streamProperty->setAccessible(true); + $streamProperty->setValue($this->output, fopen('php://memory', 'w', false)); + } + } + + /** + * @return resource + */ + private static function createStream(array $inputs) + { + $stream = fopen('php://memory', 'r+', false); + + foreach ($inputs as $input) { + fwrite($stream, $input.\PHP_EOL); + } + + rewind($stream); + + return $stream; + } +} diff --git a/vendor/symfony/console/Tests/ApplicationTest.php b/vendor/symfony/console/Tests/ApplicationTest.php deleted file mode 100644 index 3c3b128..0000000 --- a/vendor/symfony/console/Tests/ApplicationTest.php +++ /dev/null @@ -1,1678 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; -use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; -use Symfony\Component\Console\Event\ConsoleCommandEvent; -use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Event\ConsoleExceptionEvent; -use Symfony\Component\Console\Event\ConsoleTerminateEvent; -use Symfony\Component\Console\Exception\CommandNotFoundException; -use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\NullOutput; -use Symfony\Component\Console\Output\Output; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\StreamOutput; -use Symfony\Component\Console\Tester\ApplicationTester; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\EventDispatcher\EventDispatcher; - -class ApplicationTest extends TestCase -{ - protected static $fixturesPath; - - public static function setUpBeforeClass() - { - self::$fixturesPath = realpath(__DIR__.'/Fixtures/'); - require_once self::$fixturesPath.'/FooCommand.php'; - require_once self::$fixturesPath.'/FooOptCommand.php'; - require_once self::$fixturesPath.'/Foo1Command.php'; - require_once self::$fixturesPath.'/Foo2Command.php'; - require_once self::$fixturesPath.'/Foo3Command.php'; - require_once self::$fixturesPath.'/Foo4Command.php'; - require_once self::$fixturesPath.'/Foo5Command.php'; - require_once self::$fixturesPath.'/FooSameCaseUppercaseCommand.php'; - require_once self::$fixturesPath.'/FooSameCaseLowercaseCommand.php'; - require_once self::$fixturesPath.'/FoobarCommand.php'; - require_once self::$fixturesPath.'/BarBucCommand.php'; - require_once self::$fixturesPath.'/FooSubnamespaced1Command.php'; - require_once self::$fixturesPath.'/FooSubnamespaced2Command.php'; - require_once self::$fixturesPath.'/TestTiti.php'; - require_once self::$fixturesPath.'/TestToto.php'; - } - - protected function normalizeLineBreaks($text) - { - return str_replace(PHP_EOL, "\n", $text); - } - - /** - * Replaces the dynamic placeholders of the command help text with a static version. - * The placeholder %command.full_name% includes the script path that is not predictable - * and can not be tested against. - */ - protected function ensureStaticCommandHelp(Application $application) - { - foreach ($application->all() as $command) { - $command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp())); - } - } - - public function testConstructor() - { - $application = new Application('foo', 'bar'); - $this->assertEquals('foo', $application->getName(), '__construct() takes the application name as its first argument'); - $this->assertEquals('bar', $application->getVersion(), '__construct() takes the application version as its second argument'); - $this->assertEquals(array('help', 'list'), array_keys($application->all()), '__construct() registered the help and list commands by default'); - } - - public function testSetGetName() - { - $application = new Application(); - $application->setName('foo'); - $this->assertEquals('foo', $application->getName(), '->setName() sets the name of the application'); - } - - public function testSetGetVersion() - { - $application = new Application(); - $application->setVersion('bar'); - $this->assertEquals('bar', $application->getVersion(), '->setVersion() sets the version of the application'); - } - - public function testGetLongVersion() - { - $application = new Application('foo', 'bar'); - $this->assertEquals('foo <info>bar</info>', $application->getLongVersion(), '->getLongVersion() returns the long version of the application'); - } - - public function testHelp() - { - $application = new Application(); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_gethelp.txt', $this->normalizeLineBreaks($application->getHelp()), '->getHelp() returns a help message'); - } - - public function testAll() - { - $application = new Application(); - $commands = $application->all(); - $this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands'); - - $application->add(new \FooCommand()); - $commands = $application->all('foo'); - $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); - } - - public function testAllWithCommandLoader() - { - $application = new Application(); - $commands = $application->all(); - $this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands'); - - $application->add(new \FooCommand()); - $commands = $application->all('foo'); - $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); - - $application->setCommandLoader(new FactoryCommandLoader(array( - 'foo:bar1' => function () { return new \Foo1Command(); }, - ))); - $commands = $application->all('foo'); - $this->assertCount(2, $commands, '->all() takes a namespace as its first argument'); - $this->assertInstanceOf(\FooCommand::class, $commands['foo:bar'], '->all() returns the registered commands'); - $this->assertInstanceOf(\Foo1Command::class, $commands['foo:bar1'], '->all() returns the registered commands'); - } - - public function testRegister() - { - $application = new Application(); - $command = $application->register('foo'); - $this->assertEquals('foo', $command->getName(), '->register() registers a new command'); - } - - public function testAdd() - { - $application = new Application(); - $application->add($foo = new \FooCommand()); - $commands = $application->all(); - $this->assertEquals($foo, $commands['foo:bar'], '->add() registers a command'); - - $application = new Application(); - $application->addCommands(array($foo = new \FooCommand(), $foo1 = new \Foo1Command())); - $commands = $application->all(); - $this->assertEquals(array($foo, $foo1), array($commands['foo:bar'], $commands['foo:bar1']), '->addCommands() registers an array of commands'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Command class "Foo5Command" is not correctly initialized. You probably forgot to call the parent constructor. - */ - public function testAddCommandWithEmptyConstructor() - { - $application = new Application(); - $application->add(new \Foo5Command()); - } - - public function testHasGet() - { - $application = new Application(); - $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered'); - $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered'); - - $application->add($foo = new \FooCommand()); - $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered'); - $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name'); - $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias'); - - $application = new Application(); - $application->add($foo = new \FooCommand()); - // simulate --help - $r = new \ReflectionObject($application); - $p = $r->getProperty('wantHelps'); - $p->setAccessible(true); - $p->setValue($application, true); - $command = $application->get('foo:bar'); - $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $command, '->get() returns the help command if --help is provided as the input'); - } - - public function testHasGetWithCommandLoader() - { - $application = new Application(); - $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered'); - $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered'); - - $application->add($foo = new \FooCommand()); - $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered'); - $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name'); - $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias'); - - $application->setCommandLoader(new FactoryCommandLoader(array( - 'foo:bar1' => function () { return new \Foo1Command(); }, - ))); - - $this->assertTrue($application->has('afoobar'), '->has() returns true if an instance is registered for an alias even with command loader'); - $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns an instance by name even with command loader'); - $this->assertEquals($foo, $application->get('afoobar'), '->get() returns an instance by alias even with command loader'); - $this->assertTrue($application->has('foo:bar1'), '->has() returns true for commands registered in the loader'); - $this->assertInstanceOf(\Foo1Command::class, $foo1 = $application->get('foo:bar1'), '->get() returns a command by name from the command loader'); - $this->assertTrue($application->has('afoobar1'), '->has() returns true for commands registered in the loader'); - $this->assertEquals($foo1, $application->get('afoobar1'), '->get() returns a command by name from the command loader'); - } - - public function testSilentHelp() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $tester = new ApplicationTester($application); - $tester->run(array('-h' => true, '-q' => true), array('decorated' => false)); - - $this->assertEmpty($tester->getDisplay(true)); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage The command "foofoo" does not exist. - */ - public function testGetInvalidCommand() - { - $application = new Application(); - $application->get('foofoo'); - } - - public function testGetNamespaces() - { - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $this->assertEquals(array('foo'), $application->getNamespaces(), '->getNamespaces() returns an array of unique used namespaces'); - } - - public function testFindNamespace() - { - $application = new Application(); - $application->add(new \FooCommand()); - $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists'); - $this->assertEquals('foo', $application->findNamespace('f'), '->findNamespace() finds a namespace given an abbreviation'); - $application->add(new \Foo2Command()); - $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists'); - } - - public function testFindNamespaceWithSubnamespaces() - { - $application = new Application(); - $application->add(new \FooSubnamespaced1Command()); - $application->add(new \FooSubnamespaced2Command()); - $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns commands even if the commands are only contained in subnamespaces'); - } - - public function testFindAmbiguousNamespace() - { - $application = new Application(); - $application->add(new \BarBucCommand()); - $application->add(new \FooCommand()); - $application->add(new \Foo2Command()); - - $expectedMsg = "The namespace \"f\" is ambiguous.\nDid you mean one of these?\n foo\n foo1"; - - if (method_exists($this, 'expectException')) { - $this->expectException(CommandNotFoundException::class); - $this->expectExceptionMessage($expectedMsg); - } else { - $this->setExpectedException(CommandNotFoundException::class, $expectedMsg); - } - - $application->findNamespace('f'); - } - - public function testFindNonAmbiguous() - { - $application = new Application(); - $application->add(new \TestTiti()); - $application->add(new \TestToto()); - $this->assertEquals('test-toto', $application->find('test')->getName()); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage There are no commands defined in the "bar" namespace. - */ - public function testFindInvalidNamespace() - { - $application = new Application(); - $application->findNamespace('bar'); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage Command "foo1" is not defined - */ - public function testFindUniqueNameButNamespaceName() - { - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - - $application->find($commandName = 'foo1'); - } - - public function testFind() - { - $application = new Application(); - $application->add(new \FooCommand()); - - $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists'); - $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists'); - $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists'); - $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist'); - $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); - } - - public function testFindCaseSensitiveFirst() - { - $application = new Application(); - $application->add(new \FooSameCaseUppercaseCommand()); - $application->add(new \FooSameCaseLowercaseCommand()); - - $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:B'), '->find() returns a command if the abbreviation is the correct case'); - $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:BAR'), '->find() returns a command if the abbreviation is the correct case'); - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case'); - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation is the correct case'); - } - - public function testFindCaseInsensitiveAsFallback() - { - $application = new Application(); - $application->add(new \FooSameCaseLowercaseCommand()); - - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case'); - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:B'), '->find() will fallback to case insensitivity'); - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will fallback to case insensitivity'); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage Command "FoO:BaR" is ambiguous - */ - public function testFindCaseInsensitiveSuggestions() - { - $application = new Application(); - $application->add(new \FooSameCaseLowercaseCommand()); - $application->add(new \FooSameCaseUppercaseCommand()); - - $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will find two suggestions with case insensitivity'); - } - - public function testFindWithCommandLoader() - { - $application = new Application(); - $application->setCommandLoader(new FactoryCommandLoader(array( - 'foo:bar' => $f = function () { return new \FooCommand(); }, - ))); - - $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists'); - $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists'); - $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists'); - $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist'); - $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); - } - - /** - * @dataProvider provideAmbiguousAbbreviations - */ - public function testFindWithAmbiguousAbbreviations($abbreviation, $expectedExceptionMessage) - { - if (method_exists($this, 'expectException')) { - $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); - $this->expectExceptionMessage($expectedExceptionMessage); - } else { - $this->setExpectedException('Symfony\Component\Console\Exception\CommandNotFoundException', $expectedExceptionMessage); - } - - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - - $application->find($abbreviation); - } - - public function provideAmbiguousAbbreviations() - { - return array( - array('f', 'Command "f" is not defined.'), - array( - 'a', - "Command \"a\" is ambiguous.\nDid you mean one of these?\n". - " afoobar The foo:bar command\n". - " afoobar1 The foo:bar1 command\n". - ' afoobar2 The foo1:bar command', - ), - array( - 'foo:b', - "Command \"foo:b\" is ambiguous.\nDid you mean one of these?\n". - " foo:bar The foo:bar command\n". - " foo:bar1 The foo:bar1 command\n". - ' foo1:bar The foo1:bar command', - ), - ); - } - - public function testFindCommandEqualNamespace() - { - $application = new Application(); - $application->add(new \Foo3Command()); - $application->add(new \Foo4Command()); - - $this->assertInstanceOf('Foo3Command', $application->find('foo3:bar'), '->find() returns the good command even if a namespace has same name'); - $this->assertInstanceOf('Foo4Command', $application->find('foo3:bar:toh'), '->find() returns a command even if its namespace equals another command name'); - } - - public function testFindCommandWithAmbiguousNamespacesButUniqueName() - { - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \FoobarCommand()); - - $this->assertInstanceOf('FoobarCommand', $application->find('f:f')); - } - - public function testFindCommandWithMissingNamespace() - { - $application = new Application(); - $application->add(new \Foo4Command()); - - $this->assertInstanceOf('Foo4Command', $application->find('f::t')); - } - - /** - * @dataProvider provideInvalidCommandNamesSingle - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage Did you mean this - */ - public function testFindAlternativeExceptionMessageSingle($name) - { - $application = new Application(); - $application->add(new \Foo3Command()); - $application->find($name); - } - - public function provideInvalidCommandNamesSingle() - { - return array( - array('foo3:barr'), - array('fooo3:bar'), - ); - } - - public function testFindAlternativeExceptionMessageMultiple() - { - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - - // Command + plural - try { - $application->find('foo:baR'); - $this->fail('->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/foo1:bar/', $e->getMessage()); - $this->assertRegExp('/foo:bar/', $e->getMessage()); - } - - // Namespace + plural - try { - $application->find('foo2:bar'); - $this->fail('->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/foo1/', $e->getMessage()); - } - - $application->add(new \Foo3Command()); - $application->add(new \Foo4Command()); - - // Subnamespace + plural - try { - $a = $application->find('foo3:'); - $this->fail('->find() should throw an Symfony\Component\Console\Exception\CommandNotFoundException if a command is ambiguous because of a subnamespace, with alternatives'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e); - $this->assertRegExp('/foo3:bar/', $e->getMessage()); - $this->assertRegExp('/foo3:bar:toh/', $e->getMessage()); - } - } - - public function testFindAlternativeCommands() - { - $application = new Application(); - - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - - try { - $application->find($commandName = 'Unknown command'); - $this->fail('->find() throws a CommandNotFoundException if command does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist'); - $this->assertSame(array(), $e->getAlternatives()); - $this->assertEquals(sprintf('Command "%s" is not defined.', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without alternatives'); - } - - // Test if "bar1" command throw a "CommandNotFoundException" and does not contain - // "foo:bar" as alternative because "bar1" is too far from "foo:bar" - try { - $application->find($commandName = 'bar1'); - $this->fail('->find() throws a CommandNotFoundException if command does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist'); - $this->assertSame(array('afoobar1', 'foo:bar1'), $e->getAlternatives()); - $this->assertRegExp(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); - $this->assertRegExp('/afoobar1/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternative : "afoobar1"'); - $this->assertRegExp('/foo:bar1/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternative : "foo:bar1"'); - $this->assertNotRegExp('/foo:bar(?>!1)/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without "foo:bar" alternative'); - } - } - - public function testFindAlternativeCommandsWithAnAlias() - { - $fooCommand = new \FooCommand(); - $fooCommand->setAliases(array('foo2')); - - $application = new Application(); - $application->add($fooCommand); - - $result = $application->find('foo'); - - $this->assertSame($fooCommand, $result); - } - - public function testFindAlternativeNamespace() - { - $application = new Application(); - - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - $application->add(new \Foo3Command()); - - try { - $application->find('Unknown-namespace:Unknown-command'); - $this->fail('->find() throws a CommandNotFoundException if namespace does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if namespace does not exist'); - $this->assertSame(array(), $e->getAlternatives()); - $this->assertEquals('There are no commands defined in the "Unknown-namespace" namespace.', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, without alternatives'); - } - - try { - $application->find('foo2:command'); - $this->fail('->find() throws a CommandNotFoundException if namespace does not exist'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if namespace does not exist'); - $this->assertCount(3, $e->getAlternatives()); - $this->assertContains('foo', $e->getAlternatives()); - $this->assertContains('foo1', $e->getAlternatives()); - $this->assertContains('foo3', $e->getAlternatives()); - $this->assertRegExp('/There are no commands defined in the "foo2" namespace./', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative'); - $this->assertRegExp('/foo/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo"'); - $this->assertRegExp('/foo1/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo1"'); - $this->assertRegExp('/foo3/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo3"'); - } - } - - public function testFindAlternativesOutput() - { - $application = new Application(); - - $application->add(new \FooCommand()); - $application->add(new \Foo1Command()); - $application->add(new \Foo2Command()); - $application->add(new \Foo3Command()); - - $expectedAlternatives = array( - 'afoobar', - 'afoobar1', - 'afoobar2', - 'foo1:bar', - 'foo3:bar', - 'foo:bar', - 'foo:bar1', - ); - - try { - $application->find('foo'); - $this->fail('->find() throws a CommandNotFoundException if command is not defined'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command is not defined'); - $this->assertSame($expectedAlternatives, $e->getAlternatives()); - - $this->assertRegExp('/Command "foo" is not defined\..*Did you mean one of these\?.*/Ums', $e->getMessage()); - } - } - - public function testFindNamespaceDoesNotFailOnDeepSimilarNamespaces() - { - $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('getNamespaces'))->getMock(); - $application->expects($this->once()) - ->method('getNamespaces') - ->will($this->returnValue(array('foo:sublong', 'bar:sub'))); - - $this->assertEquals('foo:sublong', $application->findNamespace('f:sub')); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - * @expectedExceptionMessage Command "foo::bar" is not defined. - */ - public function testFindWithDoubleColonInNameThrowsException() - { - $application = new Application(); - $application->add(new \FooCommand()); - $application->add(new \Foo4Command()); - $application->find('foo::bar'); - } - - public function testSetCatchExceptions() - { - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=120'); - $tester = new ApplicationTester($application); - - $application->setCatchExceptions(true); - $this->assertTrue($application->areExceptionsCaught()); - - $tester->run(array('command' => 'foo'), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getDisplay(true), '->setCatchExceptions() sets the catch exception flag'); - - $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->setCatchExceptions() sets the catch exception flag'); - $this->assertSame('', $tester->getDisplay(true)); - - $application->setCatchExceptions(false); - try { - $tester->run(array('command' => 'foo'), array('decorated' => false)); - $this->fail('->setCatchExceptions() sets the catch exception flag'); - } catch (\Exception $e) { - $this->assertInstanceOf('\Exception', $e, '->setCatchExceptions() sets the catch exception flag'); - $this->assertEquals('Command "foo" is not defined.', $e->getMessage(), '->setCatchExceptions() sets the catch exception flag'); - } - } - - public function testAutoExitSetting() - { - $application = new Application(); - $this->assertTrue($application->isAutoExitEnabled()); - - $application->setAutoExit(false); - $this->assertFalse($application->isAutoExitEnabled()); - } - - public function testRenderException() - { - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=120'); - $tester = new ApplicationTester($application); - - $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exception'); - - $tester->run(array('command' => 'foo'), array('decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE, 'capture_stderr_separately' => true)); - $this->assertContains('Exception trace', $tester->getErrorOutput(), '->renderException() renders a pretty exception with a stack trace when verbosity is verbose'); - - $tester->run(array('command' => 'list', '--foo' => true), array('decorated' => false, 'capture_stderr_separately' => true)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception2.txt', $tester->getErrorOutput(true), '->renderException() renders the command synopsis when an exception occurs in the context of a command'); - - $application->add(new \Foo3Command()); - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo3:bar'), array('decorated' => false, 'capture_stderr_separately' => true)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); - - $tester->run(array('command' => 'foo3:bar'), array('decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); - $this->assertRegExp('/\[Exception\]\s*First exception/', $tester->getDisplay(), '->renderException() renders a pretty exception without code exception when code exception is default and verbosity is verbose'); - $this->assertRegExp('/\[Exception\]\s*Second exception/', $tester->getDisplay(), '->renderException() renders a pretty exception without code exception when code exception is 0 and verbosity is verbose'); - $this->assertRegExp('/\[Exception \(404\)\]\s*Third exception/', $tester->getDisplay(), '->renderException() renders a pretty exception with code exception when code exception is 404 and verbosity is verbose'); - - $tester->run(array('command' => 'foo3:bar'), array('decorated' => true)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions'); - - $tester->run(array('command' => 'foo3:bar'), array('decorated' => true, 'capture_stderr_separately' => true)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); - - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=32'); - $tester = new ApplicationTester($application); - - $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal'); - putenv('COLUMNS=120'); - } - - public function testRenderExceptionWithDoubleWidthCharacters() - { - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=120'); - $application->register('foo')->setCode(function () { - throw new \Exception('エラーメッセージ'); - }); - $tester = new ApplicationTester($application); - - $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); - - $tester->run(array('command' => 'foo'), array('decorated' => true, 'capture_stderr_separately' => true)); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth1decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); - - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=32'); - $application->register('foo')->setCode(function () { - throw new \Exception('コマンドの実行中にエラーが発生しました。'); - }); - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo'), array('decorated' => false, 'capture_stderr_separately' => true)); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal'); - putenv('COLUMNS=120'); - } - - public function testRenderExceptionEscapesLines() - { - $application = new Application(); - $application->setAutoExit(false); - putenv('COLUMNS=22'); - $application->register('foo')->setCode(function () { - throw new \Exception('dont break here <info>!</info>'); - }); - $tester = new ApplicationTester($application); - - $tester->run(array('command' => 'foo'), array('decorated' => false)); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_escapeslines.txt', $tester->getDisplay(true), '->renderException() escapes lines containing formatting'); - putenv('COLUMNS=120'); - } - - public function testRenderExceptionLineBreaks() - { - $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('getTerminalWidth'))->getMock(); - $application->setAutoExit(false); - $application->expects($this->any()) - ->method('getTerminalWidth') - ->will($this->returnValue(120)); - $application->register('foo')->setCode(function () { - throw new \InvalidArgumentException("\n\nline 1 with extra spaces \nline 2\n\nline 4\n"); - }); - $tester = new ApplicationTester($application); - - $tester->run(array('command' => 'foo'), array('decorated' => false)); - $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_linebreaks.txt', $tester->getDisplay(true), '->renderException() keep multiple line breaks'); - } - - public function testRun() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->add($command = new \Foo1Command()); - $_SERVER['argv'] = array('cli.php', 'foo:bar1'); - - ob_start(); - $application->run(); - ob_end_clean(); - - $this->assertInstanceOf('Symfony\Component\Console\Input\ArgvInput', $command->input, '->run() creates an ArgvInput by default if none is given'); - $this->assertInstanceOf('Symfony\Component\Console\Output\ConsoleOutput', $command->output, '->run() creates a ConsoleOutput by default if none is given'); - - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $this->ensureStaticCommandHelp($application); - $tester = new ApplicationTester($application); - - $tester->run(array(), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run1.txt', $tester->getDisplay(true), '->run() runs the list command if no argument is passed'); - - $tester->run(array('--help' => true), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if --help is passed'); - - $tester->run(array('-h' => true), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if -h is passed'); - - $tester->run(array('command' => 'list', '--help' => true), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if --help is passed'); - - $tester->run(array('command' => 'list', '-h' => true), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if -h is passed'); - - $tester->run(array('--ansi' => true)); - $this->assertTrue($tester->getOutput()->isDecorated(), '->run() forces color output if --ansi is passed'); - - $tester->run(array('--no-ansi' => true)); - $this->assertFalse($tester->getOutput()->isDecorated(), '->run() forces color output to be disabled if --no-ansi is passed'); - - $tester->run(array('--version' => true), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if --version is passed'); - - $tester->run(array('-V' => true), array('decorated' => false)); - $this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if -v is passed'); - - $tester->run(array('command' => 'list', '--quiet' => true)); - $this->assertSame('', $tester->getDisplay(), '->run() removes all output if --quiet is passed'); - $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if --quiet is passed'); - - $tester->run(array('command' => 'list', '-q' => true)); - $this->assertSame('', $tester->getDisplay(), '->run() removes all output if -q is passed'); - $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if -q is passed'); - - $tester->run(array('command' => 'list', '--verbose' => true)); - $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose is passed'); - - $tester->run(array('command' => 'list', '--verbose' => 1)); - $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose=1 is passed'); - - $tester->run(array('command' => 'list', '--verbose' => 2)); - $this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to very verbose if --verbose=2 is passed'); - - $tester->run(array('command' => 'list', '--verbose' => 3)); - $this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to debug if --verbose=3 is passed'); - - $tester->run(array('command' => 'list', '--verbose' => 4)); - $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if unknown --verbose level is passed'); - - $tester->run(array('command' => 'list', '-v' => true)); - $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed'); - - $tester->run(array('command' => 'list', '-vv' => true)); - $this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed'); - - $tester->run(array('command' => 'list', '-vvv' => true)); - $this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed'); - - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->add(new \FooCommand()); - $tester = new ApplicationTester($application); - - $tester->run(array('command' => 'foo:bar', '--no-interaction' => true), array('decorated' => false)); - $this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if --no-interaction is passed'); - - $tester->run(array('command' => 'foo:bar', '-n' => true), array('decorated' => false)); - $this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if -n is passed'); - } - - /** - * Issue #9285. - * - * If the "verbose" option is just before an argument in ArgvInput, - * an argument value should not be treated as verbosity value. - * This test will fail with "Not enough arguments." if broken - */ - public function testVerboseValueNotBreakArguments() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->add(new \FooCommand()); - - $output = new StreamOutput(fopen('php://memory', 'w', false)); - - $input = new ArgvInput(array('cli.php', '-v', 'foo:bar')); - $application->run($input, $output); - - $this->addToAssertionCount(1); - - $input = new ArgvInput(array('cli.php', '--verbose', 'foo:bar')); - $application->run($input, $output); - - $this->addToAssertionCount(1); - } - - public function testRunReturnsIntegerExitCode() - { - $exception = new \Exception('', 4); - - $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('doRun'))->getMock(); - $application->setAutoExit(false); - $application->expects($this->once()) - ->method('doRun') - ->will($this->throwException($exception)); - - $exitCode = $application->run(new ArrayInput(array()), new NullOutput()); - - $this->assertSame(4, $exitCode, '->run() returns integer exit code extracted from raised exception'); - } - - public function testRunReturnsExitCodeOneForExceptionCodeZero() - { - $exception = new \Exception('', 0); - - $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('doRun'))->getMock(); - $application->setAutoExit(false); - $application->expects($this->once()) - ->method('doRun') - ->will($this->throwException($exception)); - - $exitCode = $application->run(new ArrayInput(array()), new NullOutput()); - - $this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage An option with shortcut "e" already exists. - */ - public function testAddingOptionWithDuplicateShortcut() - { - $dispatcher = new EventDispatcher(); - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->setDispatcher($dispatcher); - - $application->getDefinition()->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'Environment')); - - $application - ->register('foo') - ->setAliases(array('f')) - ->setDefinition(array(new InputOption('survey', 'e', InputOption::VALUE_REQUIRED, 'My option with a shortcut.'))) - ->setCode(function (InputInterface $input, OutputInterface $output) {}) - ; - - $input = new ArrayInput(array('command' => 'foo')); - $output = new NullOutput(); - - $application->run($input, $output); - } - - /** - * @expectedException \LogicException - * @dataProvider getAddingAlreadySetDefinitionElementData - */ - public function testAddingAlreadySetDefinitionElementData($def) - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application - ->register('foo') - ->setDefinition(array($def)) - ->setCode(function (InputInterface $input, OutputInterface $output) {}) - ; - - $input = new ArrayInput(array('command' => 'foo')); - $output = new NullOutput(); - $application->run($input, $output); - } - - public function getAddingAlreadySetDefinitionElementData() - { - return array( - array(new InputArgument('command', InputArgument::REQUIRED)), - array(new InputOption('quiet', '', InputOption::VALUE_NONE)), - array(new InputOption('query', 'q', InputOption::VALUE_NONE)), - ); - } - - public function testGetDefaultHelperSetReturnsDefaultValues() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $helperSet = $application->getHelperSet(); - - $this->assertTrue($helperSet->has('formatter')); - } - - public function testAddingSingleHelperSetOverwritesDefaultValues() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->setHelperSet(new HelperSet(array(new FormatterHelper()))); - - $helperSet = $application->getHelperSet(); - - $this->assertTrue($helperSet->has('formatter')); - - // no other default helper set should be returned - $this->assertFalse($helperSet->has('dialog')); - $this->assertFalse($helperSet->has('progress')); - } - - public function testOverwritingDefaultHelperSetOverwritesDefaultValues() - { - $application = new CustomApplication(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->setHelperSet(new HelperSet(array(new FormatterHelper()))); - - $helperSet = $application->getHelperSet(); - - $this->assertTrue($helperSet->has('formatter')); - - // no other default helper set should be returned - $this->assertFalse($helperSet->has('dialog')); - $this->assertFalse($helperSet->has('progress')); - } - - public function testGetDefaultInputDefinitionReturnsDefaultValues() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $inputDefinition = $application->getDefinition(); - - $this->assertTrue($inputDefinition->hasArgument('command')); - - $this->assertTrue($inputDefinition->hasOption('help')); - $this->assertTrue($inputDefinition->hasOption('quiet')); - $this->assertTrue($inputDefinition->hasOption('verbose')); - $this->assertTrue($inputDefinition->hasOption('version')); - $this->assertTrue($inputDefinition->hasOption('ansi')); - $this->assertTrue($inputDefinition->hasOption('no-ansi')); - $this->assertTrue($inputDefinition->hasOption('no-interaction')); - } - - public function testOverwritingDefaultInputDefinitionOverwritesDefaultValues() - { - $application = new CustomApplication(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $inputDefinition = $application->getDefinition(); - - // check whether the default arguments and options are not returned any more - $this->assertFalse($inputDefinition->hasArgument('command')); - - $this->assertFalse($inputDefinition->hasOption('help')); - $this->assertFalse($inputDefinition->hasOption('quiet')); - $this->assertFalse($inputDefinition->hasOption('verbose')); - $this->assertFalse($inputDefinition->hasOption('version')); - $this->assertFalse($inputDefinition->hasOption('ansi')); - $this->assertFalse($inputDefinition->hasOption('no-ansi')); - $this->assertFalse($inputDefinition->hasOption('no-interaction')); - - $this->assertTrue($inputDefinition->hasOption('custom')); - } - - public function testSettingCustomInputDefinitionOverwritesDefaultValues() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->setDefinition(new InputDefinition(array(new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.')))); - - $inputDefinition = $application->getDefinition(); - - // check whether the default arguments and options are not returned any more - $this->assertFalse($inputDefinition->hasArgument('command')); - - $this->assertFalse($inputDefinition->hasOption('help')); - $this->assertFalse($inputDefinition->hasOption('quiet')); - $this->assertFalse($inputDefinition->hasOption('verbose')); - $this->assertFalse($inputDefinition->hasOption('version')); - $this->assertFalse($inputDefinition->hasOption('ansi')); - $this->assertFalse($inputDefinition->hasOption('no-ansi')); - $this->assertFalse($inputDefinition->hasOption('no-interaction')); - - $this->assertTrue($inputDefinition->hasOption('custom')); - } - - public function testRunWithDispatcher() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setDispatcher($this->getDispatcher()); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo')); - $this->assertEquals('before.foo.after.'.PHP_EOL, $tester->getDisplay()); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage error - */ - public function testRunWithExceptionAndDispatcher() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher()); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - throw new \RuntimeException('foo'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo')); - } - - public function testRunDispatchesAllEventsWithException() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher()); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - - throw new \RuntimeException('foo'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo')); - $this->assertContains('before.foo.error.after.', $tester->getDisplay()); - } - - public function testRunDispatchesAllEventsWithExceptionInListener() - { - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.command', function () { - throw new \RuntimeException('foo'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo')); - $this->assertContains('before.error.after.', $tester->getDisplay()); - } - - /** - * @requires PHP 7 - */ - public function testRunWithError() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('dym.'); - - throw new \Error('dymerr'); - }); - - $tester = new ApplicationTester($application); - - try { - $tester->run(array('command' => 'dym')); - $this->fail('Error expected.'); - } catch (\Error $e) { - $this->assertSame('dymerr', $e->getMessage()); - } - } - - public function testRunAllowsErrorListenersToSilenceTheException() - { - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { - $event->getOutput()->write('silenced.'); - - $event->setExitCode(0); - }); - - $dispatcher->addListener('console.command', function () { - throw new \RuntimeException('foo'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo')); - $this->assertContains('before.error.silenced.after.', $tester->getDisplay()); - $this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $tester->getStatusCode()); - } - - public function testConsoleErrorEventIsTriggeredOnCommandNotFound() - { - $dispatcher = new EventDispatcher(); - $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { - $this->assertNull($event->getCommand()); - $this->assertInstanceOf(CommandNotFoundException::class, $event->getError()); - $event->getOutput()->write('silenced command not found'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'unknown')); - $this->assertContains('silenced command not found', $tester->getDisplay()); - $this->assertEquals(1, $tester->getStatusCode()); - } - - /** - * @group legacy - * @expectedDeprecation The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead. - */ - public function testLegacyExceptionListenersAreStillTriggered() - { - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) { - $event->getOutput()->write('caught.'); - - $event->setException(new \RuntimeException('replaced in caught.')); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - throw new \RuntimeException('foo'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo')); - $this->assertContains('before.caught.error.after.', $tester->getDisplay()); - $this->assertContains('replaced in caught.', $tester->getDisplay()); - } - - /** - * @requires PHP 7 - */ - public function testErrorIsRethrownIfNotHandledByConsoleErrorEvent() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - $application->setDispatcher(new EventDispatcher()); - - $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { - new \UnknownClass(); - }); - - $tester = new ApplicationTester($application); - - try { - $tester->run(array('command' => 'dym')); - $this->fail('->run() should rethrow PHP errors if not handled via ConsoleErrorEvent.'); - } catch (\Error $e) { - $this->assertSame($e->getMessage(), 'Class \'UnknownClass\' not found'); - } - } - - /** - * @requires PHP 7 - * @expectedException \LogicException - * @expectedExceptionMessage error - */ - public function testRunWithErrorAndDispatcher() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher()); - $application->setAutoExit(false); - $application->setCatchExceptions(false); - - $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('dym.'); - - throw new \Error('dymerr'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'dym')); - $this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); - } - - /** - * @requires PHP 7 - */ - public function testRunDispatchesAllEventsWithError() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher()); - $application->setAutoExit(false); - - $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('dym.'); - - throw new \Error('dymerr'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'dym')); - $this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); - } - - /** - * @requires PHP 7 - */ - public function testRunWithErrorFailingStatusCode() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher()); - $application->setAutoExit(false); - - $application->register('dus')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('dus.'); - - throw new \Error('duserr'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'dus')); - $this->assertSame(1, $tester->getStatusCode(), 'Status code should be 1'); - } - - public function testRunWithDispatcherSkippingCommand() - { - $application = new Application(); - $application->setDispatcher($this->getDispatcher(true)); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $exitCode = $tester->run(array('command' => 'foo')); - $this->assertContains('before.after.', $tester->getDisplay()); - $this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $exitCode); - } - - public function testRunWithDispatcherAccessingInputOptions() - { - $noInteractionValue = null; - $quietValue = null; - - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use (&$noInteractionValue, &$quietValue) { - $input = $event->getInput(); - - $noInteractionValue = $input->getOption('no-interaction'); - $quietValue = $input->getOption('quiet'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo', '--no-interaction' => true)); - - $this->assertTrue($noInteractionValue); - $this->assertFalse($quietValue); - } - - public function testRunWithDispatcherAddingInputOptions() - { - $extraValue = null; - - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use (&$extraValue) { - $definition = $event->getCommand()->getDefinition(); - $input = $event->getInput(); - - $definition->addOption(new InputOption('extra', null, InputOption::VALUE_REQUIRED)); - $input->bind($definition); - - $extraValue = $input->getOption('extra'); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - $output->write('foo.'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo', '--extra' => 'some test value')); - - $this->assertEquals('some test value', $extraValue); - } - - /** - * @group legacy - */ - public function testTerminalDimensions() - { - $application = new Application(); - $originalDimensions = $application->getTerminalDimensions(); - $this->assertCount(2, $originalDimensions); - - $width = 80; - if ($originalDimensions[0] == $width) { - $width = 100; - } - - $application->setTerminalDimensions($width, 80); - $this->assertSame(array($width, 80), $application->getTerminalDimensions()); - } - - public function testSetRunCustomDefaultCommand() - { - $command = new \FooCommand(); - - $application = new Application(); - $application->setAutoExit(false); - $application->add($command); - $application->setDefaultCommand($command->getName()); - - $tester = new ApplicationTester($application); - $tester->run(array(), array('interactive' => false)); - $this->assertEquals('called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); - - $application = new CustomDefaultCommandApplication(); - $application->setAutoExit(false); - - $tester = new ApplicationTester($application); - $tester->run(array(), array('interactive' => false)); - - $this->assertEquals('called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); - } - - public function testSetRunCustomDefaultCommandWithOption() - { - $command = new \FooOptCommand(); - - $application = new Application(); - $application->setAutoExit(false); - $application->add($command); - $application->setDefaultCommand($command->getName()); - - $tester = new ApplicationTester($application); - $tester->run(array('--fooopt' => 'opt'), array('interactive' => false)); - - $this->assertEquals('called'.PHP_EOL.'opt'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); - } - - public function testSetRunCustomSingleCommand() - { - $command = new \FooCommand(); - - $application = new Application(); - $application->setAutoExit(false); - $application->add($command); - $application->setDefaultCommand($command->getName(), true); - - $tester = new ApplicationTester($application); - - $tester->run(array()); - $this->assertContains('called', $tester->getDisplay()); - - $tester->run(array('--help' => true)); - $this->assertContains('The foo:bar command', $tester->getDisplay()); - } - - /** - * @requires function posix_isatty - */ - public function testCanCheckIfTerminalIsInteractive() - { - $application = new CustomDefaultCommandApplication(); - $application->setAutoExit(false); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'help')); - - $this->assertFalse($tester->getInput()->hasParameterOption(array('--no-interaction', '-n'))); - - $inputStream = $tester->getInput()->getStream(); - $this->assertEquals($tester->getInput()->isInteractive(), @posix_isatty($inputStream)); - } - - public function testRunLazyCommandService() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddConsoleCommandPass()); - $container - ->register('lazy-command', LazyCommand::class) - ->addTag('console.command', array('command' => 'lazy:command')) - ->addTag('console.command', array('command' => 'lazy:alias')) - ->addTag('console.command', array('command' => 'lazy:alias2')); - $container->compile(); - - $application = new Application(); - $application->setCommandLoader($container->get('console.command_loader')); - $application->setAutoExit(false); - - $tester = new ApplicationTester($application); - - $tester->run(array('command' => 'lazy:command')); - $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); - - $tester->run(array('command' => 'lazy:alias')); - $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); - - $tester->run(array('command' => 'lazy:alias2')); - $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); - - $command = $application->get('lazy:command'); - $this->assertSame(array('lazy:alias', 'lazy:alias2'), $command->getAliases()); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - */ - public function testGetDisabledLazyCommand() - { - $application = new Application(); - $application->setCommandLoader(new FactoryCommandLoader(array('disabled' => function () { return new DisabledCommand(); }))); - $application->get('disabled'); - } - - public function testHasReturnsFalseForDisabledLazyCommand() - { - $application = new Application(); - $application->setCommandLoader(new FactoryCommandLoader(array('disabled' => function () { return new DisabledCommand(); }))); - $this->assertFalse($application->has('disabled')); - } - - public function testAllExcludesDisabledLazyCommand() - { - $application = new Application(); - $application->setCommandLoader(new FactoryCommandLoader(array('disabled' => function () { return new DisabledCommand(); }))); - $this->assertArrayNotHasKey('disabled', $application->all()); - } - - protected function getDispatcher($skipCommand = false) - { - $dispatcher = new EventDispatcher(); - $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) { - $event->getOutput()->write('before.'); - - if ($skipCommand) { - $event->disableCommand(); - } - }); - $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) { - $event->getOutput()->writeln('after.'); - - if (!$skipCommand) { - $event->setExitCode(ConsoleCommandEvent::RETURN_CODE_DISABLED); - } - }); - $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { - $event->getOutput()->write('error.'); - - $event->setError(new \LogicException('error.', $event->getExitCode(), $event->getError())); - }); - - return $dispatcher; - } - - /** - * @requires PHP 7 - */ - public function testErrorIsRethrownIfNotHandledByConsoleErrorEventWithCatchingEnabled() - { - $application = new Application(); - $application->setAutoExit(false); - $application->setDispatcher(new EventDispatcher()); - - $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { - new \UnknownClass(); - }); - - $tester = new ApplicationTester($application); - - try { - $tester->run(array('command' => 'dym')); - $this->fail('->run() should rethrow PHP errors if not handled via ConsoleErrorEvent.'); - } catch (\Error $e) { - $this->assertSame($e->getMessage(), 'Class \'UnknownClass\' not found'); - } - } - - protected function tearDown() - { - putenv('SHELL_VERBOSITY'); - unset($_ENV['SHELL_VERBOSITY']); - unset($_SERVER['SHELL_VERBOSITY']); - } -} - -class CustomApplication extends Application -{ - /** - * Overwrites the default input definition. - * - * @return InputDefinition An InputDefinition instance - */ - protected function getDefaultInputDefinition() - { - return new InputDefinition(array(new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.'))); - } - - /** - * Gets the default helper set with the helpers that should always be available. - * - * @return HelperSet A HelperSet instance - */ - protected function getDefaultHelperSet() - { - return new HelperSet(array(new FormatterHelper())); - } -} - -class CustomDefaultCommandApplication extends Application -{ - /** - * Overwrites the constructor in order to set a different default command. - */ - public function __construct() - { - parent::__construct(); - - $command = new \FooCommand(); - $this->add($command); - $this->setDefaultCommand($command->getName()); - } -} - -class LazyCommand extends Command -{ - public function execute(InputInterface $input, OutputInterface $output) - { - $output->writeln('lazy-command called'); - } -} - -class DisabledCommand extends Command -{ - public function isEnabled() - { - return false; - } -} diff --git a/vendor/symfony/console/Tests/Command/CommandTest.php b/vendor/symfony/console/Tests/Command/CommandTest.php deleted file mode 100644 index 6bc3f75..0000000 --- a/vendor/symfony/console/Tests/Command/CommandTest.php +++ /dev/null @@ -1,434 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Command; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\StringInput; -use Symfony\Component\Console\Output\NullOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tester\CommandTester; - -class CommandTest extends TestCase -{ - protected static $fixturesPath; - - public static function setUpBeforeClass() - { - self::$fixturesPath = __DIR__.'/../Fixtures/'; - require_once self::$fixturesPath.'/TestCommand.php'; - } - - public function testConstructor() - { - $command = new Command('foo:bar'); - $this->assertEquals('foo:bar', $command->getName(), '__construct() takes the command name as its first argument'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage The command defined in "Symfony\Component\Console\Command\Command" cannot have an empty name. - */ - public function testCommandNameCannotBeEmpty() - { - (new Application())->add(new Command()); - } - - public function testSetApplication() - { - $application = new Application(); - $command = new \TestCommand(); - $command->setApplication($application); - $this->assertEquals($application, $command->getApplication(), '->setApplication() sets the current application'); - $this->assertEquals($application->getHelperSet(), $command->getHelperSet()); - } - - public function testSetApplicationNull() - { - $command = new \TestCommand(); - $command->setApplication(null); - $this->assertNull($command->getHelperSet()); - } - - public function testSetGetDefinition() - { - $command = new \TestCommand(); - $ret = $command->setDefinition($definition = new InputDefinition()); - $this->assertEquals($command, $ret, '->setDefinition() implements a fluent interface'); - $this->assertEquals($definition, $command->getDefinition(), '->setDefinition() sets the current InputDefinition instance'); - $command->setDefinition(array(new InputArgument('foo'), new InputOption('bar'))); - $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument'); - $this->assertTrue($command->getDefinition()->hasOption('bar'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument'); - $command->setDefinition(new InputDefinition()); - } - - public function testAddArgument() - { - $command = new \TestCommand(); - $ret = $command->addArgument('foo'); - $this->assertEquals($command, $ret, '->addArgument() implements a fluent interface'); - $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->addArgument() adds an argument to the command'); - } - - public function testAddOption() - { - $command = new \TestCommand(); - $ret = $command->addOption('foo'); - $this->assertEquals($command, $ret, '->addOption() implements a fluent interface'); - $this->assertTrue($command->getDefinition()->hasOption('foo'), '->addOption() adds an option to the command'); - } - - public function testSetHidden() - { - $command = new \TestCommand(); - $command->setHidden(true); - $this->assertTrue($command->isHidden()); - } - - public function testGetNamespaceGetNameSetName() - { - $command = new \TestCommand(); - $this->assertEquals('namespace:name', $command->getName(), '->getName() returns the command name'); - $command->setName('foo'); - $this->assertEquals('foo', $command->getName(), '->setName() sets the command name'); - - $ret = $command->setName('foobar:bar'); - $this->assertEquals($command, $ret, '->setName() implements a fluent interface'); - $this->assertEquals('foobar:bar', $command->getName(), '->setName() sets the command name'); - } - - /** - * @dataProvider provideInvalidCommandNames - */ - public function testInvalidCommandNames($name) - { - if (method_exists($this, 'expectException')) { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage(sprintf('Command name "%s" is invalid.', $name)); - } else { - $this->setExpectedException('InvalidArgumentException', sprintf('Command name "%s" is invalid.', $name)); - } - - $command = new \TestCommand(); - $command->setName($name); - } - - public function provideInvalidCommandNames() - { - return array( - array(''), - array('foo:'), - ); - } - - public function testGetSetDescription() - { - $command = new \TestCommand(); - $this->assertEquals('description', $command->getDescription(), '->getDescription() returns the description'); - $ret = $command->setDescription('description1'); - $this->assertEquals($command, $ret, '->setDescription() implements a fluent interface'); - $this->assertEquals('description1', $command->getDescription(), '->setDescription() sets the description'); - } - - public function testGetSetHelp() - { - $command = new \TestCommand(); - $this->assertEquals('help', $command->getHelp(), '->getHelp() returns the help'); - $ret = $command->setHelp('help1'); - $this->assertEquals($command, $ret, '->setHelp() implements a fluent interface'); - $this->assertEquals('help1', $command->getHelp(), '->setHelp() sets the help'); - $command->setHelp(''); - $this->assertEquals('', $command->getHelp(), '->getHelp() does not fall back to the description'); - } - - public function testGetProcessedHelp() - { - $command = new \TestCommand(); - $command->setHelp('The %command.name% command does... Example: php %command.full_name%.'); - $this->assertContains('The namespace:name command does...', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.name% correctly'); - $this->assertNotContains('%command.full_name%', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.full_name%'); - - $command = new \TestCommand(); - $command->setHelp(''); - $this->assertContains('description', $command->getProcessedHelp(), '->getProcessedHelp() falls back to the description'); - } - - public function testGetSetAliases() - { - $command = new \TestCommand(); - $this->assertEquals(array('name'), $command->getAliases(), '->getAliases() returns the aliases'); - $ret = $command->setAliases(array('name1')); - $this->assertEquals($command, $ret, '->setAliases() implements a fluent interface'); - $this->assertEquals(array('name1'), $command->getAliases(), '->setAliases() sets the aliases'); - } - - public function testSetAliasesNull() - { - $command = new \TestCommand(); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); - $command->setAliases(null); - } - - public function testGetSynopsis() - { - $command = new \TestCommand(); - $command->addOption('foo'); - $command->addArgument('bar'); - $this->assertEquals('namespace:name [--foo] [--] [<bar>]', $command->getSynopsis(), '->getSynopsis() returns the synopsis'); - } - - public function testAddGetUsages() - { - $command = new \TestCommand(); - $command->addUsage('foo1'); - $command->addUsage('foo2'); - $this->assertContains('namespace:name foo1', $command->getUsages()); - $this->assertContains('namespace:name foo2', $command->getUsages()); - } - - public function testGetHelper() - { - $application = new Application(); - $command = new \TestCommand(); - $command->setApplication($application); - $formatterHelper = new FormatterHelper(); - $this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->getHelper() returns the correct helper'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Cannot retrieve helper "formatter" because there is no HelperSet defined. - */ - public function testGetHelperWithoutHelperSet() - { - $command = new \TestCommand(); - $command->getHelper('formatter'); - } - - public function testMergeApplicationDefinition() - { - $application1 = new Application(); - $application1->getDefinition()->addArguments(array(new InputArgument('foo'))); - $application1->getDefinition()->addOptions(array(new InputOption('bar'))); - $command = new \TestCommand(); - $command->setApplication($application1); - $command->setDefinition($definition = new InputDefinition(array(new InputArgument('bar'), new InputOption('foo')))); - - $r = new \ReflectionObject($command); - $m = $r->getMethod('mergeApplicationDefinition'); - $m->setAccessible(true); - $m->invoke($command); - $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition() merges the application arguments and the command arguments'); - $this->assertTrue($command->getDefinition()->hasArgument('bar'), '->mergeApplicationDefinition() merges the application arguments and the command arguments'); - $this->assertTrue($command->getDefinition()->hasOption('foo'), '->mergeApplicationDefinition() merges the application options and the command options'); - $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition() merges the application options and the command options'); - - $m->invoke($command); - $this->assertEquals(3, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments and options'); - } - - public function testMergeApplicationDefinitionWithoutArgsThenWithArgsAddsArgs() - { - $application1 = new Application(); - $application1->getDefinition()->addArguments(array(new InputArgument('foo'))); - $application1->getDefinition()->addOptions(array(new InputOption('bar'))); - $command = new \TestCommand(); - $command->setApplication($application1); - $command->setDefinition($definition = new InputDefinition(array())); - - $r = new \ReflectionObject($command); - $m = $r->getMethod('mergeApplicationDefinition'); - $m->setAccessible(true); - $m->invoke($command, false); - $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition(false) merges the application and the command options'); - $this->assertFalse($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(false) does not merge the application arguments'); - - $m->invoke($command, true); - $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(true) merges the application arguments and the command arguments'); - - $m->invoke($command); - $this->assertEquals(2, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments'); - } - - public function testRunInteractive() - { - $tester = new CommandTester(new \TestCommand()); - - $tester->execute(array(), array('interactive' => true)); - - $this->assertEquals('interact called'.PHP_EOL.'execute called'.PHP_EOL, $tester->getDisplay(), '->run() calls the interact() method if the input is interactive'); - } - - public function testRunNonInteractive() - { - $tester = new CommandTester(new \TestCommand()); - - $tester->execute(array(), array('interactive' => false)); - - $this->assertEquals('execute called'.PHP_EOL, $tester->getDisplay(), '->run() does not call the interact() method if the input is not interactive'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage You must override the execute() method in the concrete command class. - */ - public function testExecuteMethodNeedsToBeOverridden() - { - $command = new Command('foo'); - $command->run(new StringInput(''), new NullOutput()); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\InvalidOptionException - * @expectedExceptionMessage The "--bar" option does not exist. - */ - public function testRunWithInvalidOption() - { - $command = new \TestCommand(); - $tester = new CommandTester($command); - $tester->execute(array('--bar' => true)); - } - - public function testRunReturnsIntegerExitCode() - { - $command = new \TestCommand(); - $exitCode = $command->run(new StringInput(''), new NullOutput()); - $this->assertSame(0, $exitCode, '->run() returns integer exit code (treats null as 0)'); - - $command = $this->getMockBuilder('TestCommand')->setMethods(array('execute'))->getMock(); - $command->expects($this->once()) - ->method('execute') - ->will($this->returnValue('2.3')); - $exitCode = $command->run(new StringInput(''), new NullOutput()); - $this->assertSame(2, $exitCode, '->run() returns integer exit code (casts numeric to int)'); - } - - public function testRunWithApplication() - { - $command = new \TestCommand(); - $command->setApplication(new Application()); - $exitCode = $command->run(new StringInput(''), new NullOutput()); - - $this->assertSame(0, $exitCode, '->run() returns an integer exit code'); - } - - public function testRunReturnsAlwaysInteger() - { - $command = new \TestCommand(); - - $this->assertSame(0, $command->run(new StringInput(''), new NullOutput())); - } - - public function testRunWithProcessTitle() - { - $command = new \TestCommand(); - $command->setApplication(new Application()); - $command->setProcessTitle('foo'); - $this->assertSame(0, $command->run(new StringInput(''), new NullOutput())); - if (\function_exists('cli_set_process_title')) { - if (null === @cli_get_process_title() && 'Darwin' === PHP_OS) { - $this->markTestSkipped('Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.'); - } - $this->assertEquals('foo', cli_get_process_title()); - } - } - - public function testSetCode() - { - $command = new \TestCommand(); - $ret = $command->setCode(function (InputInterface $input, OutputInterface $output) { - $output->writeln('from the code...'); - }); - $this->assertEquals($command, $ret, '->setCode() implements a fluent interface'); - $tester = new CommandTester($command); - $tester->execute(array()); - $this->assertEquals('interact called'.PHP_EOL.'from the code...'.PHP_EOL, $tester->getDisplay()); - } - - public function getSetCodeBindToClosureTests() - { - return array( - array(true, 'not bound to the command'), - array(false, 'bound to the command'), - ); - } - - /** - * @dataProvider getSetCodeBindToClosureTests - */ - public function testSetCodeBindToClosure($previouslyBound, $expected) - { - $code = createClosure(); - if ($previouslyBound) { - $code = $code->bindTo($this); - } - - $command = new \TestCommand(); - $command->setCode($code); - $tester = new CommandTester($command); - $tester->execute(array()); - $this->assertEquals('interact called'.PHP_EOL.$expected.PHP_EOL, $tester->getDisplay()); - } - - public function testSetCodeWithStaticClosure() - { - $command = new \TestCommand(); - $command->setCode(self::createClosure()); - $tester = new CommandTester($command); - $tester->execute(array()); - - if (\PHP_VERSION_ID < 70000) { - // Cannot bind static closures in PHP 5 - $this->assertEquals('interact called'.PHP_EOL.'not bound'.PHP_EOL, $tester->getDisplay()); - } else { - // Can bind static closures in PHP 7 - $this->assertEquals('interact called'.PHP_EOL.'bound'.PHP_EOL, $tester->getDisplay()); - } - } - - private static function createClosure() - { - return function (InputInterface $input, OutputInterface $output) { - $output->writeln(isset($this) ? 'bound' : 'not bound'); - }; - } - - public function testSetCodeWithNonClosureCallable() - { - $command = new \TestCommand(); - $ret = $command->setCode(array($this, 'callableMethodCommand')); - $this->assertEquals($command, $ret, '->setCode() implements a fluent interface'); - $tester = new CommandTester($command); - $tester->execute(array()); - $this->assertEquals('interact called'.PHP_EOL.'from the code...'.PHP_EOL, $tester->getDisplay()); - } - - public function callableMethodCommand(InputInterface $input, OutputInterface $output) - { - $output->writeln('from the code...'); - } -} - -// In order to get an unbound closure, we should create it outside a class -// scope. -function createClosure() -{ - return function (InputInterface $input, OutputInterface $output) { - $output->writeln($this instanceof Command ? 'bound to the command' : 'not bound to the command'); - }; -} diff --git a/vendor/symfony/console/Tests/Command/HelpCommandTest.php b/vendor/symfony/console/Tests/Command/HelpCommandTest.php deleted file mode 100644 index 30fe2b6..0000000 --- a/vendor/symfony/console/Tests/Command/HelpCommandTest.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Command; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\HelpCommand; -use Symfony\Component\Console\Command\ListCommand; -use Symfony\Component\Console\Tester\CommandTester; - -class HelpCommandTest extends TestCase -{ - public function testExecuteForCommandAlias() - { - $command = new HelpCommand(); - $command->setApplication(new Application()); - $commandTester = new CommandTester($command); - $commandTester->execute(array('command_name' => 'li'), array('decorated' => false)); - $this->assertContains('list [options] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias'); - $this->assertContains('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias'); - $this->assertContains('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias'); - } - - public function testExecuteForCommand() - { - $command = new HelpCommand(); - $commandTester = new CommandTester($command); - $command->setCommand(new ListCommand()); - $commandTester->execute(array(), array('decorated' => false)); - $this->assertContains('list [options] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - $this->assertContains('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - $this->assertContains('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - } - - public function testExecuteForCommandWithXmlOption() - { - $command = new HelpCommand(); - $commandTester = new CommandTester($command); - $command->setCommand(new ListCommand()); - $commandTester->execute(array('--format' => 'xml')); - $this->assertContains('<command', $commandTester->getDisplay(), '->execute() returns an XML help text if --xml is passed'); - } - - public function testExecuteForApplicationCommand() - { - $application = new Application(); - $commandTester = new CommandTester($application->get('help')); - $commandTester->execute(array('command_name' => 'list')); - $this->assertContains('list [options] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - $this->assertContains('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - $this->assertContains('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - } - - public function testExecuteForApplicationCommandWithXmlOption() - { - $application = new Application(); - $commandTester = new CommandTester($application->get('help')); - $commandTester->execute(array('command_name' => 'list', '--format' => 'xml')); - $this->assertContains('list [--raw] [--format FORMAT] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); - $this->assertContains('<command', $commandTester->getDisplay(), '->execute() returns an XML help text if --format=xml is passed'); - } -} diff --git a/vendor/symfony/console/Tests/Command/ListCommandTest.php b/vendor/symfony/console/Tests/Command/ListCommandTest.php deleted file mode 100644 index b39f7ec..0000000 --- a/vendor/symfony/console/Tests/Command/ListCommandTest.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Command; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Tester\CommandTester; - -class ListCommandTest extends TestCase -{ - public function testExecuteListsCommands() - { - $application = new Application(); - $commandTester = new CommandTester($command = $application->get('list')); - $commandTester->execute(array('command' => $command->getName()), array('decorated' => false)); - - $this->assertRegExp('/help\s{2,}Displays help for a command/', $commandTester->getDisplay(), '->execute() returns a list of available commands'); - } - - public function testExecuteListsCommandsWithXmlOption() - { - $application = new Application(); - $commandTester = new CommandTester($command = $application->get('list')); - $commandTester->execute(array('command' => $command->getName(), '--format' => 'xml')); - $this->assertRegExp('/<command id="list" name="list" hidden="0">/', $commandTester->getDisplay(), '->execute() returns a list of available commands in XML if --xml is passed'); - } - - public function testExecuteListsCommandsWithRawOption() - { - $application = new Application(); - $commandTester = new CommandTester($command = $application->get('list')); - $commandTester->execute(array('command' => $command->getName(), '--raw' => true)); - $output = <<<'EOF' -help Displays help for a command -list Lists commands - -EOF; - - $this->assertEquals($output, $commandTester->getDisplay(true)); - } - - public function testExecuteListsCommandsWithNamespaceArgument() - { - require_once realpath(__DIR__.'/../Fixtures/FooCommand.php'); - $application = new Application(); - $application->add(new \FooCommand()); - $commandTester = new CommandTester($command = $application->get('list')); - $commandTester->execute(array('command' => $command->getName(), 'namespace' => 'foo', '--raw' => true)); - $output = <<<'EOF' -foo:bar The foo:bar command - -EOF; - - $this->assertEquals($output, $commandTester->getDisplay(true)); - } - - public function testExecuteListsCommandsOrder() - { - require_once realpath(__DIR__.'/../Fixtures/Foo6Command.php'); - $application = new Application(); - $application->add(new \Foo6Command()); - $commandTester = new CommandTester($command = $application->get('list')); - $commandTester->execute(array('command' => $command->getName()), array('decorated' => false)); - $output = <<<'EOF' -Console Tool - -Usage: - command [options] [arguments] - -Options: - -h, --help Display this help message - -q, --quiet Do not output any message - -V, --version Display this application version - --ansi Force ANSI output - --no-ansi Disable ANSI output - -n, --no-interaction Do not ask any interactive question - -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -Available commands: - help Displays help for a command - list Lists commands - 0foo - 0foo:bar 0foo:bar command -EOF; - - $this->assertEquals($output, trim($commandTester->getDisplay(true))); - } - - public function testExecuteListsCommandsOrderRaw() - { - require_once realpath(__DIR__.'/../Fixtures/Foo6Command.php'); - $application = new Application(); - $application->add(new \Foo6Command()); - $commandTester = new CommandTester($command = $application->get('list')); - $commandTester->execute(array('command' => $command->getName(), '--raw' => true)); - $output = <<<'EOF' -help Displays help for a command -list Lists commands -0foo:bar 0foo:bar command -EOF; - - $this->assertEquals($output, trim($commandTester->getDisplay(true))); - } -} diff --git a/vendor/symfony/console/Tests/Command/LockableTraitTest.php b/vendor/symfony/console/Tests/Command/LockableTraitTest.php deleted file mode 100644 index a622d1b..0000000 --- a/vendor/symfony/console/Tests/Command/LockableTraitTest.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Command; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\Lock\Factory; -use Symfony\Component\Lock\Store\FlockStore; -use Symfony\Component\Lock\Store\SemaphoreStore; - -class LockableTraitTest extends TestCase -{ - protected static $fixturesPath; - - public static function setUpBeforeClass() - { - self::$fixturesPath = __DIR__.'/../Fixtures/'; - require_once self::$fixturesPath.'/FooLockCommand.php'; - require_once self::$fixturesPath.'/FooLock2Command.php'; - } - - public function testLockIsReleased() - { - $command = new \FooLockCommand(); - - $tester = new CommandTester($command); - $this->assertSame(2, $tester->execute(array())); - $this->assertSame(2, $tester->execute(array())); - } - - public function testLockReturnsFalseIfAlreadyLockedByAnotherCommand() - { - $command = new \FooLockCommand(); - - if (SemaphoreStore::isSupported(false)) { - $store = new SemaphoreStore(); - } else { - $store = new FlockStore(); - } - - $lock = (new Factory($store))->createLock($command->getName()); - $lock->acquire(); - - $tester = new CommandTester($command); - $this->assertSame(1, $tester->execute(array())); - - $lock->release(); - $this->assertSame(2, $tester->execute(array())); - } - - public function testMultipleLockCallsThrowLogicException() - { - $command = new \FooLock2Command(); - - $tester = new CommandTester($command); - $this->assertSame(1, $tester->execute(array())); - } -} diff --git a/vendor/symfony/console/Tests/CommandLoader/ContainerCommandLoaderTest.php b/vendor/symfony/console/Tests/CommandLoader/ContainerCommandLoaderTest.php deleted file mode 100644 index 78eefd2..0000000 --- a/vendor/symfony/console/Tests/CommandLoader/ContainerCommandLoaderTest.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\CommandLoader; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; -use Symfony\Component\DependencyInjection\ServiceLocator; - -class ContainerCommandLoaderTest extends TestCase -{ - public function testHas() - { - $loader = new ContainerCommandLoader(new ServiceLocator(array( - 'foo-service' => function () { return new Command('foo'); }, - 'bar-service' => function () { return new Command('bar'); }, - )), array('foo' => 'foo-service', 'bar' => 'bar-service')); - - $this->assertTrue($loader->has('foo')); - $this->assertTrue($loader->has('bar')); - $this->assertFalse($loader->has('baz')); - } - - public function testGet() - { - $loader = new ContainerCommandLoader(new ServiceLocator(array( - 'foo-service' => function () { return new Command('foo'); }, - 'bar-service' => function () { return new Command('bar'); }, - )), array('foo' => 'foo-service', 'bar' => 'bar-service')); - - $this->assertInstanceOf(Command::class, $loader->get('foo')); - $this->assertInstanceOf(Command::class, $loader->get('bar')); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - */ - public function testGetUnknownCommandThrows() - { - (new ContainerCommandLoader(new ServiceLocator(array()), array()))->get('unknown'); - } - - public function testGetCommandNames() - { - $loader = new ContainerCommandLoader(new ServiceLocator(array( - 'foo-service' => function () { return new Command('foo'); }, - 'bar-service' => function () { return new Command('bar'); }, - )), array('foo' => 'foo-service', 'bar' => 'bar-service')); - - $this->assertSame(array('foo', 'bar'), $loader->getNames()); - } -} diff --git a/vendor/symfony/console/Tests/CommandLoader/FactoryCommandLoaderTest.php b/vendor/symfony/console/Tests/CommandLoader/FactoryCommandLoaderTest.php deleted file mode 100644 index 5ee6cd1..0000000 --- a/vendor/symfony/console/Tests/CommandLoader/FactoryCommandLoaderTest.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\CommandLoader; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; - -class FactoryCommandLoaderTest extends TestCase -{ - public function testHas() - { - $loader = new FactoryCommandLoader(array( - 'foo' => function () { return new Command('foo'); }, - 'bar' => function () { return new Command('bar'); }, - )); - - $this->assertTrue($loader->has('foo')); - $this->assertTrue($loader->has('bar')); - $this->assertFalse($loader->has('baz')); - } - - public function testGet() - { - $loader = new FactoryCommandLoader(array( - 'foo' => function () { return new Command('foo'); }, - 'bar' => function () { return new Command('bar'); }, - )); - - $this->assertInstanceOf(Command::class, $loader->get('foo')); - $this->assertInstanceOf(Command::class, $loader->get('bar')); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException - */ - public function testGetUnknownCommandThrows() - { - (new FactoryCommandLoader(array()))->get('unknown'); - } - - public function testGetCommandNames() - { - $loader = new FactoryCommandLoader(array( - 'foo' => function () { return new Command('foo'); }, - 'bar' => function () { return new Command('bar'); }, - )); - - $this->assertSame(array('foo', 'bar'), $loader->getNames()); - } -} diff --git a/vendor/symfony/console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/vendor/symfony/console/Tests/DependencyInjection/AddConsoleCommandPassTest.php deleted file mode 100644 index 67fbb98..0000000 --- a/vendor/symfony/console/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ /dev/null @@ -1,262 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\DependencyInjection; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; -use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\TypedReference; - -class AddConsoleCommandPassTest extends TestCase -{ - /** - * @dataProvider visibilityProvider - */ - public function testProcess($public) - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING); - $container->setParameter('my-command.class', 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand'); - - $definition = new Definition('%my-command.class%'); - $definition->setPublic($public); - $definition->addTag('console.command'); - $container->setDefinition('my-command', $definition); - - $container->compile(); - - $alias = 'console.command.symfony_component_console_tests_dependencyinjection_mycommand'; - - if ($public) { - $this->assertFalse($container->hasAlias($alias)); - $id = 'my-command'; - } else { - $id = $alias; - // The alias is replaced by a Definition by the ReplaceAliasByActualDefinitionPass - // in case the original service is private - $this->assertFalse($container->hasDefinition('my-command')); - $this->assertTrue($container->hasDefinition($alias)); - } - - $this->assertTrue($container->hasParameter('console.command.ids')); - $this->assertSame(array($alias => $id), $container->getParameter('console.command.ids')); - } - - public function testProcessRegistersLazyCommands() - { - $container = new ContainerBuilder(); - $command = $container - ->register('my-command', MyCommand::class) - ->setPublic(false) - ->addTag('console.command', array('command' => 'my:command')) - ->addTag('console.command', array('command' => 'my:alias')) - ; - - (new AddConsoleCommandPass())->process($container); - - $commandLoader = $container->getDefinition('console.command_loader'); - $commandLocator = $container->getDefinition((string) $commandLoader->getArgument(0)); - - $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); - $this->assertSame(array('my:command' => 'my-command', 'my:alias' => 'my-command'), $commandLoader->getArgument(1)); - $this->assertEquals(array(array('my-command' => new ServiceClosureArgument(new TypedReference('my-command', MyCommand::class)))), $commandLocator->getArguments()); - $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_mycommand' => 'my-command'), $container->getParameter('console.command.ids')); - $this->assertSame(array('my-command' => true), $container->getParameter('console.lazy_command.ids')); - $this->assertSame(array(array('setName', array('my:command')), array('setAliases', array(array('my:alias')))), $command->getMethodCalls()); - } - - public function testProcessFallsBackToDefaultName() - { - $container = new ContainerBuilder(); - $container - ->register('with-default-name', NamedCommand::class) - ->setPublic(false) - ->addTag('console.command') - ; - - $pass = new AddConsoleCommandPass(); - $pass->process($container); - - $commandLoader = $container->getDefinition('console.command_loader'); - $commandLocator = $container->getDefinition((string) $commandLoader->getArgument(0)); - - $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); - $this->assertSame(array('default' => 'with-default-name'), $commandLoader->getArgument(1)); - $this->assertEquals(array(array('with-default-name' => new ServiceClosureArgument(new TypedReference('with-default-name', NamedCommand::class)))), $commandLocator->getArguments()); - $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_namedcommand' => 'with-default-name'), $container->getParameter('console.command.ids')); - $this->assertSame(array('with-default-name' => true), $container->getParameter('console.lazy_command.ids')); - - $container = new ContainerBuilder(); - $container - ->register('with-default-name', NamedCommand::class) - ->setPublic(false) - ->addTag('console.command', array('command' => 'new-name')) - ; - - $pass->process($container); - - $this->assertSame(array('new-name' => 'with-default-name'), $container->getDefinition('console.command_loader')->getArgument(1)); - } - - public function visibilityProvider() - { - return array( - array(true), - array(false), - ); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "my-command" tagged "console.command" must not be abstract. - */ - public function testProcessThrowAnExceptionIfTheServiceIsAbstract() - { - $container = new ContainerBuilder(); - $container->setResourceTracking(false); - $container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING); - - $definition = new Definition('Symfony\Component\Console\Tests\DependencyInjection\MyCommand'); - $definition->addTag('console.command'); - $definition->setAbstract(true); - $container->setDefinition('my-command', $definition); - - $container->compile(); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "my-command" tagged "console.command" must be a subclass of "Symfony\Component\Console\Command\Command". - */ - public function testProcessThrowAnExceptionIfTheServiceIsNotASubclassOfCommand() - { - $container = new ContainerBuilder(); - $container->setResourceTracking(false); - $container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING); - - $definition = new Definition('SplObjectStorage'); - $definition->addTag('console.command'); - $container->setDefinition('my-command', $definition); - - $container->compile(); - } - - public function testProcessPrivateServicesWithSameCommand() - { - $container = new ContainerBuilder(); - $className = 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand'; - - $definition1 = new Definition($className); - $definition1->addTag('console.command')->setPublic(false); - - $definition2 = new Definition($className); - $definition2->addTag('console.command')->setPublic(false); - - $container->setDefinition('my-command1', $definition1); - $container->setDefinition('my-command2', $definition2); - - (new AddConsoleCommandPass())->process($container); - - $alias1 = 'console.command.symfony_component_console_tests_dependencyinjection_mycommand'; - $alias2 = $alias1.'_my-command2'; - $this->assertTrue($container->hasAlias($alias1)); - $this->assertTrue($container->hasAlias($alias2)); - } - - public function testProcessOnChildDefinitionWithClass() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING); - $className = 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand'; - - $parentId = 'my-parent-command'; - $childId = 'my-child-command'; - - $parentDefinition = new Definition(/* no class */); - $parentDefinition->setAbstract(true)->setPublic(false); - - $childDefinition = new ChildDefinition($parentId); - $childDefinition->addTag('console.command')->setPublic(true); - $childDefinition->setClass($className); - - $container->setDefinition($parentId, $parentDefinition); - $container->setDefinition($childId, $childDefinition); - - $container->compile(); - $command = $container->get($childId); - - $this->assertInstanceOf($className, $command); - } - - public function testProcessOnChildDefinitionWithParentClass() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING); - $className = 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand'; - - $parentId = 'my-parent-command'; - $childId = 'my-child-command'; - - $parentDefinition = new Definition($className); - $parentDefinition->setAbstract(true)->setPublic(false); - - $childDefinition = new ChildDefinition($parentId); - $childDefinition->addTag('console.command')->setPublic(true); - - $container->setDefinition($parentId, $parentDefinition); - $container->setDefinition($childId, $childDefinition); - - $container->compile(); - $command = $container->get($childId); - - $this->assertInstanceOf($className, $command); - } - - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage The definition for "my-child-command" has no class. - */ - public function testProcessOnChildDefinitionWithoutClass() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING); - - $parentId = 'my-parent-command'; - $childId = 'my-child-command'; - - $parentDefinition = new Definition(); - $parentDefinition->setAbstract(true)->setPublic(false); - - $childDefinition = new ChildDefinition($parentId); - $childDefinition->addTag('console.command')->setPublic(true); - - $container->setDefinition($parentId, $parentDefinition); - $container->setDefinition($childId, $childDefinition); - - $container->compile(); - } -} - -class MyCommand extends Command -{ -} - -class NamedCommand extends Command -{ - protected static $defaultName = 'default'; -} diff --git a/vendor/symfony/console/Tests/Descriptor/AbstractDescriptorTest.php b/vendor/symfony/console/Tests/Descriptor/AbstractDescriptorTest.php deleted file mode 100644 index 3686e75..0000000 --- a/vendor/symfony/console/Tests/Descriptor/AbstractDescriptorTest.php +++ /dev/null @@ -1,107 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Descriptor; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\BufferedOutput; - -abstract class AbstractDescriptorTest extends TestCase -{ - /** @dataProvider getDescribeInputArgumentTestData */ - public function testDescribeInputArgument(InputArgument $argument, $expectedDescription) - { - $this->assertDescription($expectedDescription, $argument); - } - - /** @dataProvider getDescribeInputOptionTestData */ - public function testDescribeInputOption(InputOption $option, $expectedDescription) - { - $this->assertDescription($expectedDescription, $option); - } - - /** @dataProvider getDescribeInputDefinitionTestData */ - public function testDescribeInputDefinition(InputDefinition $definition, $expectedDescription) - { - $this->assertDescription($expectedDescription, $definition); - } - - /** @dataProvider getDescribeCommandTestData */ - public function testDescribeCommand(Command $command, $expectedDescription) - { - $this->assertDescription($expectedDescription, $command); - } - - /** @dataProvider getDescribeApplicationTestData */ - public function testDescribeApplication(Application $application, $expectedDescription) - { - // Replaces the dynamic placeholders of the command help text with a static version. - // The placeholder %command.full_name% includes the script path that is not predictable - // and can not be tested against. - foreach ($application->all() as $command) { - $command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp())); - } - - $this->assertDescription($expectedDescription, $application); - } - - public function getDescribeInputArgumentTestData() - { - return $this->getDescriptionTestData(ObjectsProvider::getInputArguments()); - } - - public function getDescribeInputOptionTestData() - { - return $this->getDescriptionTestData(ObjectsProvider::getInputOptions()); - } - - public function getDescribeInputDefinitionTestData() - { - return $this->getDescriptionTestData(ObjectsProvider::getInputDefinitions()); - } - - public function getDescribeCommandTestData() - { - return $this->getDescriptionTestData(ObjectsProvider::getCommands()); - } - - public function getDescribeApplicationTestData() - { - return $this->getDescriptionTestData(ObjectsProvider::getApplications()); - } - - abstract protected function getDescriptor(); - - abstract protected function getFormat(); - - protected function getDescriptionTestData(array $objects) - { - $data = array(); - foreach ($objects as $name => $object) { - $description = file_get_contents(sprintf('%s/../Fixtures/%s.%s', __DIR__, $name, $this->getFormat())); - $data[] = array($object, $description); - } - - return $data; - } - - protected function assertDescription($expectedDescription, $describedObject, array $options = array()) - { - $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); - $this->getDescriptor()->describe($output, $describedObject, $options + array('raw_output' => true)); - $this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $output->fetch()))); - } -} diff --git a/vendor/symfony/console/Tests/Descriptor/JsonDescriptorTest.php b/vendor/symfony/console/Tests/Descriptor/JsonDescriptorTest.php deleted file mode 100644 index dffcaf6..0000000 --- a/vendor/symfony/console/Tests/Descriptor/JsonDescriptorTest.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Descriptor; - -use Symfony\Component\Console\Descriptor\JsonDescriptor; -use Symfony\Component\Console\Output\BufferedOutput; - -class JsonDescriptorTest extends AbstractDescriptorTest -{ - protected function getDescriptor() - { - return new JsonDescriptor(); - } - - protected function getFormat() - { - return 'json'; - } - - protected function assertDescription($expectedDescription, $describedObject, array $options = array()) - { - $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); - $this->getDescriptor()->describe($output, $describedObject, $options + array('raw_output' => true)); - $this->assertEquals(json_decode(trim($expectedDescription), true), json_decode(trim(str_replace(PHP_EOL, "\n", $output->fetch())), true)); - } -} diff --git a/vendor/symfony/console/Tests/Descriptor/MarkdownDescriptorTest.php b/vendor/symfony/console/Tests/Descriptor/MarkdownDescriptorTest.php deleted file mode 100644 index eb80f58..0000000 --- a/vendor/symfony/console/Tests/Descriptor/MarkdownDescriptorTest.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Descriptor; - -use Symfony\Component\Console\Descriptor\MarkdownDescriptor; -use Symfony\Component\Console\Tests\Fixtures\DescriptorApplicationMbString; -use Symfony\Component\Console\Tests\Fixtures\DescriptorCommandMbString; - -class MarkdownDescriptorTest extends AbstractDescriptorTest -{ - public function getDescribeCommandTestData() - { - return $this->getDescriptionTestData(array_merge( - ObjectsProvider::getCommands(), - array('command_mbstring' => new DescriptorCommandMbString()) - )); - } - - public function getDescribeApplicationTestData() - { - return $this->getDescriptionTestData(array_merge( - ObjectsProvider::getApplications(), - array('application_mbstring' => new DescriptorApplicationMbString()) - )); - } - - protected function getDescriptor() - { - return new MarkdownDescriptor(); - } - - protected function getFormat() - { - return 'md'; - } -} diff --git a/vendor/symfony/console/Tests/Descriptor/ObjectsProvider.php b/vendor/symfony/console/Tests/Descriptor/ObjectsProvider.php deleted file mode 100644 index b4f34ad..0000000 --- a/vendor/symfony/console/Tests/Descriptor/ObjectsProvider.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Descriptor; - -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication1; -use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication2; -use Symfony\Component\Console\Tests\Fixtures\DescriptorCommand1; -use Symfony\Component\Console\Tests\Fixtures\DescriptorCommand2; - -/** - * @author Jean-François Simon <contact@jfsimon.fr> - */ -class ObjectsProvider -{ - public static function getInputArguments() - { - return array( - 'input_argument_1' => new InputArgument('argument_name', InputArgument::REQUIRED), - 'input_argument_2' => new InputArgument('argument_name', InputArgument::IS_ARRAY, 'argument description'), - 'input_argument_3' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'default_value'), - 'input_argument_4' => new InputArgument('argument_name', InputArgument::REQUIRED, "multiline\nargument description"), - 'input_argument_with_style' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', '<comment>style</>'), - 'input_argument_with_default_inf_value' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', INF), - ); - } - - public static function getInputOptions() - { - return array( - 'input_option_1' => new InputOption('option_name', 'o', InputOption::VALUE_NONE), - 'input_option_2' => new InputOption('option_name', 'o', InputOption::VALUE_OPTIONAL, 'option description', 'default_value'), - 'input_option_3' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, 'option description'), - 'input_option_4' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'option description', array()), - 'input_option_5' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, "multiline\noption description"), - 'input_option_6' => new InputOption('option_name', array('o', 'O'), InputOption::VALUE_REQUIRED, 'option with multiple shortcuts'), - 'input_option_with_style' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, 'option description', '<comment>style</>'), - 'input_option_with_style_array' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'option description', array('<comment>Hello</comment>', '<info>world</info>')), - 'input_option_with_default_inf_value' => new InputOption('option_name', 'o', InputOption::VALUE_OPTIONAL, 'option description', INF), - ); - } - - public static function getInputDefinitions() - { - return array( - 'input_definition_1' => new InputDefinition(), - 'input_definition_2' => new InputDefinition(array(new InputArgument('argument_name', InputArgument::REQUIRED))), - 'input_definition_3' => new InputDefinition(array(new InputOption('option_name', 'o', InputOption::VALUE_NONE))), - 'input_definition_4' => new InputDefinition(array( - new InputArgument('argument_name', InputArgument::REQUIRED), - new InputOption('option_name', 'o', InputOption::VALUE_NONE), - )), - ); - } - - public static function getCommands() - { - return array( - 'command_1' => new DescriptorCommand1(), - 'command_2' => new DescriptorCommand2(), - ); - } - - public static function getApplications() - { - return array( - 'application_1' => new DescriptorApplication1(), - 'application_2' => new DescriptorApplication2(), - ); - } -} diff --git a/vendor/symfony/console/Tests/Descriptor/TextDescriptorTest.php b/vendor/symfony/console/Tests/Descriptor/TextDescriptorTest.php deleted file mode 100644 index c024a52..0000000 --- a/vendor/symfony/console/Tests/Descriptor/TextDescriptorTest.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Descriptor; - -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication2; -use Symfony\Component\Console\Tests\Fixtures\DescriptorApplicationMbString; -use Symfony\Component\Console\Tests\Fixtures\DescriptorCommandMbString; - -class TextDescriptorTest extends AbstractDescriptorTest -{ - public function getDescribeCommandTestData() - { - return $this->getDescriptionTestData(array_merge( - ObjectsProvider::getCommands(), - array('command_mbstring' => new DescriptorCommandMbString()) - )); - } - - public function getDescribeApplicationTestData() - { - return $this->getDescriptionTestData(array_merge( - ObjectsProvider::getApplications(), - array('application_mbstring' => new DescriptorApplicationMbString()) - )); - } - - public function testDescribeApplicationWithFilteredNamespace() - { - $application = new DescriptorApplication2(); - - $this->assertDescription(file_get_contents(__DIR__.'/../Fixtures/application_filtered_namespace.txt'), $application, array('namespace' => 'command4')); - } - - protected function getDescriptor() - { - return new TextDescriptor(); - } - - protected function getFormat() - { - return 'txt'; - } -} diff --git a/vendor/symfony/console/Tests/Descriptor/XmlDescriptorTest.php b/vendor/symfony/console/Tests/Descriptor/XmlDescriptorTest.php deleted file mode 100644 index 59a5d1e..0000000 --- a/vendor/symfony/console/Tests/Descriptor/XmlDescriptorTest.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Descriptor; - -use Symfony\Component\Console\Descriptor\XmlDescriptor; - -class XmlDescriptorTest extends AbstractDescriptorTest -{ - protected function getDescriptor() - { - return new XmlDescriptor(); - } - - protected function getFormat() - { - return 'xml'; - } -} diff --git a/vendor/symfony/console/Tests/EventListener/ErrorListenerTest.php b/vendor/symfony/console/Tests/EventListener/ErrorListenerTest.php deleted file mode 100644 index b3f3fb4..0000000 --- a/vendor/symfony/console/Tests/EventListener/ErrorListenerTest.php +++ /dev/null @@ -1,156 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\EventListener; - -use PHPUnit\Framework\TestCase; -use Psr\Log\LoggerInterface; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Event\ConsoleTerminateEvent; -use Symfony\Component\Console\EventListener\ErrorListener; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\Input; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\StringInput; -use Symfony\Component\Console\Output\OutputInterface; - -class ErrorListenerTest extends TestCase -{ - public function testOnConsoleError() - { - $error = new \TypeError('An error occurred'); - - $logger = $this->getLogger(); - $logger - ->expects($this->once()) - ->method('error') - ->with('Error thrown while running command "{command}". Message: "{message}"', array('exception' => $error, 'command' => 'test:run --foo=baz buzz', 'message' => 'An error occurred')) - ; - - $listener = new ErrorListener($logger); - $listener->onConsoleError(new ConsoleErrorEvent(new ArgvInput(array('console.php', 'test:run', '--foo=baz', 'buzz')), $this->getOutput(), $error, new Command('test:run'))); - } - - public function testOnConsoleErrorWithNoCommandAndNoInputString() - { - $error = new \RuntimeException('An error occurred'); - - $logger = $this->getLogger(); - $logger - ->expects($this->once()) - ->method('error') - ->with('An error occurred while using the console. Message: "{message}"', array('exception' => $error, 'message' => 'An error occurred')) - ; - - $listener = new ErrorListener($logger); - $listener->onConsoleError(new ConsoleErrorEvent(new NonStringInput(), $this->getOutput(), $error)); - } - - public function testOnConsoleTerminateForNonZeroExitCodeWritesToLog() - { - $logger = $this->getLogger(); - $logger - ->expects($this->once()) - ->method('debug') - ->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run', 'code' => 255)) - ; - - $listener = new ErrorListener($logger); - $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(array('console.php', 'test:run')), 255)); - } - - public function testOnConsoleTerminateForZeroExitCodeDoesNotWriteToLog() - { - $logger = $this->getLogger(); - $logger - ->expects($this->never()) - ->method('debug') - ; - - $listener = new ErrorListener($logger); - $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(array('console.php', 'test:run')), 0)); - } - - public function testGetSubscribedEvents() - { - $this->assertEquals( - array( - 'console.error' => array('onConsoleError', -128), - 'console.terminate' => array('onConsoleTerminate', -128), - ), - ErrorListener::getSubscribedEvents() - ); - } - - public function testAllKindsOfInputCanBeLogged() - { - $logger = $this->getLogger(); - $logger - ->expects($this->exactly(3)) - ->method('debug') - ->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run --foo=bar', 'code' => 255)) - ; - - $listener = new ErrorListener($logger); - $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArgvInput(array('console.php', 'test:run', '--foo=bar')), 255)); - $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new ArrayInput(array('name' => 'test:run', '--foo' => 'bar')), 255)); - $listener->onConsoleTerminate($this->getConsoleTerminateEvent(new StringInput('test:run --foo=bar'), 255)); - } - - public function testCommandNameIsDisplayedForNonStringableInput() - { - $logger = $this->getLogger(); - $logger - ->expects($this->once()) - ->method('debug') - ->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run', 'code' => 255)) - ; - - $listener = new ErrorListener($logger); - $listener->onConsoleTerminate($this->getConsoleTerminateEvent($this->getMockBuilder(InputInterface::class)->getMock(), 255)); - } - - private function getLogger() - { - return $this->getMockForAbstractClass(LoggerInterface::class); - } - - private function getConsoleTerminateEvent(InputInterface $input, $exitCode) - { - return new ConsoleTerminateEvent(new Command('test:run'), $input, $this->getOutput(), $exitCode); - } - - private function getOutput() - { - return $this->getMockBuilder(OutputInterface::class)->getMock(); - } -} - -class NonStringInput extends Input -{ - public function getFirstArgument() - { - } - - public function hasParameterOption($values, $onlyParams = false) - { - } - - public function getParameterOption($values, $default = false, $onlyParams = false) - { - } - - public function parse() - { - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/BarBucCommand.php b/vendor/symfony/console/Tests/Fixtures/BarBucCommand.php deleted file mode 100644 index 52b619e..0000000 --- a/vendor/symfony/console/Tests/Fixtures/BarBucCommand.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; - -class BarBucCommand extends Command -{ - protected function configure() - { - $this->setName('bar:buc'); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorApplication2.php b/vendor/symfony/console/Tests/Fixtures/DescriptorApplication2.php deleted file mode 100644 index 7bb02fa..0000000 --- a/vendor/symfony/console/Tests/Fixtures/DescriptorApplication2.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Fixtures; - -use Symfony\Component\Console\Application; - -class DescriptorApplication2 extends Application -{ - public function __construct() - { - parent::__construct('My Symfony application', 'v1.0'); - $this->add(new DescriptorCommand1()); - $this->add(new DescriptorCommand2()); - $this->add(new DescriptorCommand3()); - $this->add(new DescriptorCommand4()); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorApplicationMbString.php b/vendor/symfony/console/Tests/Fixtures/DescriptorApplicationMbString.php deleted file mode 100644 index bf170c4..0000000 --- a/vendor/symfony/console/Tests/Fixtures/DescriptorApplicationMbString.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Fixtures; - -use Symfony\Component\Console\Application; - -class DescriptorApplicationMbString extends Application -{ - public function __construct() - { - parent::__construct('MbString åpplicätion'); - - $this->add(new DescriptorCommandMbString()); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorCommand1.php b/vendor/symfony/console/Tests/Fixtures/DescriptorCommand1.php deleted file mode 100644 index ede05d7..0000000 --- a/vendor/symfony/console/Tests/Fixtures/DescriptorCommand1.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Fixtures; - -use Symfony\Component\Console\Command\Command; - -class DescriptorCommand1 extends Command -{ - protected function configure() - { - $this - ->setName('descriptor:command1') - ->setAliases(array('alias1', 'alias2')) - ->setDescription('command 1 description') - ->setHelp('command 1 help') - ; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorCommand2.php b/vendor/symfony/console/Tests/Fixtures/DescriptorCommand2.php deleted file mode 100644 index 51106b9..0000000 --- a/vendor/symfony/console/Tests/Fixtures/DescriptorCommand2.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Fixtures; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; - -class DescriptorCommand2 extends Command -{ - protected function configure() - { - $this - ->setName('descriptor:command2') - ->setDescription('command 2 description') - ->setHelp('command 2 help') - ->addUsage('-o|--option_name <argument_name>') - ->addUsage('<argument_name>') - ->addArgument('argument_name', InputArgument::REQUIRED) - ->addOption('option_name', 'o', InputOption::VALUE_NONE) - ; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorCommand3.php b/vendor/symfony/console/Tests/Fixtures/DescriptorCommand3.php deleted file mode 100644 index 77f92e2..0000000 --- a/vendor/symfony/console/Tests/Fixtures/DescriptorCommand3.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Fixtures; - -use Symfony\Component\Console\Command\Command; - -class DescriptorCommand3 extends Command -{ - protected function configure() - { - $this - ->setName('descriptor:command3') - ->setDescription('command 3 description') - ->setHelp('command 3 help') - ->setHidden(true) - ; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorCommand4.php b/vendor/symfony/console/Tests/Fixtures/DescriptorCommand4.php deleted file mode 100644 index 13e8e5b..0000000 --- a/vendor/symfony/console/Tests/Fixtures/DescriptorCommand4.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Fixtures; - -use Symfony\Component\Console\Command\Command; - -class DescriptorCommand4 extends Command -{ - protected function configure() - { - $this - ->setName('descriptor:command4') - ->setAliases(array('descriptor:alias_command4', 'command4:descriptor')) - ; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorCommandMbString.php b/vendor/symfony/console/Tests/Fixtures/DescriptorCommandMbString.php deleted file mode 100644 index 66de917..0000000 --- a/vendor/symfony/console/Tests/Fixtures/DescriptorCommandMbString.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Fixtures; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; - -class DescriptorCommandMbString extends Command -{ - protected function configure() - { - $this - ->setName('descriptor:åèä') - ->setDescription('command åèä description') - ->setHelp('command åèä help') - ->addUsage('-o|--option_name <argument_name>') - ->addUsage('<argument_name>') - ->addArgument('argument_åèä', InputArgument::REQUIRED) - ->addOption('option_åèä', 'o', InputOption::VALUE_NONE) - ; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/DummyOutput.php b/vendor/symfony/console/Tests/Fixtures/DummyOutput.php deleted file mode 100644 index 866e214..0000000 --- a/vendor/symfony/console/Tests/Fixtures/DummyOutput.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Fixtures; - -use Symfony\Component\Console\Output\BufferedOutput; - -/** - * Dummy output. - * - * @author Kévin Dunglas <dunglas@gmail.com> - */ -class DummyOutput extends BufferedOutput -{ - /** - * @return array - */ - public function getLogs() - { - $logs = array(); - foreach (explode(PHP_EOL, trim($this->fetch())) as $message) { - preg_match('/^\[(.*)\] (.*)/', $message, $matches); - $logs[] = sprintf('%s %s', $matches[1], $matches[2]); - } - - return $logs; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/Foo1Command.php b/vendor/symfony/console/Tests/Fixtures/Foo1Command.php deleted file mode 100644 index 254162f..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Foo1Command.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class Foo1Command extends Command -{ - public $input; - public $output; - - protected function configure() - { - $this - ->setName('foo:bar1') - ->setDescription('The foo:bar1 command') - ->setAliases(array('afoobar1')) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->input = $input; - $this->output = $output; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/Foo2Command.php b/vendor/symfony/console/Tests/Fixtures/Foo2Command.php deleted file mode 100644 index 8071dc8..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Foo2Command.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class Foo2Command extends Command -{ - protected function configure() - { - $this - ->setName('foo1:bar') - ->setDescription('The foo1:bar command') - ->setAliases(array('afoobar2')) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/Foo3Command.php b/vendor/symfony/console/Tests/Fixtures/Foo3Command.php deleted file mode 100644 index adb3a2d..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Foo3Command.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class Foo3Command extends Command -{ - protected function configure() - { - $this - ->setName('foo3:bar') - ->setDescription('The foo3:bar command') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - try { - try { - throw new \Exception('First exception <p>this is html</p>'); - } catch (\Exception $e) { - throw new \Exception('Second exception <comment>comment</comment>', 0, $e); - } - } catch (\Exception $e) { - throw new \Exception('Third exception <fg=blue;bg=red>comment</>', 404, $e); - } - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/Foo4Command.php b/vendor/symfony/console/Tests/Fixtures/Foo4Command.php deleted file mode 100644 index 1c54639..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Foo4Command.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; - -class Foo4Command extends Command -{ - protected function configure() - { - $this->setName('foo3:bar:toh'); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/Foo5Command.php b/vendor/symfony/console/Tests/Fixtures/Foo5Command.php deleted file mode 100644 index a1c6082..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Foo5Command.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; - -class Foo5Command extends Command -{ - public function __construct() - { - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/Foo6Command.php b/vendor/symfony/console/Tests/Fixtures/Foo6Command.php deleted file mode 100644 index 6ae987e..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Foo6Command.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - - -use Symfony\Component\Console\Command\Command; - -class Foo6Command extends Command -{ - protected function configure() - { - $this->setName('0foo:bar')->setDescription('0foo:bar command'); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/FooCommand.php b/vendor/symfony/console/Tests/Fixtures/FooCommand.php deleted file mode 100644 index 355e0ad..0000000 --- a/vendor/symfony/console/Tests/Fixtures/FooCommand.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class FooCommand extends Command -{ - public $input; - public $output; - - protected function configure() - { - $this - ->setName('foo:bar') - ->setDescription('The foo:bar command') - ->setAliases(array('afoobar')) - ; - } - - protected function interact(InputInterface $input, OutputInterface $output) - { - $output->writeln('interact called'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->input = $input; - $this->output = $output; - - $output->writeln('called'); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/FooLock2Command.php b/vendor/symfony/console/Tests/Fixtures/FooLock2Command.php deleted file mode 100644 index 4e4656f..0000000 --- a/vendor/symfony/console/Tests/Fixtures/FooLock2Command.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Command\LockableTrait; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class FooLock2Command extends Command -{ - use LockableTrait; - - protected function configure() - { - $this->setName('foo:lock2'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - try { - $this->lock(); - $this->lock(); - } catch (LogicException $e) { - return 1; - } - - return 2; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/FooLockCommand.php b/vendor/symfony/console/Tests/Fixtures/FooLockCommand.php deleted file mode 100644 index dfa28a6..0000000 --- a/vendor/symfony/console/Tests/Fixtures/FooLockCommand.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Command\LockableTrait; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class FooLockCommand extends Command -{ - use LockableTrait; - - protected function configure() - { - $this->setName('foo:lock'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - if (!$this->lock()) { - return 1; - } - - $this->release(); - - return 2; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/FooOptCommand.php b/vendor/symfony/console/Tests/Fixtures/FooOptCommand.php deleted file mode 100644 index 9043aa4..0000000 --- a/vendor/symfony/console/Tests/Fixtures/FooOptCommand.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class FooOptCommand extends Command -{ - public $input; - public $output; - - protected function configure() - { - $this - ->setName('foo:bar') - ->setDescription('The foo:bar command') - ->setAliases(array('afoobar')) - ->addOption('fooopt', 'fo', InputOption::VALUE_OPTIONAL, 'fooopt description') - ; - } - - protected function interact(InputInterface $input, OutputInterface $output) - { - $output->writeln('interact called'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->input = $input; - $this->output = $output; - - $output->writeln('called'); - $output->writeln($this->input->getOption('fooopt')); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/FooSameCaseLowercaseCommand.php b/vendor/symfony/console/Tests/Fixtures/FooSameCaseLowercaseCommand.php deleted file mode 100644 index c875be0..0000000 --- a/vendor/symfony/console/Tests/Fixtures/FooSameCaseLowercaseCommand.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; - -class FooSameCaseLowercaseCommand extends Command -{ - protected function configure() - { - $this->setName('foo:bar')->setDescription('foo:bar command'); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/FooSameCaseUppercaseCommand.php b/vendor/symfony/console/Tests/Fixtures/FooSameCaseUppercaseCommand.php deleted file mode 100644 index 75c8d00..0000000 --- a/vendor/symfony/console/Tests/Fixtures/FooSameCaseUppercaseCommand.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; - -class FooSameCaseUppercaseCommand extends Command -{ - protected function configure() - { - $this->setName('foo:BAR')->setDescription('foo:BAR command'); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/FooSubnamespaced1Command.php b/vendor/symfony/console/Tests/Fixtures/FooSubnamespaced1Command.php deleted file mode 100644 index fc50c72..0000000 --- a/vendor/symfony/console/Tests/Fixtures/FooSubnamespaced1Command.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class FooSubnamespaced1Command extends Command -{ - public $input; - public $output; - - protected function configure() - { - $this - ->setName('foo:bar:baz') - ->setDescription('The foo:bar:baz command') - ->setAliases(array('foobarbaz')) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->input = $input; - $this->output = $output; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/FooSubnamespaced2Command.php b/vendor/symfony/console/Tests/Fixtures/FooSubnamespaced2Command.php deleted file mode 100644 index 1cf31ff..0000000 --- a/vendor/symfony/console/Tests/Fixtures/FooSubnamespaced2Command.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class FooSubnamespaced2Command extends Command -{ - public $input; - public $output; - - protected function configure() - { - $this - ->setName('foo:go:bret') - ->setDescription('The foo:bar:go command') - ->setAliases(array('foobargo')) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->input = $input; - $this->output = $output; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/FoobarCommand.php b/vendor/symfony/console/Tests/Fixtures/FoobarCommand.php deleted file mode 100644 index 9681628..0000000 --- a/vendor/symfony/console/Tests/Fixtures/FoobarCommand.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class FoobarCommand extends Command -{ - public $input; - public $output; - - protected function configure() - { - $this - ->setName('foobar:foo') - ->setDescription('The foobar:foo command') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->input = $input; - $this->output = $output; - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_0.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_0.php deleted file mode 100644 index 8fe7c07..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_0.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure has single blank line at start when using block element -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $output->caution('Lorem ipsum dolor sit amet'); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_1.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_1.php deleted file mode 100644 index e5c700d..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_1.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure has single blank line between titles and blocks -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $output->title('Title'); - $output->warning('Lorem ipsum dolor sit amet'); - $output->title('Title'); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php deleted file mode 100644 index 3111873..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_10.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure that all lines are aligned to the begin of the first line in a very long line block -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $output->block( - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum', - 'CUSTOM', - 'fg=white;bg=green', - 'X ', - true - ); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php deleted file mode 100644 index 3ed897d..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_11.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -// ensure long words are properly wrapped in blocks -return function (InputInterface $input, OutputInterface $output) { - $word = 'Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon'; - $sfStyle = new SymfonyStyle($input, $output); - $sfStyle->block($word, 'CUSTOM', 'fg=white;bg=blue', ' § ', false); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_12.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_12.php deleted file mode 100644 index 8c458ae..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_12.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -// ensure that all lines are aligned to the begin of the first one and start with '//' in a very long line comment -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $output->comment( - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum' - ); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_13.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_13.php deleted file mode 100644 index 827cbad..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_13.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -// ensure that nested tags have no effect on the color of the '//' prefix -return function (InputInterface $input, OutputInterface $output) { - $output->setDecorated(true); - $output = new SymfonyStyle($input, $output); - $output->comment( - 'Lorem ipsum dolor sit <comment>amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</comment> Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum' - ); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_14.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_14.php deleted file mode 100644 index a893a48..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_14.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -// ensure that block() behaves properly with a prefix and without type -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $output->block( - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum', - null, - null, - '$ ', - true - ); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_15.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_15.php deleted file mode 100644 index 68402cd..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_15.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -// ensure that block() behaves properly with a type and without prefix -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $output->block( - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum', - 'TEST' - ); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_16.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_16.php deleted file mode 100644 index 66e8179..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_16.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -// ensure that block() output is properly formatted (even padding lines) -return function (InputInterface $input, OutputInterface $output) { - $output->setDecorated(true); - $output = new SymfonyStyle($input, $output); - $output->success( - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum', - 'TEST' - ); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_17.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_17.php deleted file mode 100644 index 311e6b3..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_17.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure symfony style helper methods handle trailing backslashes properly when decorating user texts -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - - $output->title('Title ending with \\'); - $output->section('Section ending with \\'); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_2.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_2.php deleted file mode 100644 index 791b626..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_2.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure has single blank line between blocks -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $output->warning('Warning'); - $output->caution('Caution'); - $output->error('Error'); - $output->success('Success'); - $output->note('Note'); - $output->block('Custom block', 'CUSTOM', 'fg=white;bg=green', 'X ', true); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_3.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_3.php deleted file mode 100644 index 99253a6..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_3.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure has single blank line between two titles -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $output->title('First title'); - $output->title('Second title'); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_4.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_4.php deleted file mode 100644 index 0c5d3fb..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_4.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure has single blank line after any text and a title -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - - $output->write('Lorem ipsum dolor sit amet'); - $output->title('First title'); - - $output->writeln('Lorem ipsum dolor sit amet'); - $output->title('Second title'); - - $output->write('Lorem ipsum dolor sit amet'); - $output->write(''); - $output->title('Third title'); - - //Ensure edge case by appending empty strings to history: - $output->write('Lorem ipsum dolor sit amet'); - $output->write(array('', '', '')); - $output->title('Fourth title'); - - //Ensure have manual control over number of blank lines: - $output->writeln('Lorem ipsum dolor sit amet'); - $output->writeln(array('', '')); //Should append an extra blank line - $output->title('Fifth title'); - - $output->writeln('Lorem ipsum dolor sit amet'); - $output->newLine(2); //Should append an extra blank line - $output->title('Fifth title'); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_5.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_5.php deleted file mode 100644 index 96433ed..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_5.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure has proper line ending before outputting a text block like with SymfonyStyle::listing() or SymfonyStyle::text() -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - - $output->writeln('Lorem ipsum dolor sit amet'); - $output->listing(array( - 'Lorem ipsum dolor sit amet', - 'consectetur adipiscing elit', - )); - - //Even using write: - $output->write('Lorem ipsum dolor sit amet'); - $output->listing(array( - 'Lorem ipsum dolor sit amet', - 'consectetur adipiscing elit', - )); - - $output->write('Lorem ipsum dolor sit amet'); - $output->text(array( - 'Lorem ipsum dolor sit amet', - 'consectetur adipiscing elit', - )); - - $output->newLine(); - - $output->write('Lorem ipsum dolor sit amet'); - $output->comment(array( - 'Lorem ipsum dolor sit amet', - 'consectetur adipiscing elit', - )); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_6.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_6.php deleted file mode 100644 index 8031ec9..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_6.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure has proper blank line after text block when using a block like with SymfonyStyle::success -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - - $output->listing(array( - 'Lorem ipsum dolor sit amet', - 'consectetur adipiscing elit', - )); - $output->success('Lorem ipsum dolor sit amet'); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_7.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_7.php deleted file mode 100644 index 203eb5b..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_7.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure questions do not output anything when input is non-interactive -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $output->title('Title'); - $output->askHidden('Hidden question'); - $output->choice('Choice question with default', array('choice1', 'choice2'), 'choice1'); - $output->confirm('Confirmation with yes default', true); - $output->text('Duis aute irure dolor in reprehenderit in voluptate velit esse'); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_8.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_8.php deleted file mode 100644 index 16b26b5..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_8.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php - -use Symfony\Component\Console\Helper\TableCell; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure formatting tables when using multiple headers with TableCell -return function (InputInterface $input, OutputInterface $output) { - $headers = array( - array(new TableCell('Main table title', array('colspan' => 3))), - array('ISBN', 'Title', 'Author'), - ); - - $rows = array( - array( - '978-0521567817', - 'De Monarchia', - new TableCell("Dante Alighieri\nspans multiple rows", array('rowspan' => 2)), - ), - array('978-0804169127', 'Divine Comedy'), - ); - - $output = new SymfonyStyle($input, $output); - $output->table($headers, $rows); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php deleted file mode 100644 index 57afdf0..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/command_9.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure that all lines are aligned to the begin of the first line in a multi-line block -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $output->block(array('Custom block', 'Second custom block line'), 'CUSTOM', 'fg=white;bg=green', 'X ', true); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/interactive_command_1.php b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/interactive_command_1.php deleted file mode 100644 index 3c9c744..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/command/interactive_command_1.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -//Ensure that questions have the expected outputs -return function (InputInterface $input, OutputInterface $output) { - $output = new SymfonyStyle($input, $output); - $stream = fopen('php://memory', 'r+', false); - - fwrite($stream, "Foo\nBar\nBaz"); - rewind($stream); - $input->setStream($stream); - - $output->ask('What\'s your name?'); - $output->ask('How are you?'); - $output->ask('Where do you come from?'); -}; diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/interactive_output_1.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/interactive_output_1.txt deleted file mode 100644 index 6fc7d7e..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/interactive_output_1.txt +++ /dev/null @@ -1,7 +0,0 @@ - - What's your name?: - > - How are you?: - > - Where do you come from?: - > diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_0.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_0.txt deleted file mode 100644 index a42e0f7..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_0.txt +++ /dev/null @@ -1,3 +0,0 @@ - - ! [CAUTION] Lorem ipsum dolor sit amet - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_1.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_1.txt deleted file mode 100644 index 334875f..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_1.txt +++ /dev/null @@ -1,9 +0,0 @@ - -Title -===== - - [WARNING] Lorem ipsum dolor sit amet - -Title -===== - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_10.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_10.txt deleted file mode 100644 index 385c6a2..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_10.txt +++ /dev/null @@ -1,7 +0,0 @@ - -X [CUSTOM] Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et -X dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea -X commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat -X nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit -X anim id est laborum - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt deleted file mode 100644 index 190d784..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_11.txt +++ /dev/null @@ -1,4 +0,0 @@ - - § [CUSTOM] Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophatto - § peristeralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_12.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_12.txt deleted file mode 100644 index 9983af8..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_12.txt +++ /dev/null @@ -1,6 +0,0 @@ - - // Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna - // aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. - // Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur - // sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt deleted file mode 100644 index 0f3704b..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_13.txt +++ /dev/null @@ -1,7 +0,0 @@ - - // Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et  - // dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea  - // commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla  - // pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim - // id est laborum - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_14.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_14.txt deleted file mode 100644 index 1d0d37e..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_14.txt +++ /dev/null @@ -1,6 +0,0 @@ - -$ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna -$ aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -$ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint -$ occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_15.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_15.txt deleted file mode 100644 index 66404b8..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_15.txt +++ /dev/null @@ -1,7 +0,0 @@ - - [TEST] Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore - magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo - consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla - pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est - laborum - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_16.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_16.txt deleted file mode 100644 index a0d1801..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_16.txt +++ /dev/null @@ -1,8 +0,0 @@ - -  - [OK] Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore  - magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo  - consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.  - Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum  -  - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_17.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_17.txt deleted file mode 100644 index 59d00e0..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_17.txt +++ /dev/null @@ -1,7 +0,0 @@ - -Title ending with \ -=================== - -Section ending with \ ---------------------- - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_2.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_2.txt deleted file mode 100644 index ca60976..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_2.txt +++ /dev/null @@ -1,13 +0,0 @@ - - [WARNING] Warning - - ! [CAUTION] Caution - - [ERROR] Error - - [OK] Success - - ! [NOTE] Note - -X [CUSTOM] Custom block - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_3.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_3.txt deleted file mode 100644 index f4b6d58..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_3.txt +++ /dev/null @@ -1,7 +0,0 @@ - -First title -=========== - -Second title -============ - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_4.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_4.txt deleted file mode 100644 index 2646d85..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_4.txt +++ /dev/null @@ -1,32 +0,0 @@ -Lorem ipsum dolor sit amet - -First title -=========== - -Lorem ipsum dolor sit amet - -Second title -============ - -Lorem ipsum dolor sit amet - -Third title -=========== - -Lorem ipsum dolor sit amet - -Fourth title -============ - -Lorem ipsum dolor sit amet - - -Fifth title -=========== - -Lorem ipsum dolor sit amet - - -Fifth title -=========== - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_5.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_5.txt deleted file mode 100644 index be4a2db..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_5.txt +++ /dev/null @@ -1,18 +0,0 @@ -Lorem ipsum dolor sit amet - * Lorem ipsum dolor sit amet - * consectetur adipiscing elit - -Lorem ipsum dolor sit amet - * Lorem ipsum dolor sit amet - * consectetur adipiscing elit - -Lorem ipsum dolor sit amet - Lorem ipsum dolor sit amet - consectetur adipiscing elit - -Lorem ipsum dolor sit amet - - // Lorem ipsum dolor sit amet - // - // consectetur adipiscing elit - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_6.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_6.txt deleted file mode 100644 index 5f2d33c..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_6.txt +++ /dev/null @@ -1,6 +0,0 @@ - - * Lorem ipsum dolor sit amet - * consectetur adipiscing elit - - [OK] Lorem ipsum dolor sit amet - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_7.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_7.txt deleted file mode 100644 index ecea977..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_7.txt +++ /dev/null @@ -1,5 +0,0 @@ - -Title -===== - - Duis aute irure dolor in reprehenderit in voluptate velit esse diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_8.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_8.txt deleted file mode 100644 index 005b846..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_8.txt +++ /dev/null @@ -1,9 +0,0 @@ - ---------------- --------------- --------------------- - Main table title - ---------------- --------------- --------------------- - ISBN Title Author - ---------------- --------------- --------------------- - 978-0521567817 De Monarchia Dante Alighieri - 978-0804169127 Divine Comedy spans multiple rows - ---------------- --------------- --------------------- - diff --git a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_9.txt b/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_9.txt deleted file mode 100644 index 069c0d5..0000000 --- a/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_9.txt +++ /dev/null @@ -1,5 +0,0 @@ - -X [CUSTOM] Custom block -X -X Second custom block line - diff --git a/vendor/symfony/console/Tests/Fixtures/TestCommand.php b/vendor/symfony/console/Tests/Fixtures/TestCommand.php deleted file mode 100644 index dcd3273..0000000 --- a/vendor/symfony/console/Tests/Fixtures/TestCommand.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class TestCommand extends Command -{ - protected function configure() - { - $this - ->setName('namespace:name') - ->setAliases(array('name')) - ->setDescription('description') - ->setHelp('help') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $output->writeln('execute called'); - } - - protected function interact(InputInterface $input, OutputInterface $output) - { - $output->writeln('interact called'); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/TestTiti.php b/vendor/symfony/console/Tests/Fixtures/TestTiti.php deleted file mode 100644 index 72e29d2..0000000 --- a/vendor/symfony/console/Tests/Fixtures/TestTiti.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class TestTiti extends Command -{ - protected function configure() - { - $this - ->setName('test-titi') - ->setDescription('The test:titi command') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $output->write('test-titi'); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/TestToto.php b/vendor/symfony/console/Tests/Fixtures/TestToto.php deleted file mode 100644 index f14805d..0000000 --- a/vendor/symfony/console/Tests/Fixtures/TestToto.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class TestToto extends Command -{ - protected function configure() - { - $this - ->setName('test-toto') - ->setDescription('The test-toto command') - ->setAliases(array('test')) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $output->write('test-toto'); - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/application_1.json b/vendor/symfony/console/Tests/Fixtures/application_1.json deleted file mode 100644 index 29faa82..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_1.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "commands": [ - { - "name": "help", - "hidden": false, - "usage": [ - "help [--format FORMAT] [--raw] [--] [<command_name>]" - ], - "description": "Displays help for a command", - "help": "The <info>help<\/info> command displays help for a given command:\n\n <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.", - "definition": { - "arguments": { - "command_name": { - "name": "command_name", - "is_required": false, - "is_array": false, - "description": "The command name", - "default": "help" - } - }, - "options": { - "format": { - "name": "--format", - "shortcut": "", - "accept_value": true, - "is_value_required": true, - "is_multiple": false, - "description": "The output format (txt, xml, json, or md)", - "default": "txt" - }, - "raw": { - "name": "--raw", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "To output raw command help", - "default": false - }, - "help": { - "name": "--help", - "shortcut": "-h", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this help message", - "default": false - }, - "quiet": { - "name": "--quiet", - "shortcut": "-q", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not output any message", - "default": false - }, - "verbose": { - "name": "--verbose", - "shortcut": "-v|-vv|-vvv", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", - "default": false - }, - "version": { - "name": "--version", - "shortcut": "-V", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this application version", - "default": false - }, - "ansi": { - "name": "--ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Force ANSI output", - "default": false - }, - "no-ansi": { - "name": "--no-ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Disable ANSI output", - "default": false - }, - "no-interaction": { - "name": "--no-interaction", - "shortcut": "-n", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not ask any interactive question", - "default": false - } - } - } - }, - { - "name": "list", - "hidden": false, - "usage": [ - "list [--raw] [--format FORMAT] [--] [<namespace>]" - ], - "description": "Lists commands", - "help": "The <info>list<\/info> command lists all commands:\n\n <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n <info>php app\/console list --raw<\/info>", - "definition": { - "arguments": { - "namespace": { - "name": "namespace", - "is_required": false, - "is_array": false, - "description": "The namespace name", - "default": null - } - }, - "options": { - "raw": { - "name": "--raw", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "To output raw command list", - "default": false - }, - "format": { - "name": "--format", - "shortcut": "", - "accept_value": true, - "is_value_required": true, - "is_multiple": false, - "description": "The output format (txt, xml, json, or md)", - "default": "txt" - } - } - } - } - ], - "namespaces": [ - { - "id": "_global", - "commands": [ - "help", - "list" - ] - } - ] -} diff --git a/vendor/symfony/console/Tests/Fixtures/application_1.md b/vendor/symfony/console/Tests/Fixtures/application_1.md deleted file mode 100644 index b46c975..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_1.md +++ /dev/null @@ -1,172 +0,0 @@ -Console Tool -============ - -* [`help`](#help) -* [`list`](#list) - -`help` ------- - -Displays help for a command - -### Usage - -* `help [--format FORMAT] [--raw] [--] [<command_name>]` - -The help command displays help for a given command: - - php app/console help list - -You can also output the help in other formats by using the --format option: - - php app/console help --format=xml list - -To display the list of available commands, please use the list command. - -### Arguments - -#### `command_name` - -The command name - -* Is required: no -* Is array: no -* Default: `'help'` - -### Options - -#### `--format` - -The output format (txt, xml, json, or md) - -* Accept value: yes -* Is value required: yes -* Is multiple: no -* Default: `'txt'` - -#### `--raw` - -To output raw command help - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--help|-h` - -Display this help message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--quiet|-q` - -Do not output any message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--verbose|-v|-vv|-vvv` - -Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--version|-V` - -Display this application version - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--ansi` - -Force ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-ansi` - -Disable ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-interaction|-n` - -Do not ask any interactive question - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -`list` ------- - -Lists commands - -### Usage - -* `list [--raw] [--format FORMAT] [--] [<namespace>]` - -The list command lists all commands: - - php app/console list - -You can also display the commands for a specific namespace: - - php app/console list test - -You can also output the information in other formats by using the --format option: - - php app/console list --format=xml - -It's also possible to get raw list of commands (useful for embedding command runner): - - php app/console list --raw - -### Arguments - -#### `namespace` - -The namespace name - -* Is required: no -* Is array: no -* Default: `NULL` - -### Options - -#### `--raw` - -To output raw command list - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--format` - -The output format (txt, xml, json, or md) - -* Accept value: yes -* Is value required: yes -* Is multiple: no -* Default: `'txt'` diff --git a/vendor/symfony/console/Tests/Fixtures/application_1.txt b/vendor/symfony/console/Tests/Fixtures/application_1.txt deleted file mode 100644 index 8a7b47e..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_1.txt +++ /dev/null @@ -1,17 +0,0 @@ -Console Tool - -<comment>Usage:</comment> - command [options] [arguments] - -<comment>Options:</comment> - <info>-h, --help</info> Display this help message - <info>-q, --quiet</info> Do not output any message - <info>-V, --version</info> Display this application version - <info> --ansi</info> Force ANSI output - <info> --no-ansi</info> Disable ANSI output - <info>-n, --no-interaction</info> Do not ask any interactive question - <info>-v|vv|vvv, --verbose</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -<comment>Available commands:</comment> - <info>help</info> Displays help for a command - <info>list</info> Lists commands diff --git a/vendor/symfony/console/Tests/Fixtures/application_1.xml b/vendor/symfony/console/Tests/Fixtures/application_1.xml deleted file mode 100644 index a0bd076..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_1.xml +++ /dev/null @@ -1,104 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<symfony> - <commands> - <command id="help" name="help" hidden="0"> - <usages> - <usage>help [--format FORMAT] [--raw] [--] [<command_name>]</usage> - </usages> - <description>Displays help for a command</description> - <help>The <info>help</info> command displays help for a given command: - - <info>php app/console help list</info> - - You can also output the help in other formats by using the <comment>--format</comment> option: - - <info>php app/console help --format=xml list</info> - - To display the list of available commands, please use the <info>list</info> command.</help> - <arguments> - <argument name="command_name" is_required="0" is_array="0"> - <description>The command name</description> - <defaults> - <default>help</default> - </defaults> - </argument> - </arguments> - <options> - <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0"> - <description>The output format (txt, xml, json, or md)</description> - <defaults> - <default>txt</default> - </defaults> - </option> - <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output raw command help</description> - </option> - <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this help message</description> - </option> - <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not output any message</description> - </option> - <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> - </option> - <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this application version</description> - </option> - <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Force ANSI output</description> - </option> - <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Disable ANSI output</description> - </option> - <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not ask any interactive question</description> - </option> - </options> - </command> - <command id="list" name="list" hidden="0"> - <usages> - <usage>list [--raw] [--format FORMAT] [--] [<namespace>]</usage> - </usages> - <description>Lists commands</description> - <help>The <info>list</info> command lists all commands: - - <info>php app/console list</info> - - You can also display the commands for a specific namespace: - - <info>php app/console list test</info> - - You can also output the information in other formats by using the <comment>--format</comment> option: - - <info>php app/console list --format=xml</info> - - It's also possible to get raw list of commands (useful for embedding command runner): - - <info>php app/console list --raw</info></help> - <arguments> - <argument name="namespace" is_required="0" is_array="0"> - <description>The namespace name</description> - <defaults/> - </argument> - </arguments> - <options> - <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output raw command list</description> - </option> - <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0"> - <description>The output format (txt, xml, json, or md)</description> - <defaults> - <default>txt</default> - </defaults> - </option> - </options> - </command> - </commands> - <namespaces> - <namespace id="_global"> - <command>help</command> - <command>list</command> - </namespace> - </namespaces> -</symfony> diff --git a/vendor/symfony/console/Tests/Fixtures/application_2.json b/vendor/symfony/console/Tests/Fixtures/application_2.json deleted file mode 100644 index 4777a60..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_2.json +++ /dev/null @@ -1,509 +0,0 @@ -{ - "application": { - "name": "My Symfony application", - "version": "v1.0" - }, - "commands": [ - { - "name": "help", - "hidden": false, - "usage": [ - "help [--format FORMAT] [--raw] [--] [<command_name>]" - ], - "description": "Displays help for a command", - "help": "The <info>help<\/info> command displays help for a given command:\n\n <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.", - "definition": { - "arguments": { - "command_name": { - "name": "command_name", - "is_required": false, - "is_array": false, - "description": "The command name", - "default": "help" - } - }, - "options": { - "format": { - "name": "--format", - "shortcut": "", - "accept_value": true, - "is_value_required": true, - "is_multiple": false, - "description": "The output format (txt, xml, json, or md)", - "default": "txt" - }, - "raw": { - "name": "--raw", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "To output raw command help", - "default": false - }, - "help": { - "name": "--help", - "shortcut": "-h", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this help message", - "default": false - }, - "quiet": { - "name": "--quiet", - "shortcut": "-q", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not output any message", - "default": false - }, - "verbose": { - "name": "--verbose", - "shortcut": "-v|-vv|-vvv", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", - "default": false - }, - "version": { - "name": "--version", - "shortcut": "-V", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this application version", - "default": false - }, - "ansi": { - "name": "--ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Force ANSI output", - "default": false - }, - "no-ansi": { - "name": "--no-ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Disable ANSI output", - "default": false - }, - "no-interaction": { - "name": "--no-interaction", - "shortcut": "-n", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not ask any interactive question", - "default": false - } - } - } - }, - { - "name": "list", - "hidden": false, - "usage": [ - "list [--raw] [--format FORMAT] [--] [<namespace>]" - ], - "description": "Lists commands", - "help": "The <info>list<\/info> command lists all commands:\n\n <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n <info>php app\/console list --raw<\/info>", - "definition": { - "arguments": { - "namespace": { - "name": "namespace", - "is_required": false, - "is_array": false, - "description": "The namespace name", - "default": null - } - }, - "options": { - "raw": { - "name": "--raw", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "To output raw command list", - "default": false - }, - "format": { - "name": "--format", - "shortcut": "", - "accept_value": true, - "is_value_required": true, - "is_multiple": false, - "description": "The output format (txt, xml, json, or md)", - "default": "txt" - } - } - } - }, - { - "name": "descriptor:command1", - "hidden": false, - "usage": [ - "descriptor:command1", - "alias1", - "alias2" - ], - "description": "command 1 description", - "help": "command 1 help", - "definition": { - "arguments": [], - "options": { - "help": { - "name": "--help", - "shortcut": "-h", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this help message", - "default": false - }, - "quiet": { - "name": "--quiet", - "shortcut": "-q", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not output any message", - "default": false - }, - "verbose": { - "name": "--verbose", - "shortcut": "-v|-vv|-vvv", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", - "default": false - }, - "version": { - "name": "--version", - "shortcut": "-V", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this application version", - "default": false - }, - "ansi": { - "name": "--ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Force ANSI output", - "default": false - }, - "no-ansi": { - "name": "--no-ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Disable ANSI output", - "default": false - }, - "no-interaction": { - "name": "--no-interaction", - "shortcut": "-n", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not ask any interactive question", - "default": false - } - } - } - }, - { - "name": "descriptor:command2", - "hidden": false, - "usage": [ - "descriptor:command2 [-o|--option_name] [--] <argument_name>", - "descriptor:command2 -o|--option_name <argument_name>", - "descriptor:command2 <argument_name>" - ], - "description": "command 2 description", - "help": "command 2 help", - "definition": { - "arguments": { - "argument_name": { - "name": "argument_name", - "is_required": true, - "is_array": false, - "description": "", - "default": null - } - }, - "options": { - "option_name": { - "name": "--option_name", - "shortcut": "-o", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "", - "default": false - }, - "help": { - "name": "--help", - "shortcut": "-h", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this help message", - "default": false - }, - "quiet": { - "name": "--quiet", - "shortcut": "-q", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not output any message", - "default": false - }, - "verbose": { - "name": "--verbose", - "shortcut": "-v|-vv|-vvv", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", - "default": false - }, - "version": { - "name": "--version", - "shortcut": "-V", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this application version", - "default": false - }, - "ansi": { - "name": "--ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Force ANSI output", - "default": false - }, - "no-ansi": { - "name": "--no-ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Disable ANSI output", - "default": false - }, - "no-interaction": { - "name": "--no-interaction", - "shortcut": "-n", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not ask any interactive question", - "default": false - } - } - } - }, - { - "name": "descriptor:command3", - "hidden": true, - "usage": [ - "descriptor:command3" - ], - "description": "command 3 description", - "help": "command 3 help", - "definition": { - "arguments": {}, - "options": { - "help": { - "name": "--help", - "shortcut": "-h", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this help message", - "default": false - }, - "quiet": { - "name": "--quiet", - "shortcut": "-q", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not output any message", - "default": false - }, - "verbose": { - "name": "--verbose", - "shortcut": "-v|-vv|-vvv", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", - "default": false - }, - "version": { - "name": "--version", - "shortcut": "-V", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this application version", - "default": false - }, - "ansi": { - "name": "--ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Force ANSI output", - "default": false - }, - "no-ansi": { - "name": "--no-ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Disable ANSI output", - "default": false - }, - "no-interaction": { - "name": "--no-interaction", - "shortcut": "-n", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not ask any interactive question", - "default": false - } - } - } - }, - { - "name": "descriptor:command4", - "hidden": false, - "usage": [ - "descriptor:command4", - "descriptor:alias_command4", - "command4:descriptor" - ], - "description": null, - "help": "", - "definition": { - "arguments": {}, - "options": { - "help": { - "name": "--help", - "shortcut": "-h", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this help message", - "default": false - }, - "quiet": { - "name": "--quiet", - "shortcut": "-q", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not output any message", - "default": false - }, - "verbose": { - "name": "--verbose", - "shortcut": "-v|-vv|-vvv", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", - "default": false - }, - "version": { - "name": "--version", - "shortcut": "-V", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Display this application version", - "default": false - }, - "ansi": { - "name": "--ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Force ANSI output", - "default": false - }, - "no-ansi": { - "name": "--no-ansi", - "shortcut": "", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Disable ANSI output", - "default": false - }, - "no-interaction": { - "name": "--no-interaction", - "shortcut": "-n", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "Do not ask any interactive question", - "default": false - } - } - } - } - ], - "namespaces": [ - { - "id": "_global", - "commands": [ - "alias1", - "alias2", - "help", - "list" - ] - }, - { - "id": "command4", - "commands": [ - "command4:descriptor" - ] - }, - { - "id": "descriptor", - "commands": [ - "descriptor:alias_command4", - "descriptor:command1", - "descriptor:command2", - "descriptor:command3", - "descriptor:command4" - ] - } - ] -} diff --git a/vendor/symfony/console/Tests/Fixtures/application_2.md b/vendor/symfony/console/Tests/Fixtures/application_2.md deleted file mode 100644 index 5b4896c..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_2.md +++ /dev/null @@ -1,431 +0,0 @@ -My Symfony application v1.0 -=========================== - -* [`alias1`](#descriptorcommand1) -* [`alias2`](#descriptorcommand1) -* [`help`](#help) -* [`list`](#list) - -**command4:** - -* [`command4:descriptor`](#descriptorcommand4) - -**descriptor:** - -* [`descriptor:alias_command4`](#descriptorcommand4) -* [`descriptor:command1`](#descriptorcommand1) -* [`descriptor:command2`](#descriptorcommand2) -* [`descriptor:command4`](#descriptorcommand4) - -`help` ------- - -Displays help for a command - -### Usage - -* `help [--format FORMAT] [--raw] [--] [<command_name>]` - -The help command displays help for a given command: - - php app/console help list - -You can also output the help in other formats by using the --format option: - - php app/console help --format=xml list - -To display the list of available commands, please use the list command. - -### Arguments - -#### `command_name` - -The command name - -* Is required: no -* Is array: no -* Default: `'help'` - -### Options - -#### `--format` - -The output format (txt, xml, json, or md) - -* Accept value: yes -* Is value required: yes -* Is multiple: no -* Default: `'txt'` - -#### `--raw` - -To output raw command help - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--help|-h` - -Display this help message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--quiet|-q` - -Do not output any message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--verbose|-v|-vv|-vvv` - -Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--version|-V` - -Display this application version - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--ansi` - -Force ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-ansi` - -Disable ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-interaction|-n` - -Do not ask any interactive question - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -`list` ------- - -Lists commands - -### Usage - -* `list [--raw] [--format FORMAT] [--] [<namespace>]` - -The list command lists all commands: - - php app/console list - -You can also display the commands for a specific namespace: - - php app/console list test - -You can also output the information in other formats by using the --format option: - - php app/console list --format=xml - -It's also possible to get raw list of commands (useful for embedding command runner): - - php app/console list --raw - -### Arguments - -#### `namespace` - -The namespace name - -* Is required: no -* Is array: no -* Default: `NULL` - -### Options - -#### `--raw` - -To output raw command list - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--format` - -The output format (txt, xml, json, or md) - -* Accept value: yes -* Is value required: yes -* Is multiple: no -* Default: `'txt'` - -`descriptor:command1` ---------------------- - -command 1 description - -### Usage - -* `descriptor:command1` -* `alias1` -* `alias2` - -command 1 help - -### Options - -#### `--help|-h` - -Display this help message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--quiet|-q` - -Do not output any message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--verbose|-v|-vv|-vvv` - -Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--version|-V` - -Display this application version - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--ansi` - -Force ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-ansi` - -Disable ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-interaction|-n` - -Do not ask any interactive question - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -`descriptor:command2` ---------------------- - -command 2 description - -### Usage - -* `descriptor:command2 [-o|--option_name] [--] <argument_name>` -* `descriptor:command2 -o|--option_name <argument_name>` -* `descriptor:command2 <argument_name>` - -command 2 help - -### Arguments - -#### `argument_name` - -* Is required: yes -* Is array: no -* Default: `NULL` - -### Options - -#### `--option_name|-o` - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--help|-h` - -Display this help message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--quiet|-q` - -Do not output any message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--verbose|-v|-vv|-vvv` - -Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--version|-V` - -Display this application version - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--ansi` - -Force ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-ansi` - -Disable ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-interaction|-n` - -Do not ask any interactive question - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -`descriptor:command4` ---------------------- - -### Usage - -* `descriptor:command4` -* `descriptor:alias_command4` -* `command4:descriptor` - - -### Options - -#### `--help|-h` - -Display this help message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--quiet|-q` - -Do not output any message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--verbose|-v|-vv|-vvv` - -Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--version|-V` - -Display this application version - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--ansi` - -Force ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-ansi` - -Disable ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-interaction|-n` - -Do not ask any interactive question - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/application_2.txt b/vendor/symfony/console/Tests/Fixtures/application_2.txt deleted file mode 100644 index d624f19..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_2.txt +++ /dev/null @@ -1,21 +0,0 @@ -My Symfony application <info>v1.0</info> - -<comment>Usage:</comment> - command [options] [arguments] - -<comment>Options:</comment> - <info>-h, --help</info> Display this help message - <info>-q, --quiet</info> Do not output any message - <info>-V, --version</info> Display this application version - <info> --ansi</info> Force ANSI output - <info> --no-ansi</info> Disable ANSI output - <info>-n, --no-interaction</info> Do not ask any interactive question - <info>-v|vv|vvv, --verbose</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -<comment>Available commands:</comment> - <info>help</info> Displays help for a command - <info>list</info> Lists commands - <comment>descriptor</comment> - <info>descriptor:command1</info> [alias1|alias2] command 1 description - <info>descriptor:command2</info> command 2 description - <info>descriptor:command4</info> [descriptor:alias_command4|command4:descriptor] diff --git a/vendor/symfony/console/Tests/Fixtures/application_2.xml b/vendor/symfony/console/Tests/Fixtures/application_2.xml deleted file mode 100644 index 5f0f98b..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_2.xml +++ /dev/null @@ -1,254 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<symfony name="My Symfony application" version="v1.0"> - <commands> - <command id="help" name="help" hidden="0"> - <usages> - <usage>help [--format FORMAT] [--raw] [--] [<command_name>]</usage> - </usages> - <description>Displays help for a command</description> - <help>The <info>help</info> command displays help for a given command: - - <info>php app/console help list</info> - - You can also output the help in other formats by using the <comment>--format</comment> option: - - <info>php app/console help --format=xml list</info> - - To display the list of available commands, please use the <info>list</info> command.</help> - <arguments> - <argument name="command_name" is_required="0" is_array="0"> - <description>The command name</description> - <defaults> - <default>help</default> - </defaults> - </argument> - </arguments> - <options> - <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0"> - <description>The output format (txt, xml, json, or md)</description> - <defaults> - <default>txt</default> - </defaults> - </option> - <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output raw command help</description> - </option> - <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this help message</description> - </option> - <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not output any message</description> - </option> - <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> - </option> - <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this application version</description> - </option> - <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Force ANSI output</description> - </option> - <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Disable ANSI output</description> - </option> - <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not ask any interactive question</description> - </option> - </options> - </command> - <command id="list" name="list" hidden="0"> - <usages> - <usage>list [--raw] [--format FORMAT] [--] [<namespace>]</usage> - </usages> - <description>Lists commands</description> - <help>The <info>list</info> command lists all commands: - - <info>php app/console list</info> - - You can also display the commands for a specific namespace: - - <info>php app/console list test</info> - - You can also output the information in other formats by using the <comment>--format</comment> option: - - <info>php app/console list --format=xml</info> - - It's also possible to get raw list of commands (useful for embedding command runner): - - <info>php app/console list --raw</info></help> - <arguments> - <argument name="namespace" is_required="0" is_array="0"> - <description>The namespace name</description> - <defaults/> - </argument> - </arguments> - <options> - <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>To output raw command list</description> - </option> - <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0"> - <description>The output format (txt, xml, json, or md)</description> - <defaults> - <default>txt</default> - </defaults> - </option> - </options> - </command> - <command id="descriptor:command1" name="descriptor:command1" hidden="0"> - <usages> - <usage>descriptor:command1</usage> - <usage>alias1</usage> - <usage>alias2</usage> - </usages> - <description>command 1 description</description> - <help>command 1 help</help> - <arguments/> - <options> - <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this help message</description> - </option> - <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not output any message</description> - </option> - <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> - </option> - <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this application version</description> - </option> - <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Force ANSI output</description> - </option> - <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Disable ANSI output</description> - </option> - <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not ask any interactive question</description> - </option> - </options> - </command> - <command id="descriptor:command2" name="descriptor:command2" hidden="0"> - <usages> - <usage>descriptor:command2 [-o|--option_name] [--] <argument_name></usage> - <usage>descriptor:command2 -o|--option_name <argument_name></usage> - <usage>descriptor:command2 <argument_name></usage> - </usages> - <description>command 2 description</description> - <help>command 2 help</help> - <arguments> - <argument name="argument_name" is_required="1" is_array="0"> - <description></description> - <defaults/> - </argument> - </arguments> - <options> - <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0"> - <description></description> - </option> - <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this help message</description> - </option> - <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not output any message</description> - </option> - <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> - </option> - <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this application version</description> - </option> - <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Force ANSI output</description> - </option> - <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Disable ANSI output</description> - </option> - <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not ask any interactive question</description> - </option> - </options> - </command> - <command id="descriptor:command3" name="descriptor:command3" hidden="1"> - <usages> - <usage>descriptor:command3</usage> - </usages> - <description>command 3 description</description> - <help>command 3 help</help> - <arguments/> - <options> - <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this help message</description> - </option> - <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not output any message</description> - </option> - <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> - </option> - <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this application version</description> - </option> - <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Force ANSI output</description> - </option> - <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Disable ANSI output</description> - </option> - <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not ask any interactive question</description> - </option> - </options> - </command> - <command id="descriptor:command4" name="descriptor:command4" hidden="0"> - <usages> - <usage>descriptor:command4</usage> - <usage>descriptor:alias_command4</usage> - <usage>command4:descriptor</usage> - </usages> - <description></description> - <help></help> - <arguments/> - <options> - <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this help message</description> - </option> - <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not output any message</description> - </option> - <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description> - </option> - <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Display this application version</description> - </option> - <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Force ANSI output</description> - </option> - <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Disable ANSI output</description> - </option> - <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0"> - <description>Do not ask any interactive question</description> - </option> - </options> - </command> - </commands> - <namespaces> - <namespace id="_global"> - <command>alias1</command> - <command>alias2</command> - <command>help</command> - <command>list</command> - </namespace> - <namespace id="command4"> - <command>command4:descriptor</command> - </namespace> - <namespace id="descriptor"> - <command>descriptor:alias_command4</command> - <command>descriptor:command1</command> - <command>descriptor:command2</command> - <command>descriptor:command3</command> - <command>descriptor:command4</command> - </namespace> - </namespaces> -</symfony> diff --git a/vendor/symfony/console/Tests/Fixtures/application_filtered_namespace.txt b/vendor/symfony/console/Tests/Fixtures/application_filtered_namespace.txt deleted file mode 100644 index 3bca270..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_filtered_namespace.txt +++ /dev/null @@ -1,16 +0,0 @@ -My Symfony application <info>v1.0</info> - -<comment>Usage:</comment> - command [options] [arguments] - -<comment>Options:</comment> - <info>-h, --help</info> Display this help message - <info>-q, --quiet</info> Do not output any message - <info>-V, --version</info> Display this application version - <info> --ansi</info> Force ANSI output - <info> --no-ansi</info> Disable ANSI output - <info>-n, --no-interaction</info> Do not ask any interactive question - <info>-v|vv|vvv, --verbose</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -<comment>Available commands for the "command4" namespace:</comment> - <info>command4:descriptor</info> diff --git a/vendor/symfony/console/Tests/Fixtures/application_gethelp.txt b/vendor/symfony/console/Tests/Fixtures/application_gethelp.txt deleted file mode 100644 index 5a5920d..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_gethelp.txt +++ /dev/null @@ -1 +0,0 @@ -Console Tool \ No newline at end of file diff --git a/vendor/symfony/console/Tests/Fixtures/application_mbstring.md b/vendor/symfony/console/Tests/Fixtures/application_mbstring.md deleted file mode 100644 index f34e558..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_mbstring.md +++ /dev/null @@ -1,269 +0,0 @@ -MbString åpplicätion -==================== - -* [`help`](#help) -* [`list`](#list) - -**descriptor:** - -* [`descriptor:åèä`](#descriptoråèä) - -`help` ------- - -Displays help for a command - -### Usage - -* `help [--format FORMAT] [--raw] [--] [<command_name>]` - -The help command displays help for a given command: - - php app/console help list - -You can also output the help in other formats by using the --format option: - - php app/console help --format=xml list - -To display the list of available commands, please use the list command. - -### Arguments - -#### `command_name` - -The command name - -* Is required: no -* Is array: no -* Default: `'help'` - -### Options - -#### `--format` - -The output format (txt, xml, json, or md) - -* Accept value: yes -* Is value required: yes -* Is multiple: no -* Default: `'txt'` - -#### `--raw` - -To output raw command help - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--help|-h` - -Display this help message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--quiet|-q` - -Do not output any message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--verbose|-v|-vv|-vvv` - -Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--version|-V` - -Display this application version - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--ansi` - -Force ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-ansi` - -Disable ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-interaction|-n` - -Do not ask any interactive question - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -`list` ------- - -Lists commands - -### Usage - -* `list [--raw] [--format FORMAT] [--] [<namespace>]` - -The list command lists all commands: - - php app/console list - -You can also display the commands for a specific namespace: - - php app/console list test - -You can also output the information in other formats by using the --format option: - - php app/console list --format=xml - -It's also possible to get raw list of commands (useful for embedding command runner): - - php app/console list --raw - -### Arguments - -#### `namespace` - -The namespace name - -* Is required: no -* Is array: no -* Default: `NULL` - -### Options - -#### `--raw` - -To output raw command list - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--format` - -The output format (txt, xml, json, or md) - -* Accept value: yes -* Is value required: yes -* Is multiple: no -* Default: `'txt'` - -`descriptor:åèä` ----------------- - -command åèä description - -### Usage - -* `descriptor:åèä [-o|--option_åèä] [--] <argument_åèä>` -* `descriptor:åèä -o|--option_name <argument_name>` -* `descriptor:åèä <argument_name>` - -command åèä help - -### Arguments - -#### `argument_åèä` - -* Is required: yes -* Is array: no -* Default: `NULL` - -### Options - -#### `--option_åèä|-o` - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--help|-h` - -Display this help message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--quiet|-q` - -Do not output any message - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--verbose|-v|-vv|-vvv` - -Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--version|-V` - -Display this application version - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--ansi` - -Force ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-ansi` - -Disable ANSI output - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` - -#### `--no-interaction|-n` - -Do not ask any interactive question - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/application_mbstring.txt b/vendor/symfony/console/Tests/Fixtures/application_mbstring.txt deleted file mode 100644 index b409d18..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_mbstring.txt +++ /dev/null @@ -1,19 +0,0 @@ -MbString åpplicätion - -<comment>Usage:</comment> - command [options] [arguments] - -<comment>Options:</comment> - <info>-h, --help</info> Display this help message - <info>-q, --quiet</info> Do not output any message - <info>-V, --version</info> Display this application version - <info> --ansi</info> Force ANSI output - <info> --no-ansi</info> Disable ANSI output - <info>-n, --no-interaction</info> Do not ask any interactive question - <info>-v|vv|vvv, --verbose</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -<comment>Available commands:</comment> - <info>help</info> Displays help for a command - <info>list</info> Lists commands - <comment>descriptor</comment> - <info>descriptor:åèä</info> command åèä description diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception1.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception1.txt deleted file mode 100644 index 1df5bd6..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception1.txt +++ /dev/null @@ -1,5 +0,0 @@ - - - Command "foo" is not defined. - - diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception2.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception2.txt deleted file mode 100644 index 932063d..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception2.txt +++ /dev/null @@ -1,7 +0,0 @@ - - - The "--foo" option does not exist. - - -list [--raw] [--format FORMAT] [--] [<namespace>] - diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception3.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception3.txt deleted file mode 100644 index 5366b84..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception3.txt +++ /dev/null @@ -1,18 +0,0 @@ - -In Foo3Command.php line 26: - - Third exception <fg=blue;bg=red>comment</> - - -In Foo3Command.php line 23: - - Second exception <comment>comment</comment> - - -In Foo3Command.php line 21: - - First exception <p>this is html</p> - - -foo3:bar - diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception3decorated.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception3decorated.txt deleted file mode 100644 index 5993709..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception3decorated.txt +++ /dev/null @@ -1,18 +0,0 @@ - -In Foo3Command.php line 26: -  - Third exception <fg=blue;bg=red>comment</>  -  - -In Foo3Command.php line 23: -  - Second exception <comment>comment</comment>  -  - -In Foo3Command.php line 21: -  - First exception <p>this is html</p>  -  - -foo3:bar - diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception4.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception4.txt deleted file mode 100644 index 548a13e..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception4.txt +++ /dev/null @@ -1,6 +0,0 @@ - - - Command "foo" is not define - d. - - diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1.txt deleted file mode 100644 index 4677c18..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1.txt +++ /dev/null @@ -1,8 +0,0 @@ - -In ApplicationTest.php line %d: - - エラーメッセージ - - -foo - diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt deleted file mode 100644 index 33d3265..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt +++ /dev/null @@ -1,8 +0,0 @@ - -In ApplicationTest.php line %d: -  - エラーメッセージ  -  - -foo - diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth2.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth2.txt deleted file mode 100644 index 2ee72e2..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception_doublewidth2.txt +++ /dev/null @@ -1,9 +0,0 @@ - -In ApplicationTest.php line %d: - - コマンドの実行中にエラーが - 発生しました。 - - -foo - diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception_escapeslines.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception_escapeslines.txt deleted file mode 100644 index ff7b7b3..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception_escapeslines.txt +++ /dev/null @@ -1,9 +0,0 @@ - -In ApplicationTest.php line %d: - - dont break here < - info>!</info> - - -foo - diff --git a/vendor/symfony/console/Tests/Fixtures/application_renderexception_linebreaks.txt b/vendor/symfony/console/Tests/Fixtures/application_renderexception_linebreaks.txt deleted file mode 100644 index 0e5c4b1..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_renderexception_linebreaks.txt +++ /dev/null @@ -1,11 +0,0 @@ - -In ApplicationTest.php line %d: - - line 1 with extra spaces - line 2 - - line 4 - - -foo - diff --git a/vendor/symfony/console/Tests/Fixtures/application_run1.txt b/vendor/symfony/console/Tests/Fixtures/application_run1.txt deleted file mode 100644 index 0dc2730..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_run1.txt +++ /dev/null @@ -1,17 +0,0 @@ -Console Tool - -Usage: - command [options] [arguments] - -Options: - -h, --help Display this help message - -q, --quiet Do not output any message - -V, --version Display this application version - --ansi Force ANSI output - --no-ansi Disable ANSI output - -n, --no-interaction Do not ask any interactive question - -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - -Available commands: - help Displays help for a command - list Lists commands diff --git a/vendor/symfony/console/Tests/Fixtures/application_run2.txt b/vendor/symfony/console/Tests/Fixtures/application_run2.txt deleted file mode 100644 index 65a685d..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_run2.txt +++ /dev/null @@ -1,26 +0,0 @@ -Usage: - list [options] [--] [<namespace>] - -Arguments: - namespace The namespace name - -Options: - --raw To output raw command list - --format=FORMAT The output format (txt, xml, json, or md) [default: "txt"] - -Help: - The list command lists all commands: - - php app/console list - - You can also display the commands for a specific namespace: - - php app/console list test - - You can also output the information in other formats by using the --format option: - - php app/console list --format=xml - - It's also possible to get raw list of commands (useful for embedding command runner): - - php app/console list --raw diff --git a/vendor/symfony/console/Tests/Fixtures/application_run3.txt b/vendor/symfony/console/Tests/Fixtures/application_run3.txt deleted file mode 100644 index 65a685d..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_run3.txt +++ /dev/null @@ -1,26 +0,0 @@ -Usage: - list [options] [--] [<namespace>] - -Arguments: - namespace The namespace name - -Options: - --raw To output raw command list - --format=FORMAT The output format (txt, xml, json, or md) [default: "txt"] - -Help: - The list command lists all commands: - - php app/console list - - You can also display the commands for a specific namespace: - - php app/console list test - - You can also output the information in other formats by using the --format option: - - php app/console list --format=xml - - It's also possible to get raw list of commands (useful for embedding command runner): - - php app/console list --raw diff --git a/vendor/symfony/console/Tests/Fixtures/application_run4.txt b/vendor/symfony/console/Tests/Fixtures/application_run4.txt deleted file mode 100644 index 47187fc..0000000 --- a/vendor/symfony/console/Tests/Fixtures/application_run4.txt +++ /dev/null @@ -1 +0,0 @@ -Console Tool diff --git a/vendor/symfony/console/Tests/Fixtures/command_1.json b/vendor/symfony/console/Tests/Fixtures/command_1.json deleted file mode 100644 index 0908790..0000000 --- a/vendor/symfony/console/Tests/Fixtures/command_1.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "descriptor:command1", - "hidden": false, - "usage": [ - "descriptor:command1", - "alias1", - "alias2" - ], - "description": "command 1 description", - "help": "command 1 help", - "definition": { - "arguments": [], - "options": [] - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/command_1.md b/vendor/symfony/console/Tests/Fixtures/command_1.md deleted file mode 100644 index e9a0180..0000000 --- a/vendor/symfony/console/Tests/Fixtures/command_1.md +++ /dev/null @@ -1,12 +0,0 @@ -`descriptor:command1` ---------------------- - -command 1 description - -### Usage - -* `descriptor:command1` -* `alias1` -* `alias2` - -command 1 help diff --git a/vendor/symfony/console/Tests/Fixtures/command_1.txt b/vendor/symfony/console/Tests/Fixtures/command_1.txt deleted file mode 100644 index e5e93ee..0000000 --- a/vendor/symfony/console/Tests/Fixtures/command_1.txt +++ /dev/null @@ -1,7 +0,0 @@ -<comment>Usage:</comment> - descriptor:command1 - alias1 - alias2 - -<comment>Help:</comment> - command 1 help diff --git a/vendor/symfony/console/Tests/Fixtures/command_1.xml b/vendor/symfony/console/Tests/Fixtures/command_1.xml deleted file mode 100644 index fa0cca0..0000000 --- a/vendor/symfony/console/Tests/Fixtures/command_1.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<command id="descriptor:command1" name="descriptor:command1" hidden="0"> - <usages> - <usage>descriptor:command1</usage> - <usage>alias1</usage> - <usage>alias2</usage> - </usages> - <description>command 1 description</description> - <help>command 1 help</help> - <arguments/> - <options/> -</command> diff --git a/vendor/symfony/console/Tests/Fixtures/command_2.json b/vendor/symfony/console/Tests/Fixtures/command_2.json deleted file mode 100644 index 8a1ec02..0000000 --- a/vendor/symfony/console/Tests/Fixtures/command_2.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "descriptor:command2", - "hidden": false, - "usage": [ - "descriptor:command2 [-o|--option_name] [--] <argument_name>", - "descriptor:command2 -o|--option_name <argument_name>", - "descriptor:command2 <argument_name>" - ], - "description": "command 2 description", - "help": "command 2 help", - "definition": { - "arguments": { - "argument_name": { - "name": "argument_name", - "is_required": true, - "is_array": false, - "description": "", - "default": null - } - }, - "options": { - "option_name": { - "name": "--option_name", - "shortcut": "-o", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "", - "default": false - } - } - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/command_2.md b/vendor/symfony/console/Tests/Fixtures/command_2.md deleted file mode 100644 index 41f51f0..0000000 --- a/vendor/symfony/console/Tests/Fixtures/command_2.md +++ /dev/null @@ -1,29 +0,0 @@ -`descriptor:command2` ---------------------- - -command 2 description - -### Usage - -* `descriptor:command2 [-o|--option_name] [--] <argument_name>` -* `descriptor:command2 -o|--option_name <argument_name>` -* `descriptor:command2 <argument_name>` - -command 2 help - -### Arguments - -#### `argument_name` - -* Is required: yes -* Is array: no -* Default: `NULL` - -### Options - -#### `--option_name|-o` - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/command_2.txt b/vendor/symfony/console/Tests/Fixtures/command_2.txt deleted file mode 100644 index 2864c7b..0000000 --- a/vendor/symfony/console/Tests/Fixtures/command_2.txt +++ /dev/null @@ -1,13 +0,0 @@ -<comment>Usage:</comment> - descriptor:command2 [options] [--] \<argument_name> - descriptor:command2 -o|--option_name \<argument_name> - descriptor:command2 \<argument_name> - -<comment>Arguments:</comment> - <info>argument_name</info> - -<comment>Options:</comment> - <info>-o, --option_name</info> - -<comment>Help:</comment> - command 2 help diff --git a/vendor/symfony/console/Tests/Fixtures/command_2.xml b/vendor/symfony/console/Tests/Fixtures/command_2.xml deleted file mode 100644 index ae69e2f..0000000 --- a/vendor/symfony/console/Tests/Fixtures/command_2.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<command id="descriptor:command2" name="descriptor:command2" hidden="0"> - <usages> - <usage>descriptor:command2 [-o|--option_name] [--] <argument_name></usage> - <usage>descriptor:command2 -o|--option_name <argument_name></usage> - <usage>descriptor:command2 <argument_name></usage> - </usages> - <description>command 2 description</description> - <help>command 2 help</help> - <arguments> - <argument name="argument_name" is_required="1" is_array="0"> - <description></description> - <defaults/> - </argument> - </arguments> - <options> - <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0"> - <description></description> - </option> - </options> -</command> diff --git a/vendor/symfony/console/Tests/Fixtures/command_mbstring.md b/vendor/symfony/console/Tests/Fixtures/command_mbstring.md deleted file mode 100644 index 7ef40d7..0000000 --- a/vendor/symfony/console/Tests/Fixtures/command_mbstring.md +++ /dev/null @@ -1,29 +0,0 @@ -`descriptor:åèä` ----------------- - -command åèä description - -### Usage - -* `descriptor:åèä [-o|--option_åèä] [--] <argument_åèä>` -* `descriptor:åèä -o|--option_name <argument_name>` -* `descriptor:åèä <argument_name>` - -command åèä help - -### Arguments - -#### `argument_åèä` - -* Is required: yes -* Is array: no -* Default: `NULL` - -### Options - -#### `--option_åèä|-o` - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/command_mbstring.txt b/vendor/symfony/console/Tests/Fixtures/command_mbstring.txt deleted file mode 100644 index cde457d..0000000 --- a/vendor/symfony/console/Tests/Fixtures/command_mbstring.txt +++ /dev/null @@ -1,13 +0,0 @@ -<comment>Usage:</comment> - descriptor:åèä [options] [--] \<argument_åèä> - descriptor:åèä -o|--option_name \<argument_name> - descriptor:åèä \<argument_name> - -<comment>Arguments:</comment> - <info>argument_åèä</info> - -<comment>Options:</comment> - <info>-o, --option_åèä</info> - -<comment>Help:</comment> - command åèä help diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_1.json b/vendor/symfony/console/Tests/Fixtures/input_argument_1.json deleted file mode 100644 index 0ab9329..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_1.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "argument_name", - "is_required": true, - "is_array": false, - "description": "", - "default": null -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_1.md b/vendor/symfony/console/Tests/Fixtures/input_argument_1.md deleted file mode 100644 index 7516cbd..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_1.md +++ /dev/null @@ -1,5 +0,0 @@ -#### `argument_name` - -* Is required: yes -* Is array: no -* Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_1.txt b/vendor/symfony/console/Tests/Fixtures/input_argument_1.txt deleted file mode 100644 index 5503518..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_1.txt +++ /dev/null @@ -1 +0,0 @@ - <info>argument_name</info> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_1.xml b/vendor/symfony/console/Tests/Fixtures/input_argument_1.xml deleted file mode 100644 index cb37f81..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_1.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<argument name="argument_name" is_required="1" is_array="0"> - <description></description> - <defaults/> -</argument> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_2.json b/vendor/symfony/console/Tests/Fixtures/input_argument_2.json deleted file mode 100644 index 7450016..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "argument_name", - "is_required": false, - "is_array": true, - "description": "argument description", - "default": [] -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_2.md b/vendor/symfony/console/Tests/Fixtures/input_argument_2.md deleted file mode 100644 index 2e7e758..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_2.md +++ /dev/null @@ -1,7 +0,0 @@ -#### `argument_name` - -argument description - -* Is required: no -* Is array: yes -* Default: `array ()` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_2.txt b/vendor/symfony/console/Tests/Fixtures/input_argument_2.txt deleted file mode 100644 index e713660..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_2.txt +++ /dev/null @@ -1 +0,0 @@ - <info>argument_name</info> argument description diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_2.xml b/vendor/symfony/console/Tests/Fixtures/input_argument_2.xml deleted file mode 100644 index 629da5a..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_2.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<argument name="argument_name" is_required="0" is_array="1"> - <description>argument description</description> - <defaults/> -</argument> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_3.json b/vendor/symfony/console/Tests/Fixtures/input_argument_3.json deleted file mode 100644 index 9a83c5a..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_3.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "argument_name", - "is_required": false, - "is_array": false, - "description": "argument description", - "default": "default_value" -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_3.md b/vendor/symfony/console/Tests/Fixtures/input_argument_3.md deleted file mode 100644 index b0dd878..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_3.md +++ /dev/null @@ -1,7 +0,0 @@ -#### `argument_name` - -argument description - -* Is required: no -* Is array: no -* Default: `'default_value'` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_3.txt b/vendor/symfony/console/Tests/Fixtures/input_argument_3.txt deleted file mode 100644 index 6b76639..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_3.txt +++ /dev/null @@ -1 +0,0 @@ - <info>argument_name</info> argument description<comment> [default: "default_value"]</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_3.xml b/vendor/symfony/console/Tests/Fixtures/input_argument_3.xml deleted file mode 100644 index 399a5c8..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_3.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<argument name="argument_name" is_required="0" is_array="0"> - <description>argument description</description> - <defaults> - <default>default_value</default> - </defaults> -</argument> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_4.json b/vendor/symfony/console/Tests/Fixtures/input_argument_4.json deleted file mode 100644 index cbcb19b..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_4.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "argument_name", - "is_required": true, - "is_array": false, - "description": "multiline argument description", - "default": null -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_4.md b/vendor/symfony/console/Tests/Fixtures/input_argument_4.md deleted file mode 100644 index b9bb7ed..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_4.md +++ /dev/null @@ -1,8 +0,0 @@ -#### `argument_name` - -multiline -argument description - -* Is required: yes -* Is array: no -* Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_4.txt b/vendor/symfony/console/Tests/Fixtures/input_argument_4.txt deleted file mode 100644 index fc7d669..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_4.txt +++ /dev/null @@ -1,2 +0,0 @@ - <info>argument_name</info> multiline - argument description diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_4.xml b/vendor/symfony/console/Tests/Fixtures/input_argument_4.xml deleted file mode 100644 index 5ca135e..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_4.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<argument name="argument_name" is_required="1" is_array="0"> - <description>multiline -argument description</description> - <defaults/> -</argument> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.json b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.json deleted file mode 100644 index b61ecf7..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "argument_name", - "is_required": false, - "is_array": false, - "description": "argument description", - "default": "INF" -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.md b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.md deleted file mode 100644 index 4f4d9b1..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.md +++ /dev/null @@ -1,7 +0,0 @@ -#### `argument_name` - -argument description - -* Is required: no -* Is array: no -* Default: `INF` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.txt b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.txt deleted file mode 100644 index c32d768..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.txt +++ /dev/null @@ -1 +0,0 @@ - <info>argument_name</info> argument description<comment> [default: INF]</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.xml b/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.xml deleted file mode 100644 index d457260..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_with_default_inf_value.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<argument name="argument_name" is_required="0" is_array="0"> - <description>argument description</description> - <defaults> - <default>INF</default> - </defaults> -</argument> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.json b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.json deleted file mode 100644 index 9334235..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "argument_name", - "is_required": false, - "is_array": false, - "description": "argument description", - "default": "<comment>style</>" -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.md b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.md deleted file mode 100644 index a2be967..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.md +++ /dev/null @@ -1,7 +0,0 @@ -#### `argument_name` - -argument description - -* Is required: no -* Is array: no -* Default: `'style'` diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.txt b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.txt deleted file mode 100644 index 35384a6..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.txt +++ /dev/null @@ -1 +0,0 @@ - <info>argument_name</info> argument description<comment> [default: "\<comment>style\</>"]</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.xml b/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.xml deleted file mode 100644 index 73332c7..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_argument_with_style.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<argument name="argument_name" is_required="0" is_array="0"> - <description>argument description</description> - <defaults> - <default><comment>style</></default> - </defaults> -</argument> diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_1.json b/vendor/symfony/console/Tests/Fixtures/input_definition_1.json deleted file mode 100644 index 44aa2c2..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_1.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "arguments": [], - "options": [] -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_1.md b/vendor/symfony/console/Tests/Fixtures/input_definition_1.md deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_1.txt b/vendor/symfony/console/Tests/Fixtures/input_definition_1.txt deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_1.xml b/vendor/symfony/console/Tests/Fixtures/input_definition_1.xml deleted file mode 100644 index b5481ce..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_1.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definition> - <arguments/> - <options/> -</definition> diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_2.json b/vendor/symfony/console/Tests/Fixtures/input_definition_2.json deleted file mode 100644 index 7cfd57e..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_2.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "arguments": { - "argument_name": { - "name": "argument_name", - "is_required": true, - "is_array": false, - "description": "", - "default": null - } - }, - "options": [] -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_2.md b/vendor/symfony/console/Tests/Fixtures/input_definition_2.md deleted file mode 100644 index ffc2bbb..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_2.md +++ /dev/null @@ -1,7 +0,0 @@ -### Arguments - -#### `argument_name` - -* Is required: yes -* Is array: no -* Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_2.txt b/vendor/symfony/console/Tests/Fixtures/input_definition_2.txt deleted file mode 100644 index 73b0f30..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_2.txt +++ /dev/null @@ -1,2 +0,0 @@ -<comment>Arguments:</comment> - <info>argument_name</info> diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_2.xml b/vendor/symfony/console/Tests/Fixtures/input_definition_2.xml deleted file mode 100644 index 102efc1..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_2.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definition> - <arguments> - <argument name="argument_name" is_required="1" is_array="0"> - <description></description> - <defaults/> - </argument> - </arguments> - <options/> -</definition> diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_3.json b/vendor/symfony/console/Tests/Fixtures/input_definition_3.json deleted file mode 100644 index 3b3cf73..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_3.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "arguments": [], - "options": { - "option_name": { - "name": "--option_name", - "shortcut": "-o", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "", - "default": false - } - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_3.md b/vendor/symfony/console/Tests/Fixtures/input_definition_3.md deleted file mode 100644 index 11f7cd6..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_3.md +++ /dev/null @@ -1,8 +0,0 @@ -### Options - -#### `--option_name|-o` - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_3.txt b/vendor/symfony/console/Tests/Fixtures/input_definition_3.txt deleted file mode 100644 index c02766f..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_3.txt +++ /dev/null @@ -1,2 +0,0 @@ -<comment>Options:</comment> - <info>-o, --option_name</info> diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_3.xml b/vendor/symfony/console/Tests/Fixtures/input_definition_3.xml deleted file mode 100644 index bc95151..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_3.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definition> - <arguments/> - <options> - <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0"> - <description></description> - </option> - </options> -</definition> diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_4.json b/vendor/symfony/console/Tests/Fixtures/input_definition_4.json deleted file mode 100644 index d4a51e8..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_4.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "arguments": { - "argument_name": { - "name": "argument_name", - "is_required": true, - "is_array": false, - "description": "", - "default": null - } - }, - "options": { - "option_name": { - "name": "--option_name", - "shortcut": "-o", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "", - "default": false - } - } -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_4.md b/vendor/symfony/console/Tests/Fixtures/input_definition_4.md deleted file mode 100644 index c4f947f..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_4.md +++ /dev/null @@ -1,16 +0,0 @@ -### Arguments - -#### `argument_name` - -* Is required: yes -* Is array: no -* Default: `NULL` - -### Options - -#### `--option_name|-o` - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_4.txt b/vendor/symfony/console/Tests/Fixtures/input_definition_4.txt deleted file mode 100644 index 63aa81d..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_4.txt +++ /dev/null @@ -1,5 +0,0 @@ -<comment>Arguments:</comment> - <info>argument_name</info> - -<comment>Options:</comment> - <info>-o, --option_name</info> diff --git a/vendor/symfony/console/Tests/Fixtures/input_definition_4.xml b/vendor/symfony/console/Tests/Fixtures/input_definition_4.xml deleted file mode 100644 index cffceec..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_definition_4.xml +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<definition> - <arguments> - <argument name="argument_name" is_required="1" is_array="0"> - <description></description> - <defaults/> - </argument> - </arguments> - <options> - <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0"> - <description></description> - </option> - </options> -</definition> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_1.json b/vendor/symfony/console/Tests/Fixtures/input_option_1.json deleted file mode 100644 index f86bf96..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_1.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "--option_name", - "shortcut": "-o", - "accept_value": false, - "is_value_required": false, - "is_multiple": false, - "description": "", - "default": false -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_1.md b/vendor/symfony/console/Tests/Fixtures/input_option_1.md deleted file mode 100644 index c544a4e..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_1.md +++ /dev/null @@ -1,6 +0,0 @@ -#### `--option_name|-o` - -* Accept value: no -* Is value required: no -* Is multiple: no -* Default: `false` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_1.txt b/vendor/symfony/console/Tests/Fixtures/input_option_1.txt deleted file mode 100644 index 3a5e4ee..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_1.txt +++ /dev/null @@ -1 +0,0 @@ - <info>-o, --option_name</info> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_1.xml b/vendor/symfony/console/Tests/Fixtures/input_option_1.xml deleted file mode 100644 index 8a64ea6..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_1.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0"> - <description></description> -</option> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_2.json b/vendor/symfony/console/Tests/Fixtures/input_option_2.json deleted file mode 100644 index 32dbab2..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_2.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "--option_name", - "shortcut": "-o", - "accept_value": true, - "is_value_required": false, - "is_multiple": false, - "description": "option description", - "default": "default_value" -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_2.md b/vendor/symfony/console/Tests/Fixtures/input_option_2.md deleted file mode 100644 index 293e617..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_2.md +++ /dev/null @@ -1,8 +0,0 @@ -#### `--option_name|-o` - -option description - -* Accept value: yes -* Is value required: no -* Is multiple: no -* Default: `'default_value'` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_2.txt b/vendor/symfony/console/Tests/Fixtures/input_option_2.txt deleted file mode 100644 index 1009eff..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_2.txt +++ /dev/null @@ -1 +0,0 @@ - <info>-o, --option_name[=OPTION_NAME]</info> option description<comment> [default: "default_value"]</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_2.xml b/vendor/symfony/console/Tests/Fixtures/input_option_2.xml deleted file mode 100644 index 4afac5b..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_2.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="0" is_multiple="0"> - <description>option description</description> - <defaults> - <default>default_value</default> - </defaults> -</option> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_3.json b/vendor/symfony/console/Tests/Fixtures/input_option_3.json deleted file mode 100644 index 6d55a6e..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_3.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "--option_name", - "shortcut": "-o", - "accept_value": true, - "is_value_required": true, - "is_multiple": false, - "description": "option description", - "default": null -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_3.md b/vendor/symfony/console/Tests/Fixtures/input_option_3.md deleted file mode 100644 index 7e89d69..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_3.md +++ /dev/null @@ -1,8 +0,0 @@ -#### `--option_name|-o` - -option description - -* Accept value: yes -* Is value required: yes -* Is multiple: no -* Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_3.txt b/vendor/symfony/console/Tests/Fixtures/input_option_3.txt deleted file mode 100644 index 947bb65..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_3.txt +++ /dev/null @@ -1 +0,0 @@ - <info>-o, --option_name=OPTION_NAME</info> option description diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_3.xml b/vendor/symfony/console/Tests/Fixtures/input_option_3.xml deleted file mode 100644 index dcc0631..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_3.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="1" is_multiple="0"> - <description>option description</description> - <defaults/> -</option> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_4.json b/vendor/symfony/console/Tests/Fixtures/input_option_4.json deleted file mode 100644 index 788a8ed..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_4.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "--option_name", - "shortcut": "-o", - "accept_value": true, - "is_value_required": false, - "is_multiple": true, - "description": "option description", - "default": [] -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_4.md b/vendor/symfony/console/Tests/Fixtures/input_option_4.md deleted file mode 100644 index 7eb2d2a..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_4.md +++ /dev/null @@ -1,8 +0,0 @@ -#### `--option_name|-o` - -option description - -* Accept value: yes -* Is value required: no -* Is multiple: yes -* Default: `array ()` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_4.txt b/vendor/symfony/console/Tests/Fixtures/input_option_4.txt deleted file mode 100644 index 27edf77..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_4.txt +++ /dev/null @@ -1 +0,0 @@ - <info>-o, --option_name[=OPTION_NAME]</info> option description<comment> (multiple values allowed)</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_4.xml b/vendor/symfony/console/Tests/Fixtures/input_option_4.xml deleted file mode 100644 index 5e2418b..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_4.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="0" is_multiple="1"> - <description>option description</description> - <defaults/> -</option> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_5.json b/vendor/symfony/console/Tests/Fixtures/input_option_5.json deleted file mode 100644 index 9f34d83..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_5.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "--option_name", - "shortcut": "-o", - "accept_value": true, - "is_value_required": true, - "is_multiple": false, - "description": "multiline option description", - "default": null -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_5.md b/vendor/symfony/console/Tests/Fixtures/input_option_5.md deleted file mode 100644 index 72ca439..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_5.md +++ /dev/null @@ -1,9 +0,0 @@ -#### `--option_name|-o` - -multiline -option description - -* Accept value: yes -* Is value required: yes -* Is multiple: no -* Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_5.txt b/vendor/symfony/console/Tests/Fixtures/input_option_5.txt deleted file mode 100644 index 9563b4c..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_5.txt +++ /dev/null @@ -1,2 +0,0 @@ - <info>-o, --option_name=OPTION_NAME</info> multiline - option description diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_5.xml b/vendor/symfony/console/Tests/Fixtures/input_option_5.xml deleted file mode 100644 index 90040cc..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_5.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="1" is_multiple="0"> - <description>multiline -option description</description> - <defaults/> -</option> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_6.json b/vendor/symfony/console/Tests/Fixtures/input_option_6.json deleted file mode 100644 index 0638de0..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_6.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "--option_name", - "shortcut": "-o|-O", - "accept_value": true, - "is_value_required": true, - "is_multiple": false, - "description": "option with multiple shortcuts", - "default": null -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_6.md b/vendor/symfony/console/Tests/Fixtures/input_option_6.md deleted file mode 100644 index 87acd8b..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_6.md +++ /dev/null @@ -1,8 +0,0 @@ -#### `--option_name|-o|-O` - -option with multiple shortcuts - -* Accept value: yes -* Is value required: yes -* Is multiple: no -* Default: `NULL` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_6.txt b/vendor/symfony/console/Tests/Fixtures/input_option_6.txt deleted file mode 100644 index 0e6c975..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_6.txt +++ /dev/null @@ -1 +0,0 @@ - <info>-o|O, --option_name=OPTION_NAME</info> option with multiple shortcuts diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_6.xml b/vendor/symfony/console/Tests/Fixtures/input_option_6.xml deleted file mode 100644 index 06126a2..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_6.xml +++ /dev/null @@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<option name="--option_name" shortcut="-o" shortcuts="-o|-O" accept_value="1" is_value_required="1" is_multiple="0"> - <description>option with multiple shortcuts</description> - <defaults/> -</option> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.json b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.json deleted file mode 100644 index 7c96ad3..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "--option_name", - "shortcut": "-o", - "accept_value": true, - "is_value_required": false, - "is_multiple": false, - "description": "option description", - "default": "INF" -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.md b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.md deleted file mode 100644 index c27e30a..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.md +++ /dev/null @@ -1,8 +0,0 @@ -#### `--option_name|-o` - -option description - -* Accept value: yes -* Is value required: no -* Is multiple: no -* Default: `INF` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.txt b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.txt deleted file mode 100644 index d467dcf..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.txt +++ /dev/null @@ -1 +0,0 @@ - <info>-o, --option_name[=OPTION_NAME]</info> option description<comment> [default: INF]</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.xml b/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.xml deleted file mode 100644 index 5d1d217..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_default_inf_value.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="0" is_multiple="0"> - <description>option description</description> - <defaults> - <default>INF</default> - </defaults> -</option> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.json b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.json deleted file mode 100644 index df328bf..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "--option_name", - "shortcut": "-o", - "accept_value": true, - "is_value_required": true, - "is_multiple": false, - "description": "option description", - "default": "<comment>style</>" -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.md b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.md deleted file mode 100644 index e07a564..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.md +++ /dev/null @@ -1,8 +0,0 @@ -#### `--option_name|-o` - -option description - -* Accept value: yes -* Is value required: yes -* Is multiple: no -* Default: `'style'` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.txt b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.txt deleted file mode 100644 index 880a535..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.txt +++ /dev/null @@ -1 +0,0 @@ - <info>-o, --option_name=OPTION_NAME</info> option description<comment> [default: "\<comment>style\</>"]</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.xml b/vendor/symfony/console/Tests/Fixtures/input_option_with_style.xml deleted file mode 100644 index 764b9e6..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_style.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="1" is_multiple="0"> - <description>option description</description> - <defaults> - <default><comment>style</></default> - </defaults> -</option> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.json b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.json deleted file mode 100644 index b175455..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "--option_name", - "shortcut": "-o", - "accept_value": true, - "is_value_required": true, - "is_multiple": true, - "description": "option description", - "default": [ - "<comment>Hello</comment>", - "<info>world</info>" - ] -} diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.md b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.md deleted file mode 100644 index 16a045b..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.md +++ /dev/null @@ -1,8 +0,0 @@ -#### `--option_name|-o` - -option description - -* Accept value: yes -* Is value required: yes -* Is multiple: yes -* Default: `array ( 0 => 'Hello', 1 => 'world',)` diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.txt b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.txt deleted file mode 100644 index 265c18c..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.txt +++ /dev/null @@ -1 +0,0 @@ - <info>-o, --option_name=OPTION_NAME</info> option description<comment> [default: ["\<comment>Hello\</comment>","\<info>world\</info>"]]</comment><comment> (multiple values allowed)</comment> diff --git a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.xml b/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.xml deleted file mode 100644 index 09dc865..0000000 --- a/vendor/symfony/console/Tests/Fixtures/input_option_with_style_array.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="1" is_multiple="1"> - <description>option description</description> - <defaults> - <default><comment>Hello</comment></default> - <default><info>world</info></default> - </defaults> -</option> diff --git a/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleStackTest.php b/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleStackTest.php deleted file mode 100644 index e212bf2..0000000 --- a/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleStackTest.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Formatter; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; -use Symfony\Component\Console\Formatter\OutputFormatterStyleStack; - -class OutputFormatterStyleStackTest extends TestCase -{ - public function testPush() - { - $stack = new OutputFormatterStyleStack(); - $stack->push($s1 = new OutputFormatterStyle('white', 'black')); - $stack->push($s2 = new OutputFormatterStyle('yellow', 'blue')); - - $this->assertEquals($s2, $stack->getCurrent()); - - $stack->push($s3 = new OutputFormatterStyle('green', 'red')); - - $this->assertEquals($s3, $stack->getCurrent()); - } - - public function testPop() - { - $stack = new OutputFormatterStyleStack(); - $stack->push($s1 = new OutputFormatterStyle('white', 'black')); - $stack->push($s2 = new OutputFormatterStyle('yellow', 'blue')); - - $this->assertEquals($s2, $stack->pop()); - $this->assertEquals($s1, $stack->pop()); - } - - public function testPopEmpty() - { - $stack = new OutputFormatterStyleStack(); - $style = new OutputFormatterStyle(); - - $this->assertEquals($style, $stack->pop()); - } - - public function testPopNotLast() - { - $stack = new OutputFormatterStyleStack(); - $stack->push($s1 = new OutputFormatterStyle('white', 'black')); - $stack->push($s2 = new OutputFormatterStyle('yellow', 'blue')); - $stack->push($s3 = new OutputFormatterStyle('green', 'red')); - - $this->assertEquals($s2, $stack->pop($s2)); - $this->assertEquals($s1, $stack->pop()); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testInvalidPop() - { - $stack = new OutputFormatterStyleStack(); - $stack->push(new OutputFormatterStyle('white', 'black')); - $stack->pop(new OutputFormatterStyle('yellow', 'blue')); - } -} diff --git a/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleTest.php b/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleTest.php deleted file mode 100644 index ddf7790..0000000 --- a/vendor/symfony/console/Tests/Formatter/OutputFormatterStyleTest.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Formatter; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; - -class OutputFormatterStyleTest extends TestCase -{ - public function testConstructor() - { - $style = new OutputFormatterStyle('green', 'black', array('bold', 'underscore')); - $this->assertEquals("\033[32;40;1;4mfoo\033[39;49;22;24m", $style->apply('foo')); - - $style = new OutputFormatterStyle('red', null, array('blink')); - $this->assertEquals("\033[31;5mfoo\033[39;25m", $style->apply('foo')); - - $style = new OutputFormatterStyle(null, 'white'); - $this->assertEquals("\033[47mfoo\033[49m", $style->apply('foo')); - } - - public function testForeground() - { - $style = new OutputFormatterStyle(); - - $style->setForeground('black'); - $this->assertEquals("\033[30mfoo\033[39m", $style->apply('foo')); - - $style->setForeground('blue'); - $this->assertEquals("\033[34mfoo\033[39m", $style->apply('foo')); - - $style->setForeground('default'); - $this->assertEquals("\033[39mfoo\033[39m", $style->apply('foo')); - - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); - $style->setForeground('undefined-color'); - } - - public function testBackground() - { - $style = new OutputFormatterStyle(); - - $style->setBackground('black'); - $this->assertEquals("\033[40mfoo\033[49m", $style->apply('foo')); - - $style->setBackground('yellow'); - $this->assertEquals("\033[43mfoo\033[49m", $style->apply('foo')); - - $style->setBackground('default'); - $this->assertEquals("\033[49mfoo\033[49m", $style->apply('foo')); - - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); - $style->setBackground('undefined-color'); - } - - public function testOptions() - { - $style = new OutputFormatterStyle(); - - $style->setOptions(array('reverse', 'conceal')); - $this->assertEquals("\033[7;8mfoo\033[27;28m", $style->apply('foo')); - - $style->setOption('bold'); - $this->assertEquals("\033[7;8;1mfoo\033[27;28;22m", $style->apply('foo')); - - $style->unsetOption('reverse'); - $this->assertEquals("\033[8;1mfoo\033[28;22m", $style->apply('foo')); - - $style->setOption('bold'); - $this->assertEquals("\033[8;1mfoo\033[28;22m", $style->apply('foo')); - - $style->setOptions(array('bold')); - $this->assertEquals("\033[1mfoo\033[22m", $style->apply('foo')); - - try { - $style->setOption('foo'); - $this->fail('->setOption() throws an \InvalidArgumentException when the option does not exist in the available options'); - } catch (\Exception $e) { - $this->assertInstanceOf('\InvalidArgumentException', $e, '->setOption() throws an \InvalidArgumentException when the option does not exist in the available options'); - $this->assertContains('Invalid option specified: "foo"', $e->getMessage(), '->setOption() throws an \InvalidArgumentException when the option does not exist in the available options'); - } - - try { - $style->unsetOption('foo'); - $this->fail('->unsetOption() throws an \InvalidArgumentException when the option does not exist in the available options'); - } catch (\Exception $e) { - $this->assertInstanceOf('\InvalidArgumentException', $e, '->unsetOption() throws an \InvalidArgumentException when the option does not exist in the available options'); - $this->assertContains('Invalid option specified: "foo"', $e->getMessage(), '->unsetOption() throws an \InvalidArgumentException when the option does not exist in the available options'); - } - } -} diff --git a/vendor/symfony/console/Tests/Formatter/OutputFormatterTest.php b/vendor/symfony/console/Tests/Formatter/OutputFormatterTest.php deleted file mode 100644 index 4b715c6..0000000 --- a/vendor/symfony/console/Tests/Formatter/OutputFormatterTest.php +++ /dev/null @@ -1,344 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Formatter; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; - -class OutputFormatterTest extends TestCase -{ - public function testEmptyTag() - { - $formatter = new OutputFormatter(true); - $this->assertEquals('foo<>bar', $formatter->format('foo<>bar')); - } - - public function testLGCharEscaping() - { - $formatter = new OutputFormatter(true); - - $this->assertEquals('foo<bar', $formatter->format('foo\\<bar')); - $this->assertEquals('foo << bar', $formatter->format('foo << bar')); - $this->assertEquals('foo << bar \\', $formatter->format('foo << bar \\')); - $this->assertEquals("foo << \033[32mbar \\ baz\033[39m \\", $formatter->format('foo << <info>bar \\ baz</info> \\')); - $this->assertEquals('<info>some info</info>', $formatter->format('\\<info>some info\\</info>')); - $this->assertEquals('\\<info>some info\\</info>', OutputFormatter::escape('<info>some info</info>')); - - $this->assertEquals( - "\033[33mSymfony\\Component\\Console does work very well!\033[39m", - $formatter->format('<comment>Symfony\Component\Console does work very well!</comment>') - ); - } - - public function testBundledStyles() - { - $formatter = new OutputFormatter(true); - - $this->assertTrue($formatter->hasStyle('error')); - $this->assertTrue($formatter->hasStyle('info')); - $this->assertTrue($formatter->hasStyle('comment')); - $this->assertTrue($formatter->hasStyle('question')); - - $this->assertEquals( - "\033[37;41msome error\033[39;49m", - $formatter->format('<error>some error</error>') - ); - $this->assertEquals( - "\033[32msome info\033[39m", - $formatter->format('<info>some info</info>') - ); - $this->assertEquals( - "\033[33msome comment\033[39m", - $formatter->format('<comment>some comment</comment>') - ); - $this->assertEquals( - "\033[30;46msome question\033[39;49m", - $formatter->format('<question>some question</question>') - ); - } - - public function testNestedStyles() - { - $formatter = new OutputFormatter(true); - - $this->assertEquals( - "\033[37;41msome \033[39;49m\033[32msome info\033[39m\033[37;41m error\033[39;49m", - $formatter->format('<error>some <info>some info</info> error</error>') - ); - } - - public function testAdjacentStyles() - { - $formatter = new OutputFormatter(true); - - $this->assertEquals( - "\033[37;41msome error\033[39;49m\033[32msome info\033[39m", - $formatter->format('<error>some error</error><info>some info</info>') - ); - } - - public function testStyleMatchingNotGreedy() - { - $formatter = new OutputFormatter(true); - - $this->assertEquals( - "(\033[32m>=2.0,<2.3\033[39m)", - $formatter->format('(<info>>=2.0,<2.3</info>)') - ); - } - - public function testStyleEscaping() - { - $formatter = new OutputFormatter(true); - - $this->assertEquals( - "(\033[32mz>=2.0,<<<a2.3\\\033[39m)", - $formatter->format('(<info>'.$formatter->escape('z>=2.0,<\\<<a2.3\\').'</info>)') - ); - - $this->assertEquals( - "\033[32m<error>some error</error>\033[39m", - $formatter->format('<info>'.$formatter->escape('<error>some error</error>').'</info>') - ); - } - - public function testDeepNestedStyles() - { - $formatter = new OutputFormatter(true); - - $this->assertEquals( - "\033[37;41merror\033[39;49m\033[32minfo\033[39m\033[33mcomment\033[39m\033[37;41merror\033[39;49m", - $formatter->format('<error>error<info>info<comment>comment</info>error</error>') - ); - } - - public function testNewStyle() - { - $formatter = new OutputFormatter(true); - - $style = new OutputFormatterStyle('blue', 'white'); - $formatter->setStyle('test', $style); - - $this->assertEquals($style, $formatter->getStyle('test')); - $this->assertNotEquals($style, $formatter->getStyle('info')); - - $style = new OutputFormatterStyle('blue', 'white'); - $formatter->setStyle('b', $style); - - $this->assertEquals("\033[34;47msome \033[39;49m\033[34;47mcustom\033[39;49m\033[34;47m msg\033[39;49m", $formatter->format('<test>some <b>custom</b> msg</test>')); - } - - public function testRedefineStyle() - { - $formatter = new OutputFormatter(true); - - $style = new OutputFormatterStyle('blue', 'white'); - $formatter->setStyle('info', $style); - - $this->assertEquals("\033[34;47msome custom msg\033[39;49m", $formatter->format('<info>some custom msg</info>')); - } - - public function testInlineStyle() - { - $formatter = new OutputFormatter(true); - - $this->assertEquals("\033[34;41msome text\033[39;49m", $formatter->format('<fg=blue;bg=red>some text</>')); - $this->assertEquals("\033[34;41msome text\033[39;49m", $formatter->format('<fg=blue;bg=red>some text</fg=blue;bg=red>')); - } - - /** - * @param string $tag - * @param string|null $expected - * @param string|null $input - * - * @dataProvider provideInlineStyleOptionsCases - */ - public function testInlineStyleOptions($tag, $expected = null, $input = null) - { - $styleString = substr($tag, 1, -1); - $formatter = new OutputFormatter(true); - $method = new \ReflectionMethod($formatter, 'createStyleFromString'); - $method->setAccessible(true); - $result = $method->invoke($formatter, $styleString); - if (null === $expected) { - $this->assertFalse($result); - $expected = $tag.$input.'</'.$styleString.'>'; - $this->assertSame($expected, $formatter->format($expected)); - } else { - /* @var OutputFormatterStyle $result */ - $this->assertInstanceOf(OutputFormatterStyle::class, $result); - $this->assertSame($expected, $formatter->format($tag.$input.'</>')); - $this->assertSame($expected, $formatter->format($tag.$input.'</'.$styleString.'>')); - } - } - - public function provideInlineStyleOptionsCases() - { - return array( - array('<unknown=_unknown_>'), - array('<unknown=_unknown_;a=1;b>'), - array('<fg=green;>', "\033[32m[test]\033[39m", '[test]'), - array('<fg=green;bg=blue;>', "\033[32;44ma\033[39;49m", 'a'), - array('<fg=green;options=bold>', "\033[32;1mb\033[39;22m", 'b'), - array('<fg=green;options=reverse;>', "\033[32;7m<a>\033[39;27m", '<a>'), - array('<fg=green;options=bold,underscore>', "\033[32;1;4mz\033[39;22;24m", 'z'), - array('<fg=green;options=bold,underscore,reverse;>', "\033[32;1;4;7md\033[39;22;24;27m", 'd'), - ); - } - - /** - * @group legacy - * @dataProvider provideInlineStyleTagsWithUnknownOptions - * @expectedDeprecation Unknown style options are deprecated since Symfony 3.2 and will be removed in 4.0. Exception "Invalid option specified: "%s". Expected one of (bold, underscore, blink, reverse, conceal)". - */ - public function testInlineStyleOptionsUnknownAreDeprecated($tag, $option) - { - $formatter = new OutputFormatter(true); - $formatter->format($tag); - } - - public function provideInlineStyleTagsWithUnknownOptions() - { - return array( - array('<options=abc;>', 'abc'), - array('<options=abc,def;>', 'abc'), - array('<fg=green;options=xyz;>', 'xyz'), - array('<fg=green;options=efg,abc>', 'efg'), - ); - } - - public function testNonStyleTag() - { - $formatter = new OutputFormatter(true); - - $this->assertEquals("\033[32msome \033[39m\033[32m<tag>\033[39m\033[32m \033[39m\033[32m<setting=value>\033[39m\033[32m styled \033[39m\033[32m<p>\033[39m\033[32msingle-char tag\033[39m\033[32m</p>\033[39m", $formatter->format('<info>some <tag> <setting=value> styled <p>single-char tag</p></info>')); - } - - public function testFormatLongString() - { - $formatter = new OutputFormatter(true); - $long = str_repeat('\\', 14000); - $this->assertEquals("\033[37;41msome error\033[39;49m".$long, $formatter->format('<error>some error</error>'.$long)); - } - - public function testFormatToStringObject() - { - $formatter = new OutputFormatter(false); - $this->assertEquals( - 'some info', $formatter->format(new TableCell()) - ); - } - - public function testNotDecoratedFormatter() - { - $formatter = new OutputFormatter(false); - - $this->assertTrue($formatter->hasStyle('error')); - $this->assertTrue($formatter->hasStyle('info')); - $this->assertTrue($formatter->hasStyle('comment')); - $this->assertTrue($formatter->hasStyle('question')); - - $this->assertEquals( - 'some error', $formatter->format('<error>some error</error>') - ); - $this->assertEquals( - 'some info', $formatter->format('<info>some info</info>') - ); - $this->assertEquals( - 'some comment', $formatter->format('<comment>some comment</comment>') - ); - $this->assertEquals( - 'some question', $formatter->format('<question>some question</question>') - ); - $this->assertEquals( - 'some text with inline style', $formatter->format('<fg=red>some text with inline style</>') - ); - - $formatter->setDecorated(true); - - $this->assertEquals( - "\033[37;41msome error\033[39;49m", $formatter->format('<error>some error</error>') - ); - $this->assertEquals( - "\033[32msome info\033[39m", $formatter->format('<info>some info</info>') - ); - $this->assertEquals( - "\033[33msome comment\033[39m", $formatter->format('<comment>some comment</comment>') - ); - $this->assertEquals( - "\033[30;46msome question\033[39;49m", $formatter->format('<question>some question</question>') - ); - $this->assertEquals( - "\033[31msome text with inline style\033[39m", $formatter->format('<fg=red>some text with inline style</>') - ); - } - - public function testContentWithLineBreaks() - { - $formatter = new OutputFormatter(true); - - $this->assertEquals(<<<EOF -\033[32m -some text\033[39m -EOF - , $formatter->format(<<<'EOF' -<info> -some text</info> -EOF - )); - - $this->assertEquals(<<<EOF -\033[32msome text -\033[39m -EOF - , $formatter->format(<<<'EOF' -<info>some text -</info> -EOF - )); - - $this->assertEquals(<<<EOF -\033[32m -some text -\033[39m -EOF - , $formatter->format(<<<'EOF' -<info> -some text -</info> -EOF - )); - - $this->assertEquals(<<<EOF -\033[32m -some text -more text -\033[39m -EOF - , $formatter->format(<<<'EOF' -<info> -some text -more text -</info> -EOF - )); - } -} - -class TableCell -{ - public function __toString() - { - return '<info>some info</info>'; - } -} diff --git a/vendor/symfony/console/Tests/Helper/AbstractQuestionHelperTest.php b/vendor/symfony/console/Tests/Helper/AbstractQuestionHelperTest.php deleted file mode 100644 index 56dd65f..0000000 --- a/vendor/symfony/console/Tests/Helper/AbstractQuestionHelperTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Input\StreamableInputInterface; - -abstract class AbstractQuestionHelperTest extends TestCase -{ - protected function createStreamableInputInterfaceMock($stream = null, $interactive = true) - { - $mock = $this->getMockBuilder(StreamableInputInterface::class)->getMock(); - $mock->expects($this->any()) - ->method('isInteractive') - ->will($this->returnValue($interactive)); - - if ($stream) { - $mock->expects($this->any()) - ->method('getStream') - ->willReturn($stream); - } - - return $mock; - } -} diff --git a/vendor/symfony/console/Tests/Helper/FormatterHelperTest.php b/vendor/symfony/console/Tests/Helper/FormatterHelperTest.php deleted file mode 100644 index f5d891a..0000000 --- a/vendor/symfony/console/Tests/Helper/FormatterHelperTest.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Helper\FormatterHelper; - -class FormatterHelperTest extends TestCase -{ - public function testFormatSection() - { - $formatter = new FormatterHelper(); - - $this->assertEquals( - '<info>[cli]</info> Some text to display', - $formatter->formatSection('cli', 'Some text to display'), - '::formatSection() formats a message in a section' - ); - } - - public function testFormatBlock() - { - $formatter = new FormatterHelper(); - - $this->assertEquals( - '<error> Some text to display </error>', - $formatter->formatBlock('Some text to display', 'error'), - '::formatBlock() formats a message in a block' - ); - - $this->assertEquals( - '<error> Some text to display </error>'."\n". - '<error> foo bar </error>', - $formatter->formatBlock(array('Some text to display', 'foo bar'), 'error'), - '::formatBlock() formats a message in a block' - ); - - $this->assertEquals( - '<error> </error>'."\n". - '<error> Some text to display </error>'."\n". - '<error> </error>', - $formatter->formatBlock('Some text to display', 'error', true), - '::formatBlock() formats a message in a block' - ); - } - - public function testFormatBlockWithDiacriticLetters() - { - $formatter = new FormatterHelper(); - - $this->assertEquals( - '<error> </error>'."\n". - '<error> Du texte à afficher </error>'."\n". - '<error> </error>', - $formatter->formatBlock('Du texte à afficher', 'error', true), - '::formatBlock() formats a message in a block' - ); - } - - public function testFormatBlockWithDoubleWidthDiacriticLetters() - { - $formatter = new FormatterHelper(); - $this->assertEquals( - '<error> </error>'."\n". - '<error> 表示するテキスト </error>'."\n". - '<error> </error>', - $formatter->formatBlock('表示するテキスト', 'error', true), - '::formatBlock() formats a message in a block' - ); - } - - public function testFormatBlockLGEscaping() - { - $formatter = new FormatterHelper(); - - $this->assertEquals( - '<error> </error>'."\n". - '<error> \<info>some info\</info> </error>'."\n". - '<error> </error>', - $formatter->formatBlock('<info>some info</info>', 'error', true), - '::formatBlock() escapes \'<\' chars' - ); - } - - public function testTruncatingWithShorterLengthThanMessageWithSuffix() - { - $formatter = new FormatterHelper(); - $message = 'testing truncate'; - - $this->assertSame('test...', $formatter->truncate($message, 4)); - $this->assertSame('testing truncat...', $formatter->truncate($message, 15)); - $this->assertSame('testing truncate...', $formatter->truncate($message, 16)); - $this->assertSame('zażółć gęślą...', $formatter->truncate('zażółć gęślą jaźń', 12)); - } - - public function testTruncatingMessageWithCustomSuffix() - { - $formatter = new FormatterHelper(); - $message = 'testing truncate'; - - $this->assertSame('test!', $formatter->truncate($message, 4, '!')); - } - - public function testTruncatingWithLongerLengthThanMessageWithSuffix() - { - $formatter = new FormatterHelper(); - $message = 'test'; - - $this->assertSame($message, $formatter->truncate($message, 10)); - } - - public function testTruncatingWithNegativeLength() - { - $formatter = new FormatterHelper(); - $message = 'testing truncate'; - - $this->assertSame('testing tru...', $formatter->truncate($message, -5)); - $this->assertSame('...', $formatter->truncate($message, -100)); - } -} diff --git a/vendor/symfony/console/Tests/Helper/HelperSetTest.php b/vendor/symfony/console/Tests/Helper/HelperSetTest.php deleted file mode 100644 index 0fdb2ce..0000000 --- a/vendor/symfony/console/Tests/Helper/HelperSetTest.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\HelperSet; - -class HelperSetTest extends TestCase -{ - public function testConstructor() - { - $mock_helper = $this->getGenericMockHelper('fake_helper'); - $helperset = new HelperSet(array('fake_helper_alias' => $mock_helper)); - - $this->assertEquals($mock_helper, $helperset->get('fake_helper_alias'), '__construct sets given helper to helpers'); - $this->assertTrue($helperset->has('fake_helper_alias'), '__construct sets helper alias for given helper'); - } - - public function testSet() - { - $helperset = new HelperSet(); - $helperset->set($this->getGenericMockHelper('fake_helper', $helperset)); - $this->assertTrue($helperset->has('fake_helper'), '->set() adds helper to helpers'); - - $helperset = new HelperSet(); - $helperset->set($this->getGenericMockHelper('fake_helper_01', $helperset)); - $helperset->set($this->getGenericMockHelper('fake_helper_02', $helperset)); - $this->assertTrue($helperset->has('fake_helper_01'), '->set() will set multiple helpers on consecutive calls'); - $this->assertTrue($helperset->has('fake_helper_02'), '->set() will set multiple helpers on consecutive calls'); - - $helperset = new HelperSet(); - $helperset->set($this->getGenericMockHelper('fake_helper', $helperset), 'fake_helper_alias'); - $this->assertTrue($helperset->has('fake_helper'), '->set() adds helper alias when set'); - $this->assertTrue($helperset->has('fake_helper_alias'), '->set() adds helper alias when set'); - } - - public function testHas() - { - $helperset = new HelperSet(array('fake_helper_alias' => $this->getGenericMockHelper('fake_helper'))); - $this->assertTrue($helperset->has('fake_helper'), '->has() finds set helper'); - $this->assertTrue($helperset->has('fake_helper_alias'), '->has() finds set helper by alias'); - } - - public function testGet() - { - $helper_01 = $this->getGenericMockHelper('fake_helper_01'); - $helper_02 = $this->getGenericMockHelper('fake_helper_02'); - $helperset = new HelperSet(array('fake_helper_01_alias' => $helper_01, 'fake_helper_02_alias' => $helper_02)); - $this->assertEquals($helper_01, $helperset->get('fake_helper_01'), '->get() returns correct helper by name'); - $this->assertEquals($helper_01, $helperset->get('fake_helper_01_alias'), '->get() returns correct helper by alias'); - $this->assertEquals($helper_02, $helperset->get('fake_helper_02'), '->get() returns correct helper by name'); - $this->assertEquals($helper_02, $helperset->get('fake_helper_02_alias'), '->get() returns correct helper by alias'); - - $helperset = new HelperSet(); - try { - $helperset->get('foo'); - $this->fail('->get() throws InvalidArgumentException when helper not found'); - } catch (\Exception $e) { - $this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws InvalidArgumentException when helper not found'); - $this->assertInstanceOf('Symfony\Component\Console\Exception\ExceptionInterface', $e, '->get() throws domain specific exception when helper not found'); - $this->assertContains('The helper "foo" is not defined.', $e->getMessage(), '->get() throws InvalidArgumentException when helper not found'); - } - } - - public function testSetCommand() - { - $cmd_01 = new Command('foo'); - $cmd_02 = new Command('bar'); - - $helperset = new HelperSet(); - $helperset->setCommand($cmd_01); - $this->assertEquals($cmd_01, $helperset->getCommand(), '->setCommand() stores given command'); - - $helperset = new HelperSet(); - $helperset->setCommand($cmd_01); - $helperset->setCommand($cmd_02); - $this->assertEquals($cmd_02, $helperset->getCommand(), '->setCommand() overwrites stored command with consecutive calls'); - } - - public function testGetCommand() - { - $cmd = new Command('foo'); - $helperset = new HelperSet(); - $helperset->setCommand($cmd); - $this->assertEquals($cmd, $helperset->getCommand(), '->getCommand() retrieves stored command'); - } - - public function testIteration() - { - $helperset = new HelperSet(); - $helperset->set($this->getGenericMockHelper('fake_helper_01', $helperset)); - $helperset->set($this->getGenericMockHelper('fake_helper_02', $helperset)); - - $helpers = array('fake_helper_01', 'fake_helper_02'); - $i = 0; - - foreach ($helperset as $helper) { - $this->assertEquals($helpers[$i++], $helper->getName()); - } - } - - private function getGenericMockHelper($name, HelperSet $helperset = null) - { - $mock_helper = $this->getMockBuilder('\Symfony\Component\Console\Helper\HelperInterface')->getMock(); - $mock_helper->expects($this->any()) - ->method('getName') - ->will($this->returnValue($name)); - - if ($helperset) { - $mock_helper->expects($this->any()) - ->method('setHelperSet') - ->with($this->equalTo($helperset)); - } - - return $mock_helper; - } -} diff --git a/vendor/symfony/console/Tests/Helper/HelperTest.php b/vendor/symfony/console/Tests/Helper/HelperTest.php deleted file mode 100644 index 1847582..0000000 --- a/vendor/symfony/console/Tests/Helper/HelperTest.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Helper\Helper; - -class HelperTest extends TestCase -{ - public function formatTimeProvider() - { - return array( - array(0, '< 1 sec'), - array(1, '1 sec'), - array(2, '2 secs'), - array(59, '59 secs'), - array(60, '1 min'), - array(61, '1 min'), - array(119, '1 min'), - array(120, '2 mins'), - array(121, '2 mins'), - array(3599, '59 mins'), - array(3600, '1 hr'), - array(7199, '1 hr'), - array(7200, '2 hrs'), - array(7201, '2 hrs'), - array(86399, '23 hrs'), - array(86400, '1 day'), - array(86401, '1 day'), - array(172799, '1 day'), - array(172800, '2 days'), - array(172801, '2 days'), - ); - } - - /** - * @dataProvider formatTimeProvider - * - * @param int $secs - * @param string $expectedFormat - */ - public function testFormatTime($secs, $expectedFormat) - { - $this->assertEquals($expectedFormat, Helper::formatTime($secs)); - } -} diff --git a/vendor/symfony/console/Tests/Helper/ProcessHelperTest.php b/vendor/symfony/console/Tests/Helper/ProcessHelperTest.php deleted file mode 100644 index 382c9f4..0000000 --- a/vendor/symfony/console/Tests/Helper/ProcessHelperTest.php +++ /dev/null @@ -1,118 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Helper\DebugFormatterHelper; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Helper\ProcessHelper; -use Symfony\Component\Console\Output\StreamOutput; -use Symfony\Component\Process\Process; - -class ProcessHelperTest extends TestCase -{ - /** - * @dataProvider provideCommandsAndOutput - */ - public function testVariousProcessRuns($expected, $cmd, $verbosity, $error) - { - $helper = new ProcessHelper(); - $helper->setHelperSet(new HelperSet(array(new DebugFormatterHelper()))); - $output = $this->getOutputStream($verbosity); - $helper->run($output, $cmd, $error); - $this->assertEquals($expected, $this->getOutput($output)); - } - - public function testPassedCallbackIsExecuted() - { - $helper = new ProcessHelper(); - $helper->setHelperSet(new HelperSet(array(new DebugFormatterHelper()))); - $output = $this->getOutputStream(StreamOutput::VERBOSITY_NORMAL); - - $executed = false; - $callback = function () use (&$executed) { $executed = true; }; - - $helper->run($output, 'php -r "echo 42;"', null, $callback); - $this->assertTrue($executed); - } - - public function provideCommandsAndOutput() - { - $successOutputVerbose = <<<'EOT' - RUN php -r "echo 42;" - RES Command ran successfully - -EOT; - $successOutputDebug = <<<'EOT' - RUN php -r "echo 42;" - OUT 42 - RES Command ran successfully - -EOT; - $successOutputDebugWithTags = <<<'EOT' - RUN php -r "echo '<info>42</info>';" - OUT <info>42</info> - RES Command ran successfully - -EOT; - $successOutputProcessDebug = <<<'EOT' - RUN 'php' '-r' 'echo 42;' - OUT 42 - RES Command ran successfully - -EOT; - $syntaxErrorOutputVerbose = <<<'EOT' - RUN php -r "fwrite(STDERR, 'error message');usleep(50000);fwrite(STDOUT, 'out message');exit(252);" - RES 252 Command did not run successfully - -EOT; - $syntaxErrorOutputDebug = <<<'EOT' - RUN php -r "fwrite(STDERR, 'error message');usleep(500000);fwrite(STDOUT, 'out message');exit(252);" - ERR error message - OUT out message - RES 252 Command did not run successfully - -EOT; - - $errorMessage = 'An error occurred'; - $args = new Process(array('php', '-r', 'echo 42;')); - $args = $args->getCommandLine(); - $successOutputProcessDebug = str_replace("'php' '-r' 'echo 42;'", $args, $successOutputProcessDebug); - - return array( - array('', 'php -r "echo 42;"', StreamOutput::VERBOSITY_VERBOSE, null), - array($successOutputVerbose, 'php -r "echo 42;"', StreamOutput::VERBOSITY_VERY_VERBOSE, null), - array($successOutputDebug, 'php -r "echo 42;"', StreamOutput::VERBOSITY_DEBUG, null), - array($successOutputDebugWithTags, 'php -r "echo \'<info>42</info>\';"', StreamOutput::VERBOSITY_DEBUG, null), - array('', 'php -r "syntax error"', StreamOutput::VERBOSITY_VERBOSE, null), - array($syntaxErrorOutputVerbose, 'php -r "fwrite(STDERR, \'error message\');usleep(50000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_VERY_VERBOSE, null), - array($syntaxErrorOutputDebug, 'php -r "fwrite(STDERR, \'error message\');usleep(500000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_DEBUG, null), - array($errorMessage.PHP_EOL, 'php -r "fwrite(STDERR, \'error message\');usleep(50000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_VERBOSE, $errorMessage), - array($syntaxErrorOutputVerbose.$errorMessage.PHP_EOL, 'php -r "fwrite(STDERR, \'error message\');usleep(50000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_VERY_VERBOSE, $errorMessage), - array($syntaxErrorOutputDebug.$errorMessage.PHP_EOL, 'php -r "fwrite(STDERR, \'error message\');usleep(500000);fwrite(STDOUT, \'out message\');exit(252);"', StreamOutput::VERBOSITY_DEBUG, $errorMessage), - array($successOutputProcessDebug, array('php', '-r', 'echo 42;'), StreamOutput::VERBOSITY_DEBUG, null), - array($successOutputDebug, new Process('php -r "echo 42;"'), StreamOutput::VERBOSITY_DEBUG, null), - ); - } - - private function getOutputStream($verbosity) - { - return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, false); - } - - private function getOutput(StreamOutput $output) - { - rewind($output->getStream()); - - return stream_get_contents($output->getStream()); - } -} diff --git a/vendor/symfony/console/Tests/Helper/ProgressBarTest.php b/vendor/symfony/console/Tests/Helper/ProgressBarTest.php deleted file mode 100644 index 4c2de26..0000000 --- a/vendor/symfony/console/Tests/Helper/ProgressBarTest.php +++ /dev/null @@ -1,792 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Helper\ProgressBar; -use Symfony\Component\Console\Output\StreamOutput; - -/** - * @group time-sensitive - */ -class ProgressBarTest extends TestCase -{ - public function testMultipleStart() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->start(); - $bar->advance(); - $bar->start(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'. - $this->generateOutput(' 1 [->--------------------------]'). - $this->generateOutput(' 0 [>---------------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testAdvance() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->start(); - $bar->advance(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'. - $this->generateOutput(' 1 [->--------------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testAdvanceWithStep() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->start(); - $bar->advance(5); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'. - $this->generateOutput(' 5 [----->----------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testAdvanceMultipleTimes() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->start(); - $bar->advance(3); - $bar->advance(2); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'. - $this->generateOutput(' 3 [--->------------------------]'). - $this->generateOutput(' 5 [----->----------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testAdvanceOverMax() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 10); - $bar->setProgress(9); - $bar->advance(); - $bar->advance(); - - rewind($output->getStream()); - $this->assertEquals( - ' 9/10 [=========================>--] 90%'. - $this->generateOutput(' 10/10 [============================] 100%'). - $this->generateOutput(' 11/11 [============================] 100%'), - stream_get_contents($output->getStream()) - ); - } - - public function testRegress() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->start(); - $bar->advance(); - $bar->advance(); - $bar->advance(-1); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'. - $this->generateOutput(' 1 [->--------------------------]'). - $this->generateOutput(' 2 [-->-------------------------]'). - $this->generateOutput(' 1 [->--------------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testRegressWithStep() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->start(); - $bar->advance(4); - $bar->advance(4); - $bar->advance(-2); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'. - $this->generateOutput(' 4 [---->-----------------------]'). - $this->generateOutput(' 8 [-------->-------------------]'). - $this->generateOutput(' 6 [------>---------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testRegressMultipleTimes() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->start(); - $bar->advance(3); - $bar->advance(3); - $bar->advance(-1); - $bar->advance(-2); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'. - $this->generateOutput(' 3 [--->------------------------]'). - $this->generateOutput(' 6 [------>---------------------]'). - $this->generateOutput(' 5 [----->----------------------]'). - $this->generateOutput(' 3 [--->------------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testRegressBelowMin() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 10); - $bar->setProgress(1); - $bar->advance(-1); - $bar->advance(-1); - - rewind($output->getStream()); - $this->assertEquals( - ' 1/10 [==>-------------------------] 10%'. - $this->generateOutput(' 0/10 [>---------------------------] 0%'), - stream_get_contents($output->getStream()) - ); - } - - public function testFormat() - { - $expected = - ' 0/10 [>---------------------------] 0%'. - $this->generateOutput(' 10/10 [============================] 100%'). - $this->generateOutput(' 10/10 [============================] 100%') - ; - - // max in construct, no format - $bar = new ProgressBar($output = $this->getOutputStream(), 10); - $bar->start(); - $bar->advance(10); - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals($expected, stream_get_contents($output->getStream())); - - // max in start, no format - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->start(10); - $bar->advance(10); - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals($expected, stream_get_contents($output->getStream())); - - // max in construct, explicit format before - $bar = new ProgressBar($output = $this->getOutputStream(), 10); - $bar->setFormat('normal'); - $bar->start(); - $bar->advance(10); - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals($expected, stream_get_contents($output->getStream())); - - // max in start, explicit format before - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->setFormat('normal'); - $bar->start(10); - $bar->advance(10); - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals($expected, stream_get_contents($output->getStream())); - } - - public function testCustomizations() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 10); - $bar->setBarWidth(10); - $bar->setBarCharacter('_'); - $bar->setEmptyBarCharacter(' '); - $bar->setProgressCharacter('/'); - $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%%'); - $bar->start(); - $bar->advance(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/10 [/ ] 0%'. - $this->generateOutput(' 1/10 [_/ ] 10%'), - stream_get_contents($output->getStream()) - ); - } - - public function testDisplayWithoutStart() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 50); - $bar->display(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/50 [>---------------------------] 0%', - stream_get_contents($output->getStream()) - ); - } - - public function testDisplayWithQuietVerbosity() - { - $bar = new ProgressBar($output = $this->getOutputStream(true, StreamOutput::VERBOSITY_QUIET), 50); - $bar->display(); - - rewind($output->getStream()); - $this->assertEquals( - '', - stream_get_contents($output->getStream()) - ); - } - - public function testFinishWithoutStart() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 50); - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals( - ' 50/50 [============================] 100%', - stream_get_contents($output->getStream()) - ); - } - - public function testPercent() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 50); - $bar->start(); - $bar->display(); - $bar->advance(); - $bar->advance(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/50 [>---------------------------] 0%'. - $this->generateOutput(' 0/50 [>---------------------------] 0%'). - $this->generateOutput(' 1/50 [>---------------------------] 2%'). - $this->generateOutput(' 2/50 [=>--------------------------] 4%'), - stream_get_contents($output->getStream()) - ); - } - - public function testOverwriteWithShorterLine() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 50); - $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%%'); - $bar->start(); - $bar->display(); - $bar->advance(); - - // set shorter format - $bar->setFormat(' %current%/%max% [%bar%]'); - $bar->advance(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/50 [>---------------------------] 0%'. - $this->generateOutput(' 0/50 [>---------------------------] 0%'). - $this->generateOutput(' 1/50 [>---------------------------] 2%'). - $this->generateOutput(' 2/50 [=>--------------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testStartWithMax() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->setFormat('%current%/%max% [%bar%]'); - $bar->start(50); - $bar->advance(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/50 [>---------------------------]'. - $this->generateOutput(' 1/50 [>---------------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testSetCurrentProgress() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 50); - $bar->start(); - $bar->display(); - $bar->advance(); - $bar->setProgress(15); - $bar->setProgress(25); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/50 [>---------------------------] 0%'. - $this->generateOutput(' 0/50 [>---------------------------] 0%'). - $this->generateOutput(' 1/50 [>---------------------------] 2%'). - $this->generateOutput(' 15/50 [========>-------------------] 30%'). - $this->generateOutput(' 25/50 [==============>-------------] 50%'), - stream_get_contents($output->getStream()) - ); - } - - public function testSetCurrentBeforeStarting() - { - $bar = new ProgressBar($this->getOutputStream()); - $bar->setProgress(15); - $this->assertNotNull($bar->getStartTime()); - } - - public function testRedrawFrequency() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 6); - $bar->setRedrawFrequency(2); - $bar->start(); - $bar->setProgress(1); - $bar->advance(2); - $bar->advance(2); - $bar->advance(1); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/6 [>---------------------------] 0%'. - $this->generateOutput(' 3/6 [==============>-------------] 50%'). - $this->generateOutput(' 5/6 [=======================>----] 83%'). - $this->generateOutput(' 6/6 [============================] 100%'), - stream_get_contents($output->getStream()) - ); - } - - public function testRedrawFrequencyIsAtLeastOneIfZeroGiven() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->setRedrawFrequency(0); - $bar->start(); - $bar->advance(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'. - $this->generateOutput(' 1 [->--------------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testRedrawFrequencyIsAtLeastOneIfSmallerOneGiven() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->setRedrawFrequency(0.9); - $bar->start(); - $bar->advance(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'. - $this->generateOutput(' 1 [->--------------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testMultiByteSupport() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->start(); - $bar->setBarCharacter('■'); - $bar->advance(3); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'. - $this->generateOutput(' 3 [■■■>------------------------]'), - stream_get_contents($output->getStream()) - ); - } - - public function testClear() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 50); - $bar->start(); - $bar->setProgress(25); - $bar->clear(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/50 [>---------------------------] 0%'. - $this->generateOutput(' 25/50 [==============>-------------] 50%'). - $this->generateOutput(''), - stream_get_contents($output->getStream()) - ); - } - - public function testPercentNotHundredBeforeComplete() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 200); - $bar->start(); - $bar->display(); - $bar->advance(199); - $bar->advance(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/200 [>---------------------------] 0%'. - $this->generateOutput(' 0/200 [>---------------------------] 0%'). - $this->generateOutput(' 199/200 [===========================>] 99%'). - $this->generateOutput(' 200/200 [============================] 100%'), - stream_get_contents($output->getStream()) - ); - } - - public function testNonDecoratedOutput() - { - $bar = new ProgressBar($output = $this->getOutputStream(false), 200); - $bar->start(); - - for ($i = 0; $i < 200; ++$i) { - $bar->advance(); - } - - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/200 [>---------------------------] 0%'.PHP_EOL. - ' 20/200 [==>-------------------------] 10%'.PHP_EOL. - ' 40/200 [=====>----------------------] 20%'.PHP_EOL. - ' 60/200 [========>-------------------] 30%'.PHP_EOL. - ' 80/200 [===========>----------------] 40%'.PHP_EOL. - ' 100/200 [==============>-------------] 50%'.PHP_EOL. - ' 120/200 [================>-----------] 60%'.PHP_EOL. - ' 140/200 [===================>--------] 70%'.PHP_EOL. - ' 160/200 [======================>-----] 80%'.PHP_EOL. - ' 180/200 [=========================>--] 90%'.PHP_EOL. - ' 200/200 [============================] 100%', - stream_get_contents($output->getStream()) - ); - } - - public function testNonDecoratedOutputWithClear() - { - $bar = new ProgressBar($output = $this->getOutputStream(false), 50); - $bar->start(); - $bar->setProgress(25); - $bar->clear(); - $bar->setProgress(50); - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/50 [>---------------------------] 0%'.PHP_EOL. - ' 25/50 [==============>-------------] 50%'.PHP_EOL. - ' 50/50 [============================] 100%', - stream_get_contents($output->getStream()) - ); - } - - public function testNonDecoratedOutputWithoutMax() - { - $bar = new ProgressBar($output = $this->getOutputStream(false)); - $bar->start(); - $bar->advance(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]'.PHP_EOL. - ' 1 [->--------------------------]', - stream_get_contents($output->getStream()) - ); - } - - public function testParallelBars() - { - $output = $this->getOutputStream(); - $bar1 = new ProgressBar($output, 2); - $bar2 = new ProgressBar($output, 3); - $bar2->setProgressCharacter('#'); - $bar3 = new ProgressBar($output); - - $bar1->start(); - $output->write("\n"); - $bar2->start(); - $output->write("\n"); - $bar3->start(); - - for ($i = 1; $i <= 3; ++$i) { - // up two lines - $output->write("\033[2A"); - if ($i <= 2) { - $bar1->advance(); - } - $output->write("\n"); - $bar2->advance(); - $output->write("\n"); - $bar3->advance(); - } - $output->write("\033[2A"); - $output->write("\n"); - $output->write("\n"); - $bar3->finish(); - - rewind($output->getStream()); - $this->assertEquals( - ' 0/2 [>---------------------------] 0%'."\n". - ' 0/3 [#---------------------------] 0%'."\n". - rtrim(' 0 [>---------------------------]'). - - "\033[2A". - $this->generateOutput(' 1/2 [==============>-------------] 50%')."\n". - $this->generateOutput(' 1/3 [=========#------------------] 33%')."\n". - rtrim($this->generateOutput(' 1 [->--------------------------]')). - - "\033[2A". - $this->generateOutput(' 2/2 [============================] 100%')."\n". - $this->generateOutput(' 2/3 [==================#---------] 66%')."\n". - rtrim($this->generateOutput(' 2 [-->-------------------------]')). - - "\033[2A". - "\n". - $this->generateOutput(' 3/3 [============================] 100%')."\n". - rtrim($this->generateOutput(' 3 [--->------------------------]')). - - "\033[2A". - "\n". - "\n". - rtrim($this->generateOutput(' 3 [============================]')), - stream_get_contents($output->getStream()) - ); - } - - public function testWithoutMax() - { - $output = $this->getOutputStream(); - - $bar = new ProgressBar($output); - $bar->start(); - $bar->advance(); - $bar->advance(); - $bar->advance(); - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals( - rtrim(' 0 [>---------------------------]'). - rtrim($this->generateOutput(' 1 [->--------------------------]')). - rtrim($this->generateOutput(' 2 [-->-------------------------]')). - rtrim($this->generateOutput(' 3 [--->------------------------]')). - rtrim($this->generateOutput(' 3 [============================]')), - stream_get_contents($output->getStream()) - ); - } - - public function testWithSmallScreen() - { - $output = $this->getOutputStream(); - - $bar = new ProgressBar($output); - putenv('COLUMNS=12'); - $bar->start(); - $bar->advance(); - putenv('COLUMNS=120'); - - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---]'. - $this->generateOutput(' 1 [->--]'), - stream_get_contents($output->getStream()) - ); - } - - public function testAddingPlaceholderFormatter() - { - ProgressBar::setPlaceholderFormatterDefinition('remaining_steps', function (ProgressBar $bar) { - return $bar->getMaxSteps() - $bar->getProgress(); - }); - $bar = new ProgressBar($output = $this->getOutputStream(), 3); - $bar->setFormat(' %remaining_steps% [%bar%]'); - - $bar->start(); - $bar->advance(); - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals( - ' 3 [>---------------------------]'. - $this->generateOutput(' 2 [=========>------------------]'). - $this->generateOutput(' 0 [============================]'), - stream_get_contents($output->getStream()) - ); - } - - public function testMultilineFormat() - { - $bar = new ProgressBar($output = $this->getOutputStream(), 3); - $bar->setFormat("%bar%\nfoobar"); - - $bar->start(); - $bar->advance(); - $bar->clear(); - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals( - ">---------------------------\nfoobar". - $this->generateOutput("=========>------------------\nfoobar"). - "\x0D\x1B[2K\x1B[1A\x1B[2K". - $this->generateOutput("============================\nfoobar"), - stream_get_contents($output->getStream()) - ); - } - - public function testAnsiColorsAndEmojis() - { - putenv('COLUMNS=156'); - - $bar = new ProgressBar($output = $this->getOutputStream(), 15); - ProgressBar::setPlaceholderFormatterDefinition('memory', function (ProgressBar $bar) { - static $i = 0; - $mem = 100000 * $i; - $colors = $i++ ? '41;37' : '44;37'; - - return "\033[".$colors.'m '.Helper::formatMemory($mem)." \033[0m"; - }); - $bar->setFormat(" \033[44;37m %title:-37s% \033[0m\n %current%/%max% %bar% %percent:3s%%\n 🏁 %remaining:-10s% %memory:37s%"); - $bar->setBarCharacter($done = "\033[32m●\033[0m"); - $bar->setEmptyBarCharacter($empty = "\033[31m●\033[0m"); - $bar->setProgressCharacter($progress = "\033[32m➤ \033[0m"); - - $bar->setMessage('Starting the demo... fingers crossed', 'title'); - $bar->start(); - - rewind($output->getStream()); - $this->assertEquals( - " \033[44;37m Starting the demo... fingers crossed \033[0m\n". - ' 0/15 '.$progress.str_repeat($empty, 26)." 0%\n". - " \xf0\x9f\x8f\x81 < 1 sec \033[44;37m 0 B \033[0m", - stream_get_contents($output->getStream()) - ); - ftruncate($output->getStream(), 0); - rewind($output->getStream()); - - $bar->setMessage('Looks good to me...', 'title'); - $bar->advance(4); - - rewind($output->getStream()); - $this->assertEquals( - $this->generateOutput( - " \033[44;37m Looks good to me... \033[0m\n". - ' 4/15 '.str_repeat($done, 7).$progress.str_repeat($empty, 19)." 26%\n". - " \xf0\x9f\x8f\x81 < 1 sec \033[41;37m 97 KiB \033[0m" - ), - stream_get_contents($output->getStream()) - ); - ftruncate($output->getStream(), 0); - rewind($output->getStream()); - - $bar->setMessage('Thanks, bye', 'title'); - $bar->finish(); - - rewind($output->getStream()); - $this->assertEquals( - $this->generateOutput( - " \033[44;37m Thanks, bye \033[0m\n". - ' 15/15 '.str_repeat($done, 28)." 100%\n". - " \xf0\x9f\x8f\x81 < 1 sec \033[41;37m 195 KiB \033[0m" - ), - stream_get_contents($output->getStream()) - ); - putenv('COLUMNS=120'); - } - - public function testSetFormat() - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->setFormat('normal'); - $bar->start(); - rewind($output->getStream()); - $this->assertEquals( - ' 0 [>---------------------------]', - stream_get_contents($output->getStream()) - ); - - $bar = new ProgressBar($output = $this->getOutputStream(), 10); - $bar->setFormat('normal'); - $bar->start(); - rewind($output->getStream()); - $this->assertEquals( - ' 0/10 [>---------------------------] 0%', - stream_get_contents($output->getStream()) - ); - } - - /** - * @dataProvider provideFormat - */ - public function testFormatsWithoutMax($format) - { - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->setFormat($format); - $bar->start(); - - rewind($output->getStream()); - $this->assertNotEmpty(stream_get_contents($output->getStream())); - } - - /** - * Provides each defined format. - * - * @return array - */ - public function provideFormat() - { - return array( - array('normal'), - array('verbose'), - array('very_verbose'), - array('debug'), - ); - } - - protected function getOutputStream($decorated = true, $verbosity = StreamOutput::VERBOSITY_NORMAL) - { - return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, $decorated); - } - - protected function generateOutput($expected) - { - $count = substr_count($expected, "\n"); - - return "\x0D\x1B[2K".($count ? str_repeat("\x1B[1A\x1B[2K", $count) : '').$expected; - } - - public function testBarWidthWithMultilineFormat() - { - putenv('COLUMNS=10'); - - $bar = new ProgressBar($output = $this->getOutputStream()); - $bar->setFormat("%bar%\n0123456789"); - - // before starting - $bar->setBarWidth(5); - $this->assertEquals(5, $bar->getBarWidth()); - - // after starting - $bar->start(); - rewind($output->getStream()); - $this->assertEquals(5, $bar->getBarWidth(), stream_get_contents($output->getStream())); - putenv('COLUMNS=120'); - } -} diff --git a/vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php b/vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php deleted file mode 100644 index c85018d..0000000 --- a/vendor/symfony/console/Tests/Helper/ProgressIndicatorTest.php +++ /dev/null @@ -1,183 +0,0 @@ -<?php - -namespace Symfony\Component\Console\Tests\Helper; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Helper\ProgressIndicator; -use Symfony\Component\Console\Output\StreamOutput; - -/** - * @group time-sensitive - */ -class ProgressIndicatorTest extends TestCase -{ - public function testDefaultIndicator() - { - $bar = new ProgressIndicator($output = $this->getOutputStream()); - $bar->start('Starting...'); - usleep(101000); - $bar->advance(); - usleep(101000); - $bar->advance(); - usleep(101000); - $bar->advance(); - usleep(101000); - $bar->advance(); - usleep(101000); - $bar->advance(); - usleep(101000); - $bar->setMessage('Advancing...'); - $bar->advance(); - $bar->finish('Done...'); - $bar->start('Starting Again...'); - usleep(101000); - $bar->advance(); - $bar->finish('Done Again...'); - - rewind($output->getStream()); - - $this->assertEquals( - $this->generateOutput(' - Starting...'). - $this->generateOutput(' \\ Starting...'). - $this->generateOutput(' | Starting...'). - $this->generateOutput(' / Starting...'). - $this->generateOutput(' - Starting...'). - $this->generateOutput(' \\ Starting...'). - $this->generateOutput(' \\ Advancing...'). - $this->generateOutput(' | Advancing...'). - $this->generateOutput(' | Done...'). - PHP_EOL. - $this->generateOutput(' - Starting Again...'). - $this->generateOutput(' \\ Starting Again...'). - $this->generateOutput(' \\ Done Again...'). - PHP_EOL, - stream_get_contents($output->getStream()) - ); - } - - public function testNonDecoratedOutput() - { - $bar = new ProgressIndicator($output = $this->getOutputStream(false)); - - $bar->start('Starting...'); - $bar->advance(); - $bar->advance(); - $bar->setMessage('Midway...'); - $bar->advance(); - $bar->advance(); - $bar->finish('Done...'); - - rewind($output->getStream()); - - $this->assertEquals( - ' Starting...'.PHP_EOL. - ' Midway...'.PHP_EOL. - ' Done...'.PHP_EOL.PHP_EOL, - stream_get_contents($output->getStream()) - ); - } - - public function testCustomIndicatorValues() - { - $bar = new ProgressIndicator($output = $this->getOutputStream(), null, 100, array('a', 'b', 'c')); - - $bar->start('Starting...'); - usleep(101000); - $bar->advance(); - usleep(101000); - $bar->advance(); - usleep(101000); - $bar->advance(); - - rewind($output->getStream()); - - $this->assertEquals( - $this->generateOutput(' a Starting...'). - $this->generateOutput(' b Starting...'). - $this->generateOutput(' c Starting...'). - $this->generateOutput(' a Starting...'), - stream_get_contents($output->getStream()) - ); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Must have at least 2 indicator value characters. - */ - public function testCannotSetInvalidIndicatorCharacters() - { - $bar = new ProgressIndicator($this->getOutputStream(), null, 100, array('1')); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Progress indicator already started. - */ - public function testCannotStartAlreadyStartedIndicator() - { - $bar = new ProgressIndicator($this->getOutputStream()); - $bar->start('Starting...'); - $bar->start('Starting Again.'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Progress indicator has not yet been started. - */ - public function testCannotAdvanceUnstartedIndicator() - { - $bar = new ProgressIndicator($this->getOutputStream()); - $bar->advance(); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Progress indicator has not yet been started. - */ - public function testCannotFinishUnstartedIndicator() - { - $bar = new ProgressIndicator($this->getOutputStream()); - $bar->finish('Finished'); - } - - /** - * @dataProvider provideFormat - */ - public function testFormats($format) - { - $bar = new ProgressIndicator($output = $this->getOutputStream(), $format); - $bar->start('Starting...'); - $bar->advance(); - - rewind($output->getStream()); - - $this->assertNotEmpty(stream_get_contents($output->getStream())); - } - - /** - * Provides each defined format. - * - * @return array - */ - public function provideFormat() - { - return array( - array('normal'), - array('verbose'), - array('very_verbose'), - array('debug'), - ); - } - - protected function getOutputStream($decorated = true, $verbosity = StreamOutput::VERBOSITY_NORMAL) - { - return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, $decorated); - } - - protected function generateOutput($expected) - { - $count = substr_count($expected, "\n"); - - return "\x0D\x1B[2K".($count ? sprintf("\033[%dA", $count) : '').$expected; - } -} diff --git a/vendor/symfony/console/Tests/Helper/QuestionHelperTest.php b/vendor/symfony/console/Tests/Helper/QuestionHelperTest.php deleted file mode 100644 index 675f95a..0000000 --- a/vendor/symfony/console/Tests/Helper/QuestionHelperTest.php +++ /dev/null @@ -1,959 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Helper\QuestionHelper; -use Symfony\Component\Console\Output\StreamOutput; -use Symfony\Component\Console\Question\ChoiceQuestion; -use Symfony\Component\Console\Question\ConfirmationQuestion; -use Symfony\Component\Console\Question\Question; - -/** - * @group tty - */ -class QuestionHelperTest extends AbstractQuestionHelperTest -{ - public function testAskChoice() - { - $questionHelper = new QuestionHelper(); - - $helperSet = new HelperSet(array(new FormatterHelper())); - $questionHelper->setHelperSet($helperSet); - - $heroes = array('Superman', 'Batman', 'Spiderman'); - - $inputStream = $this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n"); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2'); - $question->setMaxAttempts(1); - // first answer is an empty answer, we're supposed to receive the default value - $this->assertEquals('Spiderman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); - $question->setMaxAttempts(1); - $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); - $question->setErrorMessage('Input "%s" is not a superhero!'); - $question->setMaxAttempts(2); - $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); - - rewind($output->getStream()); - $stream = stream_get_contents($output->getStream()); - $this->assertContains('Input "Fabien" is not a superhero!', $stream); - - try { - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1'); - $question->setMaxAttempts(1); - $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertEquals('Value "Fabien" is invalid', $e->getMessage()); - } - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1'); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 '); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, 0); - // We are supposed to get the default value since we are not in interactive mode - $this->assertEquals('Superman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, true), $this->createOutputInterface(), $question)); - } - - public function testAsk() - { - $dialog = new QuestionHelper(); - - $inputStream = $this->getInputStream("\n8AM\n"); - - $question = new Question('What time is it?', '2PM'); - $this->assertEquals('2PM', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - - $question = new Question('What time is it?', '2PM'); - $this->assertEquals('8AM', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); - - rewind($output->getStream()); - $this->assertEquals('What time is it?', stream_get_contents($output->getStream())); - } - - public function testAskWithAutocomplete() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stty` is required to test autocomplete functionality'); - } - - // Acm<NEWLINE> - // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE> - // <NEWLINE> - // <UP ARROW><UP ARROW><NEWLINE> - // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE> - // <DOWN ARROW><NEWLINE> - // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE> - // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE> - $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n"); - - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new Question('Please select a bundle', 'FrameworkBundle'); - $question->setAutocompleterValues(array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle')); - - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('FrameworkBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('SecurityBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('FooBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - } - - public function testAskWithAutocompleteWithNonSequentialKeys() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stty` is required to test autocomplete functionality'); - } - - // <UP ARROW><UP ARROW><NEWLINE><DOWN ARROW><DOWN ARROW><NEWLINE> - $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n"); - - $dialog = new QuestionHelper(); - $dialog->setHelperSet(new HelperSet(array(new FormatterHelper()))); - - $question = new ChoiceQuestion('Please select a bundle', array(1 => 'AcmeDemoBundle', 4 => 'AsseticBundle')); - $question->setMaxAttempts(1); - - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - } - - public function testAskWithAutocompleteWithExactMatch() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stty` is required to test autocomplete functionality'); - } - - $inputStream = $this->getInputStream("b\n"); - - $possibleChoices = array( - 'a' => 'berlin', - 'b' => 'copenhagen', - 'c' => 'amsterdam', - ); - - $dialog = new QuestionHelper(); - $dialog->setHelperSet(new HelperSet(array(new FormatterHelper()))); - - $question = new ChoiceQuestion('Please select a city', $possibleChoices); - $question->setMaxAttempts(1); - - $this->assertSame('b', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - } - - public function testAutocompleteWithTrailingBackslash() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stty` is required to test autocomplete functionality'); - } - - $inputStream = $this->getInputStream('E'); - - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new Question(''); - $expectedCompletion = 'ExampleNamespace\\'; - $question->setAutocompleterValues(array($expectedCompletion)); - - $output = $this->createOutputInterface(); - $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output, $question); - - $outputStream = $output->getStream(); - rewind($outputStream); - $actualOutput = stream_get_contents($outputStream); - - // Shell control (esc) sequences are not so important: we only care that - // <hl> tag is interpreted correctly and replaced - $irrelevantEscSequences = array( - "\0337" => '', // Save cursor position - "\0338" => '', // Restore cursor position - "\033[K" => '', // Clear line from cursor till the end - ); - - $importantActualOutput = strtr($actualOutput, $irrelevantEscSequences); - - // Remove colors (e.g. "\033[30m", "\033[31;41m") - $importantActualOutput = preg_replace('/\033\[\d+(;\d+)?m/', '', $importantActualOutput); - - $this->assertEquals($expectedCompletion, $importantActualOutput); - } - - public function testAskHiddenResponse() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test is not supported on Windows'); - } - - $dialog = new QuestionHelper(); - - $question = new Question('What time is it?'); - $question->setHidden(true); - - $this->assertEquals('8AM', $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("8AM\n")), $this->createOutputInterface(), $question)); - } - - /** - * @dataProvider getAskConfirmationData - */ - public function testAskConfirmation($question, $expected, $default = true) - { - $dialog = new QuestionHelper(); - - $inputStream = $this->getInputStream($question."\n"); - $question = new ConfirmationQuestion('Do you like French fries?', $default); - $this->assertEquals($expected, $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel')); - } - - public function getAskConfirmationData() - { - return array( - array('', true), - array('', false, false), - array('y', true), - array('yes', true), - array('n', false), - array('no', false), - ); - } - - public function testAskConfirmationWithCustomTrueAnswer() - { - $dialog = new QuestionHelper(); - - $inputStream = $this->getInputStream("j\ny\n"); - $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i'); - $this->assertTrue($dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i'); - $this->assertTrue($dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - } - - public function testAskAndValidate() - { - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $error = 'This is not a color!'; - $validator = function ($color) use ($error) { - if (!\in_array($color, array('white', 'black'))) { - throw new \InvalidArgumentException($error); - } - - return $color; - }; - - $question = new Question('What color was the white horse of Henry IV?', 'white'); - $question->setValidator($validator); - $question->setMaxAttempts(2); - - $inputStream = $this->getInputStream("\nblack\n"); - $this->assertEquals('white', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('black', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - - try { - $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("green\nyellow\norange\n")), $this->createOutputInterface(), $question); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertEquals($error, $e->getMessage()); - } - } - - /** - * @dataProvider simpleAnswerProvider - */ - public function testSelectChoiceFromSimpleChoices($providedAnswer, $expectedValue) - { - $possibleChoices = array( - 'My environment 1', - 'My environment 2', - 'My environment 3', - ); - - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question); - - $this->assertSame($expectedValue, $answer); - } - - public function simpleAnswerProvider() - { - return array( - array(0, 'My environment 1'), - array(1, 'My environment 2'), - array(2, 'My environment 3'), - array('My environment 1', 'My environment 1'), - array('My environment 2', 'My environment 2'), - array('My environment 3', 'My environment 3'), - ); - } - - /** - * @dataProvider specialCharacterInMultipleChoice - */ - public function testSpecialCharacterChoiceFromMultipleChoiceList($providedAnswer, $expectedValue) - { - $possibleChoices = array( - '.', - 'src', - ); - - $dialog = new QuestionHelper(); - $inputStream = $this->getInputStream($providedAnswer."\n"); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the directory', $possibleChoices); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - $answer = $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question); - - $this->assertSame($expectedValue, $answer); - } - - public function specialCharacterInMultipleChoice() - { - return array( - array('.', array('.')), - array('., src', array('.', 'src')), - ); - } - - /** - * @dataProvider mixedKeysChoiceListAnswerProvider - */ - public function testChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue) - { - $possibleChoices = array( - '0' => 'No environment', - '1' => 'My environment 1', - 'env_2' => 'My environment 2', - 3 => 'My environment 3', - ); - - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question); - - $this->assertSame($expectedValue, $answer); - } - - public function mixedKeysChoiceListAnswerProvider() - { - return array( - array('0', '0'), - array('No environment', '0'), - array('1', '1'), - array('env_2', 'env_2'), - array(3, '3'), - array('My environment 1', '1'), - ); - } - - /** - * @dataProvider answerProvider - */ - public function testSelectChoiceFromChoiceList($providedAnswer, $expectedValue) - { - $possibleChoices = array( - 'env_1' => 'My environment 1', - 'env_2' => 'My environment', - 'env_3' => 'My environment', - ); - - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream($providedAnswer."\n")), $this->createOutputInterface(), $question); - - $this->assertSame($expectedValue, $answer); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The provided answer is ambiguous. Value should be one of env_2 or env_3. - */ - public function testAmbiguousChoiceFromChoicelist() - { - $possibleChoices = array( - 'env_1' => 'My first environment', - 'env_2' => 'My environment', - 'env_3' => 'My environment', - ); - - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - - $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("My environment\n")), $this->createOutputInterface(), $question); - } - - public function answerProvider() - { - return array( - array('env_1', 'env_1'), - array('env_2', 'env_2'), - array('env_3', 'env_3'), - array('My environment 1', 'env_1'), - ); - } - - public function testNoInteraction() - { - $dialog = new QuestionHelper(); - $question = new Question('Do you have a job?', 'not yet'); - $this->assertEquals('not yet', $dialog->ask($this->createStreamableInputInterfaceMock(null, false), $this->createOutputInterface(), $question)); - } - - /** - * @requires function mb_strwidth - */ - public function testChoiceOutputFormattingQuestionForUtf8Keys() - { - $question = 'Lorem ipsum?'; - $possibleChoices = array( - 'foo' => 'foo', - 'żółw' => 'bar', - 'łabądź' => 'baz', - ); - $outputShown = array( - $question, - ' [<info>foo </info>] foo', - ' [<info>żółw </info>] bar', - ' [<info>łabądź</info>] baz', - ); - $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock(); - $output->method('getFormatter')->willReturn(new OutputFormatter()); - - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $output->expects($this->once())->method('writeln')->with($this->equalTo($outputShown)); - - $question = new ChoiceQuestion($question, $possibleChoices, 'foo'); - $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("\n")), $output, $question); - } - - /** - * @group legacy - */ - public function testLegacyAskChoice() - { - $questionHelper = new QuestionHelper(); - - $helperSet = new HelperSet(array(new FormatterHelper())); - $questionHelper->setHelperSet($helperSet); - - $heroes = array('Superman', 'Batman', 'Spiderman'); - - $questionHelper->setInputStream($this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n")); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2'); - $question->setMaxAttempts(1); - // first answer is an empty answer, we're supposed to receive the default value - $this->assertEquals('Spiderman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); - $question->setMaxAttempts(1); - $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); - $question->setErrorMessage('Input "%s" is not a superhero!'); - $question->setMaxAttempts(2); - $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question)); - - rewind($output->getStream()); - $stream = stream_get_contents($output->getStream()); - $this->assertContains('Input "Fabien" is not a superhero!', $stream); - - try { - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1'); - $question->setMaxAttempts(1); - $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertEquals('Value "Fabien" is invalid', $e->getMessage()); - } - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1'); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 '); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - } - - /** - * @group legacy - */ - public function testLegacyAsk() - { - $dialog = new QuestionHelper(); - - $dialog->setInputStream($this->getInputStream("\n8AM\n")); - - $question = new Question('What time is it?', '2PM'); - $this->assertEquals('2PM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $question = new Question('What time is it?', '2PM'); - $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question)); - - rewind($output->getStream()); - $this->assertEquals('What time is it?', stream_get_contents($output->getStream())); - } - - /** - * @group legacy - */ - public function testLegacyAskWithAutocomplete() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stty` is required to test autocomplete functionality'); - } - - // Acm<NEWLINE> - // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE> - // <NEWLINE> - // <UP ARROW><UP ARROW><NEWLINE> - // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE> - // <DOWN ARROW><NEWLINE> - // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE> - // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE> - $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n"); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($inputStream); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new Question('Please select a bundle', 'FrameworkBundle'); - $question->setAutocompleterValues(array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle')); - - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('FrameworkBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('SecurityBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('FooBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('FooBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - } - - /** - * @group legacy - */ - public function testLegacyAskWithAutocompleteWithNonSequentialKeys() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stty` is required to test autocomplete functionality'); - } - - // <UP ARROW><UP ARROW><NEWLINE><DOWN ARROW><DOWN ARROW><NEWLINE> - $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n"); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($inputStream); - $dialog->setHelperSet(new HelperSet(array(new FormatterHelper()))); - - $question = new ChoiceQuestion('Please select a bundle', array(1 => 'AcmeDemoBundle', 4 => 'AsseticBundle')); - $question->setMaxAttempts(1); - - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - } - - /** - * @group legacy - */ - public function testLegacyAskHiddenResponse() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test is not supported on Windows'); - } - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream("8AM\n")); - - $question = new Question('What time is it?'); - $question->setHidden(true); - - $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - } - - /** - * @group legacy - * @dataProvider getAskConfirmationData - */ - public function testLegacyAskConfirmation($question, $expected, $default = true) - { - $dialog = new QuestionHelper(); - - $dialog->setInputStream($this->getInputStream($question."\n")); - $question = new ConfirmationQuestion('Do you like French fries?', $default); - $this->assertEquals($expected, $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel')); - } - - /** - * @group legacy - */ - public function testLegacyAskConfirmationWithCustomTrueAnswer() - { - $dialog = new QuestionHelper(); - - $dialog->setInputStream($this->getInputStream("j\ny\n")); - $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i'); - $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i'); - $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - } - - /** - * @group legacy - */ - public function testLegacyAskAndValidate() - { - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $error = 'This is not a color!'; - $validator = function ($color) use ($error) { - if (!\in_array($color, array('white', 'black'))) { - throw new \InvalidArgumentException($error); - } - - return $color; - }; - - $question = new Question('What color was the white horse of Henry IV?', 'white'); - $question->setValidator($validator); - $question->setMaxAttempts(2); - - $dialog->setInputStream($this->getInputStream("\nblack\n")); - $this->assertEquals('white', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('black', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n")); - try { - $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertEquals($error, $e->getMessage()); - } - } - - /** - * @group legacy - * @dataProvider simpleAnswerProvider - */ - public function testLegacySelectChoiceFromSimpleChoices($providedAnswer, $expectedValue) - { - $possibleChoices = array( - 'My environment 1', - 'My environment 2', - 'My environment 3', - ); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); - - $this->assertSame($expectedValue, $answer); - } - - /** - * @group legacy - * @dataProvider mixedKeysChoiceListAnswerProvider - */ - public function testLegacyChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue) - { - $possibleChoices = array( - '0' => 'No environment', - '1' => 'My environment 1', - 'env_2' => 'My environment 2', - 3 => 'My environment 3', - ); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); - - $this->assertSame($expectedValue, $answer); - } - - /** - * @group legacy - * @dataProvider answerProvider - */ - public function testLegacySelectChoiceFromChoiceList($providedAnswer, $expectedValue) - { - $possibleChoices = array( - 'env_1' => 'My environment 1', - 'env_2' => 'My environment', - 'env_3' => 'My environment', - ); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); - - $this->assertSame($expectedValue, $answer); - } - - /** - * @group legacy - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The provided answer is ambiguous. Value should be one of env_2 or env_3. - */ - public function testLegacyAmbiguousChoiceFromChoicelist() - { - $possibleChoices = array( - 'env_1' => 'My first environment', - 'env_2' => 'My environment', - 'env_3' => 'My environment', - ); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream("My environment\n")); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - - $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); - } - - /** - * @requires function mb_strwidth - * @group legacy - */ - public function testLegacyChoiceOutputFormattingQuestionForUtf8Keys() - { - $question = 'Lorem ipsum?'; - $possibleChoices = array( - 'foo' => 'foo', - 'żółw' => 'bar', - 'łabądź' => 'baz', - ); - $outputShown = array( - $question, - ' [<info>foo </info>] foo', - ' [<info>żółw </info>] bar', - ' [<info>łabądź</info>] baz', - ); - $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock(); - $output->method('getFormatter')->willReturn(new OutputFormatter()); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream("\n")); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $output->expects($this->once())->method('writeln')->with($this->equalTo($outputShown)); - - $question = new ChoiceQuestion($question, $possibleChoices, 'foo'); - $dialog->ask($this->createInputInterfaceMock(), $output, $question); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\RuntimeException - * @expectedExceptionMessage Aborted - */ - public function testAskThrowsExceptionOnMissingInput() - { - $dialog = new QuestionHelper(); - $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new Question('What\'s your name?')); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\RuntimeException - * @expectedExceptionMessage Aborted - */ - public function testAskThrowsExceptionOnMissingInputWithValidator() - { - $dialog = new QuestionHelper(); - - $question = new Question('What\'s your name?'); - $question->setValidator(function () { - if (!$value) { - throw new \Exception('A value is required.'); - } - }); - - $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), $question); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Choice question must have at least 1 choice available. - */ - public function testEmptyChoices() - { - new ChoiceQuestion('Question', array(), 'irrelevant'); - } - - public function testTraversableAutocomplete() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stty` is required to test autocomplete functionality'); - } - - // Acm<NEWLINE> - // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE> - // <NEWLINE> - // <UP ARROW><UP ARROW><NEWLINE> - // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE> - // <DOWN ARROW><NEWLINE> - // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE> - // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE> - $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n"); - - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new Question('Please select a bundle', 'FrameworkBundle'); - $question->setAutocompleterValues(new AutocompleteValues(array('irrelevant' => 'AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle'))); - - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('FrameworkBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('SecurityBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('FooBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - } - - protected function getInputStream($input) - { - $stream = fopen('php://memory', 'r+', false); - fwrite($stream, $input); - rewind($stream); - - return $stream; - } - - protected function createOutputInterface() - { - return new StreamOutput(fopen('php://memory', 'r+', false)); - } - - protected function createInputInterfaceMock($interactive = true) - { - $mock = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->getMock(); - $mock->expects($this->any()) - ->method('isInteractive') - ->will($this->returnValue($interactive)); - - return $mock; - } - - private function hasSttyAvailable() - { - exec('stty 2>&1', $output, $exitcode); - - return 0 === $exitcode; - } -} - -class AutocompleteValues implements \IteratorAggregate -{ - private $values; - - public function __construct(array $values) - { - $this->values = $values; - } - - public function getIterator() - { - return new \ArrayIterator($this->values); - } -} diff --git a/vendor/symfony/console/Tests/Helper/SymfonyQuestionHelperTest.php b/vendor/symfony/console/Tests/Helper/SymfonyQuestionHelperTest.php deleted file mode 100644 index fff72d4..0000000 --- a/vendor/symfony/console/Tests/Helper/SymfonyQuestionHelperTest.php +++ /dev/null @@ -1,156 +0,0 @@ -<?php - -namespace Symfony\Component\Console\Tests\Helper; - -use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Helper\SymfonyQuestionHelper; -use Symfony\Component\Console\Output\StreamOutput; -use Symfony\Component\Console\Question\ChoiceQuestion; -use Symfony\Component\Console\Question\Question; - -/** - * @group tty - */ -class SymfonyQuestionHelperTest extends AbstractQuestionHelperTest -{ - public function testAskChoice() - { - $questionHelper = new SymfonyQuestionHelper(); - - $helperSet = new HelperSet(array(new FormatterHelper())); - $questionHelper->setHelperSet($helperSet); - - $heroes = array('Superman', 'Batman', 'Spiderman'); - - $inputStream = $this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n"); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2'); - $question->setMaxAttempts(1); - // first answer is an empty answer, we're supposed to receive the default value - $this->assertEquals('Spiderman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); - $this->assertOutputContains('What is your favorite superhero? [Spiderman]', $output); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); - $question->setMaxAttempts(1); - $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); - $question->setErrorMessage('Input "%s" is not a superhero!'); - $question->setMaxAttempts(2); - $this->assertEquals('Batman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); - $this->assertOutputContains('Input "Fabien" is not a superhero!', $output); - - try { - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1'); - $question->setMaxAttempts(1); - $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertEquals('Value "Fabien" is invalid', $e->getMessage()); - } - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1'); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); - $this->assertOutputContains('What is your favorite superhero? [Superman, Batman]', $output); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 '); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); - $this->assertOutputContains('What is your favorite superhero? [Superman, Batman]', $output); - } - - public function testAskReturnsNullIfValidatorAllowsIt() - { - $questionHelper = new SymfonyQuestionHelper(); - $question = new Question('What is your favorite superhero?'); - $question->setValidator(function ($value) { return $value; }); - $input = $this->createStreamableInputInterfaceMock($this->getInputStream("\n")); - $this->assertNull($questionHelper->ask($input, $this->createOutputInterface(), $question)); - } - - public function testAskEscapeDefaultValue() - { - $helper = new SymfonyQuestionHelper(); - $input = $this->createStreamableInputInterfaceMock($this->getInputStream('\\')); - $helper->ask($input, $output = $this->createOutputInterface(), new Question('Can I have a backslash?', '\\')); - - $this->assertOutputContains('Can I have a backslash? [\]', $output); - } - - public function testAskEscapeAndFormatLabel() - { - $helper = new SymfonyQuestionHelper(); - $input = $this->createStreamableInputInterfaceMock($this->getInputStream('Foo\\Bar')); - $helper->ask($input, $output = $this->createOutputInterface(), new Question('Do you want to use Foo\\Bar <comment>or</comment> Foo\\Baz\\?', 'Foo\\Baz')); - - $this->assertOutputContains('Do you want to use Foo\\Bar or Foo\\Baz\\? [Foo\\Baz]:', $output); - } - - public function testLabelTrailingBackslash() - { - $helper = new SymfonyQuestionHelper(); - $input = $this->createStreamableInputInterfaceMock($this->getInputStream('sure')); - $helper->ask($input, $output = $this->createOutputInterface(), new Question('Question with a trailing \\')); - - $this->assertOutputContains('Question with a trailing \\', $output); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\RuntimeException - * @expectedExceptionMessage Aborted - */ - public function testAskThrowsExceptionOnMissingInput() - { - $dialog = new SymfonyQuestionHelper(); - $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new Question('What\'s your name?')); - } - - protected function getInputStream($input) - { - $stream = fopen('php://memory', 'r+', false); - fwrite($stream, $input); - rewind($stream); - - return $stream; - } - - protected function createOutputInterface() - { - $output = new StreamOutput(fopen('php://memory', 'r+', false)); - $output->setDecorated(false); - - return $output; - } - - protected function createInputInterfaceMock($interactive = true) - { - $mock = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->getMock(); - $mock->expects($this->any()) - ->method('isInteractive') - ->will($this->returnValue($interactive)); - - return $mock; - } - - private function assertOutputContains($expected, StreamOutput $output) - { - rewind($output->getStream()); - $stream = stream_get_contents($output->getStream()); - $this->assertContains($expected, $stream); - } -} diff --git a/vendor/symfony/console/Tests/Helper/TableStyleTest.php b/vendor/symfony/console/Tests/Helper/TableStyleTest.php deleted file mode 100644 index 13e918b..0000000 --- a/vendor/symfony/console/Tests/Helper/TableStyleTest.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Helper\TableStyle; - -class TableStyleTest extends TestCase -{ - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH). - */ - public function testSetPadTypeWithInvalidType() - { - $style = new TableStyle(); - $style->setPadType('TEST'); - } -} diff --git a/vendor/symfony/console/Tests/Helper/TableTest.php b/vendor/symfony/console/Tests/Helper/TableTest.php deleted file mode 100644 index 3f7c7ef..0000000 --- a/vendor/symfony/console/Tests/Helper/TableTest.php +++ /dev/null @@ -1,838 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Helper; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Helper\TableCell; -use Symfony\Component\Console\Helper\TableSeparator; -use Symfony\Component\Console\Helper\TableStyle; -use Symfony\Component\Console\Output\StreamOutput; - -class TableTest extends TestCase -{ - protected $stream; - - protected function setUp() - { - $this->stream = fopen('php://memory', 'r+'); - } - - protected function tearDown() - { - fclose($this->stream); - $this->stream = null; - } - - /** - * @dataProvider renderProvider - */ - public function testRender($headers, $rows, $style, $expected, $decorated = false) - { - $table = new Table($output = $this->getOutputStream($decorated)); - $table - ->setHeaders($headers) - ->setRows($rows) - ->setStyle($style) - ; - $table->render(); - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - /** - * @dataProvider renderProvider - */ - public function testRenderAddRows($headers, $rows, $style, $expected, $decorated = false) - { - $table = new Table($output = $this->getOutputStream($decorated)); - $table - ->setHeaders($headers) - ->addRows($rows) - ->setStyle($style) - ; - $table->render(); - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - /** - * @dataProvider renderProvider - */ - public function testRenderAddRowsOneByOne($headers, $rows, $style, $expected, $decorated = false) - { - $table = new Table($output = $this->getOutputStream($decorated)); - $table - ->setHeaders($headers) - ->setStyle($style) - ; - foreach ($rows as $row) { - $table->addRow($row); - } - $table->render(); - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - public function renderProvider() - { - $books = array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), - array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), - array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), - array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), - ); - - return array( - array( - array('ISBN', 'Title', 'Author'), - $books, - 'default', -<<<'TABLE' -+---------------+--------------------------+------------------+ -| ISBN | Title | Author | -+---------------+--------------------------+------------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | -| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | -| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | -| 80-902734-1-6 | And Then There Were None | Agatha Christie | -+---------------+--------------------------+------------------+ - -TABLE - ), - array( - array('ISBN', 'Title', 'Author'), - $books, - 'compact', -<<<'TABLE' - ISBN Title Author - 99921-58-10-7 Divine Comedy Dante Alighieri - 9971-5-0210-0 A Tale of Two Cities Charles Dickens - 960-425-059-0 The Lord of the Rings J. R. R. Tolkien - 80-902734-1-6 And Then There Were None Agatha Christie - -TABLE - ), - array( - array('ISBN', 'Title', 'Author'), - $books, - 'borderless', -<<<'TABLE' - =============== ========================== ================== - ISBN Title Author - =============== ========================== ================== - 99921-58-10-7 Divine Comedy Dante Alighieri - 9971-5-0210-0 A Tale of Two Cities Charles Dickens - 960-425-059-0 The Lord of the Rings J. R. R. Tolkien - 80-902734-1-6 And Then There Were None Agatha Christie - =============== ========================== ================== - -TABLE - ), - array( - array('ISBN', 'Title'), - array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), - array('9971-5-0210-0'), - array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), - array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), - ), - 'default', -<<<'TABLE' -+---------------+--------------------------+------------------+ -| ISBN | Title | | -+---------------+--------------------------+------------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | -| 9971-5-0210-0 | | | -| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | -| 80-902734-1-6 | And Then There Were None | Agatha Christie | -+---------------+--------------------------+------------------+ - -TABLE - ), - array( - array(), - array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), - array('9971-5-0210-0'), - array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'), - array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'), - ), - 'default', -<<<'TABLE' -+---------------+--------------------------+------------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | -| 9971-5-0210-0 | | | -| 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | -| 80-902734-1-6 | And Then There Were None | Agatha Christie | -+---------------+--------------------------+------------------+ - -TABLE - ), - array( - array('ISBN', 'Title', 'Author'), - array( - array('99921-58-10-7', "Divine\nComedy", 'Dante Alighieri'), - array('9971-5-0210-2', "Harry Potter\nand the Chamber of Secrets", "Rowling\nJoanne K."), - array('9971-5-0210-2', "Harry Potter\nand the Chamber of Secrets", "Rowling\nJoanne K."), - array('960-425-059-0', 'The Lord of the Rings', "J. R. R.\nTolkien"), - ), - 'default', -<<<'TABLE' -+---------------+----------------------------+-----------------+ -| ISBN | Title | Author | -+---------------+----------------------------+-----------------+ -| 99921-58-10-7 | Divine | Dante Alighieri | -| | Comedy | | -| 9971-5-0210-2 | Harry Potter | Rowling | -| | and the Chamber of Secrets | Joanne K. | -| 9971-5-0210-2 | Harry Potter | Rowling | -| | and the Chamber of Secrets | Joanne K. | -| 960-425-059-0 | The Lord of the Rings | J. R. R. | -| | | Tolkien | -+---------------+----------------------------+-----------------+ - -TABLE - ), - array( - array('ISBN', 'Title'), - array(), - 'default', -<<<'TABLE' -+------+-------+ -| ISBN | Title | -+------+-------+ - -TABLE - ), - array( - array(), - array(), - 'default', - '', - ), - 'Cell text with tags used for Output styling' => array( - array('ISBN', 'Title', 'Author'), - array( - array('<info>99921-58-10-7</info>', '<error>Divine Comedy</error>', '<fg=blue;bg=white>Dante Alighieri</fg=blue;bg=white>'), - array('9971-5-0210-0', 'A Tale of Two Cities', '<info>Charles Dickens</>'), - ), - 'default', -<<<'TABLE' -+---------------+----------------------+-----------------+ -| ISBN | Title | Author | -+---------------+----------------------+-----------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | -| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | -+---------------+----------------------+-----------------+ - -TABLE - ), - 'Cell text with tags not used for Output styling' => array( - array('ISBN', 'Title', 'Author'), - array( - array('<strong>99921-58-10-700</strong>', '<f>Divine Com</f>', 'Dante Alighieri'), - array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'), - ), - 'default', -<<<'TABLE' -+----------------------------------+----------------------+-----------------+ -| ISBN | Title | Author | -+----------------------------------+----------------------+-----------------+ -| <strong>99921-58-10-700</strong> | <f>Divine Com</f> | Dante Alighieri | -| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | -+----------------------------------+----------------------+-----------------+ - -TABLE - ), - 'Cell with colspan' => array( - array('ISBN', 'Title', 'Author'), - array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'), - new TableSeparator(), - array(new TableCell('Divine Comedy(Dante Alighieri)', array('colspan' => 3))), - new TableSeparator(), - array( - new TableCell('Arduino: A Quick-Start Guide', array('colspan' => 2)), - 'Mark Schmidt', - ), - new TableSeparator(), - array( - '9971-5-0210-0', - new TableCell("A Tale of \nTwo Cities", array('colspan' => 2)), - ), - new TableSeparator(), - array( - new TableCell('Cupiditate dicta atque porro, tempora exercitationem modi animi nulla nemo vel nihil!', array('colspan' => 3)), - ), - ), - 'default', -<<<'TABLE' -+-------------------------------+-------------------------------+-----------------------------+ -| ISBN | Title | Author | -+-------------------------------+-------------------------------+-----------------------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | -+-------------------------------+-------------------------------+-----------------------------+ -| Divine Comedy(Dante Alighieri) | -+-------------------------------+-------------------------------+-----------------------------+ -| Arduino: A Quick-Start Guide | Mark Schmidt | -+-------------------------------+-------------------------------+-----------------------------+ -| 9971-5-0210-0 | A Tale of | -| | Two Cities | -+-------------------------------+-------------------------------+-----------------------------+ -| Cupiditate dicta atque porro, tempora exercitationem modi animi nulla nemo vel nihil! | -+-------------------------------+-------------------------------+-----------------------------+ - -TABLE - ), - 'Cell with rowspan' => array( - array('ISBN', 'Title', 'Author'), - array( - array( - new TableCell('9971-5-0210-0', array('rowspan' => 3)), - new TableCell('Divine Comedy', array('rowspan' => 2)), - 'Dante Alighieri', - ), - array(), - array("The Lord of \nthe Rings", "J. R. \nR. Tolkien"), - new TableSeparator(), - array('80-902734-1-6', new TableCell("And Then \nThere \nWere None", array('rowspan' => 3)), 'Agatha Christie'), - array('80-902734-1-7', 'Test'), - ), - 'default', -<<<'TABLE' -+---------------+---------------+-----------------+ -| ISBN | Title | Author | -+---------------+---------------+-----------------+ -| 9971-5-0210-0 | Divine Comedy | Dante Alighieri | -| | | | -| | The Lord of | J. R. | -| | the Rings | R. Tolkien | -+---------------+---------------+-----------------+ -| 80-902734-1-6 | And Then | Agatha Christie | -| 80-902734-1-7 | There | Test | -| | Were None | | -+---------------+---------------+-----------------+ - -TABLE - ), - 'Cell with rowspan and colspan' => array( - array('ISBN', 'Title', 'Author'), - array( - array( - new TableCell('9971-5-0210-0', array('rowspan' => 2, 'colspan' => 2)), - 'Dante Alighieri', - ), - array('Charles Dickens'), - new TableSeparator(), - array( - 'Dante Alighieri', - new TableCell('9971-5-0210-0', array('rowspan' => 3, 'colspan' => 2)), - ), - array('J. R. R. Tolkien'), - array('J. R. R'), - ), - 'default', -<<<'TABLE' -+------------------+---------+-----------------+ -| ISBN | Title | Author | -+------------------+---------+-----------------+ -| 9971-5-0210-0 | Dante Alighieri | -| | Charles Dickens | -+------------------+---------+-----------------+ -| Dante Alighieri | 9971-5-0210-0 | -| J. R. R. Tolkien | | -| J. R. R | | -+------------------+---------+-----------------+ - -TABLE - ), - 'Cell with rowspan and colspan contains new line break' => array( - array('ISBN', 'Title', 'Author'), - array( - array( - new TableCell("9971\n-5-\n021\n0-0", array('rowspan' => 2, 'colspan' => 2)), - 'Dante Alighieri', - ), - array('Charles Dickens'), - new TableSeparator(), - array( - 'Dante Alighieri', - new TableCell("9971\n-5-\n021\n0-0", array('rowspan' => 2, 'colspan' => 2)), - ), - array('Charles Dickens'), - new TableSeparator(), - array( - new TableCell("9971\n-5-\n021\n0-0", array('rowspan' => 2, 'colspan' => 2)), - new TableCell("Dante \nAlighieri", array('rowspan' => 2, 'colspan' => 1)), - ), - ), - 'default', -<<<'TABLE' -+-----------------+-------+-----------------+ -| ISBN | Title | Author | -+-----------------+-------+-----------------+ -| 9971 | Dante Alighieri | -| -5- | Charles Dickens | -| 021 | | -| 0-0 | | -+-----------------+-------+-----------------+ -| Dante Alighieri | 9971 | -| Charles Dickens | -5- | -| | 021 | -| | 0-0 | -+-----------------+-------+-----------------+ -| 9971 | Dante | -| -5- | Alighieri | -| 021 | | -| 0-0 | | -+-----------------+-------+-----------------+ - -TABLE - ), - 'Cell with rowspan and colspan without using TableSeparator' => array( - array('ISBN', 'Title', 'Author'), - array( - array( - new TableCell("9971\n-5-\n021\n0-0", array('rowspan' => 2, 'colspan' => 2)), - 'Dante Alighieri', - ), - array('Charles Dickens'), - array( - 'Dante Alighieri', - new TableCell("9971\n-5-\n021\n0-0", array('rowspan' => 2, 'colspan' => 2)), - ), - array('Charles Dickens'), - ), - 'default', -<<<'TABLE' -+-----------------+-------+-----------------+ -| ISBN | Title | Author | -+-----------------+-------+-----------------+ -| 9971 | Dante Alighieri | -| -5- | Charles Dickens | -| 021 | | -| 0-0 | | -| Dante Alighieri | 9971 | -| Charles Dickens | -5- | -| | 021 | -| | 0-0 | -+-----------------+-------+-----------------+ - -TABLE - ), - 'Cell with rowspan and colspan with separator inside a rowspan' => array( - array('ISBN', 'Author'), - array( - array( - new TableCell('9971-5-0210-0', array('rowspan' => 3, 'colspan' => 1)), - 'Dante Alighieri', - ), - array(new TableSeparator()), - array('Charles Dickens'), - ), - 'default', -<<<'TABLE' -+---------------+-----------------+ -| ISBN | Author | -+---------------+-----------------+ -| 9971-5-0210-0 | Dante Alighieri | -| |-----------------| -| | Charles Dickens | -+---------------+-----------------+ - -TABLE - ), - 'Multiple header lines' => array( - array( - array(new TableCell('Main title', array('colspan' => 3))), - array('ISBN', 'Title', 'Author'), - ), - array(), - 'default', -<<<'TABLE' -+------+-------+--------+ -| Main title | -+------+-------+--------+ -| ISBN | Title | Author | -+------+-------+--------+ - -TABLE - ), - 'Row with multiple cells' => array( - array(), - array( - array( - new TableCell('1', array('colspan' => 3)), - new TableCell('2', array('colspan' => 2)), - new TableCell('3', array('colspan' => 2)), - new TableCell('4', array('colspan' => 2)), - ), - ), - 'default', -<<<'TABLE' -+---+--+--+---+--+---+--+---+--+ -| 1 | 2 | 3 | 4 | -+---+--+--+---+--+---+--+---+--+ - -TABLE - ), - 'Coslpan and table cells with comment style' => array( - array( - new TableCell('<comment>Long Title</comment>', array('colspan' => 3)), - ), - array( - array( - new TableCell('9971-5-0210-0', array('colspan' => 3)), - ), - new TableSeparator(), - array( - 'Dante Alighieri', - 'J. R. R. Tolkien', - 'J. R. R', - ), - ), - 'default', - <<<TABLE -+-----------------+------------------+---------+ -|\033[32m \033[39m\033[33mLong Title\033[39m\033[32m \033[39m| -+-----------------+------------------+---------+ -| 9971-5-0210-0 | -+-----------------+------------------+---------+ -| Dante Alighieri | J. R. R. Tolkien | J. R. R | -+-----------------+------------------+---------+ - -TABLE - , - true, - ), - 'Row with formatted cells containing a newline' => array( - array(), - array( - array( - new TableCell('<error>Dont break'."\n".'here</error>', array('colspan' => 2)), - ), - new TableSeparator(), - array( - 'foo', - new TableCell('<error>Dont break'."\n".'here</error>', array('rowspan' => 2)), - ), - array( - 'bar', - ), - ), - 'default', - <<<'TABLE' -+-------+------------+ -| Dont break | -| here | -+-------+------------+ -| foo | Dont break | -| bar | here | -+-------+------------+ - -TABLE - , - true, - ), - ); - } - - public function testRenderMultiByte() - { - $table = new Table($output = $this->getOutputStream()); - $table - ->setHeaders(array('■■')) - ->setRows(array(array(1234))) - ->setStyle('default') - ; - $table->render(); - - $expected = -<<<'TABLE' -+------+ -| ■■ | -+------+ -| 1234 | -+------+ - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - public function testTableCellWithNumericIntValue() - { - $table = new Table($output = $this->getOutputStream()); - - $table->setRows(array(array(new TableCell(12345)))); - $table->render(); - - $expected = -<<<'TABLE' -+-------+ -| 12345 | -+-------+ - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - public function testTableCellWithNumericFloatValue() - { - $table = new Table($output = $this->getOutputStream()); - - $table->setRows(array(array(new TableCell(12345.01)))); - $table->render(); - - $expected = -<<<'TABLE' -+----------+ -| 12345.01 | -+----------+ - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - public function testStyle() - { - $style = new TableStyle(); - $style - ->setHorizontalBorderChar('.') - ->setVerticalBorderChar('.') - ->setCrossingChar('.') - ; - - Table::setStyleDefinition('dotfull', $style); - $table = new Table($output = $this->getOutputStream()); - $table - ->setHeaders(array('Foo')) - ->setRows(array(array('Bar'))) - ->setStyle('dotfull'); - $table->render(); - - $expected = -<<<'TABLE' -....... -. Foo . -....... -. Bar . -....... - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - public function testRowSeparator() - { - $table = new Table($output = $this->getOutputStream()); - $table - ->setHeaders(array('Foo')) - ->setRows(array( - array('Bar1'), - new TableSeparator(), - array('Bar2'), - new TableSeparator(), - array('Bar3'), - )); - $table->render(); - - $expected = -<<<'TABLE' -+------+ -| Foo | -+------+ -| Bar1 | -+------+ -| Bar2 | -+------+ -| Bar3 | -+------+ - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - - $this->assertEquals($table, $table->addRow(new TableSeparator()), 'fluent interface on addRow() with a single TableSeparator() works'); - } - - public function testRenderMultiCalls() - { - $table = new Table($output = $this->getOutputStream()); - $table->setRows(array( - array(new TableCell('foo', array('colspan' => 2))), - )); - $table->render(); - $table->render(); - $table->render(); - - $expected = -<<<TABLE -+----+---+ -| foo | -+----+---+ -+----+---+ -| foo | -+----+---+ -+----+---+ -| foo | -+----+---+ - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - public function testColumnStyle() - { - $table = new Table($output = $this->getOutputStream()); - $table - ->setHeaders(array('ISBN', 'Title', 'Author', 'Price')) - ->setRows(array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'), - array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'), - )); - - $style = new TableStyle(); - $style->setPadType(STR_PAD_LEFT); - $table->setColumnStyle(3, $style); - - $table->render(); - - $expected = - <<<TABLE -+---------------+----------------------+-----------------+--------+ -| ISBN | Title | Author | Price | -+---------------+----------------------+-----------------+--------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 | -| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 | -+---------------+----------------------+-----------------+--------+ - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\InvalidArgumentException - * @expectedExceptionMessage A cell must be a TableCell, a scalar or an object implementing __toString, array given. - */ - public function testThrowsWhenTheCellInAnArray() - { - $table = new Table($output = $this->getOutputStream()); - $table - ->setHeaders(array('ISBN', 'Title', 'Author', 'Price')) - ->setRows(array( - array('99921-58-10-7', array(), 'Dante Alighieri', '9.95'), - )); - - $table->render(); - } - - public function testColumnWith() - { - $table = new Table($output = $this->getOutputStream()); - $table - ->setHeaders(array('ISBN', 'Title', 'Author', 'Price')) - ->setRows(array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'), - array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'), - )) - ->setColumnWidth(0, 15) - ->setColumnWidth(3, 10); - - $style = new TableStyle(); - $style->setPadType(STR_PAD_LEFT); - $table->setColumnStyle(3, $style); - - $table->render(); - - $expected = - <<<TABLE -+-----------------+----------------------+-----------------+------------+ -| ISBN | Title | Author | Price | -+-----------------+----------------------+-----------------+------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 | -| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 | -+-----------------+----------------------+-----------------+------------+ - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - public function testColumnWiths() - { - $table = new Table($output = $this->getOutputStream()); - $table - ->setHeaders(array('ISBN', 'Title', 'Author', 'Price')) - ->setRows(array( - array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri', '9.95'), - array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens', '139.25'), - )) - ->setColumnWidths(array(15, 0, -1, 10)); - - $style = new TableStyle(); - $style->setPadType(STR_PAD_LEFT); - $table->setColumnStyle(3, $style); - - $table->render(); - - $expected = - <<<TABLE -+-----------------+----------------------+-----------------+------------+ -| ISBN | Title | Author | Price | -+-----------------+----------------------+-----------------+------------+ -| 99921-58-10-7 | Divine Comedy | Dante Alighieri | 9.95 | -| 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | 139.25 | -+-----------------+----------------------+-----------------+------------+ - -TABLE; - - $this->assertEquals($expected, $this->getOutputContent($output)); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\InvalidArgumentException - * @expectedExceptionMessage Style "absent" is not defined. - */ - public function testIsNotDefinedStyleException() - { - $table = new Table($this->getOutputStream()); - $table->setStyle('absent'); - } - - /** - * @expectedException \Symfony\Component\Console\Exception\InvalidArgumentException - * @expectedExceptionMessage Style "absent" is not defined. - */ - public function testGetStyleDefinition() - { - Table::getStyleDefinition('absent'); - } - - protected function getOutputStream($decorated = false) - { - return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, $decorated); - } - - protected function getOutputContent(StreamOutput $output) - { - rewind($output->getStream()); - - return str_replace(PHP_EOL, "\n", stream_get_contents($output->getStream())); - } -} diff --git a/vendor/symfony/console/Tests/Input/ArgvInputTest.php b/vendor/symfony/console/Tests/Input/ArgvInputTest.php deleted file mode 100644 index 7574240..0000000 --- a/vendor/symfony/console/Tests/Input/ArgvInputTest.php +++ /dev/null @@ -1,453 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Input; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -class ArgvInputTest extends TestCase -{ - public function testConstructor() - { - $_SERVER['argv'] = array('cli.php', 'foo'); - $input = new ArgvInput(); - $r = new \ReflectionObject($input); - $p = $r->getProperty('tokens'); - $p->setAccessible(true); - - $this->assertEquals(array('foo'), $p->getValue($input), '__construct() automatically get its input from the argv server variable'); - } - - public function testParseArguments() - { - $input = new ArgvInput(array('cli.php', 'foo')); - $input->bind(new InputDefinition(array(new InputArgument('name')))); - $this->assertEquals(array('name' => 'foo'), $input->getArguments(), '->parse() parses required arguments'); - - $input->bind(new InputDefinition(array(new InputArgument('name')))); - $this->assertEquals(array('name' => 'foo'), $input->getArguments(), '->parse() is stateless'); - } - - /** - * @dataProvider provideOptions - */ - public function testParseOptions($input, $options, $expectedOptions, $message) - { - $input = new ArgvInput($input); - $input->bind(new InputDefinition($options)); - - $this->assertSame($expectedOptions, $input->getOptions(), $message); - } - - public function provideOptions() - { - return array( - array( - array('cli.php', '--foo'), - array(new InputOption('foo')), - array('foo' => true), - '->parse() parses long options without a value', - ), - array( - array('cli.php', '--foo=bar'), - array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)), - array('foo' => 'bar'), - '->parse() parses long options with a required value (with a = separator)', - ), - array( - array('cli.php', '--foo', 'bar'), - array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)), - array('foo' => 'bar'), - '->parse() parses long options with a required value (with a space separator)', - ), - array( - array('cli.php', '--foo='), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)), - array('foo' => ''), - '->parse() parses long options with optional value which is empty (with a = separator) as empty string', - ), - array( - array('cli.php', '--foo=', 'bar'), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)), - array('foo' => ''), - '->parse() parses long options with optional value without value specified or an empty string (with a = separator) followed by an argument as empty string', - ), - array( - array('cli.php', 'bar', '--foo'), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)), - array('foo' => null), - '->parse() parses long options with optional value which is empty (with a = separator) preceded by an argument', - ), - array( - array('cli.php', '--foo', '', 'bar'), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)), - array('foo' => ''), - '->parse() parses long options with optional value which is empty as empty string even followed by an argument', - ), - array( - array('cli.php', '--foo'), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)), - array('foo' => null), - '->parse() parses long options with optional value specified with no separator and no value as null', - ), - array( - array('cli.php', '-f'), - array(new InputOption('foo', 'f')), - array('foo' => true), - '->parse() parses short options without a value', - ), - array( - array('cli.php', '-fbar'), - array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)), - array('foo' => 'bar'), - '->parse() parses short options with a required value (with no separator)', - ), - array( - array('cli.php', '-f', 'bar'), - array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)), - array('foo' => 'bar'), - '->parse() parses short options with a required value (with a space separator)', - ), - array( - array('cli.php', '-f', ''), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)), - array('foo' => ''), - '->parse() parses short options with an optional empty value', - ), - array( - array('cli.php', '-f', '', 'foo'), - array(new InputArgument('name'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)), - array('foo' => ''), - '->parse() parses short options with an optional empty value followed by an argument', - ), - array( - array('cli.php', '-f', '', '-b'), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputOption('bar', 'b')), - array('foo' => '', 'bar' => true), - '->parse() parses short options with an optional empty value followed by an option', - ), - array( - array('cli.php', '-f', '-b', 'foo'), - array(new InputArgument('name'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputOption('bar', 'b')), - array('foo' => null, 'bar' => true), - '->parse() parses short options with an optional value which is not present', - ), - array( - array('cli.php', '-fb'), - array(new InputOption('foo', 'f'), new InputOption('bar', 'b')), - array('foo' => true, 'bar' => true), - '->parse() parses short options when they are aggregated as a single one', - ), - array( - array('cli.php', '-fb', 'bar'), - array(new InputOption('foo', 'f'), new InputOption('bar', 'b', InputOption::VALUE_REQUIRED)), - array('foo' => true, 'bar' => 'bar'), - '->parse() parses short options when they are aggregated as a single one and the last one has a required value', - ), - array( - array('cli.php', '-fb', 'bar'), - array(new InputOption('foo', 'f'), new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL)), - array('foo' => true, 'bar' => 'bar'), - '->parse() parses short options when they are aggregated as a single one and the last one has an optional value', - ), - array( - array('cli.php', '-fbbar'), - array(new InputOption('foo', 'f'), new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL)), - array('foo' => true, 'bar' => 'bar'), - '->parse() parses short options when they are aggregated as a single one and the last one has an optional value with no separator', - ), - array( - array('cli.php', '-fbbar'), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL)), - array('foo' => 'bbar', 'bar' => null), - '->parse() parses short options when they are aggregated as a single one and one of them takes a value', - ), - ); - } - - /** - * @dataProvider provideInvalidInput - */ - public function testInvalidInput($argv, $definition, $expectedExceptionMessage) - { - if (method_exists($this, 'expectException')) { - $this->expectException('RuntimeException'); - $this->expectExceptionMessage($expectedExceptionMessage); - } else { - $this->setExpectedException('RuntimeException', $expectedExceptionMessage); - } - - $input = new ArgvInput($argv); - $input->bind($definition); - } - - public function provideInvalidInput() - { - return array( - array( - array('cli.php', '--foo'), - new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED))), - 'The "--foo" option requires a value.', - ), - array( - array('cli.php', '-f'), - new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED))), - 'The "--foo" option requires a value.', - ), - array( - array('cli.php', '-ffoo'), - new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_NONE))), - 'The "-o" option does not exist.', - ), - array( - array('cli.php', '--foo=bar'), - new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_NONE))), - 'The "--foo" option does not accept a value.', - ), - array( - array('cli.php', 'foo', 'bar'), - new InputDefinition(), - 'No arguments expected, got "foo".', - ), - array( - array('cli.php', 'foo', 'bar'), - new InputDefinition(array(new InputArgument('number'))), - 'Too many arguments, expected arguments "number".', - ), - array( - array('cli.php', 'foo', 'bar', 'zzz'), - new InputDefinition(array(new InputArgument('number'), new InputArgument('county'))), - 'Too many arguments, expected arguments "number" "county".', - ), - array( - array('cli.php', '--foo'), - new InputDefinition(), - 'The "--foo" option does not exist.', - ), - array( - array('cli.php', '-f'), - new InputDefinition(), - 'The "-f" option does not exist.', - ), - array( - array('cli.php', '-1'), - new InputDefinition(array(new InputArgument('number'))), - 'The "-1" option does not exist.', - ), - ); - } - - public function testParseArrayArgument() - { - $input = new ArgvInput(array('cli.php', 'foo', 'bar', 'baz', 'bat')); - $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::IS_ARRAY)))); - - $this->assertEquals(array('name' => array('foo', 'bar', 'baz', 'bat')), $input->getArguments(), '->parse() parses array arguments'); - } - - public function testParseArrayOption() - { - $input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name=baz')); - $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)))); - - $this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions(), '->parse() parses array options ("--option=value" syntax)'); - - $input = new ArgvInput(array('cli.php', '--name', 'foo', '--name', 'bar', '--name', 'baz')); - $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)))); - $this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions(), '->parse() parses array options ("--option value" syntax)'); - - $input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name=')); - $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY)))); - $this->assertSame(array('name' => array('foo', 'bar', '')), $input->getOptions(), '->parse() parses empty array options as null ("--option=value" syntax)'); - - $input = new ArgvInput(array('cli.php', '--name', 'foo', '--name', 'bar', '--name', '--anotherOption')); - $input->bind(new InputDefinition(array( - new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY), - new InputOption('anotherOption', null, InputOption::VALUE_NONE), - ))); - $this->assertSame(array('name' => array('foo', 'bar', null), 'anotherOption' => true), $input->getOptions(), '->parse() parses empty array options ("--option value" syntax)'); - } - - public function testParseNegativeNumberAfterDoubleDash() - { - $input = new ArgvInput(array('cli.php', '--', '-1')); - $input->bind(new InputDefinition(array(new InputArgument('number')))); - $this->assertEquals(array('number' => '-1'), $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence'); - - $input = new ArgvInput(array('cli.php', '-f', 'bar', '--', '-1')); - $input->bind(new InputDefinition(array(new InputArgument('number'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)))); - $this->assertEquals(array('foo' => 'bar'), $input->getOptions(), '->parse() parses arguments with leading dashes as options before having encountered a double-dash sequence'); - $this->assertEquals(array('number' => '-1'), $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence'); - } - - public function testParseEmptyStringArgument() - { - $input = new ArgvInput(array('cli.php', '-f', 'bar', '')); - $input->bind(new InputDefinition(array(new InputArgument('empty'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)))); - - $this->assertEquals(array('empty' => ''), $input->getArguments(), '->parse() parses empty string arguments'); - } - - public function testGetFirstArgument() - { - $input = new ArgvInput(array('cli.php', '-fbbar')); - $this->assertNull($input->getFirstArgument(), '->getFirstArgument() returns null when there is no arguments'); - - $input = new ArgvInput(array('cli.php', '-fbbar', 'foo')); - $this->assertEquals('foo', $input->getFirstArgument(), '->getFirstArgument() returns the first argument from the raw input'); - } - - public function testHasParameterOption() - { - $input = new ArgvInput(array('cli.php', '-f', 'foo')); - $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input'); - - $input = new ArgvInput(array('cli.php', '-etest')); - $this->assertTrue($input->hasParameterOption('-e'), '->hasParameterOption() returns true if the given short option is in the raw input'); - $this->assertFalse($input->hasParameterOption('-s'), '->hasParameterOption() returns true if the given short option is in the raw input'); - - $input = new ArgvInput(array('cli.php', '--foo', 'foo')); - $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given short option is in the raw input'); - - $input = new ArgvInput(array('cli.php', 'foo')); - $this->assertFalse($input->hasParameterOption('--foo'), '->hasParameterOption() returns false if the given short option is not in the raw input'); - - $input = new ArgvInput(array('cli.php', '--foo=bar')); - $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given option with provided value is in the raw input'); - } - - public function testHasParameterOptionOnlyOptions() - { - $input = new ArgvInput(array('cli.php', '-f', 'foo')); - $this->assertTrue($input->hasParameterOption('-f', true), '->hasParameterOption() returns true if the given short option is in the raw input'); - - $input = new ArgvInput(array('cli.php', '--foo', '--', 'foo')); - $this->assertTrue($input->hasParameterOption('--foo', true), '->hasParameterOption() returns true if the given long option is in the raw input'); - - $input = new ArgvInput(array('cli.php', '--foo=bar', 'foo')); - $this->assertTrue($input->hasParameterOption('--foo', true), '->hasParameterOption() returns true if the given long option with provided value is in the raw input'); - - $input = new ArgvInput(array('cli.php', '--', '--foo')); - $this->assertFalse($input->hasParameterOption('--foo', true), '->hasParameterOption() returns false if the given option is in the raw input but after an end of options signal'); - } - - public function testHasParameterOptionEdgeCasesAndLimitations() - { - $input = new ArgvInput(array('cli.php', '-fh')); - // hasParameterOption does not know if the previous short option, -f, - // takes a value or not. If -f takes a value, then -fh does NOT include - // -h; Otherwise it does. Since we do not know which short options take - // values, hasParameterOption does not support this use-case. - $this->assertFalse($input->hasParameterOption('-h'), '->hasParameterOption() returns true if the given short option is in the raw input'); - // hasParameterOption does detect that `-fh` contains `-f`, since - // `-f` is the first short option in the set. - $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input'); - // The test below happens to pass, although it might make more sense - // to disallow it, and require the use of - // $input->hasParameterOption('-f') && $input->hasParameterOption('-h') - // instead. - $this->assertTrue($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input'); - // In theory, if -fh is supported, then -hf should also work. - // However, this is not supported. - $this->assertFalse($input->hasParameterOption('-hf'), '->hasParameterOption() returns true if the given short option is in the raw input'); - - $input = new ArgvInput(array('cli.php', '-f', '-h')); - // If hasParameterOption('-fh') is supported for 'cli.php -fh', then - // one might also expect that it should also be supported for - // 'cli.php -f -h'. However, this is not supported. - $this->assertFalse($input->hasParameterOption('-fh'), '->hasParameterOption() returns true if the given short option is in the raw input'); - } - - public function testNoWarningOnInvalidParameterOption() - { - $input = new ArgvInput(array('cli.php', '-edev')); - - $this->assertTrue($input->hasParameterOption(array('-e', ''))); - // No warning thrown - $this->assertFalse($input->hasParameterOption(array('-m', ''))); - - $this->assertEquals('dev', $input->getParameterOption(array('-e', ''))); - // No warning thrown - $this->assertFalse($input->getParameterOption(array('-m', ''))); - } - - public function testToString() - { - $input = new ArgvInput(array('cli.php', '-f', 'foo')); - $this->assertEquals('-f foo', (string) $input); - - $input = new ArgvInput(array('cli.php', '-f', '--bar=foo', 'a b c d', "A\nB'C")); - $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d').' '.escapeshellarg("A\nB'C"), (string) $input); - } - - /** - * @dataProvider provideGetParameterOptionValues - */ - public function testGetParameterOptionEqualSign($argv, $key, $default, $onlyParams, $expected) - { - $input = new ArgvInput($argv); - $this->assertEquals($expected, $input->getParameterOption($key, $default, $onlyParams), '->getParameterOption() returns the expected value'); - } - - public function provideGetParameterOptionValues() - { - return array( - array(array('app/console', 'foo:bar'), '-e', 'default', false, 'default'), - array(array('app/console', 'foo:bar', '-e', 'dev'), '-e', 'default', false, 'dev'), - array(array('app/console', 'foo:bar', '--env=dev'), '--env', 'default', false, 'dev'), - array(array('app/console', 'foo:bar', '-e', 'dev'), array('-e', '--env'), 'default', false, 'dev'), - array(array('app/console', 'foo:bar', '--env=dev'), array('-e', '--env'), 'default', false, 'dev'), - array(array('app/console', 'foo:bar', '--env=dev', '--en=1'), array('--en'), 'default', false, '1'), - array(array('app/console', 'foo:bar', '--env=dev', '', '--en=1'), array('--en'), 'default', false, '1'), - array(array('app/console', 'foo:bar', '--env', 'val'), '--env', 'default', false, 'val'), - array(array('app/console', 'foo:bar', '--env', 'val', '--dummy'), '--env', 'default', false, 'val'), - array(array('app/console', 'foo:bar', '--', '--env=dev'), '--env', 'default', false, 'dev'), - array(array('app/console', 'foo:bar', '--', '--env=dev'), '--env', 'default', true, 'default'), - ); - } - - public function testParseSingleDashAsArgument() - { - $input = new ArgvInput(array('cli.php', '-')); - $input->bind(new InputDefinition(array(new InputArgument('file')))); - $this->assertEquals(array('file' => '-'), $input->getArguments(), '->parse() parses single dash as an argument'); - } - - public function testParseOptionWithValueOptionalGivenEmptyAndRequiredArgument() - { - $input = new ArgvInput(array('cli.php', '--foo=', 'bar')); - $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)))); - $this->assertEquals(array('foo' => null), $input->getOptions(), '->parse() parses optional options with empty value as null'); - $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses required arguments'); - - $input = new ArgvInput(array('cli.php', '--foo=0', 'bar')); - $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::REQUIRED)))); - $this->assertEquals(array('foo' => '0'), $input->getOptions(), '->parse() parses optional options with empty value as null'); - $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses required arguments'); - } - - public function testParseOptionWithValueOptionalGivenEmptyAndOptionalArgument() - { - $input = new ArgvInput(array('cli.php', '--foo=', 'bar')); - $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL)))); - $this->assertEquals(array('foo' => null), $input->getOptions(), '->parse() parses optional options with empty value as null'); - $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses optional arguments'); - - $input = new ArgvInput(array('cli.php', '--foo=0', 'bar')); - $input->bind(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputArgument('name', InputArgument::OPTIONAL)))); - $this->assertEquals(array('foo' => '0'), $input->getOptions(), '->parse() parses optional options with empty value as null'); - $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->parse() parses optional arguments'); - } -} diff --git a/vendor/symfony/console/Tests/Input/ArrayInputTest.php b/vendor/symfony/console/Tests/Input/ArrayInputTest.php deleted file mode 100644 index 4bc83b3..0000000 --- a/vendor/symfony/console/Tests/Input/ArrayInputTest.php +++ /dev/null @@ -1,177 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Input; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -class ArrayInputTest extends TestCase -{ - public function testGetFirstArgument() - { - $input = new ArrayInput(array()); - $this->assertNull($input->getFirstArgument(), '->getFirstArgument() returns null if no argument were passed'); - $input = new ArrayInput(array('name' => 'Fabien')); - $this->assertEquals('Fabien', $input->getFirstArgument(), '->getFirstArgument() returns the first passed argument'); - $input = new ArrayInput(array('--foo' => 'bar', 'name' => 'Fabien')); - $this->assertEquals('Fabien', $input->getFirstArgument(), '->getFirstArgument() returns the first passed argument'); - } - - public function testHasParameterOption() - { - $input = new ArrayInput(array('name' => 'Fabien', '--foo' => 'bar')); - $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if an option is present in the passed parameters'); - $this->assertFalse($input->hasParameterOption('--bar'), '->hasParameterOption() returns false if an option is not present in the passed parameters'); - - $input = new ArrayInput(array('--foo')); - $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if an option is present in the passed parameters'); - - $input = new ArrayInput(array('--foo', '--', '--bar')); - $this->assertTrue($input->hasParameterOption('--bar'), '->hasParameterOption() returns true if an option is present in the passed parameters'); - $this->assertFalse($input->hasParameterOption('--bar', true), '->hasParameterOption() returns false if an option is present in the passed parameters after an end of options signal'); - } - - public function testGetParameterOption() - { - $input = new ArrayInput(array('name' => 'Fabien', '--foo' => 'bar')); - $this->assertEquals('bar', $input->getParameterOption('--foo'), '->getParameterOption() returns the option of specified name'); - $this->assertEquals('default', $input->getParameterOption('--bar', 'default'), '->getParameterOption() returns the default value if an option is not present in the passed parameters'); - - $input = new ArrayInput(array('Fabien', '--foo' => 'bar')); - $this->assertEquals('bar', $input->getParameterOption('--foo'), '->getParameterOption() returns the option of specified name'); - - $input = new ArrayInput(array('--foo', '--', '--bar' => 'woop')); - $this->assertEquals('woop', $input->getParameterOption('--bar'), '->getParameterOption() returns the correct value if an option is present in the passed parameters'); - $this->assertEquals('default', $input->getParameterOption('--bar', 'default', true), '->getParameterOption() returns the default value if an option is present in the passed parameters after an end of options signal'); - } - - public function testParseArguments() - { - $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name')))); - - $this->assertEquals(array('name' => 'foo'), $input->getArguments(), '->parse() parses required arguments'); - } - - /** - * @dataProvider provideOptions - */ - public function testParseOptions($input, $options, $expectedOptions, $message) - { - $input = new ArrayInput($input, new InputDefinition($options)); - - $this->assertEquals($expectedOptions, $input->getOptions(), $message); - } - - public function provideOptions() - { - return array( - array( - array('--foo' => 'bar'), - array(new InputOption('foo')), - array('foo' => 'bar'), - '->parse() parses long options', - ), - array( - array('--foo' => 'bar'), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')), - array('foo' => 'bar'), - '->parse() parses long options with a default value', - ), - array( - array(), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')), - array('foo' => 'default'), - '->parse() uses the default value for long options with value optional which are not passed', - ), - array( - array('--foo' => null), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')), - array('foo' => null), - '->parse() parses long options with a default value', - ), - array( - array('-f' => 'bar'), - array(new InputOption('foo', 'f')), - array('foo' => 'bar'), - '->parse() parses short options', - ), - array( - array('--' => null, '-f' => 'bar'), - array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')), - array('foo' => 'default'), - '->parse() does not parse opts after an end of options signal', - ), - array( - array('--' => null), - array(), - array(), - '->parse() does not choke on end of options signal', - ), - ); - } - - /** - * @dataProvider provideInvalidInput - */ - public function testParseInvalidInput($parameters, $definition, $expectedExceptionMessage) - { - if (method_exists($this, 'expectException')) { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage($expectedExceptionMessage); - } else { - $this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage); - } - - new ArrayInput($parameters, $definition); - } - - public function provideInvalidInput() - { - return array( - array( - array('foo' => 'foo'), - new InputDefinition(array(new InputArgument('name'))), - 'The "foo" argument does not exist.', - ), - array( - array('--foo' => null), - new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED))), - 'The "--foo" option requires a value.', - ), - array( - array('--foo' => 'foo'), - new InputDefinition(), - 'The "--foo" option does not exist.', - ), - array( - array('-o' => 'foo'), - new InputDefinition(), - 'The "-o" option does not exist.', - ), - ); - } - - public function testToString() - { - $input = new ArrayInput(array('-f' => null, '-b' => 'bar', '--foo' => 'b a z', '--lala' => null, 'test' => 'Foo', 'test2' => "A\nB'C")); - $this->assertEquals('-f -b=bar --foo='.escapeshellarg('b a z').' --lala Foo '.escapeshellarg("A\nB'C"), (string) $input); - - $input = new ArrayInput(array('-b' => array('bval_1', 'bval_2'), '--f' => array('fval_1', 'fval_2'))); - $this->assertSame('-b=bval_1 -b=bval_2 --f=fval_1 --f=fval_2', (string) $input); - - $input = new ArrayInput(array('array_arg' => array('val_1', 'val_2'))); - $this->assertSame('val_1 val_2', (string) $input); - } -} diff --git a/vendor/symfony/console/Tests/Input/InputArgumentTest.php b/vendor/symfony/console/Tests/Input/InputArgumentTest.php deleted file mode 100644 index 66af98b..0000000 --- a/vendor/symfony/console/Tests/Input/InputArgumentTest.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Input; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Input\InputArgument; - -class InputArgumentTest extends TestCase -{ - public function testConstructor() - { - $argument = new InputArgument('foo'); - $this->assertEquals('foo', $argument->getName(), '__construct() takes a name as its first argument'); - } - - public function testModes() - { - $argument = new InputArgument('foo'); - $this->assertFalse($argument->isRequired(), '__construct() gives a "InputArgument::OPTIONAL" mode by default'); - - $argument = new InputArgument('foo', null); - $this->assertFalse($argument->isRequired(), '__construct() can take "InputArgument::OPTIONAL" as its mode'); - - $argument = new InputArgument('foo', InputArgument::OPTIONAL); - $this->assertFalse($argument->isRequired(), '__construct() can take "InputArgument::OPTIONAL" as its mode'); - - $argument = new InputArgument('foo', InputArgument::REQUIRED); - $this->assertTrue($argument->isRequired(), '__construct() can take "InputArgument::REQUIRED" as its mode'); - } - - /** - * @dataProvider provideInvalidModes - */ - public function testInvalidModes($mode) - { - if (method_exists($this, 'expectException')) { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage(sprintf('Argument mode "%s" is not valid.', $mode)); - } else { - $this->setExpectedException('InvalidArgumentException', sprintf('Argument mode "%s" is not valid.', $mode)); - } - - new InputArgument('foo', $mode); - } - - public function provideInvalidModes() - { - return array( - array('ANOTHER_ONE'), - array(-1), - ); - } - - public function testIsArray() - { - $argument = new InputArgument('foo', InputArgument::IS_ARRAY); - $this->assertTrue($argument->isArray(), '->isArray() returns true if the argument can be an array'); - $argument = new InputArgument('foo', InputArgument::OPTIONAL | InputArgument::IS_ARRAY); - $this->assertTrue($argument->isArray(), '->isArray() returns true if the argument can be an array'); - $argument = new InputArgument('foo', InputArgument::OPTIONAL); - $this->assertFalse($argument->isArray(), '->isArray() returns false if the argument can not be an array'); - } - - public function testGetDescription() - { - $argument = new InputArgument('foo', null, 'Some description'); - $this->assertEquals('Some description', $argument->getDescription(), '->getDescription() return the message description'); - } - - public function testGetDefault() - { - $argument = new InputArgument('foo', InputArgument::OPTIONAL, '', 'default'); - $this->assertEquals('default', $argument->getDefault(), '->getDefault() return the default value'); - } - - public function testSetDefault() - { - $argument = new InputArgument('foo', InputArgument::OPTIONAL, '', 'default'); - $argument->setDefault(null); - $this->assertNull($argument->getDefault(), '->setDefault() can reset the default value by passing null'); - $argument->setDefault('another'); - $this->assertEquals('another', $argument->getDefault(), '->setDefault() changes the default value'); - - $argument = new InputArgument('foo', InputArgument::OPTIONAL | InputArgument::IS_ARRAY); - $argument->setDefault(array(1, 2)); - $this->assertEquals(array(1, 2), $argument->getDefault(), '->setDefault() changes the default value'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Cannot set a default value except for InputArgument::OPTIONAL mode. - */ - public function testSetDefaultWithRequiredArgument() - { - $argument = new InputArgument('foo', InputArgument::REQUIRED); - $argument->setDefault('default'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage A default value for an array argument must be an array. - */ - public function testSetDefaultWithArrayArgument() - { - $argument = new InputArgument('foo', InputArgument::IS_ARRAY); - $argument->setDefault('default'); - } -} diff --git a/vendor/symfony/console/Tests/Input/InputDefinitionTest.php b/vendor/symfony/console/Tests/Input/InputDefinitionTest.php deleted file mode 100644 index d9ff543..0000000 --- a/vendor/symfony/console/Tests/Input/InputDefinitionTest.php +++ /dev/null @@ -1,406 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Input; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -class InputDefinitionTest extends TestCase -{ - protected static $fixtures; - - protected $foo; - protected $bar; - protected $foo1; - protected $foo2; - - public static function setUpBeforeClass() - { - self::$fixtures = __DIR__.'/../Fixtures/'; - } - - public function testConstructorArguments() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $this->assertEquals(array(), $definition->getArguments(), '__construct() creates a new InputDefinition object'); - - $definition = new InputDefinition(array($this->foo, $this->bar)); - $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getArguments(), '__construct() takes an array of InputArgument objects as its first argument'); - } - - public function testConstructorOptions() - { - $this->initializeOptions(); - - $definition = new InputDefinition(); - $this->assertEquals(array(), $definition->getOptions(), '__construct() creates a new InputDefinition object'); - - $definition = new InputDefinition(array($this->foo, $this->bar)); - $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getOptions(), '__construct() takes an array of InputOption objects as its first argument'); - } - - public function testSetArguments() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->setArguments(array($this->foo)); - $this->assertEquals(array('foo' => $this->foo), $definition->getArguments(), '->setArguments() sets the array of InputArgument objects'); - $definition->setArguments(array($this->bar)); - - $this->assertEquals(array('bar' => $this->bar), $definition->getArguments(), '->setArguments() clears all InputArgument objects'); - } - - public function testAddArguments() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->addArguments(array($this->foo)); - $this->assertEquals(array('foo' => $this->foo), $definition->getArguments(), '->addArguments() adds an array of InputArgument objects'); - $definition->addArguments(array($this->bar)); - $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getArguments(), '->addArguments() does not clear existing InputArgument objects'); - } - - public function testAddArgument() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->addArgument($this->foo); - $this->assertEquals(array('foo' => $this->foo), $definition->getArguments(), '->addArgument() adds a InputArgument object'); - $definition->addArgument($this->bar); - $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getArguments(), '->addArgument() adds a InputArgument object'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage An argument with name "foo" already exists. - */ - public function testArgumentsMustHaveDifferentNames() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->addArgument($this->foo); - $definition->addArgument($this->foo1); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Cannot add an argument after an array argument. - */ - public function testArrayArgumentHasToBeLast() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->addArgument(new InputArgument('fooarray', InputArgument::IS_ARRAY)); - $definition->addArgument(new InputArgument('anotherbar')); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Cannot add a required argument after an optional one. - */ - public function testRequiredArgumentCannotFollowAnOptionalOne() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->addArgument($this->foo); - $definition->addArgument($this->foo2); - } - - public function testGetArgument() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->addArguments(array($this->foo)); - $this->assertEquals($this->foo, $definition->getArgument('foo'), '->getArgument() returns a InputArgument by its name'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The "bar" argument does not exist. - */ - public function testGetInvalidArgument() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->addArguments(array($this->foo)); - $definition->getArgument('bar'); - } - - public function testHasArgument() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->addArguments(array($this->foo)); - - $this->assertTrue($definition->hasArgument('foo'), '->hasArgument() returns true if a InputArgument exists for the given name'); - $this->assertFalse($definition->hasArgument('bar'), '->hasArgument() returns false if a InputArgument exists for the given name'); - } - - public function testGetArgumentRequiredCount() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->addArgument($this->foo2); - $this->assertEquals(1, $definition->getArgumentRequiredCount(), '->getArgumentRequiredCount() returns the number of required arguments'); - $definition->addArgument($this->foo); - $this->assertEquals(1, $definition->getArgumentRequiredCount(), '->getArgumentRequiredCount() returns the number of required arguments'); - } - - public function testGetArgumentCount() - { - $this->initializeArguments(); - - $definition = new InputDefinition(); - $definition->addArgument($this->foo2); - $this->assertEquals(1, $definition->getArgumentCount(), '->getArgumentCount() returns the number of arguments'); - $definition->addArgument($this->foo); - $this->assertEquals(2, $definition->getArgumentCount(), '->getArgumentCount() returns the number of arguments'); - } - - public function testGetArgumentDefaults() - { - $definition = new InputDefinition(array( - new InputArgument('foo1', InputArgument::OPTIONAL), - new InputArgument('foo2', InputArgument::OPTIONAL, '', 'default'), - new InputArgument('foo3', InputArgument::OPTIONAL | InputArgument::IS_ARRAY), - // new InputArgument('foo4', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, '', array(1, 2)), - )); - $this->assertEquals(array('foo1' => null, 'foo2' => 'default', 'foo3' => array()), $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument'); - - $definition = new InputDefinition(array( - new InputArgument('foo4', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, '', array(1, 2)), - )); - $this->assertEquals(array('foo4' => array(1, 2)), $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument'); - } - - public function testSetOptions() - { - $this->initializeOptions(); - - $definition = new InputDefinition(array($this->foo)); - $this->assertEquals(array('foo' => $this->foo), $definition->getOptions(), '->setOptions() sets the array of InputOption objects'); - $definition->setOptions(array($this->bar)); - $this->assertEquals(array('bar' => $this->bar), $definition->getOptions(), '->setOptions() clears all InputOption objects'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The "-f" option does not exist. - */ - public function testSetOptionsClearsOptions() - { - $this->initializeOptions(); - - $definition = new InputDefinition(array($this->foo)); - $definition->setOptions(array($this->bar)); - $definition->getOptionForShortcut('f'); - } - - public function testAddOptions() - { - $this->initializeOptions(); - - $definition = new InputDefinition(array($this->foo)); - $this->assertEquals(array('foo' => $this->foo), $definition->getOptions(), '->addOptions() adds an array of InputOption objects'); - $definition->addOptions(array($this->bar)); - $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getOptions(), '->addOptions() does not clear existing InputOption objects'); - } - - public function testAddOption() - { - $this->initializeOptions(); - - $definition = new InputDefinition(); - $definition->addOption($this->foo); - $this->assertEquals(array('foo' => $this->foo), $definition->getOptions(), '->addOption() adds a InputOption object'); - $definition->addOption($this->bar); - $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getOptions(), '->addOption() adds a InputOption object'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage An option named "foo" already exists. - */ - public function testAddDuplicateOption() - { - $this->initializeOptions(); - - $definition = new InputDefinition(); - $definition->addOption($this->foo); - $definition->addOption($this->foo2); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage An option with shortcut "f" already exists. - */ - public function testAddDuplicateShortcutOption() - { - $this->initializeOptions(); - - $definition = new InputDefinition(); - $definition->addOption($this->foo); - $definition->addOption($this->foo1); - } - - public function testGetOption() - { - $this->initializeOptions(); - - $definition = new InputDefinition(array($this->foo)); - $this->assertEquals($this->foo, $definition->getOption('foo'), '->getOption() returns a InputOption by its name'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The "--bar" option does not exist. - */ - public function testGetInvalidOption() - { - $this->initializeOptions(); - - $definition = new InputDefinition(array($this->foo)); - $definition->getOption('bar'); - } - - public function testHasOption() - { - $this->initializeOptions(); - - $definition = new InputDefinition(array($this->foo)); - $this->assertTrue($definition->hasOption('foo'), '->hasOption() returns true if a InputOption exists for the given name'); - $this->assertFalse($definition->hasOption('bar'), '->hasOption() returns false if a InputOption exists for the given name'); - } - - public function testHasShortcut() - { - $this->initializeOptions(); - - $definition = new InputDefinition(array($this->foo)); - $this->assertTrue($definition->hasShortcut('f'), '->hasShortcut() returns true if a InputOption exists for the given shortcut'); - $this->assertFalse($definition->hasShortcut('b'), '->hasShortcut() returns false if a InputOption exists for the given shortcut'); - } - - public function testGetOptionForShortcut() - { - $this->initializeOptions(); - - $definition = new InputDefinition(array($this->foo)); - $this->assertEquals($this->foo, $definition->getOptionForShortcut('f'), '->getOptionForShortcut() returns a InputOption by its shortcut'); - } - - public function testGetOptionForMultiShortcut() - { - $this->initializeOptions(); - - $definition = new InputDefinition(array($this->multi)); - $this->assertEquals($this->multi, $definition->getOptionForShortcut('m'), '->getOptionForShortcut() returns a InputOption by its shortcut'); - $this->assertEquals($this->multi, $definition->getOptionForShortcut('mmm'), '->getOptionForShortcut() returns a InputOption by its shortcut'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The "-l" option does not exist. - */ - public function testGetOptionForInvalidShortcut() - { - $this->initializeOptions(); - - $definition = new InputDefinition(array($this->foo)); - $definition->getOptionForShortcut('l'); - } - - public function testGetOptionDefaults() - { - $definition = new InputDefinition(array( - new InputOption('foo1', null, InputOption::VALUE_NONE), - new InputOption('foo2', null, InputOption::VALUE_REQUIRED), - new InputOption('foo3', null, InputOption::VALUE_REQUIRED, '', 'default'), - new InputOption('foo4', null, InputOption::VALUE_OPTIONAL), - new InputOption('foo5', null, InputOption::VALUE_OPTIONAL, '', 'default'), - new InputOption('foo6', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY), - new InputOption('foo7', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, '', array(1, 2)), - )); - $defaults = array( - 'foo1' => false, - 'foo2' => null, - 'foo3' => 'default', - 'foo4' => null, - 'foo5' => 'default', - 'foo6' => array(), - 'foo7' => array(1, 2), - ); - $this->assertSame($defaults, $definition->getOptionDefaults(), '->getOptionDefaults() returns the default values for all options'); - } - - /** - * @dataProvider getGetSynopsisData - */ - public function testGetSynopsis(InputDefinition $definition, $expectedSynopsis, $message = null) - { - $this->assertEquals($expectedSynopsis, $definition->getSynopsis(), $message ? '->getSynopsis() '.$message : ''); - } - - public function getGetSynopsisData() - { - return array( - array(new InputDefinition(array(new InputOption('foo'))), '[--foo]', 'puts optional options in square brackets'), - array(new InputDefinition(array(new InputOption('foo', 'f'))), '[-f|--foo]', 'separates shortcut with a pipe'), - array(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED))), '[-f|--foo FOO]', 'uses shortcut as value placeholder'), - array(new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL))), '[-f|--foo [FOO]]', 'puts optional values in square brackets'), - - array(new InputDefinition(array(new InputArgument('foo', InputArgument::REQUIRED))), '<foo>', 'puts arguments in angle brackets'), - array(new InputDefinition(array(new InputArgument('foo'))), '[<foo>]', 'puts optional arguments in square brackets'), - array(new InputDefinition(array(new InputArgument('foo', InputArgument::IS_ARRAY))), '[<foo>]...', 'uses an ellipsis for array arguments'), - array(new InputDefinition(array(new InputArgument('foo', InputArgument::REQUIRED | InputArgument::IS_ARRAY))), '<foo> (<foo>)...', 'uses parenthesis and ellipsis for required array arguments'), - - array(new InputDefinition(array(new InputOption('foo'), new InputArgument('foo', InputArgument::REQUIRED))), '[--foo] [--] <foo>', 'puts [--] between options and arguments'), - ); - } - - public function testGetShortSynopsis() - { - $definition = new InputDefinition(array(new InputOption('foo'), new InputOption('bar'), new InputArgument('cat'))); - $this->assertEquals('[options] [--] [<cat>]', $definition->getSynopsis(true), '->getSynopsis(true) groups options in [options]'); - } - - protected function initializeArguments() - { - $this->foo = new InputArgument('foo'); - $this->bar = new InputArgument('bar'); - $this->foo1 = new InputArgument('foo'); - $this->foo2 = new InputArgument('foo2', InputArgument::REQUIRED); - } - - protected function initializeOptions() - { - $this->foo = new InputOption('foo', 'f'); - $this->bar = new InputOption('bar', 'b'); - $this->foo1 = new InputOption('fooBis', 'f'); - $this->foo2 = new InputOption('foo', 'p'); - $this->multi = new InputOption('multi', 'm|mm|mmm'); - } -} diff --git a/vendor/symfony/console/Tests/Input/InputOptionTest.php b/vendor/symfony/console/Tests/Input/InputOptionTest.php deleted file mode 100644 index 943bf60..0000000 --- a/vendor/symfony/console/Tests/Input/InputOptionTest.php +++ /dev/null @@ -1,210 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Input; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Input\InputOption; - -class InputOptionTest extends TestCase -{ - public function testConstructor() - { - $option = new InputOption('foo'); - $this->assertEquals('foo', $option->getName(), '__construct() takes a name as its first argument'); - $option = new InputOption('--foo'); - $this->assertEquals('foo', $option->getName(), '__construct() removes the leading -- of the option name'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value. - */ - public function testArrayModeWithoutValue() - { - new InputOption('foo', 'f', InputOption::VALUE_IS_ARRAY); - } - - public function testShortcut() - { - $option = new InputOption('foo', 'f'); - $this->assertEquals('f', $option->getShortcut(), '__construct() can take a shortcut as its second argument'); - $option = new InputOption('foo', '-f|-ff|fff'); - $this->assertEquals('f|ff|fff', $option->getShortcut(), '__construct() removes the leading - of the shortcuts'); - $option = new InputOption('foo', array('f', 'ff', '-fff')); - $this->assertEquals('f|ff|fff', $option->getShortcut(), '__construct() removes the leading - of the shortcuts'); - $option = new InputOption('foo'); - $this->assertNull($option->getShortcut(), '__construct() makes the shortcut null by default'); - } - - public function testModes() - { - $option = new InputOption('foo', 'f'); - $this->assertFalse($option->acceptValue(), '__construct() gives a "InputOption::VALUE_NONE" mode by default'); - $this->assertFalse($option->isValueRequired(), '__construct() gives a "InputOption::VALUE_NONE" mode by default'); - $this->assertFalse($option->isValueOptional(), '__construct() gives a "InputOption::VALUE_NONE" mode by default'); - - $option = new InputOption('foo', 'f', null); - $this->assertFalse($option->acceptValue(), '__construct() can take "InputOption::VALUE_NONE" as its mode'); - $this->assertFalse($option->isValueRequired(), '__construct() can take "InputOption::VALUE_NONE" as its mode'); - $this->assertFalse($option->isValueOptional(), '__construct() can take "InputOption::VALUE_NONE" as its mode'); - - $option = new InputOption('foo', 'f', InputOption::VALUE_NONE); - $this->assertFalse($option->acceptValue(), '__construct() can take "InputOption::VALUE_NONE" as its mode'); - $this->assertFalse($option->isValueRequired(), '__construct() can take "InputOption::VALUE_NONE" as its mode'); - $this->assertFalse($option->isValueOptional(), '__construct() can take "InputOption::VALUE_NONE" as its mode'); - - $option = new InputOption('foo', 'f', InputOption::VALUE_REQUIRED); - $this->assertTrue($option->acceptValue(), '__construct() can take "InputOption::VALUE_REQUIRED" as its mode'); - $this->assertTrue($option->isValueRequired(), '__construct() can take "InputOption::VALUE_REQUIRED" as its mode'); - $this->assertFalse($option->isValueOptional(), '__construct() can take "InputOption::VALUE_REQUIRED" as its mode'); - - $option = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL); - $this->assertTrue($option->acceptValue(), '__construct() can take "InputOption::VALUE_OPTIONAL" as its mode'); - $this->assertFalse($option->isValueRequired(), '__construct() can take "InputOption::VALUE_OPTIONAL" as its mode'); - $this->assertTrue($option->isValueOptional(), '__construct() can take "InputOption::VALUE_OPTIONAL" as its mode'); - } - - /** - * @dataProvider provideInvalidModes - */ - public function testInvalidModes($mode) - { - if (method_exists($this, 'expectException')) { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage(sprintf('Option mode "%s" is not valid.', $mode)); - } else { - $this->setExpectedException('InvalidArgumentException', sprintf('Option mode "%s" is not valid.', $mode)); - } - - new InputOption('foo', 'f', $mode); - } - - public function provideInvalidModes() - { - return array( - array('ANOTHER_ONE'), - array(-1), - ); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testEmptyNameIsInvalid() - { - new InputOption(''); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testDoubleDashNameIsInvalid() - { - new InputOption('--'); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testSingleDashOptionIsInvalid() - { - new InputOption('foo', '-'); - } - - public function testIsArray() - { - $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY); - $this->assertTrue($option->isArray(), '->isArray() returns true if the option can be an array'); - $option = new InputOption('foo', null, InputOption::VALUE_NONE); - $this->assertFalse($option->isArray(), '->isArray() returns false if the option can not be an array'); - } - - public function testGetDescription() - { - $option = new InputOption('foo', 'f', null, 'Some description'); - $this->assertEquals('Some description', $option->getDescription(), '->getDescription() returns the description message'); - } - - public function testGetDefault() - { - $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL, '', 'default'); - $this->assertEquals('default', $option->getDefault(), '->getDefault() returns the default value'); - - $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED, '', 'default'); - $this->assertEquals('default', $option->getDefault(), '->getDefault() returns the default value'); - - $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED); - $this->assertNull($option->getDefault(), '->getDefault() returns null if no default value is configured'); - - $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY); - $this->assertEquals(array(), $option->getDefault(), '->getDefault() returns an empty array if option is an array'); - - $option = new InputOption('foo', null, InputOption::VALUE_NONE); - $this->assertFalse($option->getDefault(), '->getDefault() returns false if the option does not take a value'); - } - - public function testSetDefault() - { - $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED, '', 'default'); - $option->setDefault(null); - $this->assertNull($option->getDefault(), '->setDefault() can reset the default value by passing null'); - $option->setDefault('another'); - $this->assertEquals('another', $option->getDefault(), '->setDefault() changes the default value'); - - $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY); - $option->setDefault(array(1, 2)); - $this->assertEquals(array(1, 2), $option->getDefault(), '->setDefault() changes the default value'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage Cannot set a default value when using InputOption::VALUE_NONE mode. - */ - public function testDefaultValueWithValueNoneMode() - { - $option = new InputOption('foo', 'f', InputOption::VALUE_NONE); - $option->setDefault('default'); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage A default value for an array option must be an array. - */ - public function testDefaultValueWithIsArrayMode() - { - $option = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY); - $option->setDefault('default'); - } - - public function testEquals() - { - $option = new InputOption('foo', 'f', null, 'Some description'); - $option2 = new InputOption('foo', 'f', null, 'Alternative description'); - $this->assertTrue($option->equals($option2)); - - $option = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, 'Some description'); - $option2 = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, 'Some description', true); - $this->assertFalse($option->equals($option2)); - - $option = new InputOption('foo', 'f', null, 'Some description'); - $option2 = new InputOption('bar', 'f', null, 'Some description'); - $this->assertFalse($option->equals($option2)); - - $option = new InputOption('foo', 'f', null, 'Some description'); - $option2 = new InputOption('foo', '', null, 'Some description'); - $this->assertFalse($option->equals($option2)); - - $option = new InputOption('foo', 'f', null, 'Some description'); - $option2 = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, 'Some description'); - $this->assertFalse($option->equals($option2)); - } -} diff --git a/vendor/symfony/console/Tests/Input/InputTest.php b/vendor/symfony/console/Tests/Input/InputTest.php deleted file mode 100644 index 7cf1d24..0000000 --- a/vendor/symfony/console/Tests/Input/InputTest.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Input; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -class InputTest extends TestCase -{ - public function testConstructor() - { - $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name')))); - $this->assertEquals('foo', $input->getArgument('name'), '->__construct() takes a InputDefinition as an argument'); - } - - public function testOptions() - { - $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name')))); - $this->assertEquals('foo', $input->getOption('name'), '->getOption() returns the value for the given option'); - - $input->setOption('name', 'bar'); - $this->assertEquals('bar', $input->getOption('name'), '->setOption() sets the value for a given option'); - $this->assertEquals(array('name' => 'bar'), $input->getOptions(), '->getOptions() returns all option values'); - - $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')))); - $this->assertEquals('default', $input->getOption('bar'), '->getOption() returns the default value for optional options'); - $this->assertEquals(array('name' => 'foo', 'bar' => 'default'), $input->getOptions(), '->getOptions() returns all option values, even optional ones'); - - $input = new ArrayInput(array('--name' => 'foo', '--bar' => ''), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')))); - $this->assertEquals('', $input->getOption('bar'), '->getOption() returns null for options explicitly passed without value (or an empty value)'); - $this->assertEquals(array('name' => 'foo', 'bar' => ''), $input->getOptions(), '->getOptions() returns all option values.'); - - $input = new ArrayInput(array('--name' => 'foo', '--bar' => null), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')))); - $this->assertNull($input->getOption('bar'), '->getOption() returns null for options explicitly passed without value (or an empty value)'); - $this->assertEquals(array('name' => 'foo', 'bar' => null), $input->getOptions(), '->getOptions() returns all option values'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The "foo" option does not exist. - */ - public function testSetInvalidOption() - { - $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')))); - $input->setOption('foo', 'bar'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The "foo" option does not exist. - */ - public function testGetInvalidOption() - { - $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default')))); - $input->getOption('foo'); - } - - public function testArguments() - { - $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name')))); - $this->assertEquals('foo', $input->getArgument('name'), '->getArgument() returns the value for the given argument'); - - $input->setArgument('name', 'bar'); - $this->assertEquals('bar', $input->getArgument('name'), '->setArgument() sets the value for a given argument'); - $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->getArguments() returns all argument values'); - - $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'), new InputArgument('bar', InputArgument::OPTIONAL, '', 'default')))); - $this->assertEquals('default', $input->getArgument('bar'), '->getArgument() returns the default value for optional arguments'); - $this->assertEquals(array('name' => 'foo', 'bar' => 'default'), $input->getArguments(), '->getArguments() returns all argument values, even optional ones'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The "foo" argument does not exist. - */ - public function testSetInvalidArgument() - { - $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'), new InputArgument('bar', InputArgument::OPTIONAL, '', 'default')))); - $input->setArgument('foo', 'bar'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The "foo" argument does not exist. - */ - public function testGetInvalidArgument() - { - $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'), new InputArgument('bar', InputArgument::OPTIONAL, '', 'default')))); - $input->getArgument('foo'); - } - - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage Not enough arguments (missing: "name"). - */ - public function testValidateWithMissingArguments() - { - $input = new ArrayInput(array()); - $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::REQUIRED)))); - $input->validate(); - } - - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage Not enough arguments (missing: "name"). - */ - public function testValidateWithMissingRequiredArguments() - { - $input = new ArrayInput(array('bar' => 'baz')); - $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::REQUIRED), new InputArgument('bar', InputArgument::OPTIONAL)))); - $input->validate(); - } - - public function testValidate() - { - $input = new ArrayInput(array('name' => 'foo')); - $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::REQUIRED)))); - - $this->assertNull($input->validate()); - } - - public function testSetGetInteractive() - { - $input = new ArrayInput(array()); - $this->assertTrue($input->isInteractive(), '->isInteractive() returns whether the input should be interactive or not'); - $input->setInteractive(false); - $this->assertFalse($input->isInteractive(), '->setInteractive() changes the interactive flag'); - } - - public function testSetGetStream() - { - $input = new ArrayInput(array()); - $stream = fopen('php://memory', 'r+', false); - $input->setStream($stream); - $this->assertSame($stream, $input->getStream()); - } -} diff --git a/vendor/symfony/console/Tests/Input/StringInputTest.php b/vendor/symfony/console/Tests/Input/StringInputTest.php deleted file mode 100644 index f2e3467..0000000 --- a/vendor/symfony/console/Tests/Input/StringInputTest.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Input; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\StringInput; - -class StringInputTest extends TestCase -{ - /** - * @dataProvider getTokenizeData - */ - public function testTokenize($input, $tokens, $message) - { - $input = new StringInput($input); - $r = new \ReflectionClass('Symfony\Component\Console\Input\ArgvInput'); - $p = $r->getProperty('tokens'); - $p->setAccessible(true); - $this->assertEquals($tokens, $p->getValue($input), $message); - } - - public function testInputOptionWithGivenString() - { - $definition = new InputDefinition( - array(new InputOption('foo', null, InputOption::VALUE_REQUIRED)) - ); - - // call to bind - $input = new StringInput('--foo=bar'); - $input->bind($definition); - $this->assertEquals('bar', $input->getOption('foo')); - } - - public function getTokenizeData() - { - return array( - array('', array(), '->tokenize() parses an empty string'), - array('foo', array('foo'), '->tokenize() parses arguments'), - array(' foo bar ', array('foo', 'bar'), '->tokenize() ignores whitespaces between arguments'), - array('"quoted"', array('quoted'), '->tokenize() parses quoted arguments'), - array("'quoted'", array('quoted'), '->tokenize() parses quoted arguments'), - array("'a\rb\nc\td'", array("a\rb\nc\td"), '->tokenize() parses whitespace chars in strings'), - array("'a'\r'b'\n'c'\t'd'", array('a', 'b', 'c', 'd'), '->tokenize() parses whitespace chars between args as spaces'), - array('\"quoted\"', array('"quoted"'), '->tokenize() parses escaped-quoted arguments'), - array("\'quoted\'", array('\'quoted\''), '->tokenize() parses escaped-quoted arguments'), - array('-a', array('-a'), '->tokenize() parses short options'), - array('-azc', array('-azc'), '->tokenize() parses aggregated short options'), - array('-awithavalue', array('-awithavalue'), '->tokenize() parses short options with a value'), - array('-a"foo bar"', array('-afoo bar'), '->tokenize() parses short options with a value'), - array('-a"foo bar""foo bar"', array('-afoo barfoo bar'), '->tokenize() parses short options with a value'), - array('-a\'foo bar\'', array('-afoo bar'), '->tokenize() parses short options with a value'), - array('-a\'foo bar\'\'foo bar\'', array('-afoo barfoo bar'), '->tokenize() parses short options with a value'), - array('-a\'foo bar\'"foo bar"', array('-afoo barfoo bar'), '->tokenize() parses short options with a value'), - array('--long-option', array('--long-option'), '->tokenize() parses long options'), - array('--long-option=foo', array('--long-option=foo'), '->tokenize() parses long options with a value'), - array('--long-option="foo bar"', array('--long-option=foo bar'), '->tokenize() parses long options with a value'), - array('--long-option="foo bar""another"', array('--long-option=foo baranother'), '->tokenize() parses long options with a value'), - array('--long-option=\'foo bar\'', array('--long-option=foo bar'), '->tokenize() parses long options with a value'), - array("--long-option='foo bar''another'", array('--long-option=foo baranother'), '->tokenize() parses long options with a value'), - array("--long-option='foo bar'\"another\"", array('--long-option=foo baranother'), '->tokenize() parses long options with a value'), - array('foo -a -ffoo --long bar', array('foo', '-a', '-ffoo', '--long', 'bar'), '->tokenize() parses when several arguments and options'), - ); - } - - public function testToString() - { - $input = new StringInput('-f foo'); - $this->assertEquals('-f foo', (string) $input); - - $input = new StringInput('-f --bar=foo "a b c d"'); - $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d'), (string) $input); - - $input = new StringInput('-f --bar=foo \'a b c d\' '."'A\nB\\'C'"); - $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d').' '.escapeshellarg("A\nB'C"), (string) $input); - } -} diff --git a/vendor/symfony/console/Tests/Logger/ConsoleLoggerTest.php b/vendor/symfony/console/Tests/Logger/ConsoleLoggerTest.php deleted file mode 100644 index 95e78fc..0000000 --- a/vendor/symfony/console/Tests/Logger/ConsoleLoggerTest.php +++ /dev/null @@ -1,215 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Logger; - -use PHPUnit\Framework\TestCase; -use Psr\Log\LoggerInterface; -use Psr\Log\LogLevel; -use Symfony\Component\Console\Logger\ConsoleLogger; -use Symfony\Component\Console\Output\BufferedOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Tests\Fixtures\DummyOutput; - -/** - * Console logger test. - * - * @author Kévin Dunglas <dunglas@gmail.com> - * @author Jordi Boggiano <j.boggiano@seld.be> - */ -class ConsoleLoggerTest extends TestCase -{ - /** - * @var DummyOutput - */ - protected $output; - - /** - * @return LoggerInterface - */ - public function getLogger() - { - $this->output = new DummyOutput(OutputInterface::VERBOSITY_VERBOSE); - - return new ConsoleLogger($this->output, array( - LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, - LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, - LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, - LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL, - LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL, - LogLevel::NOTICE => OutputInterface::VERBOSITY_NORMAL, - LogLevel::INFO => OutputInterface::VERBOSITY_NORMAL, - LogLevel::DEBUG => OutputInterface::VERBOSITY_NORMAL, - )); - } - - /** - * Return the log messages in order. - * - * @return string[] - */ - public function getLogs() - { - return $this->output->getLogs(); - } - - /** - * @dataProvider provideOutputMappingParams - */ - public function testOutputMapping($logLevel, $outputVerbosity, $isOutput, $addVerbosityLevelMap = array()) - { - $out = new BufferedOutput($outputVerbosity); - $logger = new ConsoleLogger($out, $addVerbosityLevelMap); - $logger->log($logLevel, 'foo bar'); - $logs = $out->fetch(); - $this->assertEquals($isOutput ? "[$logLevel] foo bar".PHP_EOL : '', $logs); - } - - public function provideOutputMappingParams() - { - $quietMap = array(LogLevel::EMERGENCY => OutputInterface::VERBOSITY_QUIET); - - return array( - array(LogLevel::EMERGENCY, OutputInterface::VERBOSITY_NORMAL, true), - array(LogLevel::WARNING, OutputInterface::VERBOSITY_NORMAL, true), - array(LogLevel::INFO, OutputInterface::VERBOSITY_NORMAL, false), - array(LogLevel::DEBUG, OutputInterface::VERBOSITY_NORMAL, false), - array(LogLevel::INFO, OutputInterface::VERBOSITY_VERBOSE, false), - array(LogLevel::INFO, OutputInterface::VERBOSITY_VERY_VERBOSE, true), - array(LogLevel::DEBUG, OutputInterface::VERBOSITY_VERY_VERBOSE, false), - array(LogLevel::DEBUG, OutputInterface::VERBOSITY_DEBUG, true), - array(LogLevel::ALERT, OutputInterface::VERBOSITY_QUIET, false), - array(LogLevel::EMERGENCY, OutputInterface::VERBOSITY_QUIET, false), - array(LogLevel::ALERT, OutputInterface::VERBOSITY_QUIET, false, $quietMap), - array(LogLevel::EMERGENCY, OutputInterface::VERBOSITY_QUIET, true, $quietMap), - ); - } - - public function testHasErrored() - { - $logger = new ConsoleLogger(new BufferedOutput()); - - $this->assertFalse($logger->hasErrored()); - - $logger->warning('foo'); - $this->assertFalse($logger->hasErrored()); - - $logger->error('bar'); - $this->assertTrue($logger->hasErrored()); - } - - public function testImplements() - { - $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger()); - } - - /** - * @dataProvider provideLevelsAndMessages - */ - public function testLogsAtAllLevels($level, $message) - { - $logger = $this->getLogger(); - $logger->{$level}($message, array('user' => 'Bob')); - $logger->log($level, $message, array('user' => 'Bob')); - - $expected = array( - $level.' message of level '.$level.' with context: Bob', - $level.' message of level '.$level.' with context: Bob', - ); - $this->assertEquals($expected, $this->getLogs()); - } - - public function provideLevelsAndMessages() - { - return array( - LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), - LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), - LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), - LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), - LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), - LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), - LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), - LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), - ); - } - - /** - * @expectedException \Psr\Log\InvalidArgumentException - */ - public function testThrowsOnInvalidLevel() - { - $logger = $this->getLogger(); - $logger->log('invalid level', 'Foo'); - } - - public function testContextReplacement() - { - $logger = $this->getLogger(); - $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); - - $expected = array('info {Message {nothing} Bob Bar a}'); - $this->assertEquals($expected, $this->getLogs()); - } - - public function testObjectCastToString() - { - if (method_exists($this, 'createPartialMock')) { - $dummy = $this->createPartialMock('Symfony\Component\Console\Tests\Logger\DummyTest', array('__toString')); - } else { - $dummy = $this->getMock('Symfony\Component\Console\Tests\Logger\DummyTest', array('__toString')); - } - $dummy->method('__toString')->will($this->returnValue('DUMMY')); - - $this->getLogger()->warning($dummy); - - $expected = array('warning DUMMY'); - $this->assertEquals($expected, $this->getLogs()); - } - - public function testContextCanContainAnything() - { - $context = array( - 'bool' => true, - 'null' => null, - 'string' => 'Foo', - 'int' => 0, - 'float' => 0.5, - 'nested' => array('with object' => new DummyTest()), - 'object' => new \DateTime(), - 'resource' => fopen('php://memory', 'r'), - ); - - $this->getLogger()->warning('Crazy context data', $context); - - $expected = array('warning Crazy context data'); - $this->assertEquals($expected, $this->getLogs()); - } - - public function testContextExceptionKeyCanBeExceptionOrOtherValues() - { - $logger = $this->getLogger(); - $logger->warning('Random message', array('exception' => 'oops')); - $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); - - $expected = array( - 'warning Random message', - 'critical Uncaught Exception!', - ); - $this->assertEquals($expected, $this->getLogs()); - } -} - -class DummyTest -{ - public function __toString() - { - } -} diff --git a/vendor/symfony/console/Tests/Output/ConsoleOutputTest.php b/vendor/symfony/console/Tests/Output/ConsoleOutputTest.php deleted file mode 100644 index db39a02..0000000 --- a/vendor/symfony/console/Tests/Output/ConsoleOutputTest.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Output; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Output\Output; - -class ConsoleOutputTest extends TestCase -{ - public function testConstructor() - { - $output = new ConsoleOutput(Output::VERBOSITY_QUIET, true); - $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument'); - $this->assertSame($output->getFormatter(), $output->getErrorOutput()->getFormatter(), '__construct() takes a formatter or null as the third argument'); - } - - public function testSetFormatter() - { - $output = new ConsoleOutput(); - $outputFormatter = new OutputFormatter(); - $output->setFormatter($outputFormatter); - $this->assertSame($outputFormatter, $output->getFormatter()); - } - - public function testSetVerbosity() - { - $output = new ConsoleOutput(); - $output->setVerbosity(Output::VERBOSITY_VERBOSE); - $this->assertSame(Output::VERBOSITY_VERBOSE, $output->getVerbosity()); - } -} diff --git a/vendor/symfony/console/Tests/Output/NullOutputTest.php b/vendor/symfony/console/Tests/Output/NullOutputTest.php deleted file mode 100644 index b7ff4be..0000000 --- a/vendor/symfony/console/Tests/Output/NullOutputTest.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Output; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Output\NullOutput; -use Symfony\Component\Console\Output\Output; -use Symfony\Component\Console\Output\OutputInterface; - -class NullOutputTest extends TestCase -{ - public function testConstructor() - { - $output = new NullOutput(); - - ob_start(); - $output->write('foo'); - $buffer = ob_get_clean(); - - $this->assertSame('', $buffer, '->write() does nothing (at least nothing is printed)'); - $this->assertFalse($output->isDecorated(), '->isDecorated() returns false'); - } - - public function testVerbosity() - { - $output = new NullOutput(); - $this->assertSame(OutputInterface::VERBOSITY_QUIET, $output->getVerbosity(), '->getVerbosity() returns VERBOSITY_QUIET for NullOutput by default'); - - $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); - $this->assertSame(OutputInterface::VERBOSITY_QUIET, $output->getVerbosity(), '->getVerbosity() always returns VERBOSITY_QUIET for NullOutput'); - } - - public function testSetFormatter() - { - $output = new NullOutput(); - $outputFormatter = new OutputFormatter(); - $output->setFormatter($outputFormatter); - $this->assertNotSame($outputFormatter, $output->getFormatter()); - } - - public function testSetVerbosity() - { - $output = new NullOutput(); - $output->setVerbosity(Output::VERBOSITY_NORMAL); - $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity()); - } - - public function testSetDecorated() - { - $output = new NullOutput(); - $output->setDecorated(true); - $this->assertFalse($output->isDecorated()); - } - - public function testIsQuiet() - { - $output = new NullOutput(); - $this->assertTrue($output->isQuiet()); - } - - public function testIsVerbose() - { - $output = new NullOutput(); - $this->assertFalse($output->isVerbose()); - } - - public function testIsVeryVerbose() - { - $output = new NullOutput(); - $this->assertFalse($output->isVeryVerbose()); - } - - public function testIsDebug() - { - $output = new NullOutput(); - $this->assertFalse($output->isDebug()); - } -} diff --git a/vendor/symfony/console/Tests/Output/OutputTest.php b/vendor/symfony/console/Tests/Output/OutputTest.php deleted file mode 100644 index fbd4e84..0000000 --- a/vendor/symfony/console/Tests/Output/OutputTest.php +++ /dev/null @@ -1,176 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Output; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; -use Symfony\Component\Console\Output\Output; - -class OutputTest extends TestCase -{ - public function testConstructor() - { - $output = new TestOutput(Output::VERBOSITY_QUIET, true); - $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument'); - $this->assertTrue($output->isDecorated(), '__construct() takes the decorated flag as its second argument'); - } - - public function testSetIsDecorated() - { - $output = new TestOutput(); - $output->setDecorated(true); - $this->assertTrue($output->isDecorated(), 'setDecorated() sets the decorated flag'); - } - - public function testSetGetVerbosity() - { - $output = new TestOutput(); - $output->setVerbosity(Output::VERBOSITY_QUIET); - $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '->setVerbosity() sets the verbosity'); - - $this->assertTrue($output->isQuiet()); - $this->assertFalse($output->isVerbose()); - $this->assertFalse($output->isVeryVerbose()); - $this->assertFalse($output->isDebug()); - - $output->setVerbosity(Output::VERBOSITY_NORMAL); - $this->assertFalse($output->isQuiet()); - $this->assertFalse($output->isVerbose()); - $this->assertFalse($output->isVeryVerbose()); - $this->assertFalse($output->isDebug()); - - $output->setVerbosity(Output::VERBOSITY_VERBOSE); - $this->assertFalse($output->isQuiet()); - $this->assertTrue($output->isVerbose()); - $this->assertFalse($output->isVeryVerbose()); - $this->assertFalse($output->isDebug()); - - $output->setVerbosity(Output::VERBOSITY_VERY_VERBOSE); - $this->assertFalse($output->isQuiet()); - $this->assertTrue($output->isVerbose()); - $this->assertTrue($output->isVeryVerbose()); - $this->assertFalse($output->isDebug()); - - $output->setVerbosity(Output::VERBOSITY_DEBUG); - $this->assertFalse($output->isQuiet()); - $this->assertTrue($output->isVerbose()); - $this->assertTrue($output->isVeryVerbose()); - $this->assertTrue($output->isDebug()); - } - - public function testWriteWithVerbosityQuiet() - { - $output = new TestOutput(Output::VERBOSITY_QUIET); - $output->writeln('foo'); - $this->assertEquals('', $output->output, '->writeln() outputs nothing if verbosity is set to VERBOSITY_QUIET'); - } - - public function testWriteAnArrayOfMessages() - { - $output = new TestOutput(); - $output->writeln(array('foo', 'bar')); - $this->assertEquals("foo\nbar\n", $output->output, '->writeln() can take an array of messages to output'); - } - - /** - * @dataProvider provideWriteArguments - */ - public function testWriteRawMessage($message, $type, $expectedOutput) - { - $output = new TestOutput(); - $output->writeln($message, $type); - $this->assertEquals($expectedOutput, $output->output); - } - - public function provideWriteArguments() - { - return array( - array('<info>foo</info>', Output::OUTPUT_RAW, "<info>foo</info>\n"), - array('<info>foo</info>', Output::OUTPUT_PLAIN, "foo\n"), - ); - } - - public function testWriteWithDecorationTurnedOff() - { - $output = new TestOutput(); - $output->setDecorated(false); - $output->writeln('<info>foo</info>'); - $this->assertEquals("foo\n", $output->output, '->writeln() strips decoration tags if decoration is set to false'); - } - - public function testWriteDecoratedMessage() - { - $fooStyle = new OutputFormatterStyle('yellow', 'red', array('blink')); - $output = new TestOutput(); - $output->getFormatter()->setStyle('FOO', $fooStyle); - $output->setDecorated(true); - $output->writeln('<foo>foo</foo>'); - $this->assertEquals("\033[33;41;5mfoo\033[39;49;25m\n", $output->output, '->writeln() decorates the output'); - } - - public function testWriteWithInvalidStyle() - { - $output = new TestOutput(); - - $output->clear(); - $output->write('<bar>foo</bar>'); - $this->assertEquals('<bar>foo</bar>', $output->output, '->write() do nothing when a style does not exist'); - - $output->clear(); - $output->writeln('<bar>foo</bar>'); - $this->assertEquals("<bar>foo</bar>\n", $output->output, '->writeln() do nothing when a style does not exist'); - } - - /** - * @dataProvider verbosityProvider - */ - public function testWriteWithVerbosityOption($verbosity, $expected, $msg) - { - $output = new TestOutput(); - - $output->setVerbosity($verbosity); - $output->clear(); - $output->write('1', false); - $output->write('2', false, Output::VERBOSITY_QUIET); - $output->write('3', false, Output::VERBOSITY_NORMAL); - $output->write('4', false, Output::VERBOSITY_VERBOSE); - $output->write('5', false, Output::VERBOSITY_VERY_VERBOSE); - $output->write('6', false, Output::VERBOSITY_DEBUG); - $this->assertEquals($expected, $output->output, $msg); - } - - public function verbosityProvider() - { - return array( - array(Output::VERBOSITY_QUIET, '2', '->write() in QUIET mode only outputs when an explicit QUIET verbosity is passed'), - array(Output::VERBOSITY_NORMAL, '123', '->write() in NORMAL mode outputs anything below an explicit VERBOSE verbosity'), - array(Output::VERBOSITY_VERBOSE, '1234', '->write() in VERBOSE mode outputs anything below an explicit VERY_VERBOSE verbosity'), - array(Output::VERBOSITY_VERY_VERBOSE, '12345', '->write() in VERY_VERBOSE mode outputs anything below an explicit DEBUG verbosity'), - array(Output::VERBOSITY_DEBUG, '123456', '->write() in DEBUG mode outputs everything'), - ); - } -} - -class TestOutput extends Output -{ - public $output = ''; - - public function clear() - { - $this->output = ''; - } - - protected function doWrite($message, $newline) - { - $this->output .= $message.($newline ? "\n" : ''); - } -} diff --git a/vendor/symfony/console/Tests/Output/StreamOutputTest.php b/vendor/symfony/console/Tests/Output/StreamOutputTest.php deleted file mode 100644 index 780b568..0000000 --- a/vendor/symfony/console/Tests/Output/StreamOutputTest.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Output; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Output\Output; -use Symfony\Component\Console\Output\StreamOutput; - -class StreamOutputTest extends TestCase -{ - protected $stream; - - protected function setUp() - { - $this->stream = fopen('php://memory', 'a', false); - } - - protected function tearDown() - { - $this->stream = null; - } - - public function testConstructor() - { - $output = new StreamOutput($this->stream, Output::VERBOSITY_QUIET, true); - $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument'); - $this->assertTrue($output->isDecorated(), '__construct() takes the decorated flag as its second argument'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The StreamOutput class needs a stream as its first argument. - */ - public function testStreamIsRequired() - { - new StreamOutput('foo'); - } - - public function testGetStream() - { - $output = new StreamOutput($this->stream); - $this->assertEquals($this->stream, $output->getStream(), '->getStream() returns the current stream'); - } - - public function testDoWrite() - { - $output = new StreamOutput($this->stream); - $output->writeln('foo'); - rewind($output->getStream()); - $this->assertEquals('foo'.PHP_EOL, stream_get_contents($output->getStream()), '->doWrite() writes to the stream'); - } -} diff --git a/vendor/symfony/console/Tests/Style/SymfonyStyleTest.php b/vendor/symfony/console/Tests/Style/SymfonyStyleTest.php deleted file mode 100644 index 308030b..0000000 --- a/vendor/symfony/console/Tests/Style/SymfonyStyleTest.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Style; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Console\Tester\CommandTester; - -class SymfonyStyleTest extends TestCase -{ - /** @var Command */ - protected $command; - /** @var CommandTester */ - protected $tester; - - protected function setUp() - { - putenv('COLUMNS=121'); - $this->command = new Command('sfstyle'); - $this->tester = new CommandTester($this->command); - } - - protected function tearDown() - { - putenv('COLUMNS'); - $this->command = null; - $this->tester = null; - } - - /** - * @dataProvider inputCommandToOutputFilesProvider - */ - public function testOutputs($inputCommandFilepath, $outputFilepath) - { - $code = require $inputCommandFilepath; - $this->command->setCode($code); - $this->tester->execute(array(), array('interactive' => false, 'decorated' => false)); - $this->assertStringEqualsFile($outputFilepath, $this->tester->getDisplay(true)); - } - - /** - * @dataProvider inputInteractiveCommandToOutputFilesProvider - */ - public function testInteractiveOutputs($inputCommandFilepath, $outputFilepath) - { - $code = require $inputCommandFilepath; - $this->command->setCode($code); - $this->tester->execute(array(), array('interactive' => true, 'decorated' => false)); - $this->assertStringEqualsFile($outputFilepath, $this->tester->getDisplay(true)); - } - - public function inputInteractiveCommandToOutputFilesProvider() - { - $baseDir = __DIR__.'/../Fixtures/Style/SymfonyStyle'; - - return array_map(null, glob($baseDir.'/command/interactive_command_*.php'), glob($baseDir.'/output/interactive_output_*.txt')); - } - - public function inputCommandToOutputFilesProvider() - { - $baseDir = __DIR__.'/../Fixtures/Style/SymfonyStyle'; - - return array_map(null, glob($baseDir.'/command/command_*.php'), glob($baseDir.'/output/output_*.txt')); - } - - public function testGetErrorStyle() - { - $input = $this->getMockBuilder(InputInterface::class)->getMock(); - - $errorOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); - $errorOutput - ->method('getFormatter') - ->willReturn(new OutputFormatter()); - $errorOutput - ->expects($this->once()) - ->method('write'); - - $output = $this->getMockBuilder(ConsoleOutputInterface::class)->getMock(); - $output - ->method('getFormatter') - ->willReturn(new OutputFormatter()); - $output - ->expects($this->once()) - ->method('getErrorOutput') - ->willReturn($errorOutput); - - $io = new SymfonyStyle($input, $output); - $io->getErrorStyle()->write(''); - } - - public function testGetErrorStyleUsesTheCurrentOutputIfNoErrorOutputIsAvailable() - { - $output = $this->getMockBuilder(OutputInterface::class)->getMock(); - $output - ->method('getFormatter') - ->willReturn(new OutputFormatter()); - - $style = new SymfonyStyle($this->getMockBuilder(InputInterface::class)->getMock(), $output); - - $this->assertInstanceOf(SymfonyStyle::class, $style->getErrorStyle()); - } -} diff --git a/vendor/symfony/console/Tests/TerminalTest.php b/vendor/symfony/console/Tests/TerminalTest.php deleted file mode 100644 index 91af1d0..0000000 --- a/vendor/symfony/console/Tests/TerminalTest.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Terminal; - -class TerminalTest extends TestCase -{ - public function test() - { - putenv('COLUMNS=100'); - putenv('LINES=50'); - $terminal = new Terminal(); - $this->assertSame(100, $terminal->getWidth()); - $this->assertSame(50, $terminal->getHeight()); - - putenv('COLUMNS=120'); - putenv('LINES=60'); - $terminal = new Terminal(); - $this->assertSame(120, $terminal->getWidth()); - $this->assertSame(60, $terminal->getHeight()); - } - - public function test_zero_values() - { - putenv('COLUMNS=0'); - putenv('LINES=0'); - - $terminal = new Terminal(); - - $this->assertSame(0, $terminal->getWidth()); - $this->assertSame(0, $terminal->getHeight()); - } -} diff --git a/vendor/symfony/console/Tests/Tester/ApplicationTesterTest.php b/vendor/symfony/console/Tests/Tester/ApplicationTesterTest.php deleted file mode 100644 index 57e7136..0000000 --- a/vendor/symfony/console/Tests/Tester/ApplicationTesterTest.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Tester; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Output\Output; -use Symfony\Component\Console\Tester\ApplicationTester; - -class ApplicationTesterTest extends TestCase -{ - protected $application; - protected $tester; - - protected function setUp() - { - $this->application = new Application(); - $this->application->setAutoExit(false); - $this->application->register('foo') - ->addArgument('foo') - ->setCode(function ($input, $output) { $output->writeln('foo'); }) - ; - - $this->tester = new ApplicationTester($this->application); - $this->tester->run(array('command' => 'foo', 'foo' => 'bar'), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); - } - - protected function tearDown() - { - $this->application = null; - $this->tester = null; - } - - public function testRun() - { - $this->assertFalse($this->tester->getInput()->isInteractive(), '->execute() takes an interactive option'); - $this->assertFalse($this->tester->getOutput()->isDecorated(), '->execute() takes a decorated option'); - $this->assertEquals(Output::VERBOSITY_VERBOSE, $this->tester->getOutput()->getVerbosity(), '->execute() takes a verbosity option'); - } - - public function testGetInput() - { - $this->assertEquals('bar', $this->tester->getInput()->getArgument('foo'), '->getInput() returns the current input instance'); - } - - public function testGetOutput() - { - rewind($this->tester->getOutput()->getStream()); - $this->assertEquals('foo'.PHP_EOL, stream_get_contents($this->tester->getOutput()->getStream()), '->getOutput() returns the current output instance'); - } - - public function testGetDisplay() - { - $this->assertEquals('foo'.PHP_EOL, $this->tester->getDisplay(), '->getDisplay() returns the display of the last execution'); - } - - public function testGetStatusCode() - { - $this->assertSame(0, $this->tester->getStatusCode(), '->getStatusCode() returns the status code'); - } -} diff --git a/vendor/symfony/console/Tests/Tester/CommandTesterTest.php b/vendor/symfony/console/Tests/Tester/CommandTesterTest.php deleted file mode 100644 index 58eb810..0000000 --- a/vendor/symfony/console/Tests/Tester/CommandTesterTest.php +++ /dev/null @@ -1,163 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tests\Tester; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Helper\QuestionHelper; -use Symfony\Component\Console\Output\Output; -use Symfony\Component\Console\Question\Question; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Console\Tester\CommandTester; - -class CommandTesterTest extends TestCase -{ - protected $command; - protected $tester; - - protected function setUp() - { - $this->command = new Command('foo'); - $this->command->addArgument('command'); - $this->command->addArgument('foo'); - $this->command->setCode(function ($input, $output) { $output->writeln('foo'); }); - - $this->tester = new CommandTester($this->command); - $this->tester->execute(array('foo' => 'bar'), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE)); - } - - protected function tearDown() - { - $this->command = null; - $this->tester = null; - } - - public function testExecute() - { - $this->assertFalse($this->tester->getInput()->isInteractive(), '->execute() takes an interactive option'); - $this->assertFalse($this->tester->getOutput()->isDecorated(), '->execute() takes a decorated option'); - $this->assertEquals(Output::VERBOSITY_VERBOSE, $this->tester->getOutput()->getVerbosity(), '->execute() takes a verbosity option'); - } - - public function testGetInput() - { - $this->assertEquals('bar', $this->tester->getInput()->getArgument('foo'), '->getInput() returns the current input instance'); - } - - public function testGetOutput() - { - rewind($this->tester->getOutput()->getStream()); - $this->assertEquals('foo'.PHP_EOL, stream_get_contents($this->tester->getOutput()->getStream()), '->getOutput() returns the current output instance'); - } - - public function testGetDisplay() - { - $this->assertEquals('foo'.PHP_EOL, $this->tester->getDisplay(), '->getDisplay() returns the display of the last execution'); - } - - public function testGetStatusCode() - { - $this->assertSame(0, $this->tester->getStatusCode(), '->getStatusCode() returns the status code'); - } - - public function testCommandFromApplication() - { - $application = new Application(); - $application->setAutoExit(false); - - $command = new Command('foo'); - $command->setCode(function ($input, $output) { $output->writeln('foo'); }); - - $application->add($command); - - $tester = new CommandTester($application->find('foo')); - - // check that there is no need to pass the command name here - $this->assertEquals(0, $tester->execute(array())); - } - - public function testCommandWithInputs() - { - $questions = array( - 'What\'s your name?', - 'How are you?', - 'Where do you come from?', - ); - - $command = new Command('foo'); - $command->setHelperSet(new HelperSet(array(new QuestionHelper()))); - $command->setCode(function ($input, $output) use ($questions, $command) { - $helper = $command->getHelper('question'); - $helper->ask($input, $output, new Question($questions[0])); - $helper->ask($input, $output, new Question($questions[1])); - $helper->ask($input, $output, new Question($questions[2])); - }); - - $tester = new CommandTester($command); - $tester->setInputs(array('Bobby', 'Fine', 'France')); - $tester->execute(array()); - - $this->assertEquals(0, $tester->getStatusCode()); - $this->assertEquals(implode('', $questions), $tester->getDisplay(true)); - } - - /** - * @expectedException \RuntimeException - * @expectedMessage Aborted - */ - public function testCommandWithWrongInputsNumber() - { - $questions = array( - 'What\'s your name?', - 'How are you?', - 'Where do you come from?', - ); - - $command = new Command('foo'); - $command->setHelperSet(new HelperSet(array(new QuestionHelper()))); - $command->setCode(function ($input, $output) use ($questions, $command) { - $helper = $command->getHelper('question'); - $helper->ask($input, $output, new Question($questions[0])); - $helper->ask($input, $output, new Question($questions[1])); - $helper->ask($input, $output, new Question($questions[2])); - }); - - $tester = new CommandTester($command); - $tester->setInputs(array('Bobby', 'Fine')); - $tester->execute(array()); - } - - public function testSymfonyStyleCommandWithInputs() - { - $questions = array( - 'What\'s your name?', - 'How are you?', - 'Where do you come from?', - ); - - $command = new Command('foo'); - $command->setCode(function ($input, $output) use ($questions, $command) { - $io = new SymfonyStyle($input, $output); - $io->ask($questions[0]); - $io->ask($questions[1]); - $io->ask($questions[2]); - }); - - $tester = new CommandTester($command); - $tester->setInputs(array('Bobby', 'Fine', 'France')); - $tester->execute(array()); - - $this->assertEquals(0, $tester->getStatusCode()); - } -} diff --git a/vendor/symfony/console/composer.json b/vendor/symfony/console/composer.json index ab348ab..4fa4964 100644 --- a/vendor/symfony/console/composer.json +++ b/vendor/symfony/console/composer.json @@ -1,8 +1,8 @@ { "name": "symfony/console", "type": "library", - "description": "Symfony Console Component", - "keywords": [], + "description": "Eases the creation of beautiful and testable command line interfaces", + "keywords": ["console", "cli", "command-line", "terminal"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ @@ -16,27 +16,39 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8", + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/debug": "~2.8|~3.0|~4.0" + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" }, "require-dev": { - "symfony/config": "~3.3|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.3|~4.0", - "psr/log": "~1.0" + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0", + "psr/log": "^1|^2" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" }, "suggest": { "symfony/event-dispatcher": "", "symfony/lock": "", "symfony/process": "", - "psr/log-implementation": "For using the console logger" + "psr/log": "For using the console logger" }, "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" }, "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" }, @@ -44,10 +56,5 @@ "/Tests/" ] }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - } + "minimum-stability": "dev" } diff --git a/vendor/symfony/console/phpunit.xml.dist b/vendor/symfony/console/phpunit.xml.dist deleted file mode 100644 index 32569d6..0000000 --- a/vendor/symfony/console/phpunit.xml.dist +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" - backupGlobals="false" - colors="true" - bootstrap="vendor/autoload.php" - failOnRisky="true" - failOnWarning="true" -> - <php> - <ini name="error_reporting" value="-1" /> - </php> - - <testsuites> - <testsuite name="Symfony Console Component Test Suite"> - <directory>./Tests/</directory> - </testsuite> - </testsuites> - - <filter> - <whitelist> - <directory>./</directory> - <exclude> - <directory>./Resources</directory> - <directory>./Tests</directory> - <directory>./vendor</directory> - </exclude> - </whitelist> - </filter> - - <listeners> - <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener"> - <arguments> - <array> - <element key="time-sensitive"><string>Symfony\Component\Console</string></element> - </array> - </arguments> - </listener> - </listeners> -</phpunit> diff --git a/vendor/symfony/debug/BufferingLogger.php b/vendor/symfony/debug/BufferingLogger.php deleted file mode 100644 index a2ed75b..0000000 --- a/vendor/symfony/debug/BufferingLogger.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug; - -use Psr\Log\AbstractLogger; - -/** - * A buffering logger that stacks logs for later. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class BufferingLogger extends AbstractLogger -{ - private $logs = array(); - - public function log($level, $message, array $context = array()) - { - $this->logs[] = array($level, $message, $context); - } - - public function cleanLogs() - { - $logs = $this->logs; - $this->logs = array(); - - return $logs; - } -} diff --git a/vendor/symfony/debug/CHANGELOG.md b/vendor/symfony/debug/CHANGELOG.md deleted file mode 100644 index 122af73..0000000 --- a/vendor/symfony/debug/CHANGELOG.md +++ /dev/null @@ -1,70 +0,0 @@ -CHANGELOG -========= - -4.0.0 ------ - -* removed the symfony_debug extension -* removed `ContextErrorException` - -3.4.0 ------ - -* deprecated `ErrorHandler::stackErrors()` and `ErrorHandler::unstackErrors()` - -3.3.0 ------ - -* deprecated the `ContextErrorException` class: use \ErrorException directly now - -3.2.0 ------ - -* `FlattenException::getTrace()` now returns additional type descriptions - `integer` and `float`. - - -3.0.0 ------ - -* removed classes, methods and interfaces deprecated in 2.x - -2.8.0 ------ - -* added BufferingLogger for errors that happen before a proper logger is configured -* allow throwing from `__toString()` with `return trigger_error($e, E_USER_ERROR);` -* deprecate ExceptionHandler::createResponse - -2.7.0 ------ - -* added deprecations checking for parent interfaces/classes to DebugClassLoader -* added ZTS support to symfony_debug extension -* added symfony_debug_backtrace() to symfony_debug extension - to track the backtrace of fatal errors - -2.6.0 ------ - -* generalized ErrorHandler and ExceptionHandler, - with some new methods and others deprecated -* enhanced error messages for uncaught exceptions - -2.5.0 ------ - -* added ExceptionHandler::setHandler() -* added UndefinedMethodFatalErrorHandler -* deprecated DummyException - -2.4.0 ------ - - * added a DebugClassLoader able to wrap any autoloader providing a findFile method - * improved error messages for not found classes and functions - -2.3.0 ------ - - * added the component diff --git a/vendor/symfony/debug/Debug.php b/vendor/symfony/debug/Debug.php deleted file mode 100644 index 3f65703..0000000 --- a/vendor/symfony/debug/Debug.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug; - -/** - * Registers all the debug tools. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Debug -{ - private static $enabled = false; - - /** - * Enables the debug tools. - * - * This method registers an error handler and an exception handler. - * - * @param int $errorReportingLevel The level of error reporting you want - * @param bool $displayErrors Whether to display errors (for development) or just log them (for production) - */ - public static function enable($errorReportingLevel = E_ALL, $displayErrors = true) - { - if (static::$enabled) { - return; - } - - static::$enabled = true; - - if (null !== $errorReportingLevel) { - error_reporting($errorReportingLevel); - } else { - error_reporting(E_ALL); - } - - if (!\in_array(\PHP_SAPI, array('cli', 'phpdbg'), true)) { - ini_set('display_errors', 0); - ExceptionHandler::register(); - } elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) { - // CLI - display errors only if they're not already logged to STDERR - ini_set('display_errors', 1); - } - if ($displayErrors) { - ErrorHandler::register(new ErrorHandler(new BufferingLogger())); - } else { - ErrorHandler::register()->throwAt(0, true); - } - - DebugClassLoader::enable(); - } -} diff --git a/vendor/symfony/debug/DebugClassLoader.php b/vendor/symfony/debug/DebugClassLoader.php deleted file mode 100644 index ecf9251..0000000 --- a/vendor/symfony/debug/DebugClassLoader.php +++ /dev/null @@ -1,404 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug; - -/** - * Autoloader checking if the class is really defined in the file found. - * - * The ClassLoader will wrap all registered autoloaders - * and will throw an exception if a file is found but does - * not declare the class. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Christophe Coevoet <stof@notk.org> - * @author Nicolas Grekas <p@tchwork.com> - */ -class DebugClassLoader -{ - private $classLoader; - private $isFinder; - private $loaded = array(); - private static $caseCheck; - private static $checkedClasses = array(); - private static $final = array(); - private static $finalMethods = array(); - private static $deprecated = array(); - private static $internal = array(); - private static $internalMethods = array(); - private static $darwinCache = array('/' => array('/', array())); - - public function __construct(callable $classLoader) - { - $this->classLoader = $classLoader; - $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile'); - - if (!isset(self::$caseCheck)) { - $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR); - $i = strrpos($file, \DIRECTORY_SEPARATOR); - $dir = substr($file, 0, 1 + $i); - $file = substr($file, 1 + $i); - $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file); - $test = realpath($dir.$test); - - if (false === $test || false === $i) { - // filesystem is case sensitive - self::$caseCheck = 0; - } elseif (substr($test, -\strlen($file)) === $file) { - // filesystem is case insensitive and realpath() normalizes the case of characters - self::$caseCheck = 1; - } elseif (false !== stripos(PHP_OS, 'darwin')) { - // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters - self::$caseCheck = 2; - } else { - // filesystem case checks failed, fallback to disabling them - self::$caseCheck = 0; - } - } - } - - /** - * Gets the wrapped class loader. - * - * @return callable The wrapped class loader - */ - public function getClassLoader() - { - return $this->classLoader; - } - - /** - * Wraps all autoloaders. - */ - public static function enable() - { - // Ensures we don't hit https://bugs.php.net/42098 - class_exists('Symfony\Component\Debug\ErrorHandler'); - class_exists('Psr\Log\LogLevel'); - - if (!\is_array($functions = spl_autoload_functions())) { - return; - } - - foreach ($functions as $function) { - spl_autoload_unregister($function); - } - - foreach ($functions as $function) { - if (!\is_array($function) || !$function[0] instanceof self) { - $function = array(new static($function), 'loadClass'); - } - - spl_autoload_register($function); - } - } - - /** - * Disables the wrapping. - */ - public static function disable() - { - if (!\is_array($functions = spl_autoload_functions())) { - return; - } - - foreach ($functions as $function) { - spl_autoload_unregister($function); - } - - foreach ($functions as $function) { - if (\is_array($function) && $function[0] instanceof self) { - $function = $function[0]->getClassLoader(); - } - - spl_autoload_register($function); - } - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * - * @return bool|null True, if loaded - * - * @throws \RuntimeException - */ - public function loadClass($class) - { - $e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); - - try { - if ($this->isFinder && !isset($this->loaded[$class])) { - $this->loaded[$class] = true; - if ($file = $this->classLoader[0]->findFile($class) ?: false) { - $wasCached = \function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file); - - require $file; - - if ($wasCached) { - return; - } - } - } else { - \call_user_func($this->classLoader, $class); - $file = false; - } - } finally { - error_reporting($e); - } - - $this->checkClass($class, $file); - } - - private function checkClass($class, $file = null) - { - $exists = null === $file || \class_exists($class, false) || \interface_exists($class, false) || \trait_exists($class, false); - - if (null !== $file && $class && '\\' === $class[0]) { - $class = substr($class, 1); - } - - if ($exists) { - if (isset(self::$checkedClasses[$class])) { - return; - } - self::$checkedClasses[$class] = true; - - $refl = new \ReflectionClass($class); - if (null === $file && $refl->isInternal()) { - return; - } - $name = $refl->getName(); - - if ($name !== $class && 0 === \strcasecmp($name, $class)) { - throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name)); - } - - // Don't trigger deprecations for classes in the same vendor - if (2 > $len = 1 + (\strpos($name, '\\') ?: \strpos($name, '_'))) { - $len = 0; - $ns = ''; - } else { - $ns = \substr($name, 0, $len); - } - - // Detect annotations on the class - if (false !== $doc = $refl->getDocComment()) { - foreach (array('final', 'deprecated', 'internal') as $annotation) { - if (false !== \strpos($doc, $annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) { - self::${$annotation}[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; - } - } - } - - $parentAndTraits = \class_uses($name, false); - if ($parent = \get_parent_class($class)) { - $parentAndTraits[] = $parent; - - if (!isset(self::$checkedClasses[$parent])) { - $this->checkClass($parent); - } - - if (isset(self::$final[$parent])) { - @trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED); - } - } - - // Detect if the parent is annotated - foreach ($parentAndTraits + $this->getOwnInterfaces($name, $parent) as $use) { - if (!isset(self::$checkedClasses[$use])) { - $this->checkClass($use); - } - if (isset(self::$deprecated[$use]) && \strncmp($ns, $use, $len)) { - $type = class_exists($name, false) ? 'class' : (interface_exists($name, false) ? 'interface' : 'trait'); - $verb = class_exists($use, false) || interface_exists($name, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses'); - - @trigger_error(sprintf('The "%s" %s %s "%s" that is deprecated%s.', $name, $type, $verb, $use, self::$deprecated[$use]), E_USER_DEPRECATED); - } - if (isset(self::$internal[$use]) && \strncmp($ns, $use, $len)) { - @trigger_error(sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $name), E_USER_DEPRECATED); - } - } - - // Inherit @final and @internal annotations for methods - self::$finalMethods[$name] = array(); - self::$internalMethods[$name] = array(); - foreach ($parentAndTraits as $use) { - foreach (array('finalMethods', 'internalMethods') as $property) { - if (isset(self::${$property}[$use])) { - self::${$property}[$name] = self::${$property}[$name] ? self::${$property}[$use] + self::${$property}[$name] : self::${$property}[$use]; - } - } - } - - $isClass = \class_exists($name, false); - foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) { - if ($method->class !== $name) { - continue; - } - - // Method from a trait - if ($method->getFilename() !== $refl->getFileName()) { - continue; - } - - if ($isClass && $parent && isset(self::$finalMethods[$parent][$method->name])) { - list($declaringClass, $message) = self::$finalMethods[$parent][$method->name]; - @trigger_error(sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED); - } - - foreach ($parentAndTraits as $use) { - if (isset(self::$internalMethods[$use][$method->name])) { - list($declaringClass, $message) = self::$internalMethods[$use][$method->name]; - if (\strncmp($ns, $declaringClass, $len)) { - @trigger_error(sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED); - } - } - } - - // Detect method annotations - if (false === $doc = $method->getDocComment()) { - continue; - } - - foreach (array('final', 'internal') as $annotation) { - if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) { - $message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; - self::${$annotation.'Methods'}[$name][$method->name] = array($name, $message); - } - } - } - } - - if ($file) { - if (!$exists) { - if (false !== strpos($class, '/')) { - throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); - } - - throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); - } - if (self::$caseCheck) { - $real = explode('\\', $class.strrchr($file, '.')); - $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file)); - - $i = \count($tail) - 1; - $j = \count($real) - 1; - - while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) { - --$i; - --$j; - } - - array_splice($tail, 0, $i + 1); - } - if (self::$caseCheck && $tail) { - $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail); - $tailLen = \strlen($tail); - $real = $refl->getFileName(); - - if (2 === self::$caseCheck) { - // realpath() on MacOSX doesn't normalize the case of characters - - $i = 1 + strrpos($real, '/'); - $file = substr($real, $i); - $real = substr($real, 0, $i); - - if (isset(self::$darwinCache[$real])) { - $kDir = $real; - } else { - $kDir = strtolower($real); - - if (isset(self::$darwinCache[$kDir])) { - $real = self::$darwinCache[$kDir][0]; - } else { - $dir = getcwd(); - chdir($real); - $real = getcwd().'/'; - chdir($dir); - - $dir = $real; - $k = $kDir; - $i = \strlen($dir) - 1; - while (!isset(self::$darwinCache[$k])) { - self::$darwinCache[$k] = array($dir, array()); - self::$darwinCache[$dir] = &self::$darwinCache[$k]; - - while ('/' !== $dir[--$i]) { - } - $k = substr($k, 0, ++$i); - $dir = substr($dir, 0, $i--); - } - } - } - - $dirFiles = self::$darwinCache[$kDir][1]; - - if (isset($dirFiles[$file])) { - $kFile = $file; - } else { - $kFile = strtolower($file); - - if (!isset($dirFiles[$kFile])) { - foreach (scandir($real, 2) as $f) { - if ('.' !== $f[0]) { - $dirFiles[$f] = $f; - if ($f === $file) { - $kFile = $k = $file; - } elseif ($f !== $k = strtolower($f)) { - $dirFiles[$k] = $f; - } - } - } - self::$darwinCache[$kDir][1] = $dirFiles; - } - } - - $real .= $dirFiles[$kFile]; - } - - if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true) - && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false) - ) { - throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1))); - } - } - } - } - - /** - * `class_implements` includes interfaces from the parents so we have to manually exclude them. - * - * @param string $class - * @param string|false $parent - * - * @return string[] - */ - private function getOwnInterfaces($class, $parent) - { - $ownInterfaces = class_implements($class, false); - - if ($parent) { - foreach (class_implements($parent, false) as $interface) { - unset($ownInterfaces[$interface]); - } - } - - foreach ($ownInterfaces as $interface) { - foreach (class_implements($interface) as $interface) { - unset($ownInterfaces[$interface]); - } - } - - return $ownInterfaces; - } -} diff --git a/vendor/symfony/debug/ErrorHandler.php b/vendor/symfony/debug/ErrorHandler.php deleted file mode 100644 index caffd54..0000000 --- a/vendor/symfony/debug/ErrorHandler.php +++ /dev/null @@ -1,682 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug; - -use Psr\Log\LoggerInterface; -use Psr\Log\LogLevel; -use Symfony\Component\Debug\Exception\FatalErrorException; -use Symfony\Component\Debug\Exception\FatalThrowableError; -use Symfony\Component\Debug\Exception\OutOfMemoryException; -use Symfony\Component\Debug\Exception\SilencedErrorContext; -use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler; -use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface; -use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler; -use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler; - -/** - * A generic ErrorHandler for the PHP engine. - * - * Provides five bit fields that control how errors are handled: - * - thrownErrors: errors thrown as \ErrorException - * - loggedErrors: logged errors, when not @-silenced - * - scopedErrors: errors thrown or logged with their local context - * - tracedErrors: errors logged with their stack trace - * - screamedErrors: never @-silenced errors - * - * Each error level can be logged by a dedicated PSR-3 logger object. - * Screaming only applies to logging. - * Throwing takes precedence over logging. - * Uncaught exceptions are logged as E_ERROR. - * E_DEPRECATED and E_USER_DEPRECATED levels never throw. - * E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw. - * Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so. - * As errors have a performance cost, repeated errors are all logged, so that the developer - * can see them and weight them as more important to fix than others of the same level. - * - * @author Nicolas Grekas <p@tchwork.com> - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -class ErrorHandler -{ - private $levels = array( - E_DEPRECATED => 'Deprecated', - E_USER_DEPRECATED => 'User Deprecated', - E_NOTICE => 'Notice', - E_USER_NOTICE => 'User Notice', - E_STRICT => 'Runtime Notice', - E_WARNING => 'Warning', - E_USER_WARNING => 'User Warning', - E_COMPILE_WARNING => 'Compile Warning', - E_CORE_WARNING => 'Core Warning', - E_USER_ERROR => 'User Error', - E_RECOVERABLE_ERROR => 'Catchable Fatal Error', - E_COMPILE_ERROR => 'Compile Error', - E_PARSE => 'Parse Error', - E_ERROR => 'Error', - E_CORE_ERROR => 'Core Error', - ); - - private $loggers = array( - E_DEPRECATED => array(null, LogLevel::INFO), - E_USER_DEPRECATED => array(null, LogLevel::INFO), - E_NOTICE => array(null, LogLevel::WARNING), - E_USER_NOTICE => array(null, LogLevel::WARNING), - E_STRICT => array(null, LogLevel::WARNING), - E_WARNING => array(null, LogLevel::WARNING), - E_USER_WARNING => array(null, LogLevel::WARNING), - E_COMPILE_WARNING => array(null, LogLevel::WARNING), - E_CORE_WARNING => array(null, LogLevel::WARNING), - E_USER_ERROR => array(null, LogLevel::CRITICAL), - E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL), - E_COMPILE_ERROR => array(null, LogLevel::CRITICAL), - E_PARSE => array(null, LogLevel::CRITICAL), - E_ERROR => array(null, LogLevel::CRITICAL), - E_CORE_ERROR => array(null, LogLevel::CRITICAL), - ); - - private $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED - private $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED - private $tracedErrors = 0x77FB; // E_ALL - E_STRICT - E_PARSE - private $screamedErrors = 0x55; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE - private $loggedErrors = 0; - private $traceReflector; - - private $isRecursive = 0; - private $isRoot = false; - private $exceptionHandler; - private $bootstrappingLogger; - - private static $reservedMemory; - private static $toStringException = null; - private static $silencedErrorCache = array(); - private static $silencedErrorCount = 0; - private static $exitCode = 0; - - /** - * Registers the error handler. - * - * @param self|null $handler The handler to register - * @param bool $replace Whether to replace or not any existing handler - * - * @return self The registered error handler - */ - public static function register(self $handler = null, $replace = true) - { - if (null === self::$reservedMemory) { - self::$reservedMemory = str_repeat('x', 10240); - register_shutdown_function(__CLASS__.'::handleFatalError'); - } - - if ($handlerIsNew = null === $handler) { - $handler = new static(); - } - - if (null === $prev = set_error_handler(array($handler, 'handleError'))) { - restore_error_handler(); - // Specifying the error types earlier would expose us to https://bugs.php.net/63206 - set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors); - $handler->isRoot = true; - } - - if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) { - $handler = $prev[0]; - $replace = false; - } - if (!$replace && $prev) { - restore_error_handler(); - $handlerIsRegistered = \is_array($prev) && $handler === $prev[0]; - } else { - $handlerIsRegistered = true; - } - if (\is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] instanceof self) { - restore_exception_handler(); - if (!$handlerIsRegistered) { - $handler = $prev[0]; - } elseif ($handler !== $prev[0] && $replace) { - set_exception_handler(array($handler, 'handleException')); - $p = $prev[0]->setExceptionHandler(null); - $handler->setExceptionHandler($p); - $prev[0]->setExceptionHandler($p); - } - } else { - $handler->setExceptionHandler($prev); - } - - $handler->throwAt(E_ALL & $handler->thrownErrors, true); - - return $handler; - } - - public function __construct(BufferingLogger $bootstrappingLogger = null) - { - if ($bootstrappingLogger) { - $this->bootstrappingLogger = $bootstrappingLogger; - $this->setDefaultLogger($bootstrappingLogger); - } - $this->traceReflector = new \ReflectionProperty('Exception', 'trace'); - $this->traceReflector->setAccessible(true); - } - - /** - * Sets a logger to non assigned errors levels. - * - * @param LoggerInterface $logger A PSR-3 logger to put as default for the given levels - * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants - * @param bool $replace Whether to replace or not any existing logger - */ - public function setDefaultLogger(LoggerInterface $logger, $levels = E_ALL, $replace = false) - { - $loggers = array(); - - if (\is_array($levels)) { - foreach ($levels as $type => $logLevel) { - if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) { - $loggers[$type] = array($logger, $logLevel); - } - } - } else { - if (null === $levels) { - $levels = E_ALL; - } - foreach ($this->loggers as $type => $log) { - if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) { - $log[0] = $logger; - $loggers[$type] = $log; - } - } - } - - $this->setLoggers($loggers); - } - - /** - * Sets a logger for each error level. - * - * @param array $loggers Error levels to [LoggerInterface|null, LogLevel::*] map - * - * @return array The previous map - * - * @throws \InvalidArgumentException - */ - public function setLoggers(array $loggers) - { - $prevLogged = $this->loggedErrors; - $prev = $this->loggers; - $flush = array(); - - foreach ($loggers as $type => $log) { - if (!isset($prev[$type])) { - throw new \InvalidArgumentException('Unknown error type: '.$type); - } - if (!\is_array($log)) { - $log = array($log); - } elseif (!array_key_exists(0, $log)) { - throw new \InvalidArgumentException('No logger provided'); - } - if (null === $log[0]) { - $this->loggedErrors &= ~$type; - } elseif ($log[0] instanceof LoggerInterface) { - $this->loggedErrors |= $type; - } else { - throw new \InvalidArgumentException('Invalid logger provided'); - } - $this->loggers[$type] = $log + $prev[$type]; - - if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) { - $flush[$type] = $type; - } - } - $this->reRegister($prevLogged | $this->thrownErrors); - - if ($flush) { - foreach ($this->bootstrappingLogger->cleanLogs() as $log) { - $type = $log[2]['exception'] instanceof \ErrorException ? $log[2]['exception']->getSeverity() : E_ERROR; - if (!isset($flush[$type])) { - $this->bootstrappingLogger->log($log[0], $log[1], $log[2]); - } elseif ($this->loggers[$type][0]) { - $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]); - } - } - } - - return $prev; - } - - /** - * Sets a user exception handler. - * - * @param callable $handler A handler that will be called on Exception - * - * @return callable|null The previous exception handler - */ - public function setExceptionHandler(callable $handler = null) - { - $prev = $this->exceptionHandler; - $this->exceptionHandler = $handler; - - return $prev; - } - - /** - * Sets the PHP error levels that throw an exception when a PHP error occurs. - * - * @param int $levels A bit field of E_* constants for thrown errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function throwAt($levels, $replace = false) - { - $prev = $this->thrownErrors; - $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED; - if (!$replace) { - $this->thrownErrors |= $prev; - } - $this->reRegister($prev | $this->loggedErrors); - - return $prev; - } - - /** - * Sets the PHP error levels for which local variables are preserved. - * - * @param int $levels A bit field of E_* constants for scoped errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function scopeAt($levels, $replace = false) - { - $prev = $this->scopedErrors; - $this->scopedErrors = (int) $levels; - if (!$replace) { - $this->scopedErrors |= $prev; - } - - return $prev; - } - - /** - * Sets the PHP error levels for which the stack trace is preserved. - * - * @param int $levels A bit field of E_* constants for traced errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function traceAt($levels, $replace = false) - { - $prev = $this->tracedErrors; - $this->tracedErrors = (int) $levels; - if (!$replace) { - $this->tracedErrors |= $prev; - } - - return $prev; - } - - /** - * Sets the error levels where the @-operator is ignored. - * - * @param int $levels A bit field of E_* constants for screamed errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function screamAt($levels, $replace = false) - { - $prev = $this->screamedErrors; - $this->screamedErrors = (int) $levels; - if (!$replace) { - $this->screamedErrors |= $prev; - } - - return $prev; - } - - /** - * Re-registers as a PHP error handler if levels changed. - */ - private function reRegister($prev) - { - if ($prev !== $this->thrownErrors | $this->loggedErrors) { - $handler = set_error_handler('var_dump'); - $handler = \is_array($handler) ? $handler[0] : null; - restore_error_handler(); - if ($handler === $this) { - restore_error_handler(); - if ($this->isRoot) { - set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors); - } else { - set_error_handler(array($this, 'handleError')); - } - } - } - } - - /** - * Handles errors by filtering then logging them according to the configured bit fields. - * - * @param int $type One of the E_* constants - * @param string $message - * @param string $file - * @param int $line - * - * @return bool Returns false when no handling happens so that the PHP engine can handle the error itself - * - * @throws \ErrorException When $this->thrownErrors requests so - * - * @internal - */ - public function handleError($type, $message, $file, $line) - { - // Level is the current error reporting level to manage silent error. - $level = error_reporting(); - $silenced = 0 === ($level & $type); - // Strong errors are not authorized to be silenced. - $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED; - $log = $this->loggedErrors & $type; - $throw = $this->thrownErrors & $type & $level; - $type &= $level | $this->screamedErrors; - - if (!$type || (!$log && !$throw)) { - return !$silenced && $type && $log; - } - $scope = $this->scopedErrors & $type; - - if (4 < $numArgs = \func_num_args()) { - $context = $scope ? (func_get_arg(4) ?: array()) : array(); - } else { - $context = array(); - } - - if (isset($context['GLOBALS']) && $scope) { - $e = $context; // Whatever the signature of the method, - unset($e['GLOBALS'], $context); // $context is always a reference in 5.3 - $context = $e; - } - - $logMessage = $this->levels[$type].': '.$message; - - if (null !== self::$toStringException) { - $errorAsException = self::$toStringException; - self::$toStringException = null; - } elseif (!$throw && !($type & $level)) { - if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) { - $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array(); - $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace); - } elseif (isset(self::$silencedErrorCache[$id][$message])) { - $lightTrace = null; - $errorAsException = self::$silencedErrorCache[$id][$message]; - ++$errorAsException->count; - } else { - $lightTrace = array(); - $errorAsException = null; - } - - if (100 < ++self::$silencedErrorCount) { - self::$silencedErrorCache = $lightTrace = array(); - self::$silencedErrorCount = 1; - } - if ($errorAsException) { - self::$silencedErrorCache[$id][$message] = $errorAsException; - } - if (null === $lightTrace) { - return; - } - } else { - $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); - - // Clean the trace by removing function arguments and the first frames added by the error handler itself. - if ($throw || $this->tracedErrors & $type) { - $backtrace = $errorAsException->getTrace(); - $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); - $this->traceReflector->setValue($errorAsException, $lightTrace); - } else { - $this->traceReflector->setValue($errorAsException, array()); - $backtrace = array(); - } - } - - if ($throw) { - if (E_USER_ERROR & $type) { - for ($i = 1; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function']) - && '__toString' === $backtrace[$i]['function'] - && '->' === $backtrace[$i]['type'] - && !isset($backtrace[$i - 1]['class']) - && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function']) - ) { - // Here, we know trigger_error() has been called from __toString(). - // PHP triggers a fatal error when throwing from __toString(). - // A small convention allows working around the limitation: - // given a caught $e exception in __toString(), quitting the method with - // `return trigger_error($e, E_USER_ERROR);` allows this error handler - // to make $e get through the __toString() barrier. - - foreach ($context as $e) { - if ($e instanceof \Throwable && $e->__toString() === $message) { - self::$toStringException = $e; - - return true; - } - } - - // Display the original error message instead of the default one. - $this->handleException($errorAsException); - - // Stop the process by giving back the error to the native handler. - return false; - } - } - } - - throw $errorAsException; - } - - if ($this->isRecursive) { - $log = 0; - } else { - try { - $this->isRecursive = true; - $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; - $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? array('exception' => $errorAsException) : array()); - } finally { - $this->isRecursive = false; - } - } - - return !$silenced && $type && $log; - } - - /** - * Handles an exception by logging then forwarding it to another handler. - * - * @param \Exception|\Throwable $exception An exception to handle - * @param array $error An array as returned by error_get_last() - * - * @internal - */ - public function handleException($exception, array $error = null) - { - if (null === $error) { - self::$exitCode = 255; - } - if (!$exception instanceof \Exception) { - $exception = new FatalThrowableError($exception); - } - $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR; - $handlerException = null; - - if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) { - if ($exception instanceof FatalErrorException) { - if ($exception instanceof FatalThrowableError) { - $error = array( - 'type' => $type, - 'message' => $message = $exception->getMessage(), - 'file' => $exception->getFile(), - 'line' => $exception->getLine(), - ); - } else { - $message = 'Fatal '.$exception->getMessage(); - } - } elseif ($exception instanceof \ErrorException) { - $message = 'Uncaught '.$exception->getMessage(); - } else { - $message = 'Uncaught Exception: '.$exception->getMessage(); - } - } - if ($this->loggedErrors & $type) { - try { - $this->loggers[$type][0]->log($this->loggers[$type][1], $message, array('exception' => $exception)); - } catch (\Throwable $handlerException) { - } - } - if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) { - foreach ($this->getFatalErrorHandlers() as $handler) { - if ($e = $handler->handleError($error, $exception)) { - $exception = $e; - break; - } - } - } - $exceptionHandler = $this->exceptionHandler; - $this->exceptionHandler = null; - try { - if (null !== $exceptionHandler) { - return \call_user_func($exceptionHandler, $exception); - } - $handlerException = $handlerException ?: $exception; - } catch (\Throwable $handlerException) { - } - if ($exception === $handlerException) { - self::$reservedMemory = null; // Disable the fatal error handler - throw $exception; // Give back $exception to the native handler - } - $this->handleException($handlerException); - } - - /** - * Shutdown registered function for handling PHP fatal errors. - * - * @param array $error An array as returned by error_get_last() - * - * @internal - */ - public static function handleFatalError(array $error = null) - { - if (null === self::$reservedMemory) { - return; - } - - $handler = self::$reservedMemory = null; - $handlers = array(); - $previousHandler = null; - $sameHandlerLimit = 10; - - while (!\is_array($handler) || !$handler[0] instanceof self) { - $handler = set_exception_handler('var_dump'); - restore_exception_handler(); - - if (!$handler) { - break; - } - restore_exception_handler(); - - if ($handler !== $previousHandler) { - array_unshift($handlers, $handler); - $previousHandler = $handler; - } elseif (0 === --$sameHandlerLimit) { - $handler = null; - break; - } - } - foreach ($handlers as $h) { - set_exception_handler($h); - } - if (!$handler) { - return; - } - if ($handler !== $h) { - $handler[0]->setExceptionHandler($h); - } - $handler = $handler[0]; - $handlers = array(); - - if ($exit = null === $error) { - $error = error_get_last(); - } - - if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) { - // Let's not throw anymore but keep logging - $handler->throwAt(0, true); - $trace = isset($error['backtrace']) ? $error['backtrace'] : null; - - if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { - $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace); - } else { - $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace); - } - } else { - $exception = null; - } - - try { - if (null !== $exception) { - self::$exitCode = 255; - $handler->handleException($exception, $error); - } - } catch (FatalErrorException $e) { - // Ignore this re-throw - } - - if ($exit && self::$exitCode) { - $exitCode = self::$exitCode; - register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); }); - } - } - - /** - * Gets the fatal error handlers. - * - * Override this method if you want to define more fatal error handlers. - * - * @return FatalErrorHandlerInterface[] An array of FatalErrorHandlerInterface - */ - protected function getFatalErrorHandlers() - { - return array( - new UndefinedFunctionFatalErrorHandler(), - new UndefinedMethodFatalErrorHandler(), - new ClassNotFoundFatalErrorHandler(), - ); - } - - private function cleanTrace($backtrace, $type, $file, $line, $throw) - { - $lightTrace = $backtrace; - - for ($i = 0; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $lightTrace = \array_slice($lightTrace, 1 + $i); - break; - } - } - if (!($throw || $this->scopedErrors & $type)) { - for ($i = 0; isset($lightTrace[$i]); ++$i) { - unset($lightTrace[$i]['args'], $lightTrace[$i]['object']); - } - } - - return $lightTrace; - } -} diff --git a/vendor/symfony/debug/Exception/ClassNotFoundException.php b/vendor/symfony/debug/Exception/ClassNotFoundException.php deleted file mode 100644 index fa98c49..0000000 --- a/vendor/symfony/debug/Exception/ClassNotFoundException.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Exception; - -/** - * Class (or Trait or Interface) Not Found Exception. - * - * @author Konstanton Myakshin <koc-dp@yandex.ru> - */ -class ClassNotFoundException extends FatalErrorException -{ - public function __construct(string $message, \ErrorException $previous) - { - parent::__construct( - $message, - $previous->getCode(), - $previous->getSeverity(), - $previous->getFile(), - $previous->getLine(), - null, - true, - null, - $previous->getPrevious() - ); - $this->setTrace($previous->getTrace()); - } -} diff --git a/vendor/symfony/debug/Exception/FatalErrorException.php b/vendor/symfony/debug/Exception/FatalErrorException.php deleted file mode 100644 index 8305d39..0000000 --- a/vendor/symfony/debug/Exception/FatalErrorException.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Exception; - -/** - * Fatal Error Exception. - * - * @author Konstanton Myakshin <koc-dp@yandex.ru> - */ -class FatalErrorException extends \ErrorException -{ - public function __construct(string $message, int $code, int $severity, string $filename, int $lineno, int $traceOffset = null, bool $traceArgs = true, array $trace = null, \Throwable $previous = null) - { - parent::__construct($message, $code, $severity, $filename, $lineno, $previous); - - if (null !== $trace) { - if (!$traceArgs) { - foreach ($trace as &$frame) { - unset($frame['args'], $frame['this'], $frame); - } - } - - $this->setTrace($trace); - } elseif (null !== $traceOffset) { - if (\function_exists('xdebug_get_function_stack')) { - $trace = xdebug_get_function_stack(); - if (0 < $traceOffset) { - array_splice($trace, -$traceOffset); - } - - foreach ($trace as &$frame) { - if (!isset($frame['type'])) { - // XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695 - if (isset($frame['class'])) { - $frame['type'] = '::'; - } - } elseif ('dynamic' === $frame['type']) { - $frame['type'] = '->'; - } elseif ('static' === $frame['type']) { - $frame['type'] = '::'; - } - - // XDebug also has a different name for the parameters array - if (!$traceArgs) { - unset($frame['params'], $frame['args']); - } elseif (isset($frame['params']) && !isset($frame['args'])) { - $frame['args'] = $frame['params']; - unset($frame['params']); - } - } - - unset($frame); - $trace = array_reverse($trace); - } else { - $trace = array(); - } - - $this->setTrace($trace); - } - } - - protected function setTrace($trace) - { - $traceReflector = new \ReflectionProperty('Exception', 'trace'); - $traceReflector->setAccessible(true); - $traceReflector->setValue($this, $trace); - } -} diff --git a/vendor/symfony/debug/Exception/FatalThrowableError.php b/vendor/symfony/debug/Exception/FatalThrowableError.php deleted file mode 100644 index cdafb2a..0000000 --- a/vendor/symfony/debug/Exception/FatalThrowableError.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Exception; - -/** - * Fatal Throwable Error. - * - * @author Nicolas Grekas <p@tchwork.com> - */ -class FatalThrowableError extends FatalErrorException -{ - private $originalClassName; - - public function __construct(\Throwable $e) - { - $this->originalClassName = \get_class($e); - - if ($e instanceof \ParseError) { - $severity = E_PARSE; - } elseif ($e instanceof \TypeError) { - $severity = E_RECOVERABLE_ERROR; - } else { - $severity = E_ERROR; - } - - \ErrorException::__construct( - $e->getMessage(), - $e->getCode(), - $severity, - $e->getFile(), - $e->getLine(), - $e->getPrevious() - ); - - $this->setTrace($e->getTrace()); - } - - public function getOriginalClassName(): string - { - return $this->originalClassName; - } -} diff --git a/vendor/symfony/debug/Exception/FlattenException.php b/vendor/symfony/debug/Exception/FlattenException.php deleted file mode 100644 index b091b55..0000000 --- a/vendor/symfony/debug/Exception/FlattenException.php +++ /dev/null @@ -1,276 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Exception; - -use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; - -/** - * FlattenException wraps a PHP Error or Exception to be able to serialize it. - * - * Basically, this class removes all objects from the trace. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class FlattenException -{ - private $message; - private $code; - private $previous; - private $trace; - private $class; - private $statusCode; - private $headers; - private $file; - private $line; - - public static function create(\Exception $exception, $statusCode = null, array $headers = array()) - { - return static::createFromThrowable($exception, $statusCode, $headers); - } - - public static function createFromThrowable(\Throwable $exception, ?int $statusCode = null, array $headers = array()): self - { - $e = new static(); - $e->setMessage($exception->getMessage()); - $e->setCode($exception->getCode()); - - if ($exception instanceof HttpExceptionInterface) { - $statusCode = $exception->getStatusCode(); - $headers = array_merge($headers, $exception->getHeaders()); - } elseif ($exception instanceof RequestExceptionInterface) { - $statusCode = 400; - } - - if (null === $statusCode) { - $statusCode = 500; - } - - $e->setStatusCode($statusCode); - $e->setHeaders($headers); - $e->setTraceFromThrowable($exception); - $e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : \get_class($exception)); - $e->setFile($exception->getFile()); - $e->setLine($exception->getLine()); - - $previous = $exception->getPrevious(); - - if ($previous instanceof \Throwable) { - $e->setPrevious(static::createFromThrowable($previous)); - } - - return $e; - } - - public function toArray() - { - $exceptions = array(); - foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) { - $exceptions[] = array( - 'message' => $exception->getMessage(), - 'class' => $exception->getClass(), - 'trace' => $exception->getTrace(), - ); - } - - return $exceptions; - } - - public function getStatusCode() - { - return $this->statusCode; - } - - public function setStatusCode($code) - { - $this->statusCode = $code; - } - - public function getHeaders() - { - return $this->headers; - } - - public function setHeaders(array $headers) - { - $this->headers = $headers; - } - - public function getClass() - { - return $this->class; - } - - public function setClass($class) - { - $this->class = $class; - } - - public function getFile() - { - return $this->file; - } - - public function setFile($file) - { - $this->file = $file; - } - - public function getLine() - { - return $this->line; - } - - public function setLine($line) - { - $this->line = $line; - } - - public function getMessage() - { - return $this->message; - } - - public function setMessage($message) - { - $this->message = $message; - } - - public function getCode() - { - return $this->code; - } - - public function setCode($code) - { - $this->code = $code; - } - - public function getPrevious() - { - return $this->previous; - } - - public function setPrevious(self $previous) - { - $this->previous = $previous; - } - - public function getAllPrevious() - { - $exceptions = array(); - $e = $this; - while ($e = $e->getPrevious()) { - $exceptions[] = $e; - } - - return $exceptions; - } - - public function getTrace() - { - return $this->trace; - } - - /** - * @deprecated since 4.1, use {@see setTraceFromThrowable()} instead. - */ - public function setTraceFromException(\Exception $exception) - { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use "setTraceFromThrowable()" instead.', __METHOD__), E_USER_DEPRECATED); - - $this->setTraceFromThrowable($exception); - } - - public function setTraceFromThrowable(\Throwable $throwable): void - { - $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine()); - } - - public function setTrace($trace, $file, $line) - { - $this->trace = array(); - $this->trace[] = array( - 'namespace' => '', - 'short_class' => '', - 'class' => '', - 'type' => '', - 'function' => '', - 'file' => $file, - 'line' => $line, - 'args' => array(), - ); - foreach ($trace as $entry) { - $class = ''; - $namespace = ''; - if (isset($entry['class'])) { - $parts = explode('\\', $entry['class']); - $class = array_pop($parts); - $namespace = implode('\\', $parts); - } - - $this->trace[] = array( - 'namespace' => $namespace, - 'short_class' => $class, - 'class' => isset($entry['class']) ? $entry['class'] : '', - 'type' => isset($entry['type']) ? $entry['type'] : '', - 'function' => isset($entry['function']) ? $entry['function'] : null, - 'file' => isset($entry['file']) ? $entry['file'] : null, - 'line' => isset($entry['line']) ? $entry['line'] : null, - 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(), - ); - } - } - - private function flattenArgs($args, $level = 0, &$count = 0) - { - $result = array(); - foreach ($args as $key => $value) { - if (++$count > 1e4) { - return array('array', '*SKIPPED over 10000 entries*'); - } - if ($value instanceof \__PHP_Incomplete_Class) { - // is_object() returns false on PHP<=7.1 - $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value)); - } elseif (\is_object($value)) { - $result[$key] = array('object', \get_class($value)); - } elseif (\is_array($value)) { - if ($level > 10) { - $result[$key] = array('array', '*DEEP NESTED ARRAY*'); - } else { - $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count)); - } - } elseif (null === $value) { - $result[$key] = array('null', null); - } elseif (\is_bool($value)) { - $result[$key] = array('boolean', $value); - } elseif (\is_int($value)) { - $result[$key] = array('integer', $value); - } elseif (\is_float($value)) { - $result[$key] = array('float', $value); - } elseif (\is_resource($value)) { - $result[$key] = array('resource', get_resource_type($value)); - } else { - $result[$key] = array('string', (string) $value); - } - } - - return $result; - } - - private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value) - { - $array = new \ArrayObject($value); - - return $array['__PHP_Incomplete_Class_Name']; - } -} diff --git a/vendor/symfony/debug/Exception/SilencedErrorContext.php b/vendor/symfony/debug/Exception/SilencedErrorContext.php deleted file mode 100644 index 6f84617..0000000 --- a/vendor/symfony/debug/Exception/SilencedErrorContext.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Exception; - -/** - * Data Object that represents a Silenced Error. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -class SilencedErrorContext implements \JsonSerializable -{ - public $count = 1; - - private $severity; - private $file; - private $line; - private $trace; - - public function __construct(int $severity, string $file, int $line, array $trace = array(), int $count = 1) - { - $this->severity = $severity; - $this->file = $file; - $this->line = $line; - $this->trace = $trace; - $this->count = $count; - } - - public function getSeverity() - { - return $this->severity; - } - - public function getFile() - { - return $this->file; - } - - public function getLine() - { - return $this->line; - } - - public function getTrace() - { - return $this->trace; - } - - public function JsonSerialize() - { - return array( - 'severity' => $this->severity, - 'file' => $this->file, - 'line' => $this->line, - 'trace' => $this->trace, - 'count' => $this->count, - ); - } -} diff --git a/vendor/symfony/debug/Exception/UndefinedFunctionException.php b/vendor/symfony/debug/Exception/UndefinedFunctionException.php deleted file mode 100644 index d936c87..0000000 --- a/vendor/symfony/debug/Exception/UndefinedFunctionException.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Exception; - -/** - * Undefined Function Exception. - * - * @author Konstanton Myakshin <koc-dp@yandex.ru> - */ -class UndefinedFunctionException extends FatalErrorException -{ - public function __construct(string $message, \ErrorException $previous) - { - parent::__construct( - $message, - $previous->getCode(), - $previous->getSeverity(), - $previous->getFile(), - $previous->getLine(), - null, - true, - null, - $previous->getPrevious() - ); - $this->setTrace($previous->getTrace()); - } -} diff --git a/vendor/symfony/debug/Exception/UndefinedMethodException.php b/vendor/symfony/debug/Exception/UndefinedMethodException.php deleted file mode 100644 index f627561..0000000 --- a/vendor/symfony/debug/Exception/UndefinedMethodException.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Exception; - -/** - * Undefined Method Exception. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -class UndefinedMethodException extends FatalErrorException -{ - public function __construct(string $message, \ErrorException $previous) - { - parent::__construct( - $message, - $previous->getCode(), - $previous->getSeverity(), - $previous->getFile(), - $previous->getLine(), - null, - true, - null, - $previous->getPrevious() - ); - $this->setTrace($previous->getTrace()); - } -} diff --git a/vendor/symfony/debug/ExceptionHandler.php b/vendor/symfony/debug/ExceptionHandler.php deleted file mode 100644 index 1845bc8..0000000 --- a/vendor/symfony/debug/ExceptionHandler.php +++ /dev/null @@ -1,440 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug; - -use Symfony\Component\Debug\Exception\FlattenException; -use Symfony\Component\Debug\Exception\OutOfMemoryException; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; - -/** - * ExceptionHandler converts an exception to a Response object. - * - * It is mostly useful in debug mode to replace the default PHP/XDebug - * output with something prettier and more useful. - * - * As this class is mainly used during Kernel boot, where nothing is yet - * available, the Response content is always HTML. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class ExceptionHandler -{ - private $debug; - private $charset; - private $handler; - private $caughtBuffer; - private $caughtLength; - private $fileLinkFormat; - - public function __construct(bool $debug = true, string $charset = null, $fileLinkFormat = null) - { - $this->debug = $debug; - $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8'; - $this->fileLinkFormat = $fileLinkFormat; - } - - /** - * Registers the exception handler. - * - * @param bool $debug Enable/disable debug mode, where the stack trace is displayed - * @param string|null $charset The charset used by exception messages - * @param string|null $fileLinkFormat The IDE link template - * - * @return static - */ - public static function register($debug = true, $charset = null, $fileLinkFormat = null) - { - $handler = new static($debug, $charset, $fileLinkFormat); - - $prev = set_exception_handler(array($handler, 'handle')); - if (\is_array($prev) && $prev[0] instanceof ErrorHandler) { - restore_exception_handler(); - $prev[0]->setExceptionHandler(array($handler, 'handle')); - } - - return $handler; - } - - /** - * Sets a user exception handler. - * - * @param callable $handler An handler that will be called on Exception - * - * @return callable|null The previous exception handler if any - */ - public function setHandler(callable $handler = null) - { - $old = $this->handler; - $this->handler = $handler; - - return $old; - } - - /** - * Sets the format for links to source files. - * - * @param string|FileLinkFormatter $fileLinkFormat The format for links to source files - * - * @return string The previous file link format - */ - public function setFileLinkFormat($fileLinkFormat) - { - $old = $this->fileLinkFormat; - $this->fileLinkFormat = $fileLinkFormat; - - return $old; - } - - /** - * Sends a response for the given Exception. - * - * To be as fail-safe as possible, the exception is first handled - * by our simple exception handler, then by the user exception handler. - * The latter takes precedence and any output from the former is cancelled, - * if and only if nothing bad happens in this handling path. - */ - public function handle(\Exception $exception) - { - if (null === $this->handler || $exception instanceof OutOfMemoryException) { - $this->sendPhpResponse($exception); - - return; - } - - $caughtLength = $this->caughtLength = 0; - - ob_start(function ($buffer) { - $this->caughtBuffer = $buffer; - - return ''; - }); - - $this->sendPhpResponse($exception); - while (null === $this->caughtBuffer && ob_end_flush()) { - // Empty loop, everything is in the condition - } - if (isset($this->caughtBuffer[0])) { - ob_start(function ($buffer) { - if ($this->caughtLength) { - // use substr_replace() instead of substr() for mbstring overloading resistance - $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength); - if (isset($cleanBuffer[0])) { - $buffer = $cleanBuffer; - } - } - - return $buffer; - }); - - echo $this->caughtBuffer; - $caughtLength = ob_get_length(); - } - $this->caughtBuffer = null; - - try { - \call_user_func($this->handler, $exception); - $this->caughtLength = $caughtLength; - } catch (\Exception $e) { - if (!$caughtLength) { - // All handlers failed. Let PHP handle that now. - throw $exception; - } - } - } - - /** - * Sends the error associated with the given Exception as a plain PHP response. - * - * This method uses plain PHP functions like header() and echo to output - * the response. - * - * @param \Exception|FlattenException $exception An \Exception or FlattenException instance - */ - public function sendPhpResponse($exception) - { - if (!$exception instanceof FlattenException) { - $exception = FlattenException::create($exception); - } - - if (!headers_sent()) { - header(sprintf('HTTP/1.0 %s', $exception->getStatusCode())); - foreach ($exception->getHeaders() as $name => $value) { - header($name.': '.$value, false); - } - header('Content-Type: text/html; charset='.$this->charset); - } - - echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception)); - } - - /** - * Gets the full HTML content associated with the given exception. - * - * @param \Exception|FlattenException $exception An \Exception or FlattenException instance - * - * @return string The HTML content as a string - */ - public function getHtml($exception) - { - if (!$exception instanceof FlattenException) { - $exception = FlattenException::create($exception); - } - - return $this->decorate($this->getContent($exception), $this->getStylesheet($exception)); - } - - /** - * Gets the HTML content associated with the given exception. - * - * @return string The content as a string - */ - public function getContent(FlattenException $exception) - { - switch ($exception->getStatusCode()) { - case 404: - $title = 'Sorry, the page you are looking for could not be found.'; - break; - default: - $title = 'Whoops, looks like something went wrong.'; - } - - if (!$this->debug) { - return <<<EOF - <div class="container"> - <h1>$title</h1> - </div> -EOF; - } - - $content = ''; - try { - $count = \count($exception->getAllPrevious()); - $total = $count + 1; - foreach ($exception->toArray() as $position => $e) { - $ind = $count - $position + 1; - $class = $this->formatClass($e['class']); - $message = nl2br($this->escapeHtml($e['message'])); - $content .= sprintf(<<<'EOF' - <div class="trace trace-as-html"> - <table class="trace-details"> - <thead class="trace-head"><tr><th> - <h3 class="trace-class"> - <span class="text-muted">(%d/%d)</span> - <span class="exception_title">%s</span> - </h3> - <p class="break-long-words trace-message">%s</p> - </th></tr></thead> - <tbody> -EOF - , $ind, $total, $class, $message); - foreach ($e['trace'] as $trace) { - $content .= '<tr><td>'; - if ($trace['function']) { - $content .= sprintf('at <span class="trace-class">%s</span><span class="trace-type">%s</span><span class="trace-method">%s</span>(<span class="trace-arguments">%s</span>)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args'])); - } - if (isset($trace['file']) && isset($trace['line'])) { - $content .= $this->formatPath($trace['file'], $trace['line']); - } - $content .= "</td></tr>\n"; - } - - $content .= "</tbody>\n</table>\n</div>\n"; - } - } catch (\Exception $e) { - // something nasty happened and we cannot throw an exception anymore - if ($this->debug) { - $title = sprintf('Exception thrown when handling an exception (%s: %s)', \get_class($e), $this->escapeHtml($e->getMessage())); - } else { - $title = 'Whoops, looks like something went wrong.'; - } - } - - $symfonyGhostImageContents = $this->getSymfonyGhostAsSvg(); - - return <<<EOF - <div class="exception-summary"> - <div class="container"> - <div class="exception-message-wrapper"> - <h1 class="break-long-words exception-message">$title</h1> - <div class="exception-illustration hidden-xs-down">$symfonyGhostImageContents</div> - </div> - </div> - </div> - - <div class="container"> - $content - </div> -EOF; - } - - /** - * Gets the stylesheet associated with the given exception. - * - * @return string The stylesheet as a string - */ - public function getStylesheet(FlattenException $exception) - { - if (!$this->debug) { - return <<<'EOF' - body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; } - .container { margin: 30px; max-width: 600px; } - h1 { color: #dc3545; font-size: 24px; } -EOF; - } - - return <<<'EOF' - body { background-color: #F9F9F9; color: #222; font: 14px/1.4 Helvetica, Arial, sans-serif; margin: 0; padding-bottom: 45px; } - - a { cursor: pointer; text-decoration: none; } - a:hover { text-decoration: underline; } - abbr[title] { border-bottom: none; cursor: help; text-decoration: none; } - - code, pre { font: 13px/1.5 Consolas, Monaco, Menlo, "Ubuntu Mono", "Liberation Mono", monospace; } - - table, tr, th, td { background: #FFF; border-collapse: collapse; vertical-align: top; } - table { background: #FFF; border: 1px solid #E0E0E0; box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; width: 100%; } - table th, table td { border: solid #E0E0E0; border-width: 1px 0; padding: 8px 10px; } - table th { background-color: #E0E0E0; font-weight: bold; text-align: left; } - - .hidden-xs-down { display: none; } - .block { display: block; } - .break-long-words { -ms-word-break: break-all; word-break: break-all; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; } - .text-muted { color: #999; } - - .container { max-width: 1024px; margin: 0 auto; padding: 0 15px; } - .container::after { content: ""; display: table; clear: both; } - - .exception-summary { background: #B0413E; border-bottom: 2px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, .3); flex: 0 0 auto; margin-bottom: 30px; } - - .exception-message-wrapper { display: flex; align-items: center; min-height: 70px; } - .exception-message { flex-grow: 1; padding: 30px 0; } - .exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; } - .exception-message.long { font-size: 18px; } - .exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; } - .exception-message a:hover { border-bottom-color: #ffffff; } - - .exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } - - .trace + .trace { margin-top: 30px; } - .trace-head .trace-class { color: #222; font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; } - - .trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; } - - .trace-file-path, .trace-file-path a { color: #222; margin-top: 3px; font-size: 13px; } - .trace-class { color: #B0413E; } - .trace-type { padding: 0 2px; } - .trace-method { color: #B0413E; font-weight: bold; } - .trace-arguments { color: #777; font-weight: normal; padding-left: 2px; } - - @media (min-width: 575px) { - .hidden-xs-down { display: initial; } - } -EOF; - } - - private function decorate($content, $css) - { - return <<<EOF -<!DOCTYPE html> -<html> - <head> - <meta charset="{$this->charset}" /> - <meta name="robots" content="noindex,nofollow" /> - <style>$css</style> - </head> - <body> - $content - </body> -</html> -EOF; - } - - private function formatClass($class) - { - $parts = explode('\\', $class); - - return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts)); - } - - private function formatPath($path, $line) - { - $file = $this->escapeHtml(preg_match('#[^/\\\\]*+$#', $path, $file) ? $file[0] : $path); - $fmt = $this->fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - - if (!$fmt) { - return sprintf('<span class="block trace-file-path">in <a title="%s%3$s"><strong>%s</strong>%s</a></span>', $this->escapeHtml($path), $file, 0 < $line ? ' line '.$line : ''); - } - - if (\is_string($fmt)) { - $i = strpos($f = $fmt, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f); - $fmt = array(substr($f, 0, $i)) + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE); - - for ($i = 1; isset($fmt[$i]); ++$i) { - if (0 === strpos($path, $k = $fmt[$i++])) { - $path = substr_replace($path, $fmt[$i], 0, \strlen($k)); - break; - } - } - - $link = strtr($fmt[0], array('%f' => $path, '%l' => $line)); - } else { - $link = $fmt->format($path, $line); - } - - return sprintf('<span class="block trace-file-path">in <a href="%s" title="Go to source"><strong>%s</string>%s</a></span>', $this->escapeHtml($link), $file, 0 < $line ? ' line '.$line : ''); - } - - /** - * Formats an array as a string. - * - * @param array $args The argument array - * - * @return string - */ - private function formatArgs(array $args) - { - $result = array(); - foreach ($args as $key => $item) { - if ('object' === $item[0]) { - $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1])); - } elseif ('array' === $item[0]) { - $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); - } elseif ('null' === $item[0]) { - $formattedValue = '<em>null</em>'; - } elseif ('boolean' === $item[0]) { - $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>'; - } elseif ('resource' === $item[0]) { - $formattedValue = '<em>resource</em>'; - } else { - $formattedValue = str_replace("\n", '', $this->escapeHtml(var_export($item[1], true))); - } - - $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue); - } - - return implode(', ', $result); - } - - /** - * HTML-encodes a string. - */ - private function escapeHtml($str) - { - return htmlspecialchars($str, ENT_COMPAT | ENT_SUBSTITUTE, $this->charset); - } - - private function getSymfonyGhostAsSvg() - { - return '<svg viewBox="0 0 136 81" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M92.358 20.403a23.168 23.168 0 0 1 9.003 1.881 23.67 23.67 0 0 1 5.197 3.079 24.257 24.257 0 0 1 3.457 3.296 24.771 24.771 0 0 1 5.042 9.396c.486 1.72.78 3.492.895 5.28l.008.142.028.158.015.246v13.875c.116.034.232.065.348.098.193.054.383.116.577.168.487.125.989.191 1.49.215.338.016.689.023 1.021-.059.021-.005.032-.029.048-.044l.095-.1c.243-.265.461-.552.663-.851.277-.408.523-.837.746-1.279l.042-.087c-.066-.012-.131-.026-.197-.04l-.099-.023a5.536 5.536 0 0 1-.694-.242 5.649 5.649 0 0 1-2.374-1.845 5.694 5.694 0 0 1-.824-1.594 6.514 6.514 0 0 1-.267-2.781c.045-.394.126-.779.233-1.159.079-.278.162-.562.307-.812.094-.163.129-.196.247-.341l.79-.882c.143-.143.174-.186.34-.303.249-.174.536-.289.834-.333.074-.011.15-.014.224-.02l1.188-.037c.173.004.217-.002.388.028s.211.05.375.105l.018.007c.059.026.119.05.176.079.151.076.179.104.313.2l.006-.021c.073-.187.084-.238.187-.41.077-.129.167-.249.27-.357.051-.054.108-.103.162-.154l1.124-.95c.14-.107.172-.14.327-.224.155-.085.199-.094.363-.154l.019-.006c.169-.043.211-.06.385-.077.174-.016.218-.007.392.003l1.446.158c.193.033.244.033.43.098.278.097.534.259.744.47.053.053.1.112.149.167l.923 1.158.149.213.028.054.017-.014.184-.125c.196-.104.196-.104.402-.184l1.386-.451c.064-.018.126-.038.19-.052.129-.028.259-.042.39-.043.16-.002.321.017.478.047.364.069.711.21 1.032.396.162.094.316.199.469.308.088.063.176.132.27.188l.021.011c.19.123.245.146.409.305.185.178.336.393.443.63.035.079.061.162.091.243l.439 1.428c.045.175.062.219.081.4.02.193.006.381-.015.573a7.79 7.79 0 0 1-.101.645c-.09.455-.212.901-.365 1.339-.128.366-.273.73-.445 1.077-.658 1.335-1.652 2.512-2.917 3.265a6.399 6.399 0 0 1-1.019.489 6.097 6.097 0 0 1-.631.203c-.226.058-.455.1-.686.134l-.096.012-.061.007c-.01.176-.022.352-.036.528-.034.39-.082.778-.153 1.163a14.258 14.258 0 0 1-.574 2.114c-.229.654-.484 1.306-.806 1.918a9.16 9.16 0 0 1-.386.656c-.219.348-.451.686-.697 1.013-.448.594-.946 1.148-1.521 1.614-.255.207-.52.397-.808.553-.9.489-1.919.648-2.921.735-.493.038-.986.059-1.478.099-.162.015-.324.033-.486.049-.145.011-.289.022-.434.03a15.768 15.768 0 0 1-2.778-.118c0 1.416.007 2.832-.001 4.248a9.737 9.737 0 0 1-.684 3.479 9.615 9.615 0 0 1-1.72 2.804 9.326 9.326 0 0 1-3.04 2.279 9.046 9.046 0 0 1-5.33.715 9.064 9.064 0 0 1-2.988-1.079 9.363 9.363 0 0 1-2.761-2.429 10.078 10.078 0 0 1-1.05 1.16 9.281 9.281 0 0 1-1.871 1.358 9.033 9.033 0 0 1-2.495.926 9.04 9.04 0 0 1-6.462-1.072 9.395 9.395 0 0 1-2.602-2.292l-.062-.08a10.896 10.896 0 0 1-.53.635 9.266 9.266 0 0 1-2.671 2.032 9.028 9.028 0 0 1-6.044.751 9.048 9.048 0 0 1-2.436-.934 9.343 9.343 0 0 1-2.286-1.803 9.572 9.572 0 0 1-1.783-2.757 9.705 9.705 0 0 1-.773-3.693V67.244c-.157.024-.314.047-.472.067-.487.06-.977.103-1.469.109-.313.004-.627-.009-.94-.028-.426-.025-.85-.065-1.273-.125-1.833-.264-3.65-.92-5.109-2.117a8.172 8.172 0 0 1-1.064-1.049 10.155 10.155 0 0 1-.878-1.236 15.277 15.277 0 0 1-.7-1.274 20.835 20.835 0 0 1-1.889-6.194l-.018-.142-.008-.061a6.47 6.47 0 0 1-.99-.297 6.135 6.135 0 0 1-.61-.285 6.587 6.587 0 0 1-.889-.562c-1.228-.924-2.124-2.259-2.668-3.711a9.947 9.947 0 0 1-.307-.99 10.288 10.288 0 0 1-.318-1.923c-.009-.147-.011-.293-.015-.44v-.037c.008-.175.004-.22.037-.393.033-.173.053-.213.11-.378l.561-1.417c.031-.068.06-.139.095-.206a2.028 2.028 0 0 1 .771-.803c.093-.054.194-.095.289-.145l.311-.179c.352-.194.714-.358 1.107-.44.213-.044.426-.061.643-.061l.034.001c.177.014.223.01.396.052.174.041.214.065.379.132l1.347.635c.073.04.15.076.221.121.142.091.272.2.388.325.154.166.176.222.297.414l.022.047.722-.762.168-.158c.165-.122.202-.161.385-.253.206-.102.429-.168.656-.193.076-.008.152-.008.228-.011l1.46.013c.177.011.223.007.397.046.175.038.215.061.381.126l.018.008c.154.08.196.094.338.196.142.102.169.137.294.259l.853.912.152-.067.191-.063.019-.005.196-.042c.177-.019.222-.031.401-.022.066.003.133.013.199.02l1.185.182c.073.016.147.027.219.047.288.08.558.227.784.428.151.135.177.181.303.339l.714 1.004c.097.152.127.187.201.352.077.172.123.352.164.536.029.134.056.269.08.404.063.361.102.725.112 1.091.021.78-.08 1.566-.321 2.307a5.906 5.906 0 0 1-.532 1.183 5.463 5.463 0 0 1-3.257 2.489l-.03.008c.195.584.433 1.155.712 1.701.215.422.453.833.735 1.211.026.035.026.034.053.068l.058.072c.056.024.113.042.171.06.319.09.653.121.982.14.488.027.978.013 1.461-.06.167-.028.333-.062.499-.089.134-.022.267-.042.401-.066l.28-.056c.154-.023.308-.049.462-.076l.115-.021V43.881c.011-.203.006-.203.042-.404a26.66 26.66 0 0 1 .226-2.241 24.737 24.737 0 0 1 5.72-12.577 24.204 24.204 0 0 1 3.457-3.296 23.653 23.653 0 0 1 4.937-2.966 23.215 23.215 0 0 1 5.604-1.681 23.703 23.703 0 0 1 3.958-.313zm-.287 2.042a21.169 21.169 0 0 0-8.012 1.622 21.636 21.636 0 0 0-4.799 2.766 22.233 22.233 0 0 0-3.205 2.985 22.705 22.705 0 0 0-4.897 9.196 23.383 23.383 0 0 0-.737 4.867h-.025v15.744c-.258.053-.258.052-.517.101-.28.051-.56.1-.841.144-.211.04-.421.079-.632.115l-.232.037-.411.078c-.116.02-.233.035-.348.057-.305.056-.609.11-.917.14a9.929 9.929 0 0 1-1.883-.017c-.514-.056-1.044-.155-1.51-.397a1.762 1.762 0 0 1-.33-.218 1.925 1.925 0 0 1-.234-.252 5.248 5.248 0 0 1-.174-.22 8.97 8.97 0 0 1-.582-.883 13.806 13.806 0 0 1-.941-1.971 14.348 14.348 0 0 1-.608-1.954 14.04 14.04 0 0 1-.169-.86l-.015-.11-.015-.109c.161-.007.16-.007.321-.016a12.793 12.793 0 0 0 1.413-.182 4.43 4.43 0 0 0 .28-.074 3.56 3.56 0 0 0 1.199-.616c.309-.244.576-.543.786-.88.163-.261.292-.544.387-.838.123-.378.192-.774.214-1.172a5.102 5.102 0 0 0-.024-.865 7.192 7.192 0 0 0-.145-.799l-.714-1.005-1.184-.182-.019.005-.946.758-.12 1.229a4.953 4.953 0 0 1 .111.455c.032.181.052.36.043.544a1.04 1.04 0 0 1-.056.303c-.11.301-.419.451-.696.548-.402.142-.813.25-1.229.339l.07-.648c.022-.191.047-.381.08-.57.036-.207.079-.413.152-.61.077-.211.182-.412.296-.605.044-.074.092-.146.135-.222.029-.048.031-.047.055-.098.016-.033.031-.064.045-.098l-.026-1.551-1.042-1.116-.018-.008-1.459-.014-1.022 1.079c-.049.128-.08.258-.111.393a5.274 5.274 0 0 0-.1.651 5.55 5.55 0 0 0-.031.466c-.009.687.104 1.37.294 2.028.11.382.262.753.402 1.123-.115-.029-.228-.06-.342-.092a9.526 9.526 0 0 1-1.176-.446c-.108-.05-.111-.048-.191-.097a1.921 1.921 0 0 1-.327-.249c-.416-.4-.589-.986-.671-1.55a5.643 5.643 0 0 1-.057-.549c-.007-.143-.006-.286-.007-.429-.001-.186.005-.372.011-.558l.001-.039-.567-1.446-1.347-.634c-.316-.008-.599.144-.867.299-.109.063-.218.126-.33.185a2.058 2.058 0 0 1-.125.061l-.042.019-.561 1.416c0 .209.014.416.036.624.04.377.106.75.196 1.118.076.309.164.616.275.913.415 1.109 1.093 2.146 2.043 2.838.234.171.485.317.746.442.183.088.371.161.565.22.263.079.532.13.803.17.296.045.594.075.892.095l.108.007c.004.151.01.302.017.453.011.177.023.353.038.529a18.13 18.13 0 0 0 .762 3.752c.239.76.522 1.505.857 2.225.23.494.483.977.767 1.44.288.469.608.915.989 1.308 1.001 1.028 2.324 1.648 3.687 1.976.643.155 1.298.243 1.955.287.311.021.622.036.933.033.418-.006.835-.041 1.25-.094.238-.03.477-.064.713-.11.117-.023.232-.053.348-.081.196-.048.392-.097.586-.151.147-.041.291-.094.436-.144.204-.069.408-.139.608-.217l.006-.003c0 2.207-.013 4.414.001 6.62a7.942 7.942 0 0 0 .13 1.32 7.545 7.545 0 0 0 2.383 4.243 7.23 7.23 0 0 0 2.258 1.372 7.094 7.094 0 0 0 7.012-1.164 7.504 7.504 0 0 0 2.035-2.613 7.727 7.727 0 0 0 .676-2.401l.009-.088.038-.765a8.16 8.16 0 0 0 .113 1.324c.121.694.338 1.37.643 2.001a7.49 7.49 0 0 0 1.692 2.275 7.266 7.266 0 0 0 2.24 1.399 7.11 7.11 0 0 0 4.615.19 7.212 7.212 0 0 0 2.351-1.218 7.501 7.501 0 0 0 2.128-2.64 7.763 7.763 0 0 0 .702-2.39l.01-.088.009-.088.038-.765a9.339 9.339 0 0 0 .021.575 7.626 7.626 0 0 0 .621 2.504 7.507 7.507 0 0 0 2.35 2.972 7.1 7.1 0 0 0 7.026.881 7.275 7.275 0 0 0 2.268-1.515 7.525 7.525 0 0 0 1.612-2.338 7.58 7.58 0 0 0 .572-2.033c.048-.347.069-.696.071-1.046v-6.721c.136.051.271.101.408.148a12.153 12.153 0 0 0 1.976.443c.264.035.529.055.794.071.33.02.66.031.991.027.245-.002.49-.012.735-.031.245-.018.49-.048.735-.068.407-.03.814-.051 1.221-.079a9.493 9.493 0 0 0 1.384-.188c.315-.073.626-.174.912-.329a3.53 3.53 0 0 0 .586-.418c.46-.386.85-.85 1.205-1.337a12.178 12.178 0 0 0 .801-1.246c.122-.232.229-.471.33-.712a15.873 15.873 0 0 0 .681-1.988c.136-.525.23-1.058.282-1.598.035-.41.052-.822.088-1.232.03-.317.078-.632.121-.947l.018-.145.016-.145c.144.009.287.016.431.021.459.009.924.007 1.378-.07a4.456 4.456 0 0 0 1.353-.482c.989-.55 1.752-1.466 2.258-2.488.116-.235.214-.48.304-.727a7.58 7.58 0 0 0 .377-1.43c.016-.109.027-.218.039-.328l.001-.009-.438-1.428a5.206 5.206 0 0 1-.16-.096c-.158-.105-.311-.219-.467-.326a3.829 3.829 0 0 0-.159-.1 1.356 1.356 0 0 0-.509-.18l-.01-.001-1.386.452-.681 1.323c-.016.212-.023.424-.043.636a5.66 5.66 0 0 1-.139.873c-.118.494-.316.999-.702 1.338a1.865 1.865 0 0 1-.496.301l-.272.087a9.57 9.57 0 0 1-.83.205 8.797 8.797 0 0 1-.582.091l.229-.462c.079-.163.158-.325.229-.492.051-.118.096-.239.139-.36.036-.103.076-.209.103-.315.019-.075.031-.153.041-.229.017-.132.031-.263.043-.395.035-.368.06-.737.094-1.104.02-.187.048-.372.067-.559.015-.167.015-.336.012-.505a4.76 4.76 0 0 0-.074-.826c-.012-.065-.03-.13-.045-.194l-.003-.009-.923-1.157-1.446-.159-.019.006-1.124.95-.154 1.489c.011.034.024.066.037.099.044.115.107.221.161.331.046.096.088.193.13.29l.031.076c.013.033.017.07.023.105.012.096.022.191.031.287.031.364.047.73.081 1.093.013.102.028.202.04.303.014.145.027.29.033.435.014.28.016.561.023.841a9.588 9.588 0 0 1-.862-.323c-.063-.027-.128-.062-.193-.084a1.325 1.325 0 0 0-.067-.013c-.081-.01-.162-.017-.243-.025-.245-.02-.49-.037-.734-.061-.066-.007-.132-.014-.198-.028l-.017-.005c-.03-.013-.029-.014-.067-.038a1.614 1.614 0 0 1-.161-.108.863.863 0 0 1-.22-.242c-.089-.155-.102-.34-.09-.517.02-.299.117-.591.228-.866l.004-.009-.018-1.197-.874-.84-.018-.007-1.188.036-.79.882c-.037.112-.074.224-.106.338a4.756 4.756 0 0 0-.171 1.906c.039.329.115.654.233.963a3.542 3.542 0 0 0 1.263 1.636c.313.222.659.393 1.019.517.237.082.487.111.734.145.479.06.959.106 1.438.166.121.017.241.037.362.058l.158.026a12.12 12.12 0 0 1-.923 2.565 13.221 13.221 0 0 1-.829 1.474 9.474 9.474 0 0 1-.984 1.286c-.08.087-.163.17-.248.252a1.655 1.655 0 0 1-.329.262 2.376 2.376 0 0 1-.722.247c-.457.089-.927.093-1.39.071-.391-.018-.781-.06-1.168-.123a7.817 7.817 0 0 1-.609-.124c-.226-.056-.448-.124-.671-.191-.065-.019-.131-.035-.197-.054a14.75 14.75 0 0 1-.543-.165 23.384 23.384 0 0 1-.453-.128c-.196-.059-.195-.059-.39-.12l-.276-.077V43.881h-.025a34.633 34.633 0 0 0-.031-.557 23.606 23.606 0 0 0-.4-2.994 22.743 22.743 0 0 0-1.492-4.708 22.567 22.567 0 0 0-4.593-6.748 21.865 21.865 0 0 0-6.882-4.706 21.175 21.175 0 0 0-8.115-1.722l-.411-.001zm9.15 33.69c.109.015.214.038.315.085a1.012 1.012 0 0 1 .574.771c.021.132.013.268.009.4a8.38 8.38 0 0 1-.026.476 8.767 8.767 0 0 1-1.564 4.282c-.306.437-.65.846-1.024 1.222a10.09 10.09 0 0 1-4.612 2.627c-1.32.343-2.704.427-4.055.254a10.422 10.422 0 0 1-2.67-.709 9.917 9.917 0 0 1-3.57-2.503 9.312 9.312 0 0 1-.775-.984 8.933 8.933 0 0 1-.731-1.288 8.648 8.648 0 0 1-.795-3.377c-.003-.104-.008-.211 0-.316a1.042 1.042 0 0 1 .254-.609.98.98 0 0 1 1.337-.125 1.023 1.023 0 0 1 .385.719c.007.151.006.303.014.454a6.547 6.547 0 0 0 .524 2.217c.257.595.599 1.15 1.006 1.648.325.398.691.759 1.087 1.081.312.253.642.482.987.684 2.592 1.522 5.945 1.538 8.553.047a7.982 7.982 0 0 0 1.069-.731 7.619 7.619 0 0 0 1.142-1.15 6.949 6.949 0 0 0 1.018-1.741 6.538 6.538 0 0 0 .467-2.425l.004-.084a1.012 1.012 0 0 1 .672-.876c.08-.028.158-.04.241-.05.082-.003.082-.003.164.001zm-70.51-12.426c-15.5.93-28.544-5.922-30.126-16.443C-1.156 15.689 11.64 4.024 29.14 1.235c17.501-2.79 33.123 4.345 34.864 15.922 1.575 10.475-8.749 21.021-23.691 25.001l.001.099a31.185 31.185 0 0 0 .042.833c.007.094.019.188.021.282.006.178.013.356.024.534.011.16.024.32.039.48.017.154.038.306.058.459.036.273.077.544.144.811a4.723 4.723 0 0 0 .449 1.128c.192.332.434.628.702.898l.047.05c.151.139.302.275.461.403.24.192.492.367.748.537.474.314.962.6 1.457.877l.041.023.588.735-.729.586c-.376.112-.755.216-1.135.309a11.193 11.193 0 0 1-2.562.355 8.575 8.575 0 0 1-2.995-.486 8.461 8.461 0 0 1-.96-.413 11.194 11.194 0 0 1-1.836-1.152 13.345 13.345 0 0 1-1.07-.934c-.23-.221-.454-.448-.672-.681-.121-.129-.246-.258-.36-.395a23.448 23.448 0 0 1-1.328-1.773c-.051-.076-.049-.077-.095-.155l-.277-.477-.072-.13c-.081-.177-.159-.357-.238-.535l-.003-.01-.092-.707zm52.409-7.804c3.557 0 6.444 3.201 6.444 7.145 0 3.944-2.887 7.146-6.444 7.146s-6.444-3.202-6.444-7.146 2.887-7.145 6.444-7.145zm18.062 0c3.557 0 6.444 3.201 6.444 7.145 0 3.944-2.887 7.146-6.444 7.146s-6.444-3.202-6.444-7.146 2.887-7.145 6.444-7.145zM83.12 42.029c1.915 0 3.47 1.601 3.47 3.573s-1.555 3.573-3.47 3.573c-1.915 0-3.47-1.601-3.47-3.573s1.555-3.573 3.47-3.573zm17.846 0c1.915 0 3.47 1.601 3.47 3.573s-1.555 3.573-3.47 3.573c-1.915 0-3.47-1.601-3.47-3.573s1.555-3.573 3.47-3.573zM17.019 28c-.368 1.65-1.848 5.008-5.178 5.799-2.572.611-4.153-.815-4.544-2.559-.424-1.891.722-3.532 2.121-4.575a3.473 3.473 0 0 1-1.446-2.099c-.421-1.875.867-3.637 3.184-4.187 1.917-.455 3.185.248 3.462 1.482.265 1.184-.534 2.275-1.828 2.582-.878.209-1.574-.042-1.718-.683a1.4 1.4 0 0 1 .044-.704s.287.227.894.083c.751-.179 1.086-.709.972-1.219-.14-.625-.892-.827-1.739-.626-1.054.25-2.06 1.096-1.713 2.642.232 1.036.871 1.56 1.483 1.813.245-.11.481-.183.688-.233.943-.224 1.48-.005 1.587.472.092.411-.144.935-1.166 1.178a3.255 3.255 0 0 1-1.548.004c-.837.771-1.58 1.883-1.27 3.264.276 1.234 1.267 2.125 2.944 1.726 2.598-.617 3.861-3.638 4.277-4.883-.353-.574-.615-1.153-.732-1.676-.107-.477.145-1.005.863-1.175.48-.114.702.127.846.769a2.77 2.77 0 0 1-.03.995c.209.331.443.622.735.951.616-1.983 1.369-3.877 1.737-3.964.591-.141 1.492.65 1.492.65-.815.644-1.689 2.376-2.333 4.158.804.658 1.627 1.103 2.139.982.43-.102.735-.577.95-1.151-.323-2.226.975-4.331 2.31-4.648.703-.167 1.257.204 1.39.796.114.51-.044 1.379-.854 1.745-.236-1.053-.672-1.348-.944-1.283-.495.117-.844 1.413-.538 2.778.232 1.037.712 1.529 1.351 1.377.756-.179 1.333-1.176 1.699-2.128-.265-2.095.877-4.166 2.221-4.486.671-.159 1.214.162 1.391.952.332 1.48-.986 2.885-2.173 3.444.265.734.673 1.053 1.281.909.96-.229 1.578-1.465 1.923-2.506-.125-1.267-.26-2.385-.406-3.035l-.055-.247s1.568-.286 1.778.652l.019.082c.238-.663.67-1.216 1.309-1.368.83-.197 1.526.504 1.755 1.524.497 2.22-.556 4.428-1.834 4.732-.368.087-.642.066-.883-.033.121 1.288.292 2.651.542 3.77.126.559.272 1.061.448 1.47-.464.11-1.797.392-1.978-.414-.16-.716-.342-3.206-.554-5.612-.504 1.107-1.311 2.192-2.441 2.46-1.008.24-1.685-.303-2.055-1.182-.491 1.082-1.281 2.148-2.381 2.409-.817.194-1.554-.117-1.988-1.013-.36.843-.875 1.555-1.54 1.713-.639.152-1.53-.295-2.4-1.024-.239.888-.384 1.668-.39 2.241 0 0-.701.028-.804-.433-.096-.427.065-1.436.341-2.61a10.315 10.315 0 0 1-.713-.848zm38.163-17.803c.068.157.185.527.266.889.424 1.892.37 4.451.739 6.42-.065.61-.387 3.077-1.352 3.307-.192.045-.333-.06-.422-.454-.14-.626-.091-1.607-.293-2.512-.258-1.152-.782-1.686-1.517-1.511-.767.182-1.287 1.016-1.643 2.054-.022-.099-.053-.386-.093-.567-.211-.938-1.779-.652-1.779-.652a6.2 6.2 0 0 1 .457 1.364c.07.31.119.618.155.921-.246.495-.637.996-1.225 1.135-.064.015-.128.031-.195.029a6.977 6.977 0 0 0-.126-.784c-.258-1.152-.871-2.011-1.526-1.855a.712.712 0 0 0-.423.291c-1.337.317-2.358 2.107-2.118 3.919-.214.889-.551 1.757-1.059 1.877-.415.099-.724-.452-1.03-1.817-.059-.263-.09-.706-.122-1.149.142-.64.177-1.237.081-1.665-.107-.477-.417-.733-.816-.638-.715.17-.909 1.75-.52 3.801-.238.92-.639 1.915-1.278 2.067-.464.11-.835-.27-1.012-1.059-.158-.708-.196-1.929-.236-3.08 1.201-.424 1.911-1.009 1.775-1.617-.114-.51-.739-.743-.739-.743s-.124.722-1.064 1.258c-.029-.582-.064-1.111-.137-1.44-.137-.609-.458-.914-1.688-.622.158.327.274.698.359 1.076.103.46.162.949.189 1.445-.611.128-.947.052-.947.052s-.1.457-.041.72c.078.345.432.348 1.026.224.02 1.364-.067 2.701.143 3.639.306 1.365 1.231 1.89 2.046 1.697.907-.216 1.539-1.275 1.914-2.36.407 1.245 1.031 1.955 1.951 1.736.731-.174 1.261-1.142 1.587-2.195.431.765 1.15 1.129 1.983.931 1.214-.289 1.742-1.54 1.835-2.775 0 0 .147-.018.243-.04.526-.125.949-.488 1.26-.915.04.788.053 1.518.194 2.146.111.493.339.612.595.552.495-.118 1.081-.881 1.081-.881a3.93 3.93 0 0 1-.383-1.035c-.284-1.267.317-3.541.988-3.7.208-.049.377.257.492.767.057.255.092.504.115.751l.098 1.469c.024.246.059.496.116.751.158.707.63 1.236 1.381 1.058 1.317-.313 2.07-2.634 2.178-3.956.228.157.536.175.909.086-.505-2.253.089-6.136-.298-7.864-.1-.444-1.001-.58-1.607-.583l-.467.037zM33.729 22.293c.415-.099.711.246.885 1.02.287 1.283-.222 2.616-.797 2.753-.191.045-.695-.025-.961-1.21-.025-.115-.051-.23-.061-.349.05-1.277.439-2.097.934-2.214zm-5.187.955c.271-.065.511.104.588.449.137.609-.338 1.345-1.275 1.966-.255-1.36.159-2.29.687-2.415zm18.032-.403c-.607.144-1.062-.458-1.239-1.248-.217-.97.001-2.097.644-2.457.001.155.038.32.075.484.147.658.554 1.497 1.268 1.83-.017.749-.253 1.273-.748 1.391zm9.877-1.654c.103.461.496.714 1.039.585.799-.19.973-.993.847-1.553-.125-.559-.461-.93-.988-.805-.543.13-1.108.836-.898 1.773zm-14.21-5.442c-.104-.461-.497-.714-1.056-.581-.783.186-.972.993-.847 1.552.126.56.461.93.908.824.56-.133 1.172-1.006.995-1.795z" fill="#fff" fill-opacity=".6"></path></svg>'; - } -} diff --git a/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php deleted file mode 100644 index 4ccd16f..0000000 --- a/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php +++ /dev/null @@ -1,189 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\FatalErrorHandler; - -use Composer\Autoload\ClassLoader as ComposerClassLoader; -use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader; -use Symfony\Component\Debug\DebugClassLoader; -use Symfony\Component\Debug\Exception\ClassNotFoundException; -use Symfony\Component\Debug\Exception\FatalErrorException; - -/** - * ErrorHandler for classes that do not exist. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface -{ - /** - * {@inheritdoc} - */ - public function handleError(array $error, FatalErrorException $exception) - { - $messageLen = \strlen($error['message']); - $notFoundSuffix = '\' not found'; - $notFoundSuffixLen = \strlen($notFoundSuffix); - if ($notFoundSuffixLen > $messageLen) { - return; - } - - if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) { - return; - } - - foreach (array('class', 'interface', 'trait') as $typeName) { - $prefix = ucfirst($typeName).' \''; - $prefixLen = \strlen($prefix); - if (0 !== strpos($error['message'], $prefix)) { - continue; - } - - $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen); - if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) { - $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1); - $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex); - $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix); - $tail = ' for another namespace?'; - } else { - $className = $fullyQualifiedClassName; - $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className); - $tail = '?'; - } - - if ($candidates = $this->getClassCandidates($className)) { - $tail = array_pop($candidates).'"?'; - if ($candidates) { - $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail; - } else { - $tail = ' for "'.$tail; - } - } - $message .= "\nDid you forget a \"use\" statement".$tail; - - return new ClassNotFoundException($message, $exception); - } - } - - /** - * Tries to guess the full namespace for a given class name. - * - * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer - * autoloader (that should cover all common cases). - * - * @param string $class A class name (without its namespace) - * - * @return array An array of possible fully qualified class names - */ - private function getClassCandidates(string $class): array - { - if (!\is_array($functions = spl_autoload_functions())) { - return array(); - } - - // find Symfony and Composer autoloaders - $classes = array(); - - foreach ($functions as $function) { - if (!\is_array($function)) { - continue; - } - // get class loaders wrapped by DebugClassLoader - if ($function[0] instanceof DebugClassLoader) { - $function = $function[0]->getClassLoader(); - - if (!\is_array($function)) { - continue; - } - } - - if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader) { - foreach ($function[0]->getPrefixes() as $prefix => $paths) { - foreach ($paths as $path) { - $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix)); - } - } - } - if ($function[0] instanceof ComposerClassLoader) { - foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) { - foreach ($paths as $path) { - $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix)); - } - } - } - } - - return array_unique($classes); - } - - private function findClassInPath(string $path, string $class, string $prefix): array - { - if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) { - return array(); - } - - $classes = array(); - $filename = $class.'.php'; - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) { - $classes[] = $class; - } - } - - return $classes; - } - - private function convertFileToClass(string $path, string $file, string $prefix): ?string - { - $candidates = array( - // namespaced class - $namespacedClass = str_replace(array($path.\DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file), - // namespaced class (with target dir) - $prefix.$namespacedClass, - // namespaced class (with target dir and separator) - $prefix.'\\'.$namespacedClass, - // PEAR class - str_replace('\\', '_', $namespacedClass), - // PEAR class (with target dir) - str_replace('\\', '_', $prefix.$namespacedClass), - // PEAR class (with target dir and separator) - str_replace('\\', '_', $prefix.'\\'.$namespacedClass), - ); - - if ($prefix) { - $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); }); - } - - // We cannot use the autoloader here as most of them use require; but if the class - // is not found, the new autoloader call will require the file again leading to a - // "cannot redeclare class" error. - foreach ($candidates as $candidate) { - if ($this->classExists($candidate)) { - return $candidate; - } - } - - require_once $file; - - foreach ($candidates as $candidate) { - if ($this->classExists($candidate)) { - return $candidate; - } - } - - return null; - } - - private function classExists(string $class): bool - { - return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); - } -} diff --git a/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php b/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php deleted file mode 100644 index 6b87eb3..0000000 --- a/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\FatalErrorHandler; - -use Symfony\Component\Debug\Exception\FatalErrorException; - -/** - * Attempts to convert fatal errors to exceptions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface FatalErrorHandlerInterface -{ - /** - * Attempts to convert an error into an exception. - * - * @param array $error An array as returned by error_get_last() - * @param FatalErrorException $exception A FatalErrorException instance - * - * @return FatalErrorException|null A FatalErrorException instance if the class is able to convert the error, null otherwise - */ - public function handleError(array $error, FatalErrorException $exception); -} diff --git a/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php deleted file mode 100644 index db24180..0000000 --- a/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\FatalErrorHandler; - -use Symfony\Component\Debug\Exception\FatalErrorException; -use Symfony\Component\Debug\Exception\UndefinedFunctionException; - -/** - * ErrorHandler for undefined functions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface -{ - /** - * {@inheritdoc} - */ - public function handleError(array $error, FatalErrorException $exception) - { - $messageLen = \strlen($error['message']); - $notFoundSuffix = '()'; - $notFoundSuffixLen = \strlen($notFoundSuffix); - if ($notFoundSuffixLen > $messageLen) { - return; - } - - if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) { - return; - } - - $prefix = 'Call to undefined function '; - $prefixLen = \strlen($prefix); - if (0 !== strpos($error['message'], $prefix)) { - return; - } - - $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen); - if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) { - $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1); - $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex); - $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix); - } else { - $functionName = $fullyQualifiedFunctionName; - $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName); - } - - $candidates = array(); - foreach (get_defined_functions() as $type => $definedFunctionNames) { - foreach ($definedFunctionNames as $definedFunctionName) { - if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) { - $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1); - } else { - $definedFunctionNameBasename = $definedFunctionName; - } - - if ($definedFunctionNameBasename === $functionName) { - $candidates[] = '\\'.$definedFunctionName; - } - } - } - - if ($candidates) { - sort($candidates); - $last = array_pop($candidates).'"?'; - if ($candidates) { - $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; - } else { - $candidates = '"'.$last; - } - $message .= "\nDid you mean to call ".$candidates; - } - - return new UndefinedFunctionException($message, $exception); - } -} diff --git a/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php deleted file mode 100644 index 618a2c2..0000000 --- a/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\FatalErrorHandler; - -use Symfony\Component\Debug\Exception\FatalErrorException; -use Symfony\Component\Debug\Exception\UndefinedMethodException; - -/** - * ErrorHandler for undefined methods. - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - */ -class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface -{ - /** - * {@inheritdoc} - */ - public function handleError(array $error, FatalErrorException $exception) - { - preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches); - if (!$matches) { - return; - } - - $className = $matches[1]; - $methodName = $matches[2]; - - $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className); - - if (!class_exists($className) || null === $methods = get_class_methods($className)) { - // failed to get the class or its methods on which an unknown method was called (for example on an anonymous class) - return new UndefinedMethodException($message, $exception); - } - - $candidates = array(); - foreach ($methods as $definedMethodName) { - $lev = levenshtein($methodName, $definedMethodName); - if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) { - $candidates[] = $definedMethodName; - } - } - - if ($candidates) { - sort($candidates); - $last = array_pop($candidates).'"?'; - if ($candidates) { - $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; - } else { - $candidates = '"'.$last; - } - - $message .= "\nDid you mean to call ".$candidates; - } - - return new UndefinedMethodException($message, $exception); - } -} diff --git a/vendor/symfony/debug/README.md b/vendor/symfony/debug/README.md deleted file mode 100644 index a1d1617..0000000 --- a/vendor/symfony/debug/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Debug Component -=============== - -The Debug component provides tools to ease debugging PHP code. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/debug/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/debug/Tests/DebugClassLoaderTest.php b/vendor/symfony/debug/Tests/DebugClassLoaderTest.php deleted file mode 100644 index 1580ca9..0000000 --- a/vendor/symfony/debug/Tests/DebugClassLoaderTest.php +++ /dev/null @@ -1,333 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Debug\DebugClassLoader; - -class DebugClassLoaderTest extends TestCase -{ - /** - * @var int Error reporting level before running tests - */ - private $errorReporting; - - private $loader; - - protected function setUp() - { - $this->errorReporting = error_reporting(E_ALL); - $this->loader = new ClassLoader(); - spl_autoload_register(array($this->loader, 'loadClass'), true, true); - DebugClassLoader::enable(); - } - - protected function tearDown() - { - DebugClassLoader::disable(); - spl_autoload_unregister(array($this->loader, 'loadClass')); - error_reporting($this->errorReporting); - } - - public function testIdempotence() - { - DebugClassLoader::enable(); - - $functions = spl_autoload_functions(); - foreach ($functions as $function) { - if (is_array($function) && $function[0] instanceof DebugClassLoader) { - $reflClass = new \ReflectionClass($function[0]); - $reflProp = $reflClass->getProperty('classLoader'); - $reflProp->setAccessible(true); - - $this->assertNotInstanceOf('Symfony\Component\Debug\DebugClassLoader', $reflProp->getValue($function[0])); - - return; - } - } - - $this->fail('DebugClassLoader did not register'); - } - - /** - * @expectedException \Exception - * @expectedExceptionMessage boo - */ - public function testThrowingClass() - { - try { - class_exists(__NAMESPACE__.'\Fixtures\Throwing'); - $this->fail('Exception expected'); - } catch (\Exception $e) { - $this->assertSame('boo', $e->getMessage()); - } - - // the second call also should throw - class_exists(__NAMESPACE__.'\Fixtures\Throwing'); - } - - /** - * @expectedException \RuntimeException - */ - public function testNameCaseMismatch() - { - class_exists(__NAMESPACE__.'\TestingCaseMismatch', true); - } - - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage Case mismatch between class and real file names - */ - public function testFileCaseMismatch() - { - if (!file_exists(__DIR__.'/Fixtures/CaseMismatch.php')) { - $this->markTestSkipped('Can only be run on case insensitive filesystems'); - } - - class_exists(__NAMESPACE__.'\Fixtures\CaseMismatch', true); - } - - /** - * @expectedException \RuntimeException - */ - public function testPsr4CaseMismatch() - { - class_exists(__NAMESPACE__.'\Fixtures\Psr4CaseMismatch', true); - } - - public function testNotPsr0() - { - $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\NotPSR0', true)); - } - - public function testNotPsr0Bis() - { - $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\NotPSR0bis', true)); - } - - public function testClassAlias() - { - $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\ClassAlias', true)); - } - - /** - * @dataProvider provideDeprecatedSuper - */ - public function testDeprecatedSuper($class, $super, $type) - { - set_error_handler(function () { return false; }); - $e = error_reporting(0); - trigger_error('', E_USER_DEPRECATED); - - class_exists('Test\\'.__NAMESPACE__.'\\'.$class, true); - - error_reporting($e); - restore_error_handler(); - - $lastError = error_get_last(); - unset($lastError['file'], $lastError['line']); - - $xError = array( - 'type' => E_USER_DEPRECATED, - 'message' => 'The "Test\Symfony\Component\Debug\Tests\\'.$class.'" class '.$type.' "Symfony\Component\Debug\Tests\Fixtures\\'.$super.'" that is deprecated but this is a test deprecation notice.', - ); - - $this->assertSame($xError, $lastError); - } - - public function provideDeprecatedSuper() - { - return array( - array('DeprecatedInterfaceClass', 'DeprecatedInterface', 'implements'), - array('DeprecatedParentClass', 'DeprecatedClass', 'extends'), - ); - } - - public function testInterfaceExtendsDeprecatedInterface() - { - set_error_handler(function () { return false; }); - $e = error_reporting(0); - trigger_error('', E_USER_NOTICE); - - class_exists('Test\\'.__NAMESPACE__.'\\NonDeprecatedInterfaceClass', true); - - error_reporting($e); - restore_error_handler(); - - $lastError = error_get_last(); - unset($lastError['file'], $lastError['line']); - - $xError = array( - 'type' => E_USER_NOTICE, - 'message' => '', - ); - - $this->assertSame($xError, $lastError); - } - - public function testDeprecatedSuperInSameNamespace() - { - set_error_handler(function () { return false; }); - $e = error_reporting(0); - trigger_error('', E_USER_NOTICE); - - class_exists('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent', true); - - error_reporting($e); - restore_error_handler(); - - $lastError = error_get_last(); - unset($lastError['file'], $lastError['line']); - - $xError = array( - 'type' => E_USER_NOTICE, - 'message' => '', - ); - - $this->assertSame($xError, $lastError); - } - - public function testExtendedFinalClass() - { - set_error_handler(function () { return false; }); - $e = error_reporting(0); - trigger_error('', E_USER_NOTICE); - - class_exists('Test\\'.__NAMESPACE__.'\\ExtendsFinalClass', true); - - error_reporting($e); - restore_error_handler(); - - $lastError = error_get_last(); - unset($lastError['file'], $lastError['line']); - - $xError = array( - 'type' => E_USER_DEPRECATED, - 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass".', - ); - - $this->assertSame($xError, $lastError); - } - - public function testExtendedFinalMethod() - { - set_error_handler(function () { return false; }); - $e = error_reporting(0); - trigger_error('', E_USER_NOTICE); - - class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true); - - error_reporting($e); - restore_error_handler(); - - $lastError = error_get_last(); - unset($lastError['file'], $lastError['line']); - - $xError = array( - 'type' => E_USER_DEPRECATED, - 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".', - ); - - $this->assertSame($xError, $lastError); - } - - public function testExtendedDeprecatedMethodDoesntTriggerAnyNotice() - { - set_error_handler(function () { return false; }); - $e = error_reporting(0); - trigger_error('', E_USER_NOTICE); - - class_exists('Test\\'.__NAMESPACE__.'\\ExtendsAnnotatedClass', true); - - error_reporting($e); - restore_error_handler(); - - $lastError = error_get_last(); - unset($lastError['file'], $lastError['line']); - - $this->assertSame(array('type' => E_USER_NOTICE, 'message' => ''), $lastError); - } - - public function testInternalsUse() - { - $deprecations = array(); - set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; }); - $e = error_reporting(E_USER_DEPRECATED); - - class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true); - - error_reporting($e); - restore_error_handler(); - - $this->assertSame($deprecations, array( - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".', - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".', - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait2::internalMethod()" method is considered internal. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', - )); - } -} - -class ClassLoader -{ - public function loadClass($class) - { - } - - public function getClassMap() - { - return array(__NAMESPACE__.'\Fixtures\NotPSR0bis' => __DIR__.'/Fixtures/notPsr0Bis.php'); - } - - public function findFile($class) - { - $fixtureDir = __DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR; - - if (__NAMESPACE__.'\TestingUnsilencing' === $class) { - eval('-- parse error --'); - } elseif (__NAMESPACE__.'\TestingStacking' === $class) { - eval('namespace '.__NAMESPACE__.'; class TestingStacking { function foo() {} }'); - } elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) { - eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}'); - } elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) { - return $fixtureDir.'psr4'.DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php'; - } elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) { - return $fixtureDir.'reallyNotPsr0.php'; - } elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) { - return $fixtureDir.'notPsr0Bis.php'; - } elseif ('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent' === $class) { - eval('namespace Symfony\Bridge\Debug\Tests\Fixtures; class ExtendsDeprecatedParent extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}'); - } elseif ('Test\\'.__NAMESPACE__.'\DeprecatedParentClass' === $class) { - eval('namespace Test\\'.__NAMESPACE__.'; class DeprecatedParentClass extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}'); - } elseif ('Test\\'.__NAMESPACE__.'\DeprecatedInterfaceClass' === $class) { - eval('namespace Test\\'.__NAMESPACE__.'; class DeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\DeprecatedInterface {}'); - } elseif ('Test\\'.__NAMESPACE__.'\NonDeprecatedInterfaceClass' === $class) { - eval('namespace Test\\'.__NAMESPACE__.'; class NonDeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\NonDeprecatedInterface {}'); - } elseif ('Test\\'.__NAMESPACE__.'\Float' === $class) { - eval('namespace Test\\'.__NAMESPACE__.'; class Float {}'); - } elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) { - eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}'); - } elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) { - eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass { - public function deprecatedMethod() { } - }'); - } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternals' === $class) { - eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends ExtendsInternalsParent { - use \\'.__NAMESPACE__.'\Fixtures\InternalTrait; - - public function internalMethod() { } - }'); - } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternalsParent' === $class) { - eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternalsParent extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { }'); - } - } -} diff --git a/vendor/symfony/debug/Tests/ErrorHandlerTest.php b/vendor/symfony/debug/Tests/ErrorHandlerTest.php deleted file mode 100644 index 15e4763..0000000 --- a/vendor/symfony/debug/Tests/ErrorHandlerTest.php +++ /dev/null @@ -1,504 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Tests; - -use PHPUnit\Framework\TestCase; -use Psr\Log\LogLevel; -use Symfony\Component\Debug\BufferingLogger; -use Symfony\Component\Debug\ErrorHandler; -use Symfony\Component\Debug\Exception\SilencedErrorContext; - -/** - * ErrorHandlerTest. - * - * @author Robert Schönthal <seroscho@googlemail.com> - * @author Nicolas Grekas <p@tchwork.com> - */ -class ErrorHandlerTest extends TestCase -{ - public function testRegister() - { - $handler = ErrorHandler::register(); - - try { - $this->assertInstanceOf('Symfony\Component\Debug\ErrorHandler', $handler); - $this->assertSame($handler, ErrorHandler::register()); - - $newHandler = new ErrorHandler(); - - $this->assertSame($handler, ErrorHandler::register($newHandler, false)); - $h = set_error_handler('var_dump'); - restore_error_handler(); - $this->assertSame(array($handler, 'handleError'), $h); - - try { - $this->assertSame($newHandler, ErrorHandler::register($newHandler, true)); - $h = set_error_handler('var_dump'); - restore_error_handler(); - $this->assertSame(array($newHandler, 'handleError'), $h); - } catch (\Exception $e) { - } - - restore_error_handler(); - restore_exception_handler(); - - if (isset($e)) { - throw $e; - } - } catch (\Exception $e) { - } - - restore_error_handler(); - restore_exception_handler(); - - if (isset($e)) { - throw $e; - } - } - - public function testErrorGetLast() - { - $handler = ErrorHandler::register(); - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $handler->setDefaultLogger($logger); - $handler->screamAt(E_ALL); - - try { - @trigger_error('Hello', E_USER_WARNING); - $expected = array( - 'type' => E_USER_WARNING, - 'message' => 'Hello', - 'file' => __FILE__, - 'line' => __LINE__ - 5, - ); - $this->assertSame($expected, error_get_last()); - } catch (\Exception $e) { - restore_error_handler(); - restore_exception_handler(); - - throw $e; - } - } - - public function testNotice() - { - ErrorHandler::register(); - - try { - self::triggerNotice($this); - $this->fail('ErrorException expected'); - } catch (\ErrorException $exception) { - // if an exception is thrown, the test passed - $this->assertEquals(E_NOTICE, $exception->getSeverity()); - $this->assertEquals(__FILE__, $exception->getFile()); - $this->assertRegExp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage()); - - $trace = $exception->getTrace(); - - $this->assertEquals(__FILE__, $trace[0]['file']); - $this->assertEquals(__CLASS__, $trace[0]['class']); - $this->assertEquals('triggerNotice', $trace[0]['function']); - $this->assertEquals('::', $trace[0]['type']); - - $this->assertEquals(__FILE__, $trace[0]['file']); - $this->assertEquals(__CLASS__, $trace[1]['class']); - $this->assertEquals(__FUNCTION__, $trace[1]['function']); - $this->assertEquals('->', $trace[1]['type']); - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } - - // dummy function to test trace in error handler. - private static function triggerNotice($that) - { - $that->assertSame('', $foo.$foo.$bar); - } - - public function testConstruct() - { - try { - $handler = ErrorHandler::register(); - $handler->throwAt(3, true); - $this->assertEquals(3 | E_RECOVERABLE_ERROR | E_USER_ERROR, $handler->throwAt(0)); - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } - - public function testDefaultLogger() - { - try { - $handler = ErrorHandler::register(); - - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - - $handler->setDefaultLogger($logger, E_NOTICE); - $handler->setDefaultLogger($logger, array(E_USER_NOTICE => LogLevel::CRITICAL)); - - $loggers = array( - E_DEPRECATED => array(null, LogLevel::INFO), - E_USER_DEPRECATED => array(null, LogLevel::INFO), - E_NOTICE => array($logger, LogLevel::WARNING), - E_USER_NOTICE => array($logger, LogLevel::CRITICAL), - E_STRICT => array(null, LogLevel::WARNING), - E_WARNING => array(null, LogLevel::WARNING), - E_USER_WARNING => array(null, LogLevel::WARNING), - E_COMPILE_WARNING => array(null, LogLevel::WARNING), - E_CORE_WARNING => array(null, LogLevel::WARNING), - E_USER_ERROR => array(null, LogLevel::CRITICAL), - E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL), - E_COMPILE_ERROR => array(null, LogLevel::CRITICAL), - E_PARSE => array(null, LogLevel::CRITICAL), - E_ERROR => array(null, LogLevel::CRITICAL), - E_CORE_ERROR => array(null, LogLevel::CRITICAL), - ); - $this->assertSame($loggers, $handler->setLoggers(array())); - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } - - public function testHandleError() - { - try { - $handler = ErrorHandler::register(); - $handler->throwAt(0, true); - $this->assertFalse($handler->handleError(0, 'foo', 'foo.php', 12, array())); - - restore_error_handler(); - restore_exception_handler(); - - $handler = ErrorHandler::register(); - $handler->throwAt(3, true); - $this->assertFalse($handler->handleError(4, 'foo', 'foo.php', 12, array())); - - restore_error_handler(); - restore_exception_handler(); - - $handler = ErrorHandler::register(); - $handler->throwAt(3, true); - try { - $handler->handleError(4, 'foo', 'foo.php', 12, array()); - } catch (\ErrorException $e) { - $this->assertSame('Parse Error: foo', $e->getMessage()); - $this->assertSame(4, $e->getSeverity()); - $this->assertSame('foo.php', $e->getFile()); - $this->assertSame(12, $e->getLine()); - } - - restore_error_handler(); - restore_exception_handler(); - - $handler = ErrorHandler::register(); - $handler->throwAt(E_USER_DEPRECATED, true); - $this->assertFalse($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array())); - - restore_error_handler(); - restore_exception_handler(); - - $handler = ErrorHandler::register(); - $handler->throwAt(E_DEPRECATED, true); - $this->assertFalse($handler->handleError(E_DEPRECATED, 'foo', 'foo.php', 12, array())); - - restore_error_handler(); - restore_exception_handler(); - - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - - $warnArgCheck = function ($logLevel, $message, $context) { - $this->assertEquals('info', $logLevel); - $this->assertEquals('User Deprecated: foo', $message); - $this->assertArrayHasKey('exception', $context); - $exception = $context['exception']; - $this->assertInstanceOf(\ErrorException::class, $exception); - $this->assertSame('User Deprecated: foo', $exception->getMessage()); - $this->assertSame(E_USER_DEPRECATED, $exception->getSeverity()); - }; - - $logger - ->expects($this->once()) - ->method('log') - ->will($this->returnCallback($warnArgCheck)) - ; - - $handler = ErrorHandler::register(); - $handler->setDefaultLogger($logger, E_USER_DEPRECATED); - $this->assertTrue($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array())); - - restore_error_handler(); - restore_exception_handler(); - - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - - $line = null; - $logArgCheck = function ($level, $message, $context) use (&$line) { - $this->assertEquals('Notice: Undefined variable: undefVar', $message); - $this->assertArrayHasKey('exception', $context); - $exception = $context['exception']; - $this->assertInstanceOf(SilencedErrorContext::class, $exception); - $this->assertSame(E_NOTICE, $exception->getSeverity()); - $this->assertSame(__FILE__, $exception->getFile()); - $this->assertSame($line, $exception->getLine()); - $this->assertNotEmpty($exception->getTrace()); - $this->assertSame(1, $exception->count); - }; - - $logger - ->expects($this->once()) - ->method('log') - ->will($this->returnCallback($logArgCheck)) - ; - - $handler = ErrorHandler::register(); - $handler->setDefaultLogger($logger, E_NOTICE); - $handler->screamAt(E_NOTICE); - unset($undefVar); - $line = __LINE__ + 1; - @$undefVar++; - - restore_error_handler(); - restore_exception_handler(); - } catch (\Exception $e) { - restore_error_handler(); - restore_exception_handler(); - - throw $e; - } - } - - public function testHandleUserError() - { - try { - $handler = ErrorHandler::register(); - $handler->throwAt(0, true); - - $e = null; - $x = new \Exception('Foo'); - - try { - $f = new Fixtures\ToStringThrower($x); - $f .= ''; // Trigger $f->__toString() - } catch (\Exception $e) { - } - - $this->assertSame($x, $e); - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } - - public function testHandleDeprecation() - { - $logArgCheck = function ($level, $message, $context) { - $this->assertEquals(LogLevel::INFO, $level); - $this->assertArrayHasKey('exception', $context); - $exception = $context['exception']; - $this->assertInstanceOf(\ErrorException::class, $exception); - $this->assertSame('User Deprecated: Foo deprecation', $exception->getMessage()); - }; - - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $logger - ->expects($this->once()) - ->method('log') - ->will($this->returnCallback($logArgCheck)) - ; - - $handler = new ErrorHandler(); - $handler->setDefaultLogger($logger); - @$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, array()); - } - - public function testHandleException() - { - try { - $handler = ErrorHandler::register(); - - $exception = new \Exception('foo'); - - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - - $logArgCheck = function ($level, $message, $context) { - $this->assertSame('Uncaught Exception: foo', $message); - $this->assertArrayHasKey('exception', $context); - $this->assertInstanceOf(\Exception::class, $context['exception']); - }; - - $logger - ->expects($this->exactly(2)) - ->method('log') - ->will($this->returnCallback($logArgCheck)) - ; - - $handler->setDefaultLogger($logger, E_ERROR); - - try { - $handler->handleException($exception); - $this->fail('Exception expected'); - } catch (\Exception $e) { - $this->assertSame($exception, $e); - } - - $handler->setExceptionHandler(function ($e) use ($exception) { - $this->assertSame($exception, $e); - }); - - $handler->handleException($exception); - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } - - public function testBootstrappingLogger() - { - $bootLogger = new BufferingLogger(); - $handler = new ErrorHandler($bootLogger); - - $loggers = array( - E_DEPRECATED => array($bootLogger, LogLevel::INFO), - E_USER_DEPRECATED => array($bootLogger, LogLevel::INFO), - E_NOTICE => array($bootLogger, LogLevel::WARNING), - E_USER_NOTICE => array($bootLogger, LogLevel::WARNING), - E_STRICT => array($bootLogger, LogLevel::WARNING), - E_WARNING => array($bootLogger, LogLevel::WARNING), - E_USER_WARNING => array($bootLogger, LogLevel::WARNING), - E_COMPILE_WARNING => array($bootLogger, LogLevel::WARNING), - E_CORE_WARNING => array($bootLogger, LogLevel::WARNING), - E_USER_ERROR => array($bootLogger, LogLevel::CRITICAL), - E_RECOVERABLE_ERROR => array($bootLogger, LogLevel::CRITICAL), - E_COMPILE_ERROR => array($bootLogger, LogLevel::CRITICAL), - E_PARSE => array($bootLogger, LogLevel::CRITICAL), - E_ERROR => array($bootLogger, LogLevel::CRITICAL), - E_CORE_ERROR => array($bootLogger, LogLevel::CRITICAL), - ); - - $this->assertSame($loggers, $handler->setLoggers(array())); - - $handler->handleError(E_DEPRECATED, 'Foo message', __FILE__, 123, array()); - - $logs = $bootLogger->cleanLogs(); - - $this->assertCount(1, $logs); - $log = $logs[0]; - $this->assertSame('info', $log[0]); - $this->assertSame('Deprecated: Foo message', $log[1]); - $this->assertArrayHasKey('exception', $log[2]); - $exception = $log[2]['exception']; - $this->assertInstanceOf(\ErrorException::class, $exception); - $this->assertSame('Deprecated: Foo message', $exception->getMessage()); - $this->assertSame(__FILE__, $exception->getFile()); - $this->assertSame(123, $exception->getLine()); - $this->assertSame(E_DEPRECATED, $exception->getSeverity()); - - $bootLogger->log(LogLevel::WARNING, 'Foo message', array('exception' => $exception)); - - $mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $mockLogger->expects($this->once()) - ->method('log') - ->with(LogLevel::WARNING, 'Foo message', array('exception' => $exception)); - - $handler->setLoggers(array(E_DEPRECATED => array($mockLogger, LogLevel::WARNING))); - } - - public function testSettingLoggerWhenExceptionIsBuffered() - { - $bootLogger = new BufferingLogger(); - $handler = new ErrorHandler($bootLogger); - - $exception = new \Exception('Foo message'); - - $mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $mockLogger->expects($this->once()) - ->method('log') - ->with(LogLevel::CRITICAL, 'Uncaught Exception: Foo message', array('exception' => $exception)); - - $handler->setExceptionHandler(function () use ($handler, $mockLogger) { - $handler->setDefaultLogger($mockLogger); - }); - - $handler->handleException($exception); - } - - public function testHandleFatalError() - { - try { - $handler = ErrorHandler::register(); - - $error = array( - 'type' => E_PARSE, - 'message' => 'foo', - 'file' => 'bar', - 'line' => 123, - ); - - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - - $logArgCheck = function ($level, $message, $context) { - $this->assertEquals('Fatal Parse Error: foo', $message); - $this->assertArrayHasKey('exception', $context); - $this->assertInstanceOf(\Exception::class, $context['exception']); - }; - - $logger - ->expects($this->once()) - ->method('log') - ->will($this->returnCallback($logArgCheck)) - ; - - $handler->setDefaultLogger($logger, E_PARSE); - - $handler->handleFatalError($error); - - restore_error_handler(); - restore_exception_handler(); - } catch (\Exception $e) { - restore_error_handler(); - restore_exception_handler(); - - throw $e; - } - } - - public function testHandleErrorException() - { - $exception = new \Error("Class 'Foo' not found"); - - $handler = new ErrorHandler(); - $handler->setExceptionHandler(function () use (&$args) { - $args = \func_get_args(); - }); - - $handler->handleException($exception); - - $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $args[0]); - $this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage()); - } - - /** - * @expectedException \Exception - */ - public function testCustomExceptionHandler() - { - $handler = new ErrorHandler(); - $handler->setExceptionHandler(function ($e) use ($handler) { - $handler->handleException($e); - }); - - $handler->handleException(new \Exception()); - } -} diff --git a/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php b/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php deleted file mode 100644 index 4bac160..0000000 --- a/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php +++ /dev/null @@ -1,340 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Tests\Exception; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Debug\Exception\FatalThrowableError; -use Symfony\Component\Debug\Exception\FlattenException; -use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\HttpKernel\Exception\ConflictHttpException; -use Symfony\Component\HttpKernel\Exception\GoneHttpException; -use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException; -use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; -use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException; -use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException; -use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; -use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; -use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; -use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException; - -class FlattenExceptionTest extends TestCase -{ - public function testStatusCode() - { - $flattened = FlattenException::create(new \RuntimeException(), 403); - $this->assertEquals('403', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new \RuntimeException()); - $this->assertEquals('500', $flattened->getStatusCode()); - - $flattened = FlattenException::createFromThrowable(new \DivisionByZeroError(), 403); - $this->assertEquals('403', $flattened->getStatusCode()); - - $flattened = FlattenException::createFromThrowable(new \DivisionByZeroError()); - $this->assertEquals('500', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new NotFoundHttpException()); - $this->assertEquals('404', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new UnauthorizedHttpException('Basic realm="My Realm"')); - $this->assertEquals('401', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new BadRequestHttpException()); - $this->assertEquals('400', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new NotAcceptableHttpException()); - $this->assertEquals('406', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new ConflictHttpException()); - $this->assertEquals('409', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST'))); - $this->assertEquals('405', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new AccessDeniedHttpException()); - $this->assertEquals('403', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new GoneHttpException()); - $this->assertEquals('410', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new LengthRequiredHttpException()); - $this->assertEquals('411', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new PreconditionFailedHttpException()); - $this->assertEquals('412', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new PreconditionRequiredHttpException()); - $this->assertEquals('428', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new ServiceUnavailableHttpException()); - $this->assertEquals('503', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new TooManyRequestsHttpException()); - $this->assertEquals('429', $flattened->getStatusCode()); - - $flattened = FlattenException::create(new UnsupportedMediaTypeHttpException()); - $this->assertEquals('415', $flattened->getStatusCode()); - - if (class_exists(SuspiciousOperationException::class)) { - $flattened = FlattenException::create(new SuspiciousOperationException()); - $this->assertEquals('400', $flattened->getStatusCode()); - } - } - - public function testHeadersForHttpException() - { - $flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST'))); - $this->assertEquals(array('Allow' => 'POST'), $flattened->getHeaders()); - - $flattened = FlattenException::create(new UnauthorizedHttpException('Basic realm="My Realm"')); - $this->assertEquals(array('WWW-Authenticate' => 'Basic realm="My Realm"'), $flattened->getHeaders()); - - $flattened = FlattenException::create(new ServiceUnavailableHttpException('Fri, 31 Dec 1999 23:59:59 GMT')); - $this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders()); - - $flattened = FlattenException::create(new ServiceUnavailableHttpException(120)); - $this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders()); - - $flattened = FlattenException::create(new TooManyRequestsHttpException('Fri, 31 Dec 1999 23:59:59 GMT')); - $this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders()); - - $flattened = FlattenException::create(new TooManyRequestsHttpException(120)); - $this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders()); - } - - /** - * @dataProvider flattenDataProvider - */ - public function testFlattenHttpException(\Throwable $exception) - { - $flattened = FlattenException::createFromThrowable($exception); - $flattened2 = FlattenException::createFromThrowable($exception); - - $flattened->setPrevious($flattened2); - - $this->assertEquals($exception->getMessage(), $flattened->getMessage(), 'The message is copied from the original exception.'); - $this->assertEquals($exception->getCode(), $flattened->getCode(), 'The code is copied from the original exception.'); - $this->assertInstanceOf($flattened->getClass(), $exception, 'The class is set to the class of the original exception'); - } - - public function testWrappedThrowable() - { - $exception = new FatalThrowableError(new \DivisionByZeroError('Ouch', 42)); - $flattened = FlattenException::create($exception); - - $this->assertSame('Ouch', $flattened->getMessage(), 'The message is copied from the original error.'); - $this->assertSame(42, $flattened->getCode(), 'The code is copied from the original error.'); - $this->assertSame('DivisionByZeroError', $flattened->getClass(), 'The class is set to the class of the original error'); - } - - public function testThrowable() - { - $error = new \DivisionByZeroError('Ouch', 42); - $flattened = FlattenException::createFromThrowable($error); - - $this->assertSame('Ouch', $flattened->getMessage(), 'The message is copied from the original error.'); - $this->assertSame(42, $flattened->getCode(), 'The code is copied from the original error.'); - $this->assertSame('DivisionByZeroError', $flattened->getClass(), 'The class is set to the class of the original error'); - } - - /** - * @dataProvider flattenDataProvider - */ - public function testPrevious(\Throwable $exception) - { - $flattened = FlattenException::createFromThrowable($exception); - $flattened2 = FlattenException::createFromThrowable($exception); - - $flattened->setPrevious($flattened2); - - $this->assertSame($flattened2, $flattened->getPrevious()); - - $this->assertSame(array($flattened2), $flattened->getAllPrevious()); - } - - public function testPreviousError() - { - $exception = new \Exception('test', 123, new \ParseError('Oh noes!', 42)); - - $flattened = FlattenException::create($exception)->getPrevious(); - - $this->assertEquals($flattened->getMessage(), 'Oh noes!', 'The message is copied from the original exception.'); - $this->assertEquals($flattened->getCode(), 42, 'The code is copied from the original exception.'); - $this->assertEquals($flattened->getClass(), 'ParseError', 'The class is set to the class of the original exception'); - } - - /** - * @dataProvider flattenDataProvider - */ - public function testLine(\Throwable $exception) - { - $flattened = FlattenException::createFromThrowable($exception); - $this->assertSame($exception->getLine(), $flattened->getLine()); - } - - /** - * @dataProvider flattenDataProvider - */ - public function testFile(\Throwable $exception) - { - $flattened = FlattenException::createFromThrowable($exception); - $this->assertSame($exception->getFile(), $flattened->getFile()); - } - - /** - * @dataProvider flattenDataProvider - */ - public function testToArray(\Throwable $exception, string $expectedClass) - { - $flattened = FlattenException::createFromThrowable($exception); - $flattened->setTrace(array(), 'foo.php', 123); - - $this->assertEquals(array( - array( - 'message' => 'test', - 'class' => $expectedClass, - 'trace' => array(array( - 'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123, - 'args' => array(), - )), - ), - ), $flattened->toArray()); - } - - public function testCreate() - { - $exception = new NotFoundHttpException( - 'test', - new \RuntimeException('previous', 123) - ); - - $this->assertSame( - FlattenException::createFromThrowable($exception)->toArray(), - FlattenException::create($exception)->toArray() - ); - } - - public function flattenDataProvider() - { - return array( - array(new \Exception('test', 123), 'Exception'), - array(new \Error('test', 123), 'Error'), - ); - } - - public function testArguments() - { - $dh = opendir(__DIR__); - $fh = tmpfile(); - - $incomplete = unserialize('O:14:"BogusTestClass":0:{}'); - - $exception = $this->createException(array( - (object) array('foo' => 1), - new NotFoundHttpException(), - $incomplete, - $dh, - $fh, - function () {}, - array(1, 2), - array('foo' => 123), - null, - true, - false, - 0, - 0.0, - '0', - '', - INF, - NAN, - )); - - $flattened = FlattenException::create($exception); - $trace = $flattened->getTrace(); - $args = $trace[1]['args']; - $array = $args[0][1]; - - closedir($dh); - fclose($fh); - - $i = 0; - $this->assertSame(array('object', 'stdClass'), $array[$i++]); - $this->assertSame(array('object', 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'), $array[$i++]); - $this->assertSame(array('incomplete-object', 'BogusTestClass'), $array[$i++]); - $this->assertSame(array('resource', 'stream'), $array[$i++]); - $this->assertSame(array('resource', 'stream'), $array[$i++]); - - $args = $array[$i++]; - $this->assertSame($args[0], 'object'); - $this->assertTrue('Closure' === $args[1] || is_subclass_of($args[1], '\Closure'), 'Expect object class name to be Closure or a subclass of Closure.'); - - $this->assertSame(array('array', array(array('integer', 1), array('integer', 2))), $array[$i++]); - $this->assertSame(array('array', array('foo' => array('integer', 123))), $array[$i++]); - $this->assertSame(array('null', null), $array[$i++]); - $this->assertSame(array('boolean', true), $array[$i++]); - $this->assertSame(array('boolean', false), $array[$i++]); - $this->assertSame(array('integer', 0), $array[$i++]); - $this->assertSame(array('float', 0.0), $array[$i++]); - $this->assertSame(array('string', '0'), $array[$i++]); - $this->assertSame(array('string', ''), $array[$i++]); - $this->assertSame(array('float', INF), $array[$i++]); - - // assertEquals() does not like NAN values. - $this->assertEquals($array[$i][0], 'float'); - $this->assertTrue(is_nan($array[$i++][1])); - } - - public function testRecursionInArguments() - { - $a = null; - $a = array('foo', array(2, &$a)); - $exception = $this->createException($a); - - $flattened = FlattenException::create($exception); - $trace = $flattened->getTrace(); - $this->assertContains('*DEEP NESTED ARRAY*', serialize($trace)); - } - - public function testTooBigArray() - { - $a = array(); - for ($i = 0; $i < 20; ++$i) { - for ($j = 0; $j < 50; ++$j) { - for ($k = 0; $k < 10; ++$k) { - $a[$i][$j][$k] = 'value'; - } - } - } - $a[20] = 'value'; - $a[21] = 'value1'; - $exception = $this->createException($a); - - $flattened = FlattenException::create($exception); - $trace = $flattened->getTrace(); - - $this->assertSame($trace[1]['args'][0], array('array', array('array', '*SKIPPED over 10000 entries*'))); - - $serializeTrace = serialize($trace); - - $this->assertContains('*SKIPPED over 10000 entries*', $serializeTrace); - $this->assertNotContains('*value1*', $serializeTrace); - } - - private function createException($foo) - { - return new \Exception(); - } -} diff --git a/vendor/symfony/debug/Tests/ExceptionHandlerTest.php b/vendor/symfony/debug/Tests/ExceptionHandlerTest.php deleted file mode 100644 index 6ff6a74..0000000 --- a/vendor/symfony/debug/Tests/ExceptionHandlerTest.php +++ /dev/null @@ -1,133 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Debug\Exception\OutOfMemoryException; -use Symfony\Component\Debug\ExceptionHandler; -use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; - -require_once __DIR__.'/HeaderMock.php'; - -class ExceptionHandlerTest extends TestCase -{ - protected function setUp() - { - testHeader(); - } - - protected function tearDown() - { - testHeader(); - } - - public function testDebug() - { - $handler = new ExceptionHandler(false); - - ob_start(); - $handler->sendPhpResponse(new \RuntimeException('Foo')); - $response = ob_get_clean(); - - $this->assertContains('Whoops, looks like something went wrong.', $response); - $this->assertNotContains('<div class="trace trace-as-html">', $response); - - $handler = new ExceptionHandler(true); - - ob_start(); - $handler->sendPhpResponse(new \RuntimeException('Foo')); - $response = ob_get_clean(); - - $this->assertContains('Whoops, looks like something went wrong.', $response); - $this->assertContains('<div class="trace trace-as-html">', $response); - } - - public function testStatusCode() - { - $handler = new ExceptionHandler(false, 'iso8859-1'); - - ob_start(); - $handler->sendPhpResponse(new NotFoundHttpException('Foo')); - $response = ob_get_clean(); - - $this->assertContains('Sorry, the page you are looking for could not be found.', $response); - - $expectedHeaders = array( - array('HTTP/1.0 404', true, null), - array('Content-Type: text/html; charset=iso8859-1', true, null), - ); - - $this->assertSame($expectedHeaders, testHeader()); - } - - public function testHeaders() - { - $handler = new ExceptionHandler(false, 'iso8859-1'); - - ob_start(); - $handler->sendPhpResponse(new MethodNotAllowedHttpException(array('POST'))); - $response = ob_get_clean(); - - $expectedHeaders = array( - array('HTTP/1.0 405', true, null), - array('Allow: POST', false, null), - array('Content-Type: text/html; charset=iso8859-1', true, null), - ); - - $this->assertSame($expectedHeaders, testHeader()); - } - - public function testNestedExceptions() - { - $handler = new ExceptionHandler(true); - ob_start(); - $handler->sendPhpResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar'))); - $response = ob_get_clean(); - - $this->assertStringMatchesFormat('%A<p class="break-long-words trace-message">Foo</p>%A<p class="break-long-words trace-message">Bar</p>%A', $response); - } - - public function testHandle() - { - $exception = new \Exception('foo'); - - $handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(array('sendPhpResponse'))->getMock(); - $handler - ->expects($this->exactly(2)) - ->method('sendPhpResponse'); - - $handler->handle($exception); - - $handler->setHandler(function ($e) use ($exception) { - $this->assertSame($exception, $e); - }); - - $handler->handle($exception); - } - - public function testHandleOutOfMemoryException() - { - $exception = new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__); - - $handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(array('sendPhpResponse'))->getMock(); - $handler - ->expects($this->once()) - ->method('sendPhpResponse'); - - $handler->setHandler(function ($e) { - $this->fail('OutOfMemoryException should bypass the handler'); - }); - - $handler->handle($exception); - } -} diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php deleted file mode 100644 index 5cdac2f..0000000 --- a/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php +++ /dev/null @@ -1,176 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Tests\FatalErrorHandler; - -use Composer\Autoload\ClassLoader as ComposerClassLoader; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Debug\DebugClassLoader; -use Symfony\Component\Debug\Exception\FatalErrorException; -use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler; - -class ClassNotFoundFatalErrorHandlerTest extends TestCase -{ - public static function setUpBeforeClass() - { - foreach (spl_autoload_functions() as $function) { - if (!\is_array($function)) { - continue; - } - - // get class loaders wrapped by DebugClassLoader - if ($function[0] instanceof DebugClassLoader) { - $function = $function[0]->getClassLoader(); - } - - if ($function[0] instanceof ComposerClassLoader) { - $function[0]->add('Symfony_Component_Debug_Tests_Fixtures', \dirname(\dirname(\dirname(\dirname(\dirname(__DIR__)))))); - break; - } - } - } - - /** - * @dataProvider provideClassNotFoundData - */ - public function testHandleClassNotFound($error, $translatedMessage, $autoloader = null) - { - if ($autoloader) { - // Unregister all autoloaders to ensure the custom provided - // autoloader is the only one to be used during the test run. - $autoloaders = spl_autoload_functions(); - array_map('spl_autoload_unregister', $autoloaders); - spl_autoload_register($autoloader); - } - - $handler = new ClassNotFoundFatalErrorHandler(); - - $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); - - if ($autoloader) { - spl_autoload_unregister($autoloader); - array_map('spl_autoload_register', $autoloaders); - } - - $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception); - $this->assertSame($translatedMessage, $exception->getMessage()); - $this->assertSame($error['type'], $exception->getSeverity()); - $this->assertSame($error['file'], $exception->getFile()); - $this->assertSame($error['line'], $exception->getLine()); - } - - public function provideClassNotFoundData() - { - $autoloader = new ComposerClassLoader(); - $autoloader->add('Symfony\Component\Debug\Exception\\', realpath(__DIR__.'/../../Exception')); - - $debugClassLoader = new DebugClassLoader(array($autoloader, 'loadClass')); - - return array( - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Class \'WhizBangFactory\' not found', - ), - "Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement?", - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Class \'Foo\\Bar\\WhizBangFactory\' not found', - ), - "Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?", - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Class \'UndefinedFunctionException\' not found', - ), - "Attempted to load class \"UndefinedFunctionException\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Class \'PEARClass\' not found', - ), - "Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_Debug_Tests_Fixtures_PEARClass\"?", - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', - ), - "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', - ), - "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", - array($autoloader, 'loadClass'), - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', - ), - "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", - array($debugClassLoader, 'loadClass'), - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', - ), - "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?", - function ($className) { /* do nothing here */ }, - ), - ); - } - - public function testCannotRedeclareClass() - { - if (!file_exists(__DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP')) { - $this->markTestSkipped('Can only be run on case insensitive filesystems'); - } - - require_once __DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP'; - - $error = array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Class \'Foo\\Bar\\RequiredTwice\' not found', - ); - - $handler = new ClassNotFoundFatalErrorHandler(); - $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); - - $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception); - } -} diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php deleted file mode 100644 index 60153fc..0000000 --- a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Tests\FatalErrorHandler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Debug\Exception\FatalErrorException; -use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler; - -class UndefinedFunctionFatalErrorHandlerTest extends TestCase -{ - /** - * @dataProvider provideUndefinedFunctionData - */ - public function testUndefinedFunction($error, $translatedMessage) - { - $handler = new UndefinedFunctionFatalErrorHandler(); - $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); - - $this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedFunctionException', $exception); - // class names are case insensitive and PHP do not return the same - $this->assertSame(strtolower($translatedMessage), strtolower($exception->getMessage())); - $this->assertSame($error['type'], $exception->getSeverity()); - $this->assertSame($error['file'], $exception->getFile()); - $this->assertSame($error['line'], $exception->getLine()); - } - - public function provideUndefinedFunctionData() - { - return array( - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Call to undefined function test_namespaced_function()', - ), - "Attempted to call function \"test_namespaced_function\" from the global namespace.\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?", - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Call to undefined function Foo\\Bar\\Baz\\test_namespaced_function()', - ), - "Attempted to call function \"test_namespaced_function\" from namespace \"Foo\\Bar\\Baz\".\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?", - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Call to undefined function foo()', - ), - 'Attempted to call function "foo" from the global namespace.', - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Call to undefined function Foo\\Bar\\Baz\\foo()', - ), - 'Attempted to call function "foo" from namespace "Foo\Bar\Baz".', - ), - ); - } -} - -function test_namespaced_function() -{ -} diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php deleted file mode 100644 index 739e5b2..0000000 --- a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Tests\FatalErrorHandler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Debug\Exception\FatalErrorException; -use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler; - -class UndefinedMethodFatalErrorHandlerTest extends TestCase -{ - /** - * @dataProvider provideUndefinedMethodData - */ - public function testUndefinedMethod($error, $translatedMessage) - { - $handler = new UndefinedMethodFatalErrorHandler(); - $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); - - $this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedMethodException', $exception); - $this->assertSame($translatedMessage, $exception->getMessage()); - $this->assertSame($error['type'], $exception->getSeverity()); - $this->assertSame($error['file'], $exception->getFile()); - $this->assertSame($error['line'], $exception->getLine()); - } - - public function provideUndefinedMethodData() - { - return array( - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Call to undefined method SplObjectStorage::what()', - ), - 'Attempted to call an undefined method named "what" of class "SplObjectStorage".', - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Call to undefined method SplObjectStorage::walid()', - ), - "Attempted to call an undefined method named \"walid\" of class \"SplObjectStorage\".\nDid you mean to call \"valid\"?", - ), - array( - array( - 'type' => 1, - 'line' => 12, - 'file' => 'foo.php', - 'message' => 'Call to undefined method SplObjectStorage::offsetFet()', - ), - "Attempted to call an undefined method named \"offsetFet\" of class \"SplObjectStorage\".\nDid you mean to call e.g. \"offsetGet\", \"offsetSet\" or \"offsetUnset\"?", - ), - array( - array( - 'type' => 1, - 'message' => 'Call to undefined method class@anonymous::test()', - 'file' => '/home/possum/work/symfony/test.php', - 'line' => 11, - ), - 'Attempted to call an undefined method named "test" of class "class@anonymous".', - ), - ); - } -} diff --git a/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php b/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php deleted file mode 100644 index 4eecb6d..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -class AnnotatedClass -{ - /** - * @deprecated - */ - public function deprecatedMethod() - { - } -} diff --git a/vendor/symfony/debug/Tests/Fixtures/ClassAlias.php b/vendor/symfony/debug/Tests/Fixtures/ClassAlias.php deleted file mode 100644 index 9d6dbaa..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/ClassAlias.php +++ /dev/null @@ -1,3 +0,0 @@ -<?php - -class_alias('Symfony\Component\Debug\Tests\Fixtures\NotPSR0bis', 'Symfony\Component\Debug\Tests\Fixtures\ClassAlias'); diff --git a/vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php b/vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php deleted file mode 100644 index 51fde5a..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/DeprecatedClass.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -/** - * @deprecated but this is a test - * deprecation notice - * @foobar - */ -class DeprecatedClass -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php b/vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php deleted file mode 100644 index 6bab62f..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/DeprecatedInterface.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -/** - * @deprecated but this is a test - * deprecation notice - * @foobar - */ -interface DeprecatedInterface -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php b/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php deleted file mode 100644 index 2bd337e..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -class ExtendedFinalMethod extends FinalMethod -{ - /** - * {@inheritdoc} - */ - public function finalMethod() - { - } - - public function anotherMethod() - { - } -} diff --git a/vendor/symfony/debug/Tests/Fixtures/FinalClass.php b/vendor/symfony/debug/Tests/Fixtures/FinalClass.php deleted file mode 100644 index f4c69b8..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/FinalClass.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -/** - * @final - */ -class FinalClass -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php b/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php deleted file mode 100644 index d8c673a..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -class FinalMethod -{ - /** - * @final - */ - public function finalMethod() - { - } - - public function anotherMethod() - { - } -} diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalClass.php b/vendor/symfony/debug/Tests/Fixtures/InternalClass.php deleted file mode 100644 index 30efe79..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/InternalClass.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -/** - * @internal - */ -class InternalClass -{ - use InternalTrait2; - - public function usedInInternalClass() - { - } -} diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalInterface.php b/vendor/symfony/debug/Tests/Fixtures/InternalInterface.php deleted file mode 100644 index dd79f50..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/InternalInterface.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -/** - * @internal - */ -interface InternalInterface -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalTrait.php b/vendor/symfony/debug/Tests/Fixtures/InternalTrait.php deleted file mode 100644 index 7bb4635..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/InternalTrait.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -/** - * @internal - */ -trait InternalTrait -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php b/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php deleted file mode 100644 index e4cbe12..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -/** - * @internal - */ -trait InternalTrait2 -{ - /** - * @internal - */ - public function internalMethod() - { - } - - /** - * @internal but should not trigger a deprecation - */ - public function usedInInternalClass() - { - } -} diff --git a/vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php b/vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php deleted file mode 100644 index a4179a5..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/NonDeprecatedInterface.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -interface NonDeprecatedInterface extends DeprecatedInterface -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures/PEARClass.php b/vendor/symfony/debug/Tests/Fixtures/PEARClass.php deleted file mode 100644 index 39f2281..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/PEARClass.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php - -class Symfony_Component_Debug_Tests_Fixtures_PEARClass -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures/Throwing.php b/vendor/symfony/debug/Tests/Fixtures/Throwing.php deleted file mode 100644 index 21e0aba..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/Throwing.php +++ /dev/null @@ -1,3 +0,0 @@ -<?php - -throw new \Exception('boo'); diff --git a/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php b/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php deleted file mode 100644 index 40a5fb7..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -class ToStringThrower -{ - private $exception; - - public function __construct(\Exception $e) - { - $this->exception = $e; - } - - public function __toString() - { - try { - throw $this->exception; - } catch (\Exception $e) { - // Using user_error() here is on purpose so we do not forget - // that this alias also should work alongside with trigger_error(). - return user_error($e, E_USER_ERROR); - } - } -} diff --git a/vendor/symfony/debug/Tests/Fixtures/casemismatch.php b/vendor/symfony/debug/Tests/Fixtures/casemismatch.php deleted file mode 100644 index 691d660..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/casemismatch.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -class CaseMismatch -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php b/vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php deleted file mode 100644 index 4cf5267..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/notPsr0Bis.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -class NotPSR0bis -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php b/vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php deleted file mode 100644 index ec48dd2..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/psr4/Psr4CaseMismatch.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -class PSR4CaseMismatch -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php b/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php deleted file mode 100644 index 8554725..0000000 --- a/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -class NotPSR0 -{ -} diff --git a/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php b/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php deleted file mode 100644 index 604bc37..0000000 --- a/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures2; - -class RequiredTwice -{ -} diff --git a/vendor/symfony/debug/Tests/HeaderMock.php b/vendor/symfony/debug/Tests/HeaderMock.php deleted file mode 100644 index 3d8d84c..0000000 --- a/vendor/symfony/debug/Tests/HeaderMock.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug; - -function headers_sent() -{ - return false; -} - -function header($str, $replace = true, $status = null) -{ - Tests\testHeader($str, $replace, $status); -} - -namespace Symfony\Component\Debug\Tests; - -function testHeader() -{ - static $headers = array(); - - if (!$h = \func_get_args()) { - $h = $headers; - $headers = array(); - - return $h; - } - - $headers[] = \func_get_args(); -} diff --git a/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt b/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt deleted file mode 100644 index 41c56c9..0000000 --- a/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---TEST-- -Test DebugClassLoader with previously loaded parents ---FILE-- -<?php - -namespace Symfony\Component\Debug\Tests\Fixtures; - -use Symfony\Component\Debug\DebugClassLoader; - -$vendor = __DIR__; -while (!file_exists($vendor.'/vendor')) { - $vendor = \dirname($vendor); -} -require $vendor.'/vendor/autoload.php'; - -class_exists(FinalMethod::class); - -set_error_handler(function ($type, $msg) { echo $msg, "\n"; }); - -DebugClassLoader::enable(); - -class_exists(ExtendedFinalMethod::class); - -?> ---EXPECTF-- -The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod". diff --git a/vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt b/vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt deleted file mode 100644 index 74cf2e9..0000000 --- a/vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt +++ /dev/null @@ -1,47 +0,0 @@ ---TEST-- -Test catching fatal errors when handlers are nested ---FILE-- -<?php - -namespace Symfony\Component\Debug; - -$vendor = __DIR__; -while (!file_exists($vendor.'/vendor')) { - $vendor = \dirname($vendor); -} -require $vendor.'/vendor/autoload.php'; - -set_error_handler('var_dump'); -set_exception_handler('var_dump'); - -ErrorHandler::register(null, false); - -if (true) { - class foo extends missing - { - } -} - -?> ---EXPECTF-- -Fatal error: Class 'Symfony\Component\Debug\missing' not found in %s on line %d -object(Symfony\Component\Debug\Exception\ClassNotFoundException)#%d (8) { - ["message":protected]=> - string(131) "Attempted to load class "missing" from namespace "Symfony\Component\Debug". -Did you forget a "use" statement for another namespace?" - ["string":"Exception":private]=> - string(0) "" - ["code":protected]=> - int(0) - ["file":protected]=> - string(%d) "%s" - ["line":protected]=> - int(%d) - ["trace":"Exception":private]=> - array(0) { - } - ["previous":"Exception":private]=> - NULL - ["severity":protected]=> - int(1) -} diff --git a/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt b/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt deleted file mode 100644 index 3f45595..0000000 --- a/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt +++ /dev/null @@ -1,35 +0,0 @@ ---TEST-- -Test rethrowing in custom exception handler ---FILE-- -<?php - -namespace Symfony\Component\Debug; - -$vendor = __DIR__; -while (!file_exists($vendor.'/vendor')) { - $vendor = \dirname($vendor); -} -require $vendor.'/vendor/autoload.php'; - -if (true) { - class TestLogger extends \Psr\Log\AbstractLogger - { - public function log($level, $message, array $context = array()) - { - echo $message, "\n"; - } - } -} - -set_exception_handler(function ($e) { echo 123; throw $e; }); -ErrorHandler::register()->setDefaultLogger(new TestLogger()); -ini_set('display_errors', 1); - -throw new \Exception('foo'); -?> ---EXPECTF-- -Uncaught Exception: foo -123 -Fatal error: Uncaught %s:25 -Stack trace: -%a diff --git a/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt b/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt deleted file mode 100644 index 2b74e5c..0000000 --- a/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt +++ /dev/null @@ -1,42 +0,0 @@ ---TEST-- -Test catching fatal errors when handlers are nested ---FILE-- -<?php - -namespace Symfony\Component\Debug; - -$vendor = __DIR__; -while (!file_exists($vendor.'/vendor')) { - $vendor = \dirname($vendor); -} -require $vendor.'/vendor/autoload.php'; - -Debug::enable(); -ini_set('display_errors', 0); - -$eHandler = set_error_handler('var_dump'); -$xHandler = set_exception_handler('var_dump'); - -var_dump(array( - $eHandler[0] === $xHandler[0] ? 'Error and exception handlers do match' : 'Error and exception handlers are different', -)); - -$eHandler[0]->setExceptionHandler('print_r'); - -if (true) { - class Broken implements \Serializable - { - } -} - -?> ---EXPECTF-- -array(1) { - [0]=> - string(37) "Error and exception handlers do match" -} -object(Symfony\Component\Debug\Exception\FatalErrorException)#%d (%d) { - ["message":protected]=> - string(199) "Error: Class Symfony\Component\Debug\Broken contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Serializable::serialize, Serializable::unserialize)" -%a -} diff --git a/vendor/symfony/debug/composer.json b/vendor/symfony/debug/composer.json deleted file mode 100644 index 9b2deeb..0000000 --- a/vendor/symfony/debug/composer.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "symfony/debug", - "type": "library", - "description": "Symfony Debug Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.1.3", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": "<3.4" - }, - "require-dev": { - "symfony/http-kernel": "~3.4|~4.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Debug\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "4.1-dev" - } - } -} diff --git a/vendor/symfony/debug/phpunit.xml.dist b/vendor/symfony/debug/phpunit.xml.dist deleted file mode 100644 index 12e5861..0000000 --- a/vendor/symfony/debug/phpunit.xml.dist +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" - backupGlobals="false" - colors="true" - bootstrap="vendor/autoload.php" - failOnRisky="true" - failOnWarning="true" -> - <php> - <ini name="error_reporting" value="-1" /> - </php> - - <testsuites> - <testsuite name="Symfony Debug Component Test Suite"> - <directory>./Tests/</directory> - </testsuite> - <testsuite name="Symfony Debug Extension Test Suite"> - <directory suffix=".phpt">./Resources/ext/tests/</directory> - </testsuite> - </testsuites> - - <filter> - <whitelist> - <directory>./</directory> - <exclude> - <directory>./Tests</directory> - <directory>./vendor</directory> - </exclude> - </whitelist> - </filter> -</phpunit> diff --git a/vendor/symfony/console/.gitignore b/vendor/symfony/deprecation-contracts/.gitignore similarity index 100% rename from vendor/symfony/console/.gitignore rename to vendor/symfony/deprecation-contracts/.gitignore diff --git a/vendor/symfony/deprecation-contracts/CHANGELOG.md b/vendor/symfony/deprecation-contracts/CHANGELOG.md new file mode 100644 index 0000000..7932e26 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/main/CHANGELOG.md diff --git a/vendor/symfony/debug/LICENSE b/vendor/symfony/deprecation-contracts/LICENSE similarity index 96% rename from vendor/symfony/debug/LICENSE rename to vendor/symfony/deprecation-contracts/LICENSE index 21d7fb9..406242f 100644 --- a/vendor/symfony/debug/LICENSE +++ b/vendor/symfony/deprecation-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2020-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/vendor/symfony/deprecation-contracts/README.md b/vendor/symfony/deprecation-contracts/README.md new file mode 100644 index 0000000..4957933 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/README.md @@ -0,0 +1,26 @@ +Symfony Deprecation Contracts +============================= + +A generic function and convention to trigger deprecation notices. + +This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices. + +By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component, +the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments. + +The function requires at least 3 arguments: + - the name of the Composer package that is triggering the deprecation + - the version of the package that introduced the deprecation + - the message of the deprecation + - more arguments can be provided: they will be inserted in the message using `printf()` formatting + +Example: +```php +trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin'); +``` + +This will generate the following message: +`Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.` + +While not necessarily recommended, the deprecation notices can be completely ignored by declaring an empty +`function trigger_deprecation() {}` in your application. diff --git a/vendor/symfony/deprecation-contracts/composer.json b/vendor/symfony/deprecation-contracts/composer.json new file mode 100644 index 0000000..cc7cc12 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/composer.json @@ -0,0 +1,35 @@ +{ + "name": "symfony/deprecation-contracts", + "type": "library", + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/vendor/symfony/deprecation-contracts/function.php b/vendor/symfony/deprecation-contracts/function.php new file mode 100644 index 0000000..d437150 --- /dev/null +++ b/vendor/symfony/deprecation-contracts/function.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (!function_exists('trigger_deprecation')) { + /** + * Triggers a silenced deprecation notice. + * + * @param string $package The name of the Composer package that is triggering the deprecation + * @param string $version The version of the package that introduced the deprecation + * @param string $message The message of the deprecation + * @param mixed ...$args Values to insert in the message using printf() formatting + * + * @author Nicolas Grekas <p@tchwork.com> + */ + 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/vendor/symfony/debug/.gitignore b/vendor/symfony/event-dispatcher-contracts/.gitignore similarity index 100% rename from vendor/symfony/debug/.gitignore rename to vendor/symfony/event-dispatcher-contracts/.gitignore diff --git a/vendor/symfony/event-dispatcher-contracts/CHANGELOG.md b/vendor/symfony/event-dispatcher-contracts/CHANGELOG.md new file mode 100644 index 0000000..7932e26 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/main/CHANGELOG.md diff --git a/vendor/symfony/event-dispatcher/Event.php b/vendor/symfony/event-dispatcher-contracts/Event.php similarity index 74% rename from vendor/symfony/event-dispatcher/Event.php rename to vendor/symfony/event-dispatcher-contracts/Event.php index 9c56b2f..46dcb2b 100644 --- a/vendor/symfony/event-dispatcher/Event.php +++ b/vendor/symfony/event-dispatcher-contracts/Event.php @@ -9,7 +9,9 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\EventDispatcher; +namespace Symfony\Contracts\EventDispatcher; + +use Psr\EventDispatcher\StoppableEventInterface; /** * Event is the base class for classes containing event data. @@ -24,22 +26,16 @@ * @author Jonathan Wage <jonwage@gmail.com> * @author Roman Borschel <roman@code-factory.org> * @author Bernhard Schussek <bschussek@gmail.com> + * @author Nicolas Grekas <p@tchwork.com> */ -class Event +class Event implements StoppableEventInterface { - /** - * @var bool Whether no further event listeners should be triggered - */ private $propagationStopped = false; /** - * Returns whether further event listeners should be triggered. - * - * @see Event::stopPropagation() - * - * @return bool Whether propagation was already stopped for this event + * {@inheritdoc} */ - public function isPropagationStopped() + public function isPropagationStopped(): bool { return $this->propagationStopped; } @@ -51,7 +47,7 @@ public function isPropagationStopped() * further event listener will be triggered once any trigger calls * stopPropagation(). */ - public function stopPropagation() + public function stopPropagation(): void { $this->propagationStopped = true; } diff --git a/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php new file mode 100644 index 0000000..351dc51 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\EventDispatcher; + +use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface; + +/** + * Allows providing hooks on domain-specific lifecycles by dispatching events. + */ +interface EventDispatcherInterface extends PsrEventDispatcherInterface +{ + /** + * Dispatches an event to all registered listeners. + * + * @param object $event The event to pass to the event handlers/listeners + * @param string|null $eventName The name of the event to dispatch. If not supplied, + * the class of $event should be used instead. + * + * @return object The passed $event MUST be returned + */ + public function dispatch(object $event, string $eventName = null): object; +} diff --git a/vendor/symfony/event-dispatcher-contracts/LICENSE b/vendor/symfony/event-dispatcher-contracts/LICENSE new file mode 100644 index 0000000..74cdc2d --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-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 +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/vendor/symfony/event-dispatcher-contracts/README.md b/vendor/symfony/event-dispatcher-contracts/README.md new file mode 100644 index 0000000..b1ab4c0 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/README.md @@ -0,0 +1,9 @@ +Symfony EventDispatcher 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 +that already have battle tested implementations. + +See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/vendor/symfony/event-dispatcher-contracts/composer.json b/vendor/symfony/event-dispatcher-contracts/composer.json new file mode 100644 index 0000000..660df81 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/composer.json @@ -0,0 +1,38 @@ +{ + "name": "symfony/event-dispatcher-contracts", + "type": "library", + "description": "Generic abstractions related to dispatching event", + "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\EventDispatcher\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/vendor/symfony/event-dispatcher/Attribute/AsEventListener.php b/vendor/symfony/event-dispatcher/Attribute/AsEventListener.php new file mode 100644 index 0000000..bb931b8 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Attribute/AsEventListener.php @@ -0,0 +1,29 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Attribute; + +/** + * Service tag to autoconfigure event listeners. + * + * @author Alexander M. Turek <me@derrabus.de> + */ +#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] +class AsEventListener +{ + public function __construct( + public ?string $event = null, + public ?string $method = null, + public int $priority = 0, + public ?string $dispatcher = null, + ) { + } +} diff --git a/vendor/symfony/event-dispatcher/CHANGELOG.md b/vendor/symfony/event-dispatcher/CHANGELOG.md index c6aa538..0f98598 100644 --- a/vendor/symfony/event-dispatcher/CHANGELOG.md +++ b/vendor/symfony/event-dispatcher/CHANGELOG.md @@ -1,24 +1,73 @@ CHANGELOG ========= +5.4 +--- + + * Allow `#[AsEventListener]` attribute on methods + +5.3 +--- + + * Add `#[AsEventListener]` attribute for declaring listeners on PHP 8 + +5.1.0 +----- + + * The `LegacyEventDispatcherProxy` class has been deprecated. + * Added an optional `dispatcher` attribute to the listener and subscriber tags in `RegisterListenerPass`. + +5.0.0 +----- + + * The signature of the `EventDispatcherInterface::dispatch()` method has been changed to `dispatch($event, string $eventName = null): object`. + * The `Event` class has been removed in favor of `Symfony\Contracts\EventDispatcher\Event`. + * The `TraceableEventDispatcherInterface` has been removed. + * The `WrappedListener` class is now final. + +4.4.0 +----- + + * `AddEventAliasesPass` has been added, allowing applications and bundles to extend the event alias mapping used by `RegisterListenersPass`. + * Made the `event` attribute of the `kernel.event_listener` tag optional for FQCN events. + +4.3.0 +----- + + * The signature of the `EventDispatcherInterface::dispatch()` method should be updated to `dispatch($event, string $eventName = null)`, not doing so is deprecated + * deprecated the `Event` class, use `Symfony\Contracts\EventDispatcher\Event` instead + +4.1.0 +----- + + * added support for invokable event listeners tagged with `kernel.event_listener` by default + * The `TraceableEventDispatcher::getOrphanedEvents()` method has been added. + * The `TraceableEventDispatcherInterface` has been deprecated. + +4.0.0 +----- + + * removed the `ContainerAwareEventDispatcher` class + * added the `reset()` method to the `TraceableEventDispatcherInterface` + 3.4.0 ----- - * Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated. + * Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated. 3.3.0 ----- - * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead. + * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead. 3.0.0 ----- - * The method `getListenerPriority($eventName, $listener)` has been added to the - `EventDispatcherInterface`. - * The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()` - and `Event::getName()` have been removed. - The event dispatcher and the event name are passed to the listener call. + * The method `getListenerPriority($eventName, $listener)` has been added to the + `EventDispatcherInterface`. + * The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()` + and `Event::getName()` have been removed. + The event dispatcher and the event name are passed to the listener call. 2.5.0 ----- diff --git a/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php b/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php deleted file mode 100644 index cd44a31..0000000 --- a/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php +++ /dev/null @@ -1,197 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Lazily loads listeners and subscribers from the dependency injection - * container. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Jordan Alliot <jordan.alliot@gmail.com> - * - * @deprecated since 3.3, to be removed in 4.0. Use EventDispatcher with closure factories instead. - */ -class ContainerAwareEventDispatcher extends EventDispatcher -{ - private $container; - - /** - * The service IDs of the event listeners and subscribers. - */ - private $listenerIds = array(); - - /** - * The services registered as listeners. - */ - private $listeners = array(); - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - - $class = \get_class($this); - if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) { - $class = get_parent_class($class); - } - if (__CLASS__ !== $class) { - @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); - } - } - - /** - * Adds a service as event listener. - * - * @param string $eventName Event for which the listener is added - * @param array $callback The service ID of the listener service & the method - * name that has to be called - * @param int $priority The higher this value, the earlier an event listener - * will be triggered in the chain. - * Defaults to 0. - * - * @throws \InvalidArgumentException - */ - public function addListenerService($eventName, $callback, $priority = 0) - { - @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); - - if (!\is_array($callback) || 2 !== \count($callback)) { - throw new \InvalidArgumentException('Expected an array("service", "method") argument'); - } - - $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority); - } - - public function removeListener($eventName, $listener) - { - $this->lazyLoad($eventName); - - if (isset($this->listenerIds[$eventName])) { - foreach ($this->listenerIds[$eventName] as $i => list($serviceId, $method)) { - $key = $serviceId.'.'.$method; - if (isset($this->listeners[$eventName][$key]) && $listener === array($this->listeners[$eventName][$key], $method)) { - unset($this->listeners[$eventName][$key]); - if (empty($this->listeners[$eventName])) { - unset($this->listeners[$eventName]); - } - unset($this->listenerIds[$eventName][$i]); - if (empty($this->listenerIds[$eventName])) { - unset($this->listenerIds[$eventName]); - } - } - } - } - - parent::removeListener($eventName, $listener); - } - - /** - * {@inheritdoc} - */ - public function hasListeners($eventName = null) - { - if (null === $eventName) { - return $this->listenerIds || $this->listeners || parent::hasListeners(); - } - - if (isset($this->listenerIds[$eventName])) { - return true; - } - - return parent::hasListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function getListeners($eventName = null) - { - if (null === $eventName) { - foreach ($this->listenerIds as $serviceEventName => $args) { - $this->lazyLoad($serviceEventName); - } - } else { - $this->lazyLoad($eventName); - } - - return parent::getListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function getListenerPriority($eventName, $listener) - { - $this->lazyLoad($eventName); - - return parent::getListenerPriority($eventName, $listener); - } - - /** - * Adds a service as event subscriber. - * - * @param string $serviceId The service ID of the subscriber service - * @param string $class The service's class name (which must implement EventSubscriberInterface) - */ - public function addSubscriberService($serviceId, $class) - { - @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); - - foreach ($class::getSubscribedEvents() as $eventName => $params) { - if (\is_string($params)) { - $this->listenerIds[$eventName][] = array($serviceId, $params, 0); - } elseif (\is_string($params[0])) { - $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0); - } else { - foreach ($params as $listener) { - $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0); - } - } - } - } - - public function getContainer() - { - @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 as its class will be removed in 4.0. Inject the container or the services you need in your listeners/subscribers instead.', E_USER_DEPRECATED); - - return $this->container; - } - - /** - * Lazily loads listeners for this event from the dependency injection - * container. - * - * @param string $eventName The name of the event to dispatch. The name of - * the event is the name of the method that is - * invoked on listeners. - */ - protected function lazyLoad($eventName) - { - if (isset($this->listenerIds[$eventName])) { - foreach ($this->listenerIds[$eventName] as list($serviceId, $method, $priority)) { - $listener = $this->container->get($serviceId); - - $key = $serviceId.'.'.$method; - if (!isset($this->listeners[$eventName][$key])) { - $this->addListener($eventName, array($listener, $method), $priority); - } elseif ($this->listeners[$eventName][$key] !== $listener) { - parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method)); - $this->addListener($eventName, array($listener, $method), $priority); - } - - $this->listeners[$eventName][$key] = $listener; - } - } - } -} diff --git a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php index e5d5940..acfbf61 100644 --- a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php +++ b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php @@ -11,11 +11,14 @@ namespace Symfony\Component\EventDispatcher\Debug; +use Psr\EventDispatcher\StoppableEventInterface; use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Contracts\Service\ResetInterface; /** * Collects some data about event listeners. @@ -24,28 +27,35 @@ * * @author Fabien Potencier <fabien@symfony.com> */ -class TraceableEventDispatcher implements TraceableEventDispatcherInterface +class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterface { protected $logger; protected $stopwatch; - private $called; + /** + * @var \SplObjectStorage<WrappedListener, array{string, string}> + */ + private $callStack; private $dispatcher; private $wrappedListeners; + private $orphanedEvents; + private $requestStack; + private $currentRequestHash = ''; - public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null) + public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null, RequestStack $requestStack = null) { $this->dispatcher = $dispatcher; $this->stopwatch = $stopwatch; $this->logger = $logger; - $this->called = array(); - $this->wrappedListeners = array(); + $this->wrappedListeners = []; + $this->orphanedEvents = []; + $this->requestStack = $requestStack; } /** * {@inheritdoc} */ - public function addListener($eventName, $listener, $priority = 0) + public function addListener(string $eventName, $listener, int $priority = 0) { $this->dispatcher->addListener($eventName, $listener, $priority); } @@ -61,11 +71,11 @@ public function addSubscriber(EventSubscriberInterface $subscriber) /** * {@inheritdoc} */ - public function removeListener($eventName, $listener) + public function removeListener(string $eventName, $listener) { if (isset($this->wrappedListeners[$eventName])) { foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { - if ($wrappedListener->getWrappedListener() === $listener) { + if ($wrappedListener->getWrappedListener() === $listener || ($listener instanceof \Closure && $wrappedListener->getWrappedListener() == $listener)) { $listener = $wrappedListener; unset($this->wrappedListeners[$eventName][$index]); break; @@ -87,7 +97,7 @@ public function removeSubscriber(EventSubscriberInterface $subscriber) /** * {@inheritdoc} */ - public function getListeners($eventName = null) + public function getListeners(string $eventName = null) { return $this->dispatcher->getListeners($eventName); } @@ -95,13 +105,13 @@ public function getListeners($eventName = null) /** * {@inheritdoc} */ - public function getListenerPriority($eventName, $listener) + public function getListenerPriority(string $eventName, $listener) { // we might have wrapped listeners for the event (if called while dispatching) // in that case get the priority by wrapper if (isset($this->wrappedListeners[$eventName])) { - foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { - if ($wrappedListener->getWrappedListener() === $listener) { + foreach ($this->wrappedListeners[$eventName] as $wrappedListener) { + if ($wrappedListener->getWrappedListener() === $listener || ($listener instanceof \Closure && $wrappedListener->getWrappedListener() == $listener)) { return $this->dispatcher->getListenerPriority($eventName, $wrappedListener); } } @@ -113,7 +123,7 @@ public function getListenerPriority($eventName, $listener) /** * {@inheritdoc} */ - public function hasListeners($eventName = null) + public function hasListeners(string $eventName = null) { return $this->dispatcher->hasListeners($eventName); } @@ -121,42 +131,58 @@ public function hasListeners($eventName = null) /** * {@inheritdoc} */ - public function dispatch($eventName, Event $event = null) + public function dispatch(object $event, string $eventName = null): object { - if (null === $event) { - $event = new Event(); + $eventName = $eventName ?? \get_class($event); + + if (null === $this->callStack) { + $this->callStack = new \SplObjectStorage(); } - if (null !== $this->logger && $event->isPropagationStopped()) { + $currentRequestHash = $this->currentRequestHash = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_hash($request) : ''; + + if (null !== $this->logger && $event instanceof StoppableEventInterface && $event->isPropagationStopped()) { $this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName)); } $this->preProcess($eventName); - $this->preDispatch($eventName, $event); - - $e = $this->stopwatch->start($eventName, 'section'); - - $this->dispatcher->dispatch($eventName, $event); - - if ($e->isStarted()) { - $e->stop(); + try { + $this->beforeDispatch($eventName, $event); + try { + $e = $this->stopwatch->start($eventName, 'section'); + try { + $this->dispatcher->dispatch($event, $eventName); + } finally { + if ($e->isStarted()) { + $e->stop(); + } + } + } finally { + $this->afterDispatch($eventName, $event); + } + } finally { + $this->currentRequestHash = $currentRequestHash; + $this->postProcess($eventName); } - $this->postDispatch($eventName, $event); - $this->postProcess($eventName); - return $event; } /** - * {@inheritdoc} + * @return array */ - public function getCalledListeners() + public function getCalledListeners(Request $request = null) { - $called = array(); - foreach ($this->called as $eventName => $listeners) { - foreach ($listeners as $listener) { - $called[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName); + if (null === $this->callStack) { + return []; + } + + $hash = $request ? spl_object_hash($request) : null; + $called = []; + foreach ($this->callStack as $listener) { + [$eventName, $requestHash] = $this->callStack->getInfo(); + if (null === $hash || $hash === $requestHash) { + $called[] = $listener->getInfo($eventName); } } @@ -164,52 +190,69 @@ public function getCalledListeners() } /** - * {@inheritdoc} + * @return array */ - public function getNotCalledListeners() + public function getNotCalledListeners(Request $request = null) { try { $allListeners = $this->getListeners(); } catch (\Exception $e) { if (null !== $this->logger) { - $this->logger->info('An exception was thrown while getting the uncalled listeners.', array('exception' => $e)); + $this->logger->info('An exception was thrown while getting the uncalled listeners.', ['exception' => $e]); } // unable to retrieve the uncalled listeners - return array(); + return []; } - $notCalled = array(); - foreach ($allListeners as $eventName => $listeners) { - foreach ($listeners as $listener) { - $called = false; - if (isset($this->called[$eventName])) { - foreach ($this->called[$eventName] as $l) { - if ($l->getWrappedListener() === $listener) { - $called = true; - - break; - } - } + $hash = $request ? spl_object_hash($request) : null; + $calledListeners = []; + + if (null !== $this->callStack) { + foreach ($this->callStack as $calledListener) { + [, $requestHash] = $this->callStack->getInfo(); + + if (null === $hash || $hash === $requestHash) { + $calledListeners[] = $calledListener->getWrappedListener(); } + } + } - if (!$called) { + $notCalled = []; + foreach ($allListeners as $eventName => $listeners) { + foreach ($listeners as $listener) { + if (!\in_array($listener, $calledListeners, true)) { if (!$listener instanceof WrappedListener) { $listener = new WrappedListener($listener, null, $this->stopwatch, $this); } - $notCalled[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName); + $notCalled[] = $listener->getInfo($eventName); } } } - uasort($notCalled, array($this, 'sortListenersByPriority')); + uasort($notCalled, [$this, 'sortNotCalledListeners']); return $notCalled; } + public function getOrphanedEvents(Request $request = null): array + { + if ($request) { + return $this->orphanedEvents[spl_object_hash($request)] ?? []; + } + + if (!$this->orphanedEvents) { + return []; + } + + return array_merge(...array_values($this->orphanedEvents)); + } + public function reset() { - $this->called = array(); + $this->callStack = null; + $this->orphanedEvents = []; + $this->currentRequestHash = ''; } /** @@ -220,43 +263,44 @@ public function reset() * * @return mixed */ - public function __call($method, $arguments) + public function __call(string $method, array $arguments) { - return \call_user_func_array(array($this->dispatcher, $method), $arguments); + return $this->dispatcher->{$method}(...$arguments); } /** * Called before dispatching the event. - * - * @param string $eventName The event name - * @param Event $event The event */ - protected function preDispatch($eventName, Event $event) + protected function beforeDispatch(string $eventName, object $event) { } /** * Called after dispatching the event. - * - * @param string $eventName The event name - * @param Event $event The event */ - protected function postDispatch($eventName, Event $event) + protected function afterDispatch(string $eventName, object $event) { } - private function preProcess($eventName) + private function preProcess(string $eventName): void { + if (!$this->dispatcher->hasListeners($eventName)) { + $this->orphanedEvents[$this->currentRequestHash][] = $eventName; + + return; + } + foreach ($this->dispatcher->getListeners($eventName) as $listener) { $priority = $this->getListenerPriority($eventName, $listener); - $wrappedListener = new WrappedListener($listener, null, $this->stopwatch, $this); + $wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this); $this->wrappedListeners[$eventName][] = $wrappedListener; $this->dispatcher->removeListener($eventName, $listener); $this->dispatcher->addListener($eventName, $wrappedListener, $priority); + $this->callStack->attach($wrappedListener, [$eventName, $this->currentRequestHash]); } } - private function postProcess($eventName) + private function postProcess(string $eventName): void { unset($this->wrappedListeners[$eventName]); $skipped = false; @@ -270,19 +314,15 @@ private function postProcess($eventName) $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority); if (null !== $this->logger) { - $context = array('event' => $eventName, 'listener' => $listener->getPretty()); + $context = ['event' => $eventName, 'listener' => $listener->getPretty()]; } if ($listener->wasCalled()) { if (null !== $this->logger) { $this->logger->debug('Notified event "{event}" to listener "{listener}".', $context); } - - if (!isset($this->called[$eventName])) { - $this->called[$eventName] = new \SplObjectStorage(); - } - - $this->called[$eventName]->attach($listener); + } else { + $this->callStack->detach($listener); } if (null !== $this->logger && $skipped) { @@ -299,8 +339,12 @@ private function postProcess($eventName) } } - private function sortListenersByPriority($a, $b) + private function sortNotCalledListeners(array $a, array $b) { + if (0 !== $cmp = strcmp($a['event'], $b['event'])) { + return $cmp; + } + if (\is_int($a['priority']) && !\is_int($b['priority'])) { return 1; } diff --git a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php deleted file mode 100644 index f021275..0000000 --- a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Debug; - -use Symfony\Component\EventDispatcher\EventDispatcherInterface; - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @method reset() Resets the trace. - */ -interface TraceableEventDispatcherInterface extends EventDispatcherInterface -{ - /** - * Gets the called listeners. - * - * @return array An array of called listeners - */ - public function getCalledListeners(); - - /** - * Gets the not called listeners. - * - * @return array An array of not called listeners - */ - public function getNotCalledListeners(); -} diff --git a/vendor/symfony/event-dispatcher/Debug/WrappedListener.php b/vendor/symfony/event-dispatcher/Debug/WrappedListener.php index 2d8126a..3c4cc13 100644 --- a/vendor/symfony/event-dispatcher/Debug/WrappedListener.php +++ b/vendor/symfony/event-dispatcher/Debug/WrappedListener.php @@ -11,7 +11,7 @@ namespace Symfony\Component\EventDispatcher\Debug; -use Symfony\Component\EventDispatcher\Event; +use Psr\EventDispatcher\StoppableEventInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\VarDumper\Caster\ClassStub; @@ -19,9 +19,10 @@ /** * @author Fabien Potencier <fabien@symfony.com> */ -class WrappedListener +final class WrappedListener { private $listener; + private $optimizedListener; private $name; private $called; private $stoppedPropagation; @@ -29,26 +30,35 @@ class WrappedListener private $dispatcher; private $pretty; private $stub; + private $priority; private static $hasClassStub; - public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) + public function __construct($listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) { $this->listener = $listener; - $this->name = $name; + $this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? \Closure::fromCallable($listener) : null); $this->stopwatch = $stopwatch; $this->dispatcher = $dispatcher; $this->called = false; $this->stoppedPropagation = false; if (\is_array($listener)) { - $this->name = \is_object($listener[0]) ? \get_class($listener[0]) : $listener[0]; + $this->name = \is_object($listener[0]) ? get_debug_type($listener[0]) : $listener[0]; $this->pretty = $this->name.'::'.$listener[1]; } elseif ($listener instanceof \Closure) { - $this->pretty = $this->name = 'closure'; + $r = new \ReflectionFunction($listener); + if (str_contains($r->name, '{closure}')) { + $this->pretty = $this->name = 'closure'; + } elseif ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { + $this->name = $class->name; + $this->pretty = $this->name.'::'.$r->name; + } else { + $this->pretty = $this->name = $r->name; + } } elseif (\is_string($listener)) { $this->pretty = $this->name = $listener; } else { - $this->name = \get_class($listener); + $this->name = get_debug_type($listener); $this->pretty = $this->name.'::__invoke'; } @@ -66,48 +76,53 @@ public function getWrappedListener() return $this->listener; } - public function wasCalled() + public function wasCalled(): bool { return $this->called; } - public function stoppedPropagation() + public function stoppedPropagation(): bool { return $this->stoppedPropagation; } - public function getPretty() + public function getPretty(): string { return $this->pretty; } - public function getInfo($eventName) + public function getInfo(string $eventName): array { if (null === $this->stub) { $this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()'; } - return array( + return [ 'event' => $eventName, - 'priority' => null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null, + 'priority' => null !== $this->priority ? $this->priority : (null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null), 'pretty' => $this->pretty, 'stub' => $this->stub, - ); + ]; } - public function __invoke(Event $event, $eventName, EventDispatcherInterface $dispatcher) + public function __invoke(object $event, string $eventName, EventDispatcherInterface $dispatcher): void { + $dispatcher = $this->dispatcher ?: $dispatcher; + $this->called = true; + $this->priority = $dispatcher->getListenerPriority($eventName, $this->listener); $e = $this->stopwatch->start($this->name, 'event_listener'); - \call_user_func($this->listener, $event, $eventName, $this->dispatcher ?: $dispatcher); - - if ($e->isStarted()) { - $e->stop(); + try { + ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); + } finally { + if ($e->isStarted()) { + $e->stop(); + } } - if ($event->isPropagationStopped()) { + if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) { $this->stoppedPropagation = true; } } diff --git a/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php b/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php new file mode 100644 index 0000000..6e7292b --- /dev/null +++ b/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * This pass allows bundles to extend the list of event aliases. + * + * @author Alexander M. Turek <me@derrabus.de> + */ +class AddEventAliasesPass implements CompilerPassInterface +{ + private $eventAliases; + private $eventAliasesParameter; + + public function __construct(array $eventAliases, string $eventAliasesParameter = 'event_dispatcher.event_aliases') + { + if (1 < \func_num_args()) { + trigger_deprecation('symfony/event-dispatcher', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); + } + + $this->eventAliases = $eventAliases; + $this->eventAliasesParameter = $eventAliasesParameter; + } + + public function process(ContainerBuilder $container): void + { + $eventAliases = $container->hasParameter($this->eventAliasesParameter) ? $container->getParameter($this->eventAliasesParameter) : []; + + $container->setParameter( + $this->eventAliasesParameter, + array_merge($eventAliases, $this->eventAliases) + ); + } +} diff --git a/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php b/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php index a6fcde3..f47120d 100644 --- a/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php +++ b/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php @@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Contracts\EventDispatcher\Event; /** * Compiler pass to register tagged services for an event dispatcher. @@ -27,26 +28,51 @@ class RegisterListenersPass implements CompilerPassInterface protected $dispatcherService; protected $listenerTag; protected $subscriberTag; + protected $eventAliasesParameter; - private $hotPathEvents = array(); - private $hotPathTagName; + private $hotPathEvents = []; + private $hotPathTagName = 'container.hot_path'; + private $noPreloadEvents = []; + private $noPreloadTagName = 'container.no_preload'; - /** - * @param string $dispatcherService Service name of the event dispatcher in processed container - * @param string $listenerTag Tag name used for listener - * @param string $subscriberTag Tag name used for subscribers - */ - public function __construct($dispatcherService = 'event_dispatcher', $listenerTag = 'kernel.event_listener', $subscriberTag = 'kernel.event_subscriber') + public function __construct(string $dispatcherService = 'event_dispatcher', string $listenerTag = 'kernel.event_listener', string $subscriberTag = 'kernel.event_subscriber', string $eventAliasesParameter = 'event_dispatcher.event_aliases') { + if (0 < \func_num_args()) { + trigger_deprecation('symfony/event-dispatcher', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); + } + $this->dispatcherService = $dispatcherService; $this->listenerTag = $listenerTag; $this->subscriberTag = $subscriberTag; + $this->eventAliasesParameter = $eventAliasesParameter; } - public function setHotPathEvents(array $hotPathEvents, $tagName = 'container.hot_path') + /** + * @return $this + */ + public function setHotPathEvents(array $hotPathEvents) { $this->hotPathEvents = array_flip($hotPathEvents); - $this->hotPathTagName = $tagName; + + if (1 < \func_num_args()) { + trigger_deprecation('symfony/event-dispatcher', '5.4', 'Configuring "$tagName" in "%s" is deprecated.', __METHOD__); + $this->hotPathTagName = func_get_arg(1); + } + + return $this; + } + + /** + * @return $this + */ + public function setNoPreloadEvents(array $noPreloadEvents): self + { + $this->noPreloadEvents = array_flip($noPreloadEvents); + + if (1 < \func_num_args()) { + trigger_deprecation('symfony/event-dispatcher', '5.4', 'Configuring "$tagName" in "%s" is deprecated.', __METHOD__); + $this->noPreloadTagName = func_get_arg(1); + } return $this; } @@ -57,35 +83,65 @@ public function process(ContainerBuilder $container) return; } - $definition = $container->findDefinition($this->dispatcherService); + $aliases = []; + + if ($container->hasParameter($this->eventAliasesParameter)) { + $aliases = $container->getParameter($this->eventAliasesParameter); + } + + $globalDispatcherDefinition = $container->findDefinition($this->dispatcherService); foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) { + $noPreload = 0; + foreach ($events as $event) { - $priority = isset($event['priority']) ? $event['priority'] : 0; + $priority = $event['priority'] ?? 0; if (!isset($event['event'])) { - throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); + if ($container->getDefinition($id)->hasTag($this->subscriberTag)) { + continue; + } + + $event['method'] = $event['method'] ?? '__invoke'; + $event['event'] = $this->getEventFromTypeDeclaration($container, $id, $event['method']); } + $event['event'] = $aliases[$event['event']] ?? $event['event']; + if (!isset($event['method'])) { - $event['method'] = 'on'.preg_replace_callback(array( - '/(?<=\b)[a-z]/i', + $event['method'] = 'on'.preg_replace_callback([ + '/(?<=\b|_)[a-z]/i', '/[^a-z0-9]/i', - ), function ($matches) { return strtoupper($matches[0]); }, $event['event']); + ], function ($matches) { return strtoupper($matches[0]); }, $event['event']); $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); + + if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, false)) && !$r->hasMethod($event['method']) && $r->hasMethod('__invoke')) { + $event['method'] = '__invoke'; + } + } + + $dispatcherDefinition = $globalDispatcherDefinition; + if (isset($event['dispatcher'])) { + $dispatcherDefinition = $container->findDefinition($event['dispatcher']); } - $definition->addMethodCall('addListener', array($event['event'], array(new ServiceClosureArgument(new Reference($id)), $event['method']), $priority)); + $dispatcherDefinition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]); if (isset($this->hotPathEvents[$event['event']])) { $container->getDefinition($id)->addTag($this->hotPathTagName); + } elseif (isset($this->noPreloadEvents[$event['event']])) { + ++$noPreload; } } + + if ($noPreload && \count($events) === $noPreload) { + $container->getDefinition($id)->addTag($this->noPreloadTagName); + } } $extractingDispatcher = new ExtractingEventDispatcher(); - foreach ($container->findTaggedServiceIds($this->subscriberTag, true) as $id => $attributes) { + foreach ($container->findTaggedServiceIds($this->subscriberTag, true) as $id => $tags) { $def = $container->getDefinition($id); // We must assume that the class value has been correctly filled, even if the service is created by a factory @@ -99,19 +155,59 @@ public function process(ContainerBuilder $container) } $class = $r->name; + $dispatcherDefinitions = []; + foreach ($tags as $attributes) { + if (!isset($attributes['dispatcher']) || isset($dispatcherDefinitions[$attributes['dispatcher']])) { + continue; + } + + $dispatcherDefinitions[$attributes['dispatcher']] = $container->findDefinition($attributes['dispatcher']); + } + + if (!$dispatcherDefinitions) { + $dispatcherDefinitions = [$globalDispatcherDefinition]; + } + + $noPreload = 0; + ExtractingEventDispatcher::$aliases = $aliases; ExtractingEventDispatcher::$subscriber = $class; $extractingDispatcher->addSubscriber($extractingDispatcher); foreach ($extractingDispatcher->listeners as $args) { - $args[1] = array(new ServiceClosureArgument(new Reference($id)), $args[1]); - $definition->addMethodCall('addListener', $args); + $args[1] = [new ServiceClosureArgument(new Reference($id)), $args[1]]; + foreach ($dispatcherDefinitions as $dispatcherDefinition) { + $dispatcherDefinition->addMethodCall('addListener', $args); + } if (isset($this->hotPathEvents[$args[0]])) { - $container->getDefinition($id)->addTag('container.hot_path'); + $container->getDefinition($id)->addTag($this->hotPathTagName); + } elseif (isset($this->noPreloadEvents[$args[0]])) { + ++$noPreload; } } - $extractingDispatcher->listeners = array(); + if ($noPreload && \count($extractingDispatcher->listeners) === $noPreload) { + $container->getDefinition($id)->addTag($this->noPreloadTagName); + } + $extractingDispatcher->listeners = []; + ExtractingEventDispatcher::$aliases = []; } } + + private function getEventFromTypeDeclaration(ContainerBuilder $container, string $id, string $method): string + { + if ( + null === ($class = $container->getDefinition($id)->getClass()) + || !($r = $container->getReflectionClass($class, false)) + || !$r->hasMethod($method) + || 1 > ($m = $r->getMethod($method))->getNumberOfParameters() + || !($type = $m->getParameters()[0]->getType()) instanceof \ReflectionNamedType + || $type->isBuiltin() + || Event::class === ($name = $type->getName()) + ) { + throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); + } + + return $name; + } } /** @@ -119,19 +215,24 @@ public function process(ContainerBuilder $container) */ class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface { - public $listeners = array(); + public $listeners = []; + public static $aliases = []; public static $subscriber; - public function addListener($eventName, $listener, $priority = 0) + public function addListener(string $eventName, $listener, int $priority = 0) { - $this->listeners[] = array($eventName, $listener[1], $priority); + $this->listeners[] = [$eventName, $listener[1], $priority]; } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { - $callback = array(self::$subscriber, 'getSubscribedEvents'); + $events = []; + + foreach ([self::$subscriber, 'getSubscribedEvents']() as $eventName => $params) { + $events[self::$aliases[$eventName] ?? $eventName] = $params; + } - return $callback(); + return $events; } } diff --git a/vendor/symfony/event-dispatcher/EventDispatcher.php b/vendor/symfony/event-dispatcher/EventDispatcher.php index 4e75c63..8fe8fb5 100644 --- a/vendor/symfony/event-dispatcher/EventDispatcher.php +++ b/vendor/symfony/event-dispatcher/EventDispatcher.php @@ -11,6 +11,9 @@ namespace Symfony\Component\EventDispatcher; +use Psr\EventDispatcher\StoppableEventInterface; +use Symfony\Component\EventDispatcher\Debug\WrappedListener; + /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * @@ -28,20 +31,32 @@ */ class EventDispatcher implements EventDispatcherInterface { - private $listeners = array(); - private $sorted = array(); + private $listeners = []; + private $sorted = []; + private $optimized; + + public function __construct() + { + if (__CLASS__ === static::class) { + $this->optimized = []; + } + } /** * {@inheritdoc} */ - public function dispatch($eventName, Event $event = null) + public function dispatch(object $event, string $eventName = null): object { - if (null === $event) { - $event = new Event(); + $eventName = $eventName ?? \get_class($event); + + if (null !== $this->optimized) { + $listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName)); + } else { + $listeners = $this->getListeners($eventName); } - if ($listeners = $this->getListeners($eventName)) { - $this->doDispatch($listeners, $eventName, $event); + if ($listeners) { + $this->callListeners($listeners, $eventName, $event); } return $event; @@ -50,11 +65,11 @@ public function dispatch($eventName, Event $event = null) /** * {@inheritdoc} */ - public function getListeners($eventName = null) + public function getListeners(string $eventName = null) { if (null !== $eventName) { if (empty($this->listeners[$eventName])) { - return array(); + return []; } if (!isset($this->sorted[$eventName])) { @@ -76,33 +91,36 @@ public function getListeners($eventName = null) /** * {@inheritdoc} */ - public function getListenerPriority($eventName, $listener) + public function getListenerPriority(string $eventName, $listener) { if (empty($this->listeners[$eventName])) { - return; + return null; } - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { $listener[0] = $listener[0](); + $listener[1] = $listener[1] ?? '__invoke'; } - foreach ($this->listeners[$eventName] as $priority => $listeners) { - foreach ($listeners as $k => $v) { - if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) { + foreach ($this->listeners[$eventName] as $priority => &$listeners) { + foreach ($listeners as &$v) { + if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) { $v[0] = $v[0](); - $this->listeners[$eventName][$priority][$k] = $v; + $v[1] = $v[1] ?? '__invoke'; } - if ($v === $listener) { + if ($v === $listener || ($listener instanceof \Closure && $v == $listener)) { return $priority; } } } + + return null; } /** * {@inheritdoc} */ - public function hasListeners($eventName = null) + public function hasListeners(string $eventName = null) { if (null !== $eventName) { return !empty($this->listeners[$eventName]); @@ -120,40 +138,38 @@ public function hasListeners($eventName = null) /** * {@inheritdoc} */ - public function addListener($eventName, $listener, $priority = 0) + public function addListener(string $eventName, $listener, int $priority = 0) { $this->listeners[$eventName][$priority][] = $listener; - unset($this->sorted[$eventName]); + unset($this->sorted[$eventName], $this->optimized[$eventName]); } /** * {@inheritdoc} */ - public function removeListener($eventName, $listener) + public function removeListener(string $eventName, $listener) { if (empty($this->listeners[$eventName])) { return; } - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { $listener[0] = $listener[0](); + $listener[1] = $listener[1] ?? '__invoke'; } - foreach ($this->listeners[$eventName] as $priority => $listeners) { - foreach ($listeners as $k => $v) { - if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) { + foreach ($this->listeners[$eventName] as $priority => &$listeners) { + foreach ($listeners as $k => &$v) { + if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) { $v[0] = $v[0](); + $v[1] = $v[1] ?? '__invoke'; } - if ($v === $listener) { - unset($listeners[$k], $this->sorted[$eventName]); - } else { - $listeners[$k] = $v; + if ($v === $listener || ($listener instanceof \Closure && $v == $listener)) { + unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]); } } - if ($listeners) { - $this->listeners[$eventName][$priority] = $listeners; - } else { + if (!$listeners) { unset($this->listeners[$eventName][$priority]); } } @@ -166,12 +182,12 @@ public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (\is_string($params)) { - $this->addListener($eventName, array($subscriber, $params)); + $this->addListener($eventName, [$subscriber, $params]); } elseif (\is_string($params[0])) { - $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); + $this->addListener($eventName, [$subscriber, $params[0]], $params[1] ?? 0); } else { foreach ($params as $listener) { - $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); + $this->addListener($eventName, [$subscriber, $listener[0]], $listener[1] ?? 0); } } } @@ -185,10 +201,10 @@ public function removeSubscriber(EventSubscriberInterface $subscriber) foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (\is_array($params) && \is_array($params[0])) { foreach ($params as $listener) { - $this->removeListener($eventName, array($subscriber, $listener[0])); + $this->removeListener($eventName, [$subscriber, $listener[0]]); } } else { - $this->removeListener($eventName, array($subscriber, \is_string($params) ? $params : $params[0])); + $this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]); } } } @@ -201,36 +217,64 @@ public function removeSubscriber(EventSubscriberInterface $subscriber) * * @param callable[] $listeners The event listeners * @param string $eventName The name of the event to dispatch - * @param Event $event The event object to pass to the event handlers/listeners + * @param object $event The event object to pass to the event handlers/listeners */ - protected function doDispatch($listeners, $eventName, Event $event) + protected function callListeners(iterable $listeners, string $eventName, object $event) { + $stoppable = $event instanceof StoppableEventInterface; + foreach ($listeners as $listener) { - if ($event->isPropagationStopped()) { + if ($stoppable && $event->isPropagationStopped()) { break; } - \call_user_func($listener, $event, $eventName, $this); + $listener($event, $eventName, $this); } } /** * Sorts the internal list of listeners for the given event by priority. - * - * @param string $eventName The name of the event */ - private function sortListeners($eventName) + private function sortListeners(string $eventName) { krsort($this->listeners[$eventName]); - $this->sorted[$eventName] = array(); + $this->sorted[$eventName] = []; - foreach ($this->listeners[$eventName] as $priority => $listeners) { - foreach ($listeners as $k => $listener) { - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + foreach ($this->listeners[$eventName] as &$listeners) { + foreach ($listeners as $k => &$listener) { + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { $listener[0] = $listener[0](); - $this->listeners[$eventName][$priority][$k] = $listener; + $listener[1] = $listener[1] ?? '__invoke'; } $this->sorted[$eventName][] = $listener; } } } + + /** + * Optimizes the internal list of listeners for the given event by priority. + */ + private function optimizeListeners(string $eventName): array + { + krsort($this->listeners[$eventName]); + $this->optimized[$eventName] = []; + + foreach ($this->listeners[$eventName] as &$listeners) { + foreach ($listeners as &$listener) { + $closure = &$this->optimized[$eventName][]; + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { + $closure = static function (...$args) use (&$listener, &$closure) { + if ($listener[0] instanceof \Closure) { + $listener[0] = $listener[0](); + $listener[1] = $listener[1] ?? '__invoke'; + } + ($closure = \Closure::fromCallable($listener))(...$args); + }; + } else { + $closure = $listener instanceof \Closure || $listener instanceof WrappedListener ? $listener : \Closure::fromCallable($listener); + } + } + } + + return $this->optimized[$eventName]; + } } diff --git a/vendor/symfony/event-dispatcher/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher/EventDispatcherInterface.php index d3d0cb8..cc324e1 100644 --- a/vendor/symfony/event-dispatcher/EventDispatcherInterface.php +++ b/vendor/symfony/event-dispatcher/EventDispatcherInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\EventDispatcher; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface; + /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * Listeners are registered on the manager and events are dispatched through the @@ -18,76 +20,51 @@ * * @author Bernhard Schussek <bschussek@gmail.com> */ -interface EventDispatcherInterface +interface EventDispatcherInterface extends ContractsEventDispatcherInterface { - /** - * Dispatches an event to all registered listeners. - * - * @param string $eventName The name of the event to dispatch. The name of - * the event is the name of the method that is - * invoked on listeners. - * @param Event $event The event to pass to the event handlers/listeners - * If not supplied, an empty Event instance is created - * - * @return Event - */ - public function dispatch($eventName, Event $event = null); - /** * Adds an event listener that listens on the specified events. * - * @param string $eventName The event to listen on - * @param callable $listener The listener - * @param int $priority The higher this value, the earlier an event - * listener will be triggered in the chain (defaults to 0) + * @param int $priority The higher this value, the earlier an event + * listener will be triggered in the chain (defaults to 0) */ - public function addListener($eventName, $listener, $priority = 0); + public function addListener(string $eventName, callable $listener, int $priority = 0); /** * Adds an event subscriber. * - * The subscriber is asked for all the events he is + * The subscriber is asked for all the events it is * interested in and added as a listener for these events. */ public function addSubscriber(EventSubscriberInterface $subscriber); /** * Removes an event listener from the specified events. - * - * @param string $eventName The event to remove a listener from - * @param callable $listener The listener to remove */ - public function removeListener($eventName, $listener); + public function removeListener(string $eventName, callable $listener); public function removeSubscriber(EventSubscriberInterface $subscriber); /** * Gets the listeners of a specific event or all listeners sorted by descending priority. * - * @param string $eventName The name of the event - * - * @return array The event listeners for the specified event, or all event listeners by event name + * @return array<callable[]|callable> */ - public function getListeners($eventName = null); + public function getListeners(string $eventName = null); /** * Gets the listener priority for a specific event. * * Returns null if the event or the listener does not exist. * - * @param string $eventName The name of the event - * @param callable $listener The listener - * - * @return int|null The event listener priority + * @return int|null */ - public function getListenerPriority($eventName, $listener); + public function getListenerPriority(string $eventName, callable $listener); /** * Checks whether an event has any registered listeners. * - * @param string $eventName The name of the event - * - * @return bool true if the specified event has any listeners, false otherwise + * @return bool */ - public function hasListeners($eventName = null); + public function hasListeners(string $eventName = null); } diff --git a/vendor/symfony/event-dispatcher/EventSubscriberInterface.php b/vendor/symfony/event-dispatcher/EventSubscriberInterface.php index 8af7789..2085e42 100644 --- a/vendor/symfony/event-dispatcher/EventSubscriberInterface.php +++ b/vendor/symfony/event-dispatcher/EventSubscriberInterface.php @@ -12,7 +12,7 @@ namespace Symfony\Component\EventDispatcher; /** - * An EventSubscriber knows himself what events he is interested in. + * An EventSubscriber knows itself what events it is interested in. * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes * {@link getSubscribedEvents} and registers the subscriber as a listener for all * returned events. @@ -36,11 +36,14 @@ interface EventSubscriberInterface * * For instance: * - * * array('eventName' => 'methodName') - * * array('eventName' => array('methodName', $priority)) - * * array('eventName' => array(array('methodName1', $priority), array('methodName2'))) + * * ['eventName' => 'methodName'] + * * ['eventName' => ['methodName', $priority]] + * * ['eventName' => [['methodName1', $priority], ['methodName2']]] * - * @return array The event names to listen to + * The code must not depend on runtime state as it will only be called at compile time. + * All logic depending on runtime state must be put into the individual methods handling the events. + * + * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>> */ public static function getSubscribedEvents(); } diff --git a/vendor/symfony/event-dispatcher/GenericEvent.php b/vendor/symfony/event-dispatcher/GenericEvent.php index 95c9940..b32a301 100644 --- a/vendor/symfony/event-dispatcher/GenericEvent.php +++ b/vendor/symfony/event-dispatcher/GenericEvent.php @@ -11,12 +11,17 @@ namespace Symfony\Component\EventDispatcher; +use Symfony\Contracts\EventDispatcher\Event; + /** * Event encapsulation class. * * Encapsulates events thus decoupling the observer from the subject they encapsulate. * * @author Drak <drak@zikula.org> + * + * @implements \ArrayAccess<string, mixed> + * @implements \IteratorAggregate<string, mixed> */ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate { @@ -29,7 +34,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate * @param mixed $subject The subject of the event, usually an object or a callable * @param array $arguments Arguments to store in the event */ - public function __construct($subject = null, array $arguments = array()) + public function __construct($subject = null, array $arguments = []) { $this->subject = $subject; $this->arguments = $arguments; @@ -38,7 +43,7 @@ public function __construct($subject = null, array $arguments = array()) /** * Getter for subject property. * - * @return mixed $subject The observer subject + * @return mixed */ public function getSubject() { @@ -48,13 +53,11 @@ public function getSubject() /** * Get argument by key. * - * @param string $key Key - * - * @return mixed Contents of array key + * @return mixed * * @throws \InvalidArgumentException if key is not found */ - public function getArgument($key) + public function getArgument(string $key) { if ($this->hasArgument($key)) { return $this->arguments[$key]; @@ -66,12 +69,11 @@ public function getArgument($key) /** * Add argument to event. * - * @param string $key Argument name - * @param mixed $value Value + * @param mixed $value Value * * @return $this */ - public function setArgument($key, $value) + public function setArgument(string $key, $value) { $this->arguments[$key] = $value; @@ -91,11 +93,9 @@ public function getArguments() /** * Set args property. * - * @param array $args Arguments - * * @return $this */ - public function setArguments(array $args = array()) + public function setArguments(array $args = []) { $this->arguments = $args; @@ -105,13 +105,11 @@ public function setArguments(array $args = array()) /** * Has argument. * - * @param string $key Key of arguments array - * * @return bool */ - public function hasArgument($key) + public function hasArgument(string $key) { - return array_key_exists($key, $this->arguments); + return \array_key_exists($key, $this->arguments); } /** @@ -123,6 +121,7 @@ public function hasArgument($key) * * @throws \InvalidArgumentException if key does not exist in $this->args */ + #[\ReturnTypeWillChange] public function offsetGet($key) { return $this->getArgument($key); @@ -133,7 +132,10 @@ public function offsetGet($key) * * @param string $key Array key to set * @param mixed $value Value + * + * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($key, $value) { $this->setArgument($key, $value); @@ -143,7 +145,10 @@ public function offsetSet($key, $value) * ArrayAccess for unset argument. * * @param string $key Array key + * + * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($key) { if ($this->hasArgument($key)) { @@ -158,6 +163,7 @@ public function offsetUnset($key) * * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($key) { return $this->hasArgument($key); @@ -166,8 +172,9 @@ public function offsetExists($key) /** * IteratorAggregate for iterating over the object like an array. * - * @return \ArrayIterator + * @return \ArrayIterator<string, mixed> */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->arguments); diff --git a/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php b/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php index b3cf56c..568d79c 100644 --- a/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php +++ b/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php @@ -28,15 +28,15 @@ public function __construct(EventDispatcherInterface $dispatcher) /** * {@inheritdoc} */ - public function dispatch($eventName, Event $event = null) + public function dispatch(object $event, string $eventName = null): object { - return $this->dispatcher->dispatch($eventName, $event); + return $this->dispatcher->dispatch($event, $eventName); } /** * {@inheritdoc} */ - public function addListener($eventName, $listener, $priority = 0) + public function addListener(string $eventName, $listener, int $priority = 0) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } @@ -52,7 +52,7 @@ public function addSubscriber(EventSubscriberInterface $subscriber) /** * {@inheritdoc} */ - public function removeListener($eventName, $listener) + public function removeListener(string $eventName, $listener) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } @@ -68,7 +68,7 @@ public function removeSubscriber(EventSubscriberInterface $subscriber) /** * {@inheritdoc} */ - public function getListeners($eventName = null) + public function getListeners(string $eventName = null) { return $this->dispatcher->getListeners($eventName); } @@ -76,7 +76,7 @@ public function getListeners($eventName = null) /** * {@inheritdoc} */ - public function getListenerPriority($eventName, $listener) + public function getListenerPriority(string $eventName, $listener) { return $this->dispatcher->getListenerPriority($eventName, $listener); } @@ -84,7 +84,7 @@ public function getListenerPriority($eventName, $listener) /** * {@inheritdoc} */ - public function hasListeners($eventName = null) + public function hasListeners(string $eventName = null) { return $this->dispatcher->hasListeners($eventName); } diff --git a/vendor/symfony/event-dispatcher/LICENSE b/vendor/symfony/event-dispatcher/LICENSE index 21d7fb9..0138f8f 100644 --- a/vendor/symfony/event-dispatcher/LICENSE +++ b/vendor/symfony/event-dispatcher/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php b/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php new file mode 100644 index 0000000..6e17c8f --- /dev/null +++ b/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +trigger_deprecation('symfony/event-dispatcher', '5.1', '%s is deprecated, use the event dispatcher without the proxy.', LegacyEventDispatcherProxy::class); + +/** + * A helper class to provide BC/FC with the legacy signature of EventDispatcherInterface::dispatch(). + * + * @author Nicolas Grekas <p@tchwork.com> + * + * @deprecated since Symfony 5.1 + */ +final class LegacyEventDispatcherProxy +{ + public static function decorate(?EventDispatcherInterface $dispatcher): ?EventDispatcherInterface + { + return $dispatcher; + } +} diff --git a/vendor/symfony/event-dispatcher/README.md b/vendor/symfony/event-dispatcher/README.md index 185c3fe..dcdb68d 100644 --- a/vendor/symfony/event-dispatcher/README.md +++ b/vendor/symfony/event-dispatcher/README.md @@ -8,8 +8,8 @@ them. Resources --------- - * [Documentation](https://symfony.com/doc/current/components/event_dispatcher/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) + * [Documentation](https://symfony.com/doc/current/components/event_dispatcher.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php deleted file mode 100644 index 9997a7b..0000000 --- a/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php +++ /dev/null @@ -1,442 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\EventDispatcher\Event; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; - -abstract class AbstractEventDispatcherTest extends TestCase -{ - /* Some pseudo events */ - const preFoo = 'pre.foo'; - const postFoo = 'post.foo'; - const preBar = 'pre.bar'; - const postBar = 'post.bar'; - - /** - * @var EventDispatcher - */ - private $dispatcher; - - private $listener; - - protected function setUp() - { - $this->dispatcher = $this->createEventDispatcher(); - $this->listener = new TestEventListener(); - } - - protected function tearDown() - { - $this->dispatcher = null; - $this->listener = null; - } - - abstract protected function createEventDispatcher(); - - public function testInitialState() - { - $this->assertEquals(array(), $this->dispatcher->getListeners()); - $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); - $this->assertFalse($this->dispatcher->hasListeners(self::postFoo)); - } - - public function testAddListener() - { - $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); - $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo')); - $this->assertTrue($this->dispatcher->hasListeners()); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); - $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo)); - $this->assertCount(1, $this->dispatcher->getListeners(self::postFoo)); - $this->assertCount(2, $this->dispatcher->getListeners()); - } - - public function testGetListenersSortsByPriority() - { - $listener1 = new TestEventListener(); - $listener2 = new TestEventListener(); - $listener3 = new TestEventListener(); - $listener1->name = '1'; - $listener2->name = '2'; - $listener3->name = '3'; - - $this->dispatcher->addListener('pre.foo', array($listener1, 'preFoo'), -10); - $this->dispatcher->addListener('pre.foo', array($listener2, 'preFoo'), 10); - $this->dispatcher->addListener('pre.foo', array($listener3, 'preFoo')); - - $expected = array( - array($listener2, 'preFoo'), - array($listener3, 'preFoo'), - array($listener1, 'preFoo'), - ); - - $this->assertSame($expected, $this->dispatcher->getListeners('pre.foo')); - } - - public function testGetAllListenersSortsByPriority() - { - $listener1 = new TestEventListener(); - $listener2 = new TestEventListener(); - $listener3 = new TestEventListener(); - $listener4 = new TestEventListener(); - $listener5 = new TestEventListener(); - $listener6 = new TestEventListener(); - - $this->dispatcher->addListener('pre.foo', $listener1, -10); - $this->dispatcher->addListener('pre.foo', $listener2); - $this->dispatcher->addListener('pre.foo', $listener3, 10); - $this->dispatcher->addListener('post.foo', $listener4, -10); - $this->dispatcher->addListener('post.foo', $listener5); - $this->dispatcher->addListener('post.foo', $listener6, 10); - - $expected = array( - 'pre.foo' => array($listener3, $listener2, $listener1), - 'post.foo' => array($listener6, $listener5, $listener4), - ); - - $this->assertSame($expected, $this->dispatcher->getListeners()); - } - - public function testGetListenerPriority() - { - $listener1 = new TestEventListener(); - $listener2 = new TestEventListener(); - - $this->dispatcher->addListener('pre.foo', $listener1, -10); - $this->dispatcher->addListener('pre.foo', $listener2); - - $this->assertSame(-10, $this->dispatcher->getListenerPriority('pre.foo', $listener1)); - $this->assertSame(0, $this->dispatcher->getListenerPriority('pre.foo', $listener2)); - $this->assertNull($this->dispatcher->getListenerPriority('pre.bar', $listener2)); - $this->assertNull($this->dispatcher->getListenerPriority('pre.foo', function () {})); - } - - public function testDispatch() - { - $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); - $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo')); - $this->dispatcher->dispatch(self::preFoo); - $this->assertTrue($this->listener->preFooInvoked); - $this->assertFalse($this->listener->postFooInvoked); - $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch('noevent')); - $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo)); - $event = new Event(); - $return = $this->dispatcher->dispatch(self::preFoo, $event); - $this->assertSame($event, $return); - } - - public function testDispatchForClosure() - { - $invoked = 0; - $listener = function () use (&$invoked) { - ++$invoked; - }; - $this->dispatcher->addListener('pre.foo', $listener); - $this->dispatcher->addListener('post.foo', $listener); - $this->dispatcher->dispatch(self::preFoo); - $this->assertEquals(1, $invoked); - } - - public function testStopEventPropagation() - { - $otherListener = new TestEventListener(); - - // postFoo() stops the propagation, so only one listener should - // be executed - // Manually set priority to enforce $this->listener to be called first - $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'), 10); - $this->dispatcher->addListener('post.foo', array($otherListener, 'postFoo')); - $this->dispatcher->dispatch(self::postFoo); - $this->assertTrue($this->listener->postFooInvoked); - $this->assertFalse($otherListener->postFooInvoked); - } - - public function testDispatchByPriority() - { - $invoked = array(); - $listener1 = function () use (&$invoked) { - $invoked[] = '1'; - }; - $listener2 = function () use (&$invoked) { - $invoked[] = '2'; - }; - $listener3 = function () use (&$invoked) { - $invoked[] = '3'; - }; - $this->dispatcher->addListener('pre.foo', $listener1, -10); - $this->dispatcher->addListener('pre.foo', $listener2); - $this->dispatcher->addListener('pre.foo', $listener3, 10); - $this->dispatcher->dispatch(self::preFoo); - $this->assertEquals(array('3', '2', '1'), $invoked); - } - - public function testRemoveListener() - { - $this->dispatcher->addListener('pre.bar', $this->listener); - $this->assertTrue($this->dispatcher->hasListeners(self::preBar)); - $this->dispatcher->removeListener('pre.bar', $this->listener); - $this->assertFalse($this->dispatcher->hasListeners(self::preBar)); - $this->dispatcher->removeListener('notExists', $this->listener); - } - - public function testAddSubscriber() - { - $eventSubscriber = new TestEventSubscriber(); - $this->dispatcher->addSubscriber($eventSubscriber); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); - } - - public function testAddSubscriberWithPriorities() - { - $eventSubscriber = new TestEventSubscriber(); - $this->dispatcher->addSubscriber($eventSubscriber); - - $eventSubscriber = new TestEventSubscriberWithPriorities(); - $this->dispatcher->addSubscriber($eventSubscriber); - - $listeners = $this->dispatcher->getListeners('pre.foo'); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertCount(2, $listeners); - $this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]); - } - - public function testAddSubscriberWithMultipleListeners() - { - $eventSubscriber = new TestEventSubscriberWithMultipleListeners(); - $this->dispatcher->addSubscriber($eventSubscriber); - - $listeners = $this->dispatcher->getListeners('pre.foo'); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertCount(2, $listeners); - $this->assertEquals('preFoo2', $listeners[0][1]); - } - - public function testRemoveSubscriber() - { - $eventSubscriber = new TestEventSubscriber(); - $this->dispatcher->addSubscriber($eventSubscriber); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); - $this->dispatcher->removeSubscriber($eventSubscriber); - $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); - $this->assertFalse($this->dispatcher->hasListeners(self::postFoo)); - } - - public function testRemoveSubscriberWithPriorities() - { - $eventSubscriber = new TestEventSubscriberWithPriorities(); - $this->dispatcher->addSubscriber($eventSubscriber); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->dispatcher->removeSubscriber($eventSubscriber); - $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); - } - - public function testRemoveSubscriberWithMultipleListeners() - { - $eventSubscriber = new TestEventSubscriberWithMultipleListeners(); - $this->dispatcher->addSubscriber($eventSubscriber); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertCount(2, $this->dispatcher->getListeners(self::preFoo)); - $this->dispatcher->removeSubscriber($eventSubscriber); - $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); - } - - public function testEventReceivesTheDispatcherInstanceAsArgument() - { - $listener = new TestWithDispatcher(); - $this->dispatcher->addListener('test', array($listener, 'foo')); - $this->assertNull($listener->name); - $this->assertNull($listener->dispatcher); - $this->dispatcher->dispatch('test'); - $this->assertEquals('test', $listener->name); - $this->assertSame($this->dispatcher, $listener->dispatcher); - } - - /** - * @see https://bugs.php.net/bug.php?id=62976 - * - * This bug affects: - * - The PHP 5.3 branch for versions < 5.3.18 - * - The PHP 5.4 branch for versions < 5.4.8 - * - The PHP 5.5 branch is not affected - */ - public function testWorkaroundForPhpBug62976() - { - $dispatcher = $this->createEventDispatcher(); - $dispatcher->addListener('bug.62976', new CallableClass()); - $dispatcher->removeListener('bug.62976', function () {}); - $this->assertTrue($dispatcher->hasListeners('bug.62976')); - } - - public function testHasListenersWhenAddedCallbackListenerIsRemoved() - { - $listener = function () {}; - $this->dispatcher->addListener('foo', $listener); - $this->dispatcher->removeListener('foo', $listener); - $this->assertFalse($this->dispatcher->hasListeners()); - } - - public function testGetListenersWhenAddedCallbackListenerIsRemoved() - { - $listener = function () {}; - $this->dispatcher->addListener('foo', $listener); - $this->dispatcher->removeListener('foo', $listener); - $this->assertSame(array(), $this->dispatcher->getListeners()); - } - - public function testHasListenersWithoutEventsReturnsFalseAfterHasListenersWithEventHasBeenCalled() - { - $this->assertFalse($this->dispatcher->hasListeners('foo')); - $this->assertFalse($this->dispatcher->hasListeners()); - } - - public function testHasListenersIsLazy() - { - $called = 0; - $listener = array(function () use (&$called) { ++$called; }, 'onFoo'); - $this->dispatcher->addListener('foo', $listener); - $this->assertTrue($this->dispatcher->hasListeners()); - $this->assertTrue($this->dispatcher->hasListeners('foo')); - $this->assertSame(0, $called); - } - - public function testDispatchLazyListener() - { - $called = 0; - $factory = function () use (&$called) { - ++$called; - - return new TestWithDispatcher(); - }; - $this->dispatcher->addListener('foo', array($factory, 'foo')); - $this->assertSame(0, $called); - $this->dispatcher->dispatch('foo', new Event()); - $this->dispatcher->dispatch('foo', new Event()); - $this->assertSame(1, $called); - } - - public function testRemoveFindsLazyListeners() - { - $test = new TestWithDispatcher(); - $factory = function () use ($test) { return $test; }; - - $this->dispatcher->addListener('foo', array($factory, 'foo')); - $this->assertTrue($this->dispatcher->hasListeners('foo')); - $this->dispatcher->removeListener('foo', array($test, 'foo')); - $this->assertFalse($this->dispatcher->hasListeners('foo')); - - $this->dispatcher->addListener('foo', array($test, 'foo')); - $this->assertTrue($this->dispatcher->hasListeners('foo')); - $this->dispatcher->removeListener('foo', array($factory, 'foo')); - $this->assertFalse($this->dispatcher->hasListeners('foo')); - } - - public function testPriorityFindsLazyListeners() - { - $test = new TestWithDispatcher(); - $factory = function () use ($test) { return $test; }; - - $this->dispatcher->addListener('foo', array($factory, 'foo'), 3); - $this->assertSame(3, $this->dispatcher->getListenerPriority('foo', array($test, 'foo'))); - $this->dispatcher->removeListener('foo', array($factory, 'foo')); - - $this->dispatcher->addListener('foo', array($test, 'foo'), 5); - $this->assertSame(5, $this->dispatcher->getListenerPriority('foo', array($factory, 'foo'))); - } - - public function testGetLazyListeners() - { - $test = new TestWithDispatcher(); - $factory = function () use ($test) { return $test; }; - - $this->dispatcher->addListener('foo', array($factory, 'foo'), 3); - $this->assertSame(array(array($test, 'foo')), $this->dispatcher->getListeners('foo')); - - $this->dispatcher->removeListener('foo', array($test, 'foo')); - $this->dispatcher->addListener('bar', array($factory, 'foo'), 3); - $this->assertSame(array('bar' => array(array($test, 'foo'))), $this->dispatcher->getListeners()); - } -} - -class CallableClass -{ - public function __invoke() - { - } -} - -class TestEventListener -{ - public $preFooInvoked = false; - public $postFooInvoked = false; - - /* Listener methods */ - - public function preFoo(Event $e) - { - $this->preFooInvoked = true; - } - - public function postFoo(Event $e) - { - $this->postFooInvoked = true; - - $e->stopPropagation(); - } -} - -class TestWithDispatcher -{ - public $name; - public $dispatcher; - - public function foo(Event $e, $name, $dispatcher) - { - $this->name = $name; - $this->dispatcher = $dispatcher; - } -} - -class TestEventSubscriber implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array('pre.foo' => 'preFoo', 'post.foo' => 'postFoo'); - } -} - -class TestEventSubscriberWithPriorities implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array( - 'pre.foo' => array('preFoo', 10), - 'post.foo' => array('postFoo'), - ); - } -} - -class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array('pre.foo' => array( - array('preFoo1'), - array('preFoo2', 10), - )); - } -} diff --git a/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php deleted file mode 100644 index 9d5eecc..0000000 --- a/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php +++ /dev/null @@ -1,210 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests; - -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; -use Symfony\Component\EventDispatcher\Event; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; - -/** - * @group legacy - */ -class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest -{ - protected function createEventDispatcher() - { - $container = new Container(); - - return new ContainerAwareEventDispatcher($container); - } - - public function testAddAListenerService() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $dispatcher->dispatch('onEvent', $event); - } - - public function testAddASubscriberService() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\SubscriberService')->getMock(); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $service - ->expects($this->once()) - ->method('onEventWithPriority') - ->with($event) - ; - - $service - ->expects($this->once()) - ->method('onEventNested') - ->with($event) - ; - - $container = new Container(); - $container->set('service.subscriber', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addSubscriberService('service.subscriber', 'Symfony\Component\EventDispatcher\Tests\SubscriberService'); - - $dispatcher->dispatch('onEvent', $event); - $dispatcher->dispatch('onEventWithPriority', $event); - $dispatcher->dispatch('onEventNested', $event); - } - - public function testPreventDuplicateListenerService() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 5); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 10); - - $dispatcher->dispatch('onEvent', $event); - } - - public function testHasListenersOnLazyLoad() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $this->assertTrue($dispatcher->hasListeners()); - - if ($dispatcher->hasListeners('onEvent')) { - $dispatcher->dispatch('onEvent'); - } - } - - public function testGetListenersOnLazyLoad() - { - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $listeners = $dispatcher->getListeners(); - - $this->assertArrayHasKey('onEvent', $listeners); - - $this->assertCount(1, $dispatcher->getListeners('onEvent')); - } - - public function testRemoveAfterDispatch() - { - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $dispatcher->dispatch('onEvent', new Event()); - $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent')); - $this->assertFalse($dispatcher->hasListeners('onEvent')); - } - - public function testRemoveBeforeDispatch() - { - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent')); - $this->assertFalse($dispatcher->hasListeners('onEvent')); - } -} - -class Service -{ - public function onEvent(Event $e) - { - } -} - -class SubscriberService implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array( - 'onEvent' => 'onEvent', - 'onEventWithPriority' => array('onEventWithPriority', 10), - 'onEventNested' => array(array('onEventNested')), - ); - } - - public function onEvent(Event $e) - { - } - - public function onEventWithPriority(Event $e) - { - } - - public function onEventNested(Event $e) - { - } -} diff --git a/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php deleted file mode 100644 index d7c5ce1..0000000 --- a/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php +++ /dev/null @@ -1,257 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests\Debug; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; -use Symfony\Component\EventDispatcher\Event; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Stopwatch\Stopwatch; - -class TraceableEventDispatcherTest extends TestCase -{ - public function testAddRemoveListener() - { - $dispatcher = new EventDispatcher(); - $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - - $tdispatcher->addListener('foo', $listener = function () {}); - $listeners = $dispatcher->getListeners('foo'); - $this->assertCount(1, $listeners); - $this->assertSame($listener, $listeners[0]); - - $tdispatcher->removeListener('foo', $listener); - $this->assertCount(0, $dispatcher->getListeners('foo')); - } - - public function testGetListeners() - { - $dispatcher = new EventDispatcher(); - $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - - $tdispatcher->addListener('foo', $listener = function () {}); - $this->assertSame($dispatcher->getListeners('foo'), $tdispatcher->getListeners('foo')); - } - - public function testHasListeners() - { - $dispatcher = new EventDispatcher(); - $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - - $this->assertFalse($dispatcher->hasListeners('foo')); - $this->assertFalse($tdispatcher->hasListeners('foo')); - - $tdispatcher->addListener('foo', $listener = function () {}); - $this->assertTrue($dispatcher->hasListeners('foo')); - $this->assertTrue($tdispatcher->hasListeners('foo')); - } - - public function testGetListenerPriority() - { - $dispatcher = new EventDispatcher(); - $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - - $tdispatcher->addListener('foo', function () {}, 123); - - $listeners = $dispatcher->getListeners('foo'); - $this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0])); - - // Verify that priority is preserved when listener is removed and re-added - // in preProcess() and postProcess(). - $tdispatcher->dispatch('foo', new Event()); - $listeners = $dispatcher->getListeners('foo'); - $this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0])); - } - - public function testGetListenerPriorityWhileDispatching() - { - $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); - $priorityWhileDispatching = null; - - $listener = function () use ($tdispatcher, &$priorityWhileDispatching, &$listener) { - $priorityWhileDispatching = $tdispatcher->getListenerPriority('bar', $listener); - }; - - $tdispatcher->addListener('bar', $listener, 5); - $tdispatcher->dispatch('bar'); - $this->assertSame(5, $priorityWhileDispatching); - } - - public function testAddRemoveSubscriber() - { - $dispatcher = new EventDispatcher(); - $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - - $subscriber = new EventSubscriber(); - - $tdispatcher->addSubscriber($subscriber); - $listeners = $dispatcher->getListeners('foo'); - $this->assertCount(1, $listeners); - $this->assertSame(array($subscriber, 'call'), $listeners[0]); - - $tdispatcher->removeSubscriber($subscriber); - $this->assertCount(0, $dispatcher->getListeners('foo')); - } - - public function testGetCalledListeners() - { - $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); - $tdispatcher->addListener('foo', function () {}, 5); - - $listeners = $tdispatcher->getNotCalledListeners(); - $this->assertArrayHasKey('stub', $listeners['foo.closure']); - unset($listeners['foo.closure']['stub']); - $this->assertEquals(array(), $tdispatcher->getCalledListeners()); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); - - $tdispatcher->dispatch('foo'); - - $listeners = $tdispatcher->getCalledListeners(); - $this->assertArrayHasKey('stub', $listeners['foo.closure']); - unset($listeners['foo.closure']['stub']); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); - $this->assertEquals(array(), $tdispatcher->getNotCalledListeners()); - } - - public function testClearCalledListeners() - { - $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); - $tdispatcher->addListener('foo', function () {}, 5); - - $tdispatcher->dispatch('foo'); - $tdispatcher->reset(); - - $listeners = $tdispatcher->getNotCalledListeners(); - $this->assertArrayHasKey('stub', $listeners['foo.closure']); - unset($listeners['foo.closure']['stub']); - $this->assertEquals(array(), $tdispatcher->getCalledListeners()); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); - } - - public function testGetCalledListenersNested() - { - $tdispatcher = null; - $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); - $dispatcher->addListener('foo', function (Event $event, $eventName, $dispatcher) use (&$tdispatcher) { - $tdispatcher = $dispatcher; - $dispatcher->dispatch('bar'); - }); - $dispatcher->addListener('bar', function (Event $event) {}); - $dispatcher->dispatch('foo'); - $this->assertSame($dispatcher, $tdispatcher); - $this->assertCount(2, $dispatcher->getCalledListeners()); - } - - public function testLogger() - { - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - - $dispatcher = new EventDispatcher(); - $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger); - $tdispatcher->addListener('foo', $listener1 = function () {}); - $tdispatcher->addListener('foo', $listener2 = function () {}); - - $logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure')); - $logger->expects($this->at(1))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure')); - - $tdispatcher->dispatch('foo'); - } - - public function testLoggerWithStoppedEvent() - { - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - - $dispatcher = new EventDispatcher(); - $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger); - $tdispatcher->addListener('foo', $listener1 = function (Event $event) { $event->stopPropagation(); }); - $tdispatcher->addListener('foo', $listener2 = function () {}); - - $logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure')); - $logger->expects($this->at(1))->method('debug')->with('Listener "{listener}" stopped propagation of the event "{event}".', array('event' => 'foo', 'listener' => 'closure')); - $logger->expects($this->at(2))->method('debug')->with('Listener "{listener}" was not called for event "{event}".', array('event' => 'foo', 'listener' => 'closure')); - - $tdispatcher->dispatch('foo'); - } - - public function testDispatchCallListeners() - { - $called = array(); - - $dispatcher = new EventDispatcher(); - $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); - $tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo1'; }, 10); - $tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo2'; }, 20); - - $tdispatcher->dispatch('foo'); - - $this->assertSame(array('foo2', 'foo1'), $called); - } - - public function testDispatchNested() - { - $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); - $loop = 1; - $dispatchedEvents = 0; - $dispatcher->addListener('foo', $listener1 = function () use ($dispatcher, &$loop) { - ++$loop; - if (2 == $loop) { - $dispatcher->dispatch('foo'); - } - }); - $dispatcher->addListener('foo', function () use (&$dispatchedEvents) { - ++$dispatchedEvents; - }); - - $dispatcher->dispatch('foo'); - - $this->assertSame(2, $dispatchedEvents); - } - - public function testDispatchReusedEventNested() - { - $nestedCall = false; - $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); - $dispatcher->addListener('foo', function (Event $e) use ($dispatcher) { - $dispatcher->dispatch('bar', $e); - }); - $dispatcher->addListener('bar', function (Event $e) use (&$nestedCall) { - $nestedCall = true; - }); - - $this->assertFalse($nestedCall); - $dispatcher->dispatch('foo'); - $this->assertTrue($nestedCall); - } - - public function testListenerCanRemoveItselfWhenExecuted() - { - $eventDispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); - $listener1 = function ($event, $eventName, EventDispatcherInterface $dispatcher) use (&$listener1) { - $dispatcher->removeListener('foo', $listener1); - }; - $eventDispatcher->addListener('foo', $listener1); - $eventDispatcher->addListener('foo', function () {}); - $eventDispatcher->dispatch('foo'); - - $this->assertCount(1, $eventDispatcher->getListeners('foo'), 'expected listener1 to be removed'); - } -} - -class EventSubscriber implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array('foo' => 'call'); - } -} diff --git a/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php b/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php deleted file mode 100644 index c1b49f7..0000000 --- a/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests\DependencyInjection; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; - -class RegisterListenersPassTest extends TestCase -{ - /** - * Tests that event subscribers not implementing EventSubscriberInterface - * trigger an exception. - * - * @expectedException \InvalidArgumentException - */ - public function testEventSubscriberWithoutInterface() - { - $builder = new ContainerBuilder(); - $builder->register('event_dispatcher'); - $builder->register('my_event_subscriber', 'stdClass') - ->addTag('kernel.event_subscriber'); - - $registerListenersPass = new RegisterListenersPass(); - $registerListenersPass->process($builder); - } - - public function testValidEventSubscriber() - { - $services = array( - 'my_event_subscriber' => array(0 => array()), - ); - - $builder = new ContainerBuilder(); - $eventDispatcherDefinition = $builder->register('event_dispatcher'); - $builder->register('my_event_subscriber', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService') - ->addTag('kernel.event_subscriber'); - - $registerListenersPass = new RegisterListenersPass(); - $registerListenersPass->process($builder); - - $expectedCalls = array( - array( - 'addListener', - array( - 'event', - array(new ServiceClosureArgument(new Reference('my_event_subscriber')), 'onEvent'), - 0, - ), - ), - ); - $this->assertEquals($expectedCalls, $eventDispatcherDefinition->getMethodCalls()); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "foo" tagged "kernel.event_listener" must not be abstract. - */ - public function testAbstractEventListener() - { - $container = new ContainerBuilder(); - $container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_listener', array()); - $container->register('event_dispatcher', 'stdClass'); - - $registerListenersPass = new RegisterListenersPass(); - $registerListenersPass->process($container); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "foo" tagged "kernel.event_subscriber" must not be abstract. - */ - public function testAbstractEventSubscriber() - { - $container = new ContainerBuilder(); - $container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_subscriber', array()); - $container->register('event_dispatcher', 'stdClass'); - - $registerListenersPass = new RegisterListenersPass(); - $registerListenersPass->process($container); - } - - public function testEventSubscriberResolvableClassName() - { - $container = new ContainerBuilder(); - - $container->setParameter('subscriber.class', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService'); - $container->register('foo', '%subscriber.class%')->addTag('kernel.event_subscriber', array()); - $container->register('event_dispatcher', 'stdClass'); - - $registerListenersPass = new RegisterListenersPass(); - $registerListenersPass->process($container); - - $definition = $container->getDefinition('event_dispatcher'); - $expectedCalls = array( - array( - 'addListener', - array( - 'event', - array(new ServiceClosureArgument(new Reference('foo')), 'onEvent'), - 0, - ), - ), - ); - $this->assertEquals($expectedCalls, $definition->getMethodCalls()); - } - - public function testHotPathEvents() - { - $container = new ContainerBuilder(); - - $container->register('foo', SubscriberService::class)->addTag('kernel.event_subscriber', array()); - $container->register('event_dispatcher', 'stdClass'); - - (new RegisterListenersPass())->setHotPathEvents(array('event'))->process($container); - - $this->assertTrue($container->getDefinition('foo')->hasTag('container.hot_path')); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage You have requested a non-existent parameter "subscriber.class" - */ - public function testEventSubscriberUnresolvableClassName() - { - $container = new ContainerBuilder(); - $container->register('foo', '%subscriber.class%')->addTag('kernel.event_subscriber', array()); - $container->register('event_dispatcher', 'stdClass'); - - $registerListenersPass = new RegisterListenersPass(); - $registerListenersPass->process($container); - } -} - -class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array( - 'event' => 'onEvent', - ); - } -} diff --git a/vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php deleted file mode 100644 index 5faa5c8..0000000 --- a/vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests; - -use Symfony\Component\EventDispatcher\EventDispatcher; - -class EventDispatcherTest extends AbstractEventDispatcherTest -{ - protected function createEventDispatcher() - { - return new EventDispatcher(); - } -} diff --git a/vendor/symfony/event-dispatcher/Tests/EventTest.php b/vendor/symfony/event-dispatcher/Tests/EventTest.php deleted file mode 100644 index 5be2ea0..0000000 --- a/vendor/symfony/event-dispatcher/Tests/EventTest.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\EventDispatcher\Event; - -/** - * Test class for Event. - */ -class EventTest extends TestCase -{ - /** - * @var \Symfony\Component\EventDispatcher\Event - */ - protected $event; - - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - protected function setUp() - { - $this->event = new Event(); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - protected function tearDown() - { - $this->event = null; - } - - public function testIsPropagationStopped() - { - $this->assertFalse($this->event->isPropagationStopped()); - } - - public function testStopPropagationAndIsPropagationStopped() - { - $this->event->stopPropagation(); - $this->assertTrue($this->event->isPropagationStopped()); - } -} diff --git a/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php b/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php deleted file mode 100644 index 9cf68c9..0000000 --- a/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php +++ /dev/null @@ -1,140 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\EventDispatcher\GenericEvent; - -/** - * Test class for Event. - */ -class GenericEventTest extends TestCase -{ - /** - * @var GenericEvent - */ - private $event; - - private $subject; - - /** - * Prepares the environment before running a test. - */ - protected function setUp() - { - parent::setUp(); - - $this->subject = new \stdClass(); - $this->event = new GenericEvent($this->subject, array('name' => 'Event')); - } - - /** - * Cleans up the environment after running a test. - */ - protected function tearDown() - { - $this->subject = null; - $this->event = null; - - parent::tearDown(); - } - - public function testConstruct() - { - $this->assertEquals($this->event, new GenericEvent($this->subject, array('name' => 'Event'))); - } - - /** - * Tests Event->getArgs(). - */ - public function testGetArguments() - { - // test getting all - $this->assertSame(array('name' => 'Event'), $this->event->getArguments()); - } - - public function testSetArguments() - { - $result = $this->event->setArguments(array('foo' => 'bar')); - $this->assertAttributeSame(array('foo' => 'bar'), 'arguments', $this->event); - $this->assertSame($this->event, $result); - } - - public function testSetArgument() - { - $result = $this->event->setArgument('foo2', 'bar2'); - $this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event); - $this->assertEquals($this->event, $result); - } - - public function testGetArgument() - { - // test getting key - $this->assertEquals('Event', $this->event->getArgument('name')); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testGetArgException() - { - $this->event->getArgument('nameNotExist'); - } - - public function testOffsetGet() - { - // test getting key - $this->assertEquals('Event', $this->event['name']); - - // test getting invalid arg - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); - $this->assertFalse($this->event['nameNotExist']); - } - - public function testOffsetSet() - { - $this->event['foo2'] = 'bar2'; - $this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event); - } - - public function testOffsetUnset() - { - unset($this->event['name']); - $this->assertAttributeSame(array(), 'arguments', $this->event); - } - - public function testOffsetIsset() - { - $this->assertArrayHasKey('name', $this->event); - $this->assertArrayNotHasKey('nameNotExist', $this->event); - } - - public function testHasArgument() - { - $this->assertTrue($this->event->hasArgument('name')); - $this->assertFalse($this->event->hasArgument('nameNotExist')); - } - - public function testGetSubject() - { - $this->assertSame($this->subject, $this->event->getSubject()); - } - - public function testHasIterator() - { - $data = array(); - foreach ($this->event as $key => $value) { - $data[$key] = $value; - } - $this->assertEquals(array('name' => 'Event'), $data); - } -} diff --git a/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php deleted file mode 100644 index 04f2861..0000000 --- a/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\EventDispatcher\Event; -use Symfony\Component\EventDispatcher\ImmutableEventDispatcher; - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - */ -class ImmutableEventDispatcherTest extends TestCase -{ - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $innerDispatcher; - - /** - * @var ImmutableEventDispatcher - */ - private $dispatcher; - - protected function setUp() - { - $this->innerDispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); - $this->dispatcher = new ImmutableEventDispatcher($this->innerDispatcher); - } - - public function testDispatchDelegates() - { - $event = new Event(); - - $this->innerDispatcher->expects($this->once()) - ->method('dispatch') - ->with('event', $event) - ->will($this->returnValue('result')); - - $this->assertSame('result', $this->dispatcher->dispatch('event', $event)); - } - - public function testGetListenersDelegates() - { - $this->innerDispatcher->expects($this->once()) - ->method('getListeners') - ->with('event') - ->will($this->returnValue('result')); - - $this->assertSame('result', $this->dispatcher->getListeners('event')); - } - - public function testHasListenersDelegates() - { - $this->innerDispatcher->expects($this->once()) - ->method('hasListeners') - ->with('event') - ->will($this->returnValue('result')); - - $this->assertSame('result', $this->dispatcher->hasListeners('event')); - } - - /** - * @expectedException \BadMethodCallException - */ - public function testAddListenerDisallowed() - { - $this->dispatcher->addListener('event', function () { return 'foo'; }); - } - - /** - * @expectedException \BadMethodCallException - */ - public function testAddSubscriberDisallowed() - { - $subscriber = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventSubscriberInterface')->getMock(); - - $this->dispatcher->addSubscriber($subscriber); - } - - /** - * @expectedException \BadMethodCallException - */ - public function testRemoveListenerDisallowed() - { - $this->dispatcher->removeListener('event', function () { return 'foo'; }); - } - - /** - * @expectedException \BadMethodCallException - */ - public function testRemoveSubscriberDisallowed() - { - $subscriber = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventSubscriberInterface')->getMock(); - - $this->dispatcher->removeSubscriber($subscriber); - } -} diff --git a/vendor/symfony/event-dispatcher/composer.json b/vendor/symfony/event-dispatcher/composer.json index 75b881b..32b42e4 100644 --- a/vendor/symfony/event-dispatcher/composer.json +++ b/vendor/symfony/event-dispatcher/composer.json @@ -1,7 +1,7 @@ { "name": "symfony/event-dispatcher", "type": "library", - "description": "Symfony EventDispatcher Component", + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", @@ -16,17 +16,27 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/event-dispatcher-contracts": "^2|^3", + "symfony/polyfill-php80": "^1.16" }, "require-dev": { - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "psr/log": "~1.0" + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^4.4|^5.0|^6.0", + "psr/log": "^1|^2|^3" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" }, "suggest": { "symfony/dependency-injection": "", @@ -38,10 +48,5 @@ "/Tests/" ] }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - } + "minimum-stability": "dev" } diff --git a/vendor/symfony/event-dispatcher/phpunit.xml.dist b/vendor/symfony/event-dispatcher/phpunit.xml.dist deleted file mode 100644 index b3ad1bd..0000000 --- a/vendor/symfony/event-dispatcher/phpunit.xml.dist +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" - backupGlobals="false" - colors="true" - bootstrap="vendor/autoload.php" - failOnRisky="true" - failOnWarning="true" -> - <php> - <ini name="error_reporting" value="-1" /> - </php> - - <testsuites> - <testsuite name="Symfony EventDispatcher Component Test Suite"> - <directory>./Tests/</directory> - </testsuite> - </testsuites> - - <filter> - <whitelist> - <directory>./</directory> - <exclude> - <directory>./Resources</directory> - <directory>./Tests</directory> - <directory>./vendor</directory> - </exclude> - </whitelist> - </filter> -</phpunit> diff --git a/vendor/symfony/filesystem/.gitignore b/vendor/symfony/filesystem/.gitignore deleted file mode 100644 index c49a5d8..0000000 --- a/vendor/symfony/filesystem/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/vendor/symfony/filesystem/CHANGELOG.md b/vendor/symfony/filesystem/CHANGELOG.md index d01f5f4..fcb7170 100644 --- a/vendor/symfony/filesystem/CHANGELOG.md +++ b/vendor/symfony/filesystem/CHANGELOG.md @@ -1,6 +1,35 @@ CHANGELOG ========= +5.4 +--- + + * Add `Path` class + * Add `$lock` argument to `Filesystem::appendToFile()` + +5.0.0 +----- + + * `Filesystem::dumpFile()` and `appendToFile()` don't accept arrays anymore + +4.4.0 +----- + + * support for passing a `null` value to `Filesystem::isAbsolutePath()` is deprecated and will be removed in 5.0 + * `tempnam()` now accepts a third argument `$suffix`. + +4.3.0 +----- + + * support for passing arrays to `Filesystem::dumpFile()` is deprecated and will be removed in 5.0 + * support for passing arrays to `Filesystem::appendToFile()` is deprecated and will be removed in 5.0 + +4.0.0 +----- + + * removed `LockHandler` + * Support for passing relative paths to `Filesystem::makePathRelative()` has been removed. + 3.4.0 ----- diff --git a/vendor/symfony/filesystem/Exception/ExceptionInterface.php b/vendor/symfony/filesystem/Exception/ExceptionInterface.php index 8f4f10a..fc438d9 100644 --- a/vendor/symfony/filesystem/Exception/ExceptionInterface.php +++ b/vendor/symfony/filesystem/Exception/ExceptionInterface.php @@ -16,6 +16,6 @@ * * @author Romain Neutron <imprec@gmail.com> */ -interface ExceptionInterface +interface ExceptionInterface extends \Throwable { } diff --git a/vendor/symfony/filesystem/Exception/FileNotFoundException.php b/vendor/symfony/filesystem/Exception/FileNotFoundException.php index bcc8fe8..48b6408 100644 --- a/vendor/symfony/filesystem/Exception/FileNotFoundException.php +++ b/vendor/symfony/filesystem/Exception/FileNotFoundException.php @@ -19,7 +19,7 @@ */ class FileNotFoundException extends IOException { - public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null) + public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) { if (null === $message) { if (null === $path) { diff --git a/vendor/symfony/filesystem/Exception/IOException.php b/vendor/symfony/filesystem/Exception/IOException.php index 144e0e6..fea26e4 100644 --- a/vendor/symfony/filesystem/Exception/IOException.php +++ b/vendor/symfony/filesystem/Exception/IOException.php @@ -22,7 +22,7 @@ class IOException extends \RuntimeException implements IOExceptionInterface { private $path; - public function __construct($message, $code = 0, \Exception $previous = null, $path = null) + public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) { $this->path = $path; diff --git a/vendor/symfony/filesystem/Exception/IOExceptionInterface.php b/vendor/symfony/filesystem/Exception/IOExceptionInterface.php index c11965a..42829ab 100644 --- a/vendor/symfony/filesystem/Exception/IOExceptionInterface.php +++ b/vendor/symfony/filesystem/Exception/IOExceptionInterface.php @@ -21,7 +21,7 @@ interface IOExceptionInterface extends ExceptionInterface /** * Returns the associated path for the exception. * - * @return string The path + * @return string|null */ public function getPath(); } diff --git a/vendor/symfony/filesystem/Exception/InvalidArgumentException.php b/vendor/symfony/filesystem/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..abadc20 --- /dev/null +++ b/vendor/symfony/filesystem/Exception/InvalidArgumentException.php @@ -0,0 +1,19 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem\Exception; + +/** + * @author Christian Flothmann <christian.flothmann@sensiolabs.de> + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/filesystem/Exception/RuntimeException.php b/vendor/symfony/filesystem/Exception/RuntimeException.php new file mode 100644 index 0000000..a7512dc --- /dev/null +++ b/vendor/symfony/filesystem/Exception/RuntimeException.php @@ -0,0 +1,19 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem\Exception; + +/** + * @author Théo Fidry <theo.fidry@gmail.com> + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/filesystem/Filesystem.php b/vendor/symfony/filesystem/Filesystem.php index 08151cb..23192bc 100644 --- a/vendor/symfony/filesystem/Filesystem.php +++ b/vendor/symfony/filesystem/Filesystem.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Filesystem; use Symfony\Component\Filesystem\Exception\FileNotFoundException; +use Symfony\Component\Filesystem\Exception\InvalidArgumentException; use Symfony\Component\Filesystem\Exception\IOException; /** @@ -30,14 +31,10 @@ class Filesystem * If the target file is newer, it is overwritten only when the * $overwriteNewerFiles option is set to true. * - * @param string $originFile The original filename - * @param string $targetFile The target filename - * @param bool $overwriteNewerFiles If true, target files newer than origin files are overwritten - * * @throws FileNotFoundException When originFile doesn't exist * @throws IOException When copy fails */ - public function copy($originFile, $targetFile, $overwriteNewerFiles = false) + public function copy(string $originFile, string $targetFile, bool $overwriteNewerFiles = false) { $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://'); if ($originIsLocal && !is_file($originFile)) { @@ -47,19 +44,19 @@ public function copy($originFile, $targetFile, $overwriteNewerFiles = false) $this->mkdir(\dirname($targetFile)); $doCopy = true; - if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) { + if (!$overwriteNewerFiles && null === parse_url($originFile, \PHP_URL_HOST) && is_file($targetFile)) { $doCopy = filemtime($originFile) > filemtime($targetFile); } if ($doCopy) { - // https://bugs.php.net/bug.php?id=64634 - if (false === $source = @fopen($originFile, 'r')) { - throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile); + // https://bugs.php.net/64634 + if (!$source = self::box('fopen', $originFile, 'r')) { + throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading: ', $originFile, $targetFile).self::$lastError, 0, null, $originFile); } // Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default - if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) { - throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile); + if (!$target = self::box('fopen', $targetFile, 'w', false, stream_context_create(['ftp' => ['overwrite' => true]]))) { + throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing: ', $originFile, $targetFile).self::$lastError, 0, null, $originFile); } $bytesCopied = stream_copy_to_stream($source, $target); @@ -73,7 +70,7 @@ public function copy($originFile, $targetFile, $overwriteNewerFiles = false) if ($originIsLocal) { // Like `cp`, preserve executable permission bits - @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111)); + self::box('chmod', $targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111)); if ($bytesCopied !== $bytesOrigin = filesize($originFile)) { throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile); @@ -86,25 +83,18 @@ public function copy($originFile, $targetFile, $overwriteNewerFiles = false) * Creates a directory recursively. * * @param string|iterable $dirs The directory path - * @param int $mode The directory mode * * @throws IOException On any directory creation failure */ - public function mkdir($dirs, $mode = 0777) + public function mkdir($dirs, int $mode = 0777) { foreach ($this->toIterable($dirs) as $dir) { if (is_dir($dir)) { continue; } - if (!self::box('mkdir', $dir, $mode, true)) { - if (!is_dir($dir)) { - // The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one - if (self::$lastError) { - throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir); - } - throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir); - } + if (!self::box('mkdir', $dir, $mode, true) && !is_dir($dir)) { + throw new IOException(sprintf('Failed to create "%s": ', $dir).self::$lastError, 0, null, $dir); } } } @@ -114,11 +104,11 @@ public function mkdir($dirs, $mode = 0777) * * @param string|iterable $files A filename, an array of files, or a \Traversable instance to check * - * @return bool true if the file exists, false otherwise + * @return bool */ public function exists($files) { - $maxPathLength = PHP_MAXPATHLEN - 2; + $maxPathLength = \PHP_MAXPATHLEN - 2; foreach ($this->toIterable($files) as $file) { if (\strlen($file) > $maxPathLength) { @@ -137,17 +127,16 @@ public function exists($files) * Sets access and modification time of file. * * @param string|iterable $files A filename, an array of files, or a \Traversable instance to create - * @param int $time The touch time as a Unix timestamp - * @param int $atime The access time as a Unix timestamp + * @param int|null $time The touch time as a Unix timestamp, if not supplied the current system time is used + * @param int|null $atime The access time as a Unix timestamp, if not supplied the current system time is used * * @throws IOException When touch fails */ - public function touch($files, $time = null, $atime = null) + public function touch($files, int $time = null, int $atime = null) { foreach ($this->toIterable($files) as $file) { - $touch = $time ? @touch($file, $time, $atime) : @touch($file); - if (true !== $touch) { - throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file); + if (!($time ? self::box('touch', $file, $time, $atime) : self::box('touch', $file))) { + throw new IOException(sprintf('Failed to touch "%s": ', $file).self::$lastError, 0, null, $file); } } } @@ -164,23 +153,54 @@ public function remove($files) if ($files instanceof \Traversable) { $files = iterator_to_array($files, false); } elseif (!\is_array($files)) { - $files = array($files); + $files = [$files]; } + + self::doRemove($files, false); + } + + private static function doRemove(array $files, bool $isRecursive): void + { $files = array_reverse($files); foreach ($files as $file) { if (is_link($file)) { // See https://bugs.php.net/52176 if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) { - throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError)); + throw new IOException(sprintf('Failed to remove symlink "%s": ', $file).self::$lastError); } } elseif (is_dir($file)) { - $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS)); + if (!$isRecursive) { + $tmpName = \dirname(realpath($file)).'/.'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-_')); + + if (file_exists($tmpName)) { + try { + self::doRemove([$tmpName], true); + } catch (IOException $e) { + } + } - if (!self::box('rmdir', $file) && file_exists($file)) { - throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError)); + if (!file_exists($tmpName) && self::box('rename', $file, $tmpName)) { + $origFile = $file; + $file = $tmpName; + } else { + $origFile = null; + } } - } elseif (!self::box('unlink', $file) && file_exists($file)) { - throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError)); + + $files = new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS); + self::doRemove(iterator_to_array($files, true), true); + + if (!self::box('rmdir', $file) && file_exists($file) && !$isRecursive) { + $lastError = self::$lastError; + + if (null !== $origFile && self::box('rename', $file, $origFile)) { + $file = $origFile; + } + + throw new IOException(sprintf('Failed to remove directory "%s": ', $file).$lastError); + } + } elseif (!self::box('unlink', $file) && (str_contains(self::$lastError, 'Permission denied') || file_exists($file))) { + throw new IOException(sprintf('Failed to remove file "%s": ', $file).self::$lastError); } } } @@ -193,13 +213,13 @@ public function remove($files) * @param int $umask The mode mask (octal) * @param bool $recursive Whether change the mod recursively or not * - * @throws IOException When the change fail + * @throws IOException When the change fails */ - public function chmod($files, $mode, $umask = 0000, $recursive = false) + public function chmod($files, int $mode, int $umask = 0000, bool $recursive = false) { foreach ($this->toIterable($files) as $file) { - if (true !== @chmod($file, $mode & ~$umask)) { - throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file); + if ((\PHP_VERSION_ID < 80000 || \is_int($mode)) && !self::box('chmod', $file, $mode & ~$umask)) { + throw new IOException(sprintf('Failed to chmod file "%s": ', $file).self::$lastError, 0, null, $file); } if ($recursive && is_dir($file) && !is_link($file)) { $this->chmod(new \FilesystemIterator($file), $mode, $umask, true); @@ -211,24 +231,24 @@ public function chmod($files, $mode, $umask = 0000, $recursive = false) * Change the owner of an array of files or directories. * * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change owner - * @param string $user The new owner user name + * @param string|int $user A user name or number * @param bool $recursive Whether change the owner recursively or not * - * @throws IOException When the change fail + * @throws IOException When the change fails */ - public function chown($files, $user, $recursive = false) + public function chown($files, $user, bool $recursive = false) { foreach ($this->toIterable($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chown(new \FilesystemIterator($file), $user, true); } if (is_link($file) && \function_exists('lchown')) { - if (true !== @lchown($file, $user)) { - throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); + if (!self::box('lchown', $file, $user)) { + throw new IOException(sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file); } } else { - if (true !== @chown($file, $user)) { - throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); + if (!self::box('chown', $file, $user)) { + throw new IOException(sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file); } } } @@ -238,24 +258,24 @@ public function chown($files, $user, $recursive = false) * Change the group of an array of files or directories. * * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change group - * @param string $group The group name + * @param string|int $group A group name or number * @param bool $recursive Whether change the group recursively or not * - * @throws IOException When the change fail + * @throws IOException When the change fails */ - public function chgrp($files, $group, $recursive = false) + public function chgrp($files, $group, bool $recursive = false) { foreach ($this->toIterable($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chgrp(new \FilesystemIterator($file), $group, true); } if (is_link($file) && \function_exists('lchgrp')) { - if (true !== @lchgrp($file, $group) || (\defined('HHVM_VERSION') && !posix_getgrnam($group))) { - throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); + if (!self::box('lchgrp', $file, $group)) { + throw new IOException(sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file); } } else { - if (true !== @chgrp($file, $group)) { - throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); + if (!self::box('chgrp', $file, $group)) { + throw new IOException(sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file); } } } @@ -264,44 +284,36 @@ public function chgrp($files, $group, $recursive = false) /** * Renames a file or a directory. * - * @param string $origin The origin filename or directory - * @param string $target The new filename or directory - * @param bool $overwrite Whether to overwrite the target if it already exists - * * @throws IOException When target file or directory already exists * @throws IOException When origin cannot be renamed */ - public function rename($origin, $target, $overwrite = false) + public function rename(string $origin, string $target, bool $overwrite = false) { // we check that target does not exist if (!$overwrite && $this->isReadable($target)) { throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target); } - if (true !== @rename($origin, $target)) { + if (!self::box('rename', $origin, $target)) { if (is_dir($origin)) { - // See https://bugs.php.net/bug.php?id=54097 & http://php.net/manual/en/function.rename.php#113943 - $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite)); + // See https://bugs.php.net/54097 & https://php.net/rename#113943 + $this->mirror($origin, $target, null, ['override' => $overwrite, 'delete' => $overwrite]); $this->remove($origin); return; } - throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target); + throw new IOException(sprintf('Cannot rename "%s" to "%s": ', $origin, $target).self::$lastError, 0, null, $target); } } /** * Tells whether a file exists and is readable. * - * @param string $filename Path to the file - * - * @return bool - * * @throws IOException When windows path is longer than 258 characters */ - private function isReadable($filename) + private function isReadable(string $filename): bool { - $maxPathLength = PHP_MAXPATHLEN - 2; + $maxPathLength = \PHP_MAXPATHLEN - 2; if (\strlen($filename) > $maxPathLength) { throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename); @@ -313,14 +325,12 @@ private function isReadable($filename) /** * Creates a symbolic link or copy a directory. * - * @param string $originDir The origin directory path - * @param string $targetDir The symbolic link name - * @param bool $copyOnWindows Whether to copy files if on Windows - * * @throws IOException When symlink fails */ - public function symlink($originDir, $targetDir, $copyOnWindows = false) + public function symlink(string $originDir, string $targetDir, bool $copyOnWindows = false) { + self::assertFunctionExists('symlink'); + if ('\\' === \DIRECTORY_SEPARATOR) { $originDir = strtr($originDir, '/', '\\'); $targetDir = strtr($targetDir, '/', '\\'); @@ -349,20 +359,21 @@ public function symlink($originDir, $targetDir, $copyOnWindows = false) /** * Creates a hard link, or several hard links to a file. * - * @param string $originFile The original file * @param string|string[] $targetFiles The target file(s) * * @throws FileNotFoundException When original file is missing or not a file * @throws IOException When link fails, including if link already exists */ - public function hardlink($originFile, $targetFiles) + public function hardlink(string $originFile, $targetFiles) { + self::assertFunctionExists('link'); + if (!$this->exists($originFile)) { throw new FileNotFoundException(null, 0, null, $originFile); } if (!is_file($originFile)) { - throw new FileNotFoundException(sprintf('Origin file "%s" is not a file', $originFile)); + throw new FileNotFoundException(sprintf('Origin file "%s" is not a file.', $originFile)); } foreach ($this->toIterable($targetFiles) as $targetFile) { @@ -380,18 +391,16 @@ public function hardlink($originFile, $targetFiles) } /** - * @param string $origin - * @param string $target * @param string $linkType Name of the link type, typically 'symbolic' or 'hard' */ - private function linkException($origin, $target, $linkType) + private function linkException(string $origin, string $target, string $linkType) { if (self::$lastError) { - if ('\\' === \DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) { - throw new IOException(sprintf('Unable to create %s link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target); + if ('\\' === \DIRECTORY_SEPARATOR && str_contains(self::$lastError, 'error code(1314)')) { + throw new IOException(sprintf('Unable to create "%s" link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target); } } - throw new IOException(sprintf('Failed to create %s link from "%s" to "%s".', $linkType, $origin, $target), 0, null, $target); + throw new IOException(sprintf('Failed to create "%s" link from "%s" to "%s": ', $linkType, $origin, $target).self::$lastError, 0, null, $target); } /** @@ -405,30 +414,27 @@ private function linkException($origin, $target, $linkType) * - if $path does not exist, returns null * - if $path exists, returns its absolute fully resolved final version * - * @param string $path A filesystem path - * @param bool $canonicalize Whether or not to return a canonicalized path - * * @return string|null */ - public function readlink($path, $canonicalize = false) + public function readlink(string $path, bool $canonicalize = false) { if (!$canonicalize && !is_link($path)) { - return; + return null; } if ($canonicalize) { if (!$this->exists($path)) { - return; + return null; } - if ('\\' === \DIRECTORY_SEPARATOR) { + if ('\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 70410) { $path = readlink($path); } return realpath($path); } - if ('\\' === \DIRECTORY_SEPARATOR) { + if ('\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 70400) { return realpath($path); } @@ -438,15 +444,16 @@ public function readlink($path, $canonicalize = false) /** * Given an existing path, convert it to a path relative to a given starting path. * - * @param string $endPath Absolute path of target - * @param string $startPath Absolute path where traversal begins - * - * @return string Path of target relative to starting path + * @return string */ - public function makePathRelative($endPath, $startPath) + public function makePathRelative(string $endPath, string $startPath) { - if (!$this->isAbsolutePath($endPath) || !$this->isAbsolutePath($startPath)) { - @trigger_error(sprintf('Support for passing relative paths to %s() is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + if (!$this->isAbsolutePath($startPath)) { + throw new InvalidArgumentException(sprintf('The start path "%s" is not absolute.', $startPath)); + } + + if (!$this->isAbsolutePath($endPath)) { + throw new InvalidArgumentException(sprintf('The end path "%s" is not absolute.', $endPath)); } // Normalize separators on Windows @@ -455,28 +462,19 @@ public function makePathRelative($endPath, $startPath) $startPath = str_replace('\\', '/', $startPath); } - $stripDriveLetter = function ($path) { - if (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) { - return substr($path, 2); - } - - return $path; + $splitDriveLetter = function ($path) { + return (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) + ? [substr($path, 2), strtoupper($path[0])] + : [$path, null]; }; - $endPath = $stripDriveLetter($endPath); - $startPath = $stripDriveLetter($startPath); + $splitPath = function ($path) { + $result = []; - // Split the paths into arrays - $startPathArr = explode('/', trim($startPath, '/')); - $endPathArr = explode('/', trim($endPath, '/')); - - $normalizePathArray = function ($pathSegments, $absolute) { - $result = array(); - - foreach ($pathSegments as $segment) { - if ('..' === $segment && ($absolute || \count($result))) { + foreach (explode('/', trim($path, '/')) as $segment) { + if ('..' === $segment) { array_pop($result); - } elseif ('.' !== $segment) { + } elseif ('.' !== $segment && '' !== $segment) { $result[] = $segment; } } @@ -484,8 +482,16 @@ public function makePathRelative($endPath, $startPath) return $result; }; - $startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath)); - $endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath)); + [$endPath, $endDriveLetter] = $splitDriveLetter($endPath); + [$startPath, $startDriveLetter] = $splitDriveLetter($startPath); + + $startPathArr = $splitPath($startPath); + $endPathArr = $splitPath($endPath); + + if ($endDriveLetter && $startDriveLetter && $endDriveLetter != $startDriveLetter) { + // End path is on another drive, so no relative path exists + return $endDriveLetter.':/'.($endPathArr ? implode('/', $endPathArr).'/' : ''); + } // Find for which directory the common path stops $index = 0; @@ -519,23 +525,25 @@ public function makePathRelative($endPath, $startPath) * - existing files in the target directory will be overwritten, except if they are newer (see the `override` option) * - files in the target directory that do not exist in the source directory will not be deleted (see the `delete` option) * - * @param string $originDir The origin directory - * @param string $targetDir The target directory - * @param \Traversable $iterator Iterator that filters which files and directories to copy - * @param array $options An array of boolean options - * Valid options are: - * - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false) - * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false) - * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) + * @param \Traversable|null $iterator Iterator that filters which files and directories to copy, if null a recursive iterator is created + * @param array $options An array of boolean options + * Valid options are: + * - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false) + * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false) + * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) * * @throws IOException When file type is unknown */ - public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array()) + public function mirror(string $originDir, string $targetDir, \Traversable $iterator = null, array $options = []) { $targetDir = rtrim($targetDir, '/\\'); $originDir = rtrim($originDir, '/\\'); $originDirLen = \strlen($originDir); + if (!$this->exists($originDir)) { + throw new IOException(sprintf('The origin directory specified "%s" was not found.', $originDir), 0, null, $originDir); + } + // Iterate in destination folder to remove obsolete entries if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) { $deleteIterator = $iterator; @@ -552,41 +560,32 @@ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $o } } - $copyOnWindows = false; - if (isset($options['copy_on_windows'])) { - $copyOnWindows = $options['copy_on_windows']; - } + $copyOnWindows = $options['copy_on_windows'] ?? false; if (null === $iterator) { $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS; $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST); } - if ($this->exists($originDir)) { - $this->mkdir($targetDir); - } + $this->mkdir($targetDir); + $filesCreatedWhileMirroring = []; foreach ($iterator as $file) { + if ($file->getPathname() === $targetDir || $file->getRealPath() === $targetDir || isset($filesCreatedWhileMirroring[$file->getRealPath()])) { + continue; + } + $target = $targetDir.substr($file->getPathname(), $originDirLen); + $filesCreatedWhileMirroring[$target] = true; - if ($copyOnWindows) { - if (is_file($file)) { - $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); - } elseif (is_dir($file)) { - $this->mkdir($target); - } else { - throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); - } + if (!$copyOnWindows && is_link($file)) { + $this->symlink($file->getLinkTarget(), $target); + } elseif (is_dir($file)) { + $this->mkdir($target); + } elseif (is_file($file)) { + $this->copy($file, $target, $options['override'] ?? false); } else { - if (is_link($file)) { - $this->symlink($file->getLinkTarget(), $target); - } elseif (is_dir($file)) { - $this->mkdir($target); - } elseif (is_file($file)) { - $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); - } else { - throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); - } + throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); } } } @@ -594,40 +593,37 @@ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $o /** * Returns whether the file path is an absolute path. * - * @param string $file A file path - * * @return bool */ - public function isAbsolutePath($file) + public function isAbsolutePath(string $file) { - return strspn($file, '/\\', 0, 1) + return '' !== $file && (strspn($file, '/\\', 0, 1) || (\strlen($file) > 3 && ctype_alpha($file[0]) && ':' === $file[1] && strspn($file, '/\\', 2, 1) ) - || null !== parse_url($file, PHP_URL_SCHEME) - ; + || null !== parse_url($file, \PHP_URL_SCHEME) + ); } /** * Creates a temporary file with support for custom stream wrappers. * - * @param string $dir The directory where the temporary filename will be created * @param string $prefix The prefix of the generated temporary filename * Note: Windows uses only the first three characters of prefix + * @param string $suffix The suffix of the generated temporary filename * * @return string The new temporary filename (with path), or throw an exception on failure */ - public function tempnam($dir, $prefix) + public function tempnam(string $dir, string $prefix/* , string $suffix = '' */) { - list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir); + $suffix = \func_num_args() > 2 ? func_get_arg(2) : ''; + [$scheme, $hierarchy] = $this->getSchemeAndHierarchy($dir); // If no scheme or scheme is "file" or "gs" (Google Cloud) create temp file in local filesystem - if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) { - $tmpFile = @tempnam($hierarchy, $prefix); - + if ((null === $scheme || 'file' === $scheme || 'gs' === $scheme) && '' === $suffix) { // If tempnam failed or no scheme return the filename otherwise prepend the scheme - if (false !== $tmpFile) { + if ($tmpFile = self::box('tempnam', $hierarchy, $prefix)) { if (null !== $scheme && 'gs' !== $scheme) { return $scheme.'://'.$tmpFile; } @@ -635,135 +631,144 @@ public function tempnam($dir, $prefix) return $tmpFile; } - throw new IOException('A temporary file could not be created.'); + throw new IOException('A temporary file could not be created: '.self::$lastError); } // Loop until we create a valid temp file or have reached 10 attempts for ($i = 0; $i < 10; ++$i) { // Create a unique filename - $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true); + $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true).$suffix; // Use fopen instead of file_exists as some streams do not support stat // Use mode 'x+' to atomically check existence and create to avoid a TOCTOU vulnerability - $handle = @fopen($tmpFile, 'x+'); - - // If unsuccessful restart the loop - if (false === $handle) { + if (!$handle = self::box('fopen', $tmpFile, 'x+')) { continue; } // Close the file if it was successfully opened - @fclose($handle); + self::box('fclose', $handle); return $tmpFile; } - throw new IOException('A temporary file could not be created.'); + throw new IOException('A temporary file could not be created: '.self::$lastError); } /** * Atomically dumps content into a file. * - * @param string $filename The file to be written to - * @param string $content The data to write into the file + * @param string|resource $content The data to write into the file * * @throws IOException if the file cannot be written to */ - public function dumpFile($filename, $content) + public function dumpFile(string $filename, $content) { + if (\is_array($content)) { + throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__)); + } + $dir = \dirname($filename); - if (!is_dir($dir)) { - $this->mkdir($dir); + if (is_link($filename) && $linkTarget = $this->readlink($filename)) { + $this->dumpFile(Path::makeAbsolute($linkTarget, $dir), $content); + + return; } - if (!is_writable($dir)) { - throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); + if (!is_dir($dir)) { + $this->mkdir($dir); } // Will create a temp file with 0600 access rights // when the filesystem supports chmod. $tmpFile = $this->tempnam($dir, basename($filename)); - if (false === @file_put_contents($tmpFile, $content)) { - throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); - } + try { + if (false === self::box('file_put_contents', $tmpFile, $content)) { + throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename); + } - @chmod($tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask()); + self::box('chmod', $tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask()); - $this->rename($tmpFile, $filename, true); + $this->rename($tmpFile, $filename, true); + } finally { + if (file_exists($tmpFile)) { + self::box('unlink', $tmpFile); + } + } } /** * Appends content to an existing file. * - * @param string $filename The file to which to append content - * @param string $content The content to append + * @param string|resource $content The content to append + * @param bool $lock Whether the file should be locked when writing to it * * @throws IOException If the file is not writable */ - public function appendToFile($filename, $content) + public function appendToFile(string $filename, $content/* , bool $lock = false */) { + if (\is_array($content)) { + throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be string or resource, array given.', __METHOD__)); + } + $dir = \dirname($filename); if (!is_dir($dir)) { $this->mkdir($dir); } - if (!is_writable($dir)) { - throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); - } + $lock = \func_num_args() > 2 && func_get_arg(2); - if (false === @file_put_contents($filename, $content, FILE_APPEND)) { - throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); + if (false === self::box('file_put_contents', $filename, $content, \FILE_APPEND | ($lock ? \LOCK_EX : 0))) { + throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename); } } - /** - * @param mixed $files - * - * @return array|\Traversable - */ - private function toIterable($files) + private function toIterable($files): iterable { - return \is_array($files) || $files instanceof \Traversable ? $files : array($files); + return is_iterable($files) ? $files : [$files]; } /** - * Gets a 2-tuple of scheme (may be null) and hierarchical part of a filename (e.g. file:///tmp -> array(file, tmp)). - * - * @param string $filename The filename to be parsed - * - * @return array The filename scheme and hierarchical part + * Gets a 2-tuple of scheme (may be null) and hierarchical part of a filename (e.g. file:///tmp -> [file, tmp]). */ - private function getSchemeAndHierarchy($filename) + private function getSchemeAndHierarchy(string $filename): array { $components = explode('://', $filename, 2); - return 2 === \count($components) ? array($components[0], $components[1]) : array(null, $components[0]); + return 2 === \count($components) ? [$components[0], $components[1]] : [null, $components[0]]; + } + + private static function assertFunctionExists(string $func): void + { + if (!\function_exists($func)) { + throw new IOException(sprintf('Unable to perform filesystem operation because the "%s()" function has been disabled.', $func)); + } } - private static function box($func) + /** + * @param mixed ...$args + * + * @return mixed + */ + private static function box(string $func, ...$args) { + self::assertFunctionExists($func); + self::$lastError = null; - \set_error_handler(__CLASS__.'::handleError'); + set_error_handler(__CLASS__.'::handleError'); try { - $result = \call_user_func_array($func, \array_slice(\func_get_args(), 1)); - \restore_error_handler(); - - return $result; - } catch (\Throwable $e) { - } catch (\Exception $e) { + return $func(...$args); + } finally { + restore_error_handler(); } - \restore_error_handler(); - - throw $e; } /** * @internal */ - public static function handleError($type, $msg) + public static function handleError(int $type, string $msg) { self::$lastError = $msg; } diff --git a/vendor/symfony/filesystem/LICENSE b/vendor/symfony/filesystem/LICENSE index 21d7fb9..0138f8f 100644 --- a/vendor/symfony/filesystem/LICENSE +++ b/vendor/symfony/filesystem/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/filesystem/LockHandler.php b/vendor/symfony/filesystem/LockHandler.php deleted file mode 100644 index 8e0eb74..0000000 --- a/vendor/symfony/filesystem/LockHandler.php +++ /dev/null @@ -1,121 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem; - -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Lock\Store\FlockStore; -use Symfony\Component\Lock\Store\SemaphoreStore; - -@trigger_error(sprintf('The %s class is deprecated since Symfony 3.4 and will be removed in 4.0. Use %s or %s instead.', LockHandler::class, SemaphoreStore::class, FlockStore::class), E_USER_DEPRECATED); - -/** - * LockHandler class provides a simple abstraction to lock anything by means of - * a file lock. - * - * A locked file is created based on the lock name when calling lock(). Other - * lock handlers will not be able to lock the same name until it is released - * (explicitly by calling release() or implicitly when the instance holding the - * lock is destroyed). - * - * @author Grégoire Pineau <lyrixx@lyrixx.info> - * @author Romain Neutron <imprec@gmail.com> - * @author Nicolas Grekas <p@tchwork.com> - * - * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\Lock\Store\SemaphoreStore or Symfony\Component\Lock\Store\FlockStore instead. - */ -class LockHandler -{ - private $file; - private $handle; - - /** - * @param string $name The lock name - * @param string|null $lockPath The directory to store the lock. Default values will use temporary directory - * - * @throws IOException If the lock directory could not be created or is not writable - */ - public function __construct($name, $lockPath = null) - { - $lockPath = $lockPath ?: sys_get_temp_dir(); - - if (!is_dir($lockPath)) { - $fs = new Filesystem(); - $fs->mkdir($lockPath); - } - - if (!is_writable($lockPath)) { - throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath); - } - - $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name)); - } - - /** - * Lock the resource. - * - * @param bool $blocking Wait until the lock is released - * - * @return bool Returns true if the lock was acquired, false otherwise - * - * @throws IOException If the lock file could not be created or opened - */ - public function lock($blocking = false) - { - if ($this->handle) { - return true; - } - - $error = null; - - // Silence error reporting - set_error_handler(function ($errno, $msg) use (&$error) { - $error = $msg; - }); - - if (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) { - if ($this->handle = fopen($this->file, 'x')) { - chmod($this->file, 0666); - } elseif (!$this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r')) { - usleep(100); // Give some time for chmod() to complete - $this->handle = fopen($this->file, 'r+') ?: fopen($this->file, 'r'); - } - } - restore_error_handler(); - - if (!$this->handle) { - throw new IOException($error, 0, null, $this->file); - } - - // On Windows, even if PHP doc says the contrary, LOCK_NB works, see - // https://bugs.php.net/54129 - if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) { - fclose($this->handle); - $this->handle = null; - - return false; - } - - return true; - } - - /** - * Release the resource. - */ - public function release() - { - if ($this->handle) { - flock($this->handle, LOCK_UN | LOCK_NB); - fclose($this->handle); - $this->handle = null; - } - } -} diff --git a/vendor/symfony/filesystem/Path.php b/vendor/symfony/filesystem/Path.php new file mode 100644 index 0000000..9aa3735 --- /dev/null +++ b/vendor/symfony/filesystem/Path.php @@ -0,0 +1,819 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem; + +use Symfony\Component\Filesystem\Exception\InvalidArgumentException; +use Symfony\Component\Filesystem\Exception\RuntimeException; + +/** + * Contains utility methods for handling path strings. + * + * The methods in this class are able to deal with both UNIX and Windows paths + * with both forward and backward slashes. All methods return normalized parts + * containing only forward slashes and no excess "." and ".." segments. + * + * @author Bernhard Schussek <bschussek@gmail.com> + * @author Thomas Schulz <mail@king2500.net> + * @author Théo Fidry <theo.fidry@gmail.com> + */ +final class Path +{ + /** + * The number of buffer entries that triggers a cleanup operation. + */ + private const CLEANUP_THRESHOLD = 1250; + + /** + * The buffer size after the cleanup operation. + */ + private const CLEANUP_SIZE = 1000; + + /** + * Buffers input/output of {@link canonicalize()}. + * + * @var array<string, string> + */ + private static $buffer = []; + + /** + * @var int + */ + private static $bufferSize = 0; + + /** + * Canonicalizes the given path. + * + * During normalization, all slashes are replaced by forward slashes ("/"). + * Furthermore, all "." and ".." segments are removed as far as possible. + * ".." segments at the beginning of relative paths are not removed. + * + * ```php + * echo Path::canonicalize("\symfony\puli\..\css\style.css"); + * // => /symfony/css/style.css + * + * echo Path::canonicalize("../css/./style.css"); + * // => ../css/style.css + * ``` + * + * This method is able to deal with both UNIX and Windows paths. + */ + public static function canonicalize(string $path): string + { + if ('' === $path) { + return ''; + } + + // This method is called by many other methods in this class. Buffer + // the canonicalized paths to make up for the severe performance + // decrease. + if (isset(self::$buffer[$path])) { + return self::$buffer[$path]; + } + + // Replace "~" with user's home directory. + if ('~' === $path[0]) { + $path = self::getHomeDirectory().substr($path, 1); + } + + $path = self::normalize($path); + + [$root, $pathWithoutRoot] = self::split($path); + + $canonicalParts = self::findCanonicalParts($root, $pathWithoutRoot); + + // Add the root directory again + self::$buffer[$path] = $canonicalPath = $root.implode('/', $canonicalParts); + ++self::$bufferSize; + + // Clean up regularly to prevent memory leaks + if (self::$bufferSize > self::CLEANUP_THRESHOLD) { + self::$buffer = \array_slice(self::$buffer, -self::CLEANUP_SIZE, null, true); + self::$bufferSize = self::CLEANUP_SIZE; + } + + return $canonicalPath; + } + + /** + * Normalizes the given path. + * + * During normalization, all slashes are replaced by forward slashes ("/"). + * Contrary to {@link canonicalize()}, this method does not remove invalid + * or dot path segments. Consequently, it is much more efficient and should + * be used whenever the given path is known to be a valid, absolute system + * path. + * + * This method is able to deal with both UNIX and Windows paths. + */ + public static function normalize(string $path): string + { + return str_replace('\\', '/', $path); + } + + /** + * Returns the directory part of the path. + * + * This method is similar to PHP's dirname(), but handles various cases + * where dirname() returns a weird result: + * + * - dirname() does not accept backslashes on UNIX + * - dirname("C:/symfony") returns "C:", not "C:/" + * - dirname("C:/") returns ".", not "C:/" + * - dirname("C:") returns ".", not "C:/" + * - dirname("symfony") returns ".", not "" + * - dirname() does not canonicalize the result + * + * This method fixes these shortcomings and behaves like dirname() + * otherwise. + * + * The result is a canonical path. + * + * @return string The canonical directory part. Returns the root directory + * if the root directory is passed. Returns an empty string + * if a relative path is passed that contains no slashes. + * Returns an empty string if an empty string is passed. + */ + public static function getDirectory(string $path): string + { + if ('' === $path) { + return ''; + } + + $path = self::canonicalize($path); + + // Maintain scheme + if (false !== $schemeSeparatorPosition = strpos($path, '://')) { + $scheme = substr($path, 0, $schemeSeparatorPosition + 3); + $path = substr($path, $schemeSeparatorPosition + 3); + } else { + $scheme = ''; + } + + if (false === $dirSeparatorPosition = strrpos($path, '/')) { + return ''; + } + + // Directory equals root directory "/" + if (0 === $dirSeparatorPosition) { + return $scheme.'/'; + } + + // Directory equals Windows root "C:/" + if (2 === $dirSeparatorPosition && ctype_alpha($path[0]) && ':' === $path[1]) { + return $scheme.substr($path, 0, 3); + } + + return $scheme.substr($path, 0, $dirSeparatorPosition); + } + + /** + * Returns canonical path of the user's home directory. + * + * Supported operating systems: + * + * - UNIX + * - Windows8 and upper + * + * If your operating system or environment isn't supported, an exception is thrown. + * + * The result is a canonical path. + * + * @throws RuntimeException If your operating system or environment isn't supported + */ + public static function getHomeDirectory(): string + { + // For UNIX support + if (getenv('HOME')) { + return self::canonicalize(getenv('HOME')); + } + + // For >= Windows8 support + if (getenv('HOMEDRIVE') && getenv('HOMEPATH')) { + return self::canonicalize(getenv('HOMEDRIVE').getenv('HOMEPATH')); + } + + throw new RuntimeException("Cannot find the home directory path: Your environment or operating system isn't supported."); + } + + /** + * Returns the root directory of a path. + * + * The result is a canonical path. + * + * @return string The canonical root directory. Returns an empty string if + * the given path is relative or empty. + */ + public static function getRoot(string $path): string + { + if ('' === $path) { + return ''; + } + + // Maintain scheme + if (false !== $schemeSeparatorPosition = strpos($path, '://')) { + $scheme = substr($path, 0, $schemeSeparatorPosition + 3); + $path = substr($path, $schemeSeparatorPosition + 3); + } else { + $scheme = ''; + } + + $firstCharacter = $path[0]; + + // UNIX root "/" or "\" (Windows style) + if ('/' === $firstCharacter || '\\' === $firstCharacter) { + return $scheme.'/'; + } + + $length = \strlen($path); + + // Windows root + if ($length > 1 && ':' === $path[1] && ctype_alpha($firstCharacter)) { + // Special case: "C:" + if (2 === $length) { + return $scheme.$path.'/'; + } + + // Normal case: "C:/ or "C:\" + if ('/' === $path[2] || '\\' === $path[2]) { + return $scheme.$firstCharacter.$path[1].'/'; + } + } + + return ''; + } + + /** + * Returns the file name without the extension from a file path. + * + * @param string|null $extension if specified, only that extension is cut + * off (may contain leading dot) + */ + public static function getFilenameWithoutExtension(string $path, string $extension = null): string + { + if ('' === $path) { + return ''; + } + + if (null !== $extension) { + // remove extension and trailing dot + return rtrim(basename($path, $extension), '.'); + } + + return pathinfo($path, \PATHINFO_FILENAME); + } + + /** + * Returns the extension from a file path (without leading dot). + * + * @param bool $forceLowerCase forces the extension to be lower-case + */ + public static function getExtension(string $path, bool $forceLowerCase = false): string + { + if ('' === $path) { + return ''; + } + + $extension = pathinfo($path, \PATHINFO_EXTENSION); + + if ($forceLowerCase) { + $extension = self::toLower($extension); + } + + return $extension; + } + + /** + * Returns whether the path has an (or the specified) extension. + * + * @param string $path the path string + * @param string|string[]|null $extensions if null or not provided, checks if + * an extension exists, otherwise + * checks for the specified extension + * or array of extensions (with or + * without leading dot) + * @param bool $ignoreCase whether to ignore case-sensitivity + */ + public static function hasExtension(string $path, $extensions = null, bool $ignoreCase = false): bool + { + if ('' === $path) { + return false; + } + + $actualExtension = self::getExtension($path, $ignoreCase); + + // Only check if path has any extension + if ([] === $extensions || null === $extensions) { + return '' !== $actualExtension; + } + + if (\is_string($extensions)) { + $extensions = [$extensions]; + } + + foreach ($extensions as $key => $extension) { + if ($ignoreCase) { + $extension = self::toLower($extension); + } + + // remove leading '.' in extensions array + $extensions[$key] = ltrim($extension, '.'); + } + + return \in_array($actualExtension, $extensions, true); + } + + /** + * Changes the extension of a path string. + * + * @param string $path The path string with filename.ext to change. + * @param string $extension new extension (with or without leading dot) + * + * @return string the path string with new file extension + */ + public static function changeExtension(string $path, string $extension): string + { + if ('' === $path) { + return ''; + } + + $actualExtension = self::getExtension($path); + $extension = ltrim($extension, '.'); + + // No extension for paths + if ('/' === substr($path, -1)) { + return $path; + } + + // No actual extension in path + if (empty($actualExtension)) { + return $path.('.' === substr($path, -1) ? '' : '.').$extension; + } + + return substr($path, 0, -\strlen($actualExtension)).$extension; + } + + public static function isAbsolute(string $path): bool + { + if ('' === $path) { + return false; + } + + // Strip scheme + if (false !== $schemeSeparatorPosition = strpos($path, '://')) { + $path = substr($path, $schemeSeparatorPosition + 3); + } + + $firstCharacter = $path[0]; + + // UNIX root "/" or "\" (Windows style) + if ('/' === $firstCharacter || '\\' === $firstCharacter) { + return true; + } + + // Windows root + if (\strlen($path) > 1 && ctype_alpha($firstCharacter) && ':' === $path[1]) { + // Special case: "C:" + if (2 === \strlen($path)) { + return true; + } + + // Normal case: "C:/ or "C:\" + if ('/' === $path[2] || '\\' === $path[2]) { + return true; + } + } + + return false; + } + + public static function isRelative(string $path): bool + { + return !self::isAbsolute($path); + } + + /** + * Turns a relative path into an absolute path in canonical form. + * + * Usually, the relative path is appended to the given base path. Dot + * segments ("." and "..") are removed/collapsed and all slashes turned + * into forward slashes. + * + * ```php + * echo Path::makeAbsolute("../style.css", "/symfony/puli/css"); + * // => /symfony/puli/style.css + * ``` + * + * If an absolute path is passed, that path is returned unless its root + * directory is different than the one of the base path. In that case, an + * exception is thrown. + * + * ```php + * Path::makeAbsolute("/style.css", "/symfony/puli/css"); + * // => /style.css + * + * Path::makeAbsolute("C:/style.css", "C:/symfony/puli/css"); + * // => C:/style.css + * + * Path::makeAbsolute("C:/style.css", "/symfony/puli/css"); + * // InvalidArgumentException + * ``` + * + * If the base path is not an absolute path, an exception is thrown. + * + * The result is a canonical path. + * + * @param string $basePath an absolute base path + * + * @throws InvalidArgumentException if the base path is not absolute or if + * the given path is an absolute path with + * a different root than the base path + */ + public static function makeAbsolute(string $path, string $basePath): string + { + if ('' === $basePath) { + throw new InvalidArgumentException(sprintf('The base path must be a non-empty string. Got: "%s".', $basePath)); + } + + if (!self::isAbsolute($basePath)) { + throw new InvalidArgumentException(sprintf('The base path "%s" is not an absolute path.', $basePath)); + } + + if (self::isAbsolute($path)) { + return self::canonicalize($path); + } + + if (false !== $schemeSeparatorPosition = strpos($basePath, '://')) { + $scheme = substr($basePath, 0, $schemeSeparatorPosition + 3); + $basePath = substr($basePath, $schemeSeparatorPosition + 3); + } else { + $scheme = ''; + } + + return $scheme.self::canonicalize(rtrim($basePath, '/\\').'/'.$path); + } + + /** + * Turns a path into a relative path. + * + * The relative path is created relative to the given base path: + * + * ```php + * echo Path::makeRelative("/symfony/style.css", "/symfony/puli"); + * // => ../style.css + * ``` + * + * If a relative path is passed and the base path is absolute, the relative + * path is returned unchanged: + * + * ```php + * Path::makeRelative("style.css", "/symfony/puli/css"); + * // => style.css + * ``` + * + * If both paths are relative, the relative path is created with the + * assumption that both paths are relative to the same directory: + * + * ```php + * Path::makeRelative("style.css", "symfony/puli/css"); + * // => ../../../style.css + * ``` + * + * If both paths are absolute, their root directory must be the same, + * otherwise an exception is thrown: + * + * ```php + * Path::makeRelative("C:/symfony/style.css", "/symfony/puli"); + * // InvalidArgumentException + * ``` + * + * If the passed path is absolute, but the base path is not, an exception + * is thrown as well: + * + * ```php + * Path::makeRelative("/symfony/style.css", "symfony/puli"); + * // InvalidArgumentException + * ``` + * + * If the base path is not an absolute path, an exception is thrown. + * + * The result is a canonical path. + * + * @throws InvalidArgumentException if the base path is not absolute or if + * the given path has a different root + * than the base path + */ + public static function makeRelative(string $path, string $basePath): string + { + $path = self::canonicalize($path); + $basePath = self::canonicalize($basePath); + + [$root, $relativePath] = self::split($path); + [$baseRoot, $relativeBasePath] = self::split($basePath); + + // If the base path is given as absolute path and the path is already + // relative, consider it to be relative to the given absolute path + // already + if ('' === $root && '' !== $baseRoot) { + // If base path is already in its root + if ('' === $relativeBasePath) { + $relativePath = ltrim($relativePath, './\\'); + } + + return $relativePath; + } + + // If the passed path is absolute, but the base path is not, we + // cannot generate a relative path + if ('' !== $root && '' === $baseRoot) { + throw new InvalidArgumentException(sprintf('The absolute path "%s" cannot be made relative to the relative path "%s". You should provide an absolute base path instead.', $path, $basePath)); + } + + // Fail if the roots of the two paths are different + if ($baseRoot && $root !== $baseRoot) { + throw new InvalidArgumentException(sprintf('The path "%s" cannot be made relative to "%s", because they have different roots ("%s" and "%s").', $path, $basePath, $root, $baseRoot)); + } + + if ('' === $relativeBasePath) { + return $relativePath; + } + + // Build a "../../" prefix with as many "../" parts as necessary + $parts = explode('/', $relativePath); + $baseParts = explode('/', $relativeBasePath); + $dotDotPrefix = ''; + + // Once we found a non-matching part in the prefix, we need to add + // "../" parts for all remaining parts + $match = true; + + foreach ($baseParts as $index => $basePart) { + if ($match && isset($parts[$index]) && $basePart === $parts[$index]) { + unset($parts[$index]); + + continue; + } + + $match = false; + $dotDotPrefix .= '../'; + } + + return rtrim($dotDotPrefix.implode('/', $parts), '/'); + } + + /** + * Returns whether the given path is on the local filesystem. + */ + public static function isLocal(string $path): bool + { + return '' !== $path && false === strpos($path, '://'); + } + + /** + * Returns the longest common base path in canonical form of a set of paths or + * `null` if the paths are on different Windows partitions. + * + * Dot segments ("." and "..") are removed/collapsed and all slashes turned + * into forward slashes. + * + * ```php + * $basePath = Path::getLongestCommonBasePath( + * '/symfony/css/style.css', + * '/symfony/css/..' + * ); + * // => /symfony + * ``` + * + * The root is returned if no common base path can be found: + * + * ```php + * $basePath = Path::getLongestCommonBasePath( + * '/symfony/css/style.css', + * '/puli/css/..' + * ); + * // => / + * ``` + * + * If the paths are located on different Windows partitions, `null` is + * returned. + * + * ```php + * $basePath = Path::getLongestCommonBasePath( + * 'C:/symfony/css/style.css', + * 'D:/symfony/css/..' + * ); + * // => null + * ``` + */ + public static function getLongestCommonBasePath(string ...$paths): ?string + { + [$bpRoot, $basePath] = self::split(self::canonicalize(reset($paths))); + + for (next($paths); null !== key($paths) && '' !== $basePath; next($paths)) { + [$root, $path] = self::split(self::canonicalize(current($paths))); + + // If we deal with different roots (e.g. C:/ vs. D:/), it's time + // to quit + if ($root !== $bpRoot) { + return null; + } + + // Make the base path shorter until it fits into path + while (true) { + if ('.' === $basePath) { + // No more base paths + $basePath = ''; + + // next path + continue 2; + } + + // Prevent false positives for common prefixes + // see isBasePath() + if (0 === strpos($path.'/', $basePath.'/')) { + // next path + continue 2; + } + + $basePath = \dirname($basePath); + } + } + + return $bpRoot.$basePath; + } + + /** + * Joins two or more path strings into a canonical path. + */ + public static function join(string ...$paths): string + { + $finalPath = null; + $wasScheme = false; + + foreach ($paths as $path) { + if ('' === $path) { + continue; + } + + if (null === $finalPath) { + // For first part we keep slashes, like '/top', 'C:\' or 'phar://' + $finalPath = $path; + $wasScheme = (false !== strpos($path, '://')); + continue; + } + + // Only add slash if previous part didn't end with '/' or '\' + if (!\in_array(substr($finalPath, -1), ['/', '\\'])) { + $finalPath .= '/'; + } + + // If first part included a scheme like 'phar://' we allow \current part to start with '/', otherwise trim + $finalPath .= $wasScheme ? $path : ltrim($path, '/'); + $wasScheme = false; + } + + if (null === $finalPath) { + return ''; + } + + return self::canonicalize($finalPath); + } + + /** + * Returns whether a path is a base path of another path. + * + * Dot segments ("." and "..") are removed/collapsed and all slashes turned + * into forward slashes. + * + * ```php + * Path::isBasePath('/symfony', '/symfony/css'); + * // => true + * + * Path::isBasePath('/symfony', '/symfony'); + * // => true + * + * Path::isBasePath('/symfony', '/symfony/..'); + * // => false + * + * Path::isBasePath('/symfony', '/puli'); + * // => false + * ``` + */ + public static function isBasePath(string $basePath, string $ofPath): bool + { + $basePath = self::canonicalize($basePath); + $ofPath = self::canonicalize($ofPath); + + // Append slashes to prevent false positives when two paths have + // a common prefix, for example /base/foo and /base/foobar. + // Don't append a slash for the root "/", because then that root + // won't be discovered as common prefix ("//" is not a prefix of + // "/foobar/"). + return 0 === strpos($ofPath.'/', rtrim($basePath, '/').'/'); + } + + /** + * @return string[] + */ + private static function findCanonicalParts(string $root, string $pathWithoutRoot): array + { + $parts = explode('/', $pathWithoutRoot); + + $canonicalParts = []; + + // Collapse "." and "..", if possible + foreach ($parts as $part) { + if ('.' === $part || '' === $part) { + continue; + } + + // Collapse ".." with the previous part, if one exists + // Don't collapse ".." if the previous part is also ".." + if ('..' === $part && \count($canonicalParts) > 0 && '..' !== $canonicalParts[\count($canonicalParts) - 1]) { + array_pop($canonicalParts); + + continue; + } + + // Only add ".." prefixes for relative paths + if ('..' !== $part || '' === $root) { + $canonicalParts[] = $part; + } + } + + return $canonicalParts; + } + + /** + * Splits a canonical path into its root directory and the remainder. + * + * If the path has no root directory, an empty root directory will be + * returned. + * + * If the root directory is a Windows style partition, the resulting root + * will always contain a trailing slash. + * + * list ($root, $path) = Path::split("C:/symfony") + * // => ["C:/", "symfony"] + * + * list ($root, $path) = Path::split("C:") + * // => ["C:/", ""] + * + * @return array{string, string} an array with the root directory and the remaining relative path + */ + private static function split(string $path): array + { + if ('' === $path) { + return ['', '']; + } + + // Remember scheme as part of the root, if any + if (false !== $schemeSeparatorPosition = strpos($path, '://')) { + $root = substr($path, 0, $schemeSeparatorPosition + 3); + $path = substr($path, $schemeSeparatorPosition + 3); + } else { + $root = ''; + } + + $length = \strlen($path); + + // Remove and remember root directory + if (0 === strpos($path, '/')) { + $root .= '/'; + $path = $length > 1 ? substr($path, 1) : ''; + } elseif ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { + if (2 === $length) { + // Windows special case: "C:" + $root .= $path.'/'; + $path = ''; + } elseif ('/' === $path[2]) { + // Windows normal case: "C:/".. + $root .= substr($path, 0, 3); + $path = $length > 3 ? substr($path, 3) : ''; + } + } + + return [$root, $path]; + } + + private static function toLower(string $string): string + { + if (false !== $encoding = mb_detect_encoding($string, null, true)) { + return mb_strtolower($string, $encoding); + } + + return strtolower($string); + } + + private function __construct() + { + } +} diff --git a/vendor/symfony/filesystem/README.md b/vendor/symfony/filesystem/README.md index 877ab35..f2f6d45 100644 --- a/vendor/symfony/filesystem/README.md +++ b/vendor/symfony/filesystem/README.md @@ -6,8 +6,8 @@ The Filesystem component provides basic utilities for the filesystem. Resources --------- - * [Documentation](https://symfony.com/doc/current/components/filesystem/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) + * [Documentation](https://symfony.com/doc/current/components/filesystem.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/filesystem/Tests/ExceptionTest.php b/vendor/symfony/filesystem/Tests/ExceptionTest.php deleted file mode 100644 index 300acf1..0000000 --- a/vendor/symfony/filesystem/Tests/ExceptionTest.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Filesystem\Exception\FileNotFoundException; -use Symfony\Component\Filesystem\Exception\IOException; - -/** - * Test class for Filesystem. - */ -class ExceptionTest extends TestCase -{ - public function testGetPath() - { - $e = new IOException('', 0, null, '/foo'); - $this->assertEquals('/foo', $e->getPath(), 'The pass should be returned.'); - } - - public function testGeneratedMessage() - { - $e = new FileNotFoundException(null, 0, null, '/foo'); - $this->assertEquals('/foo', $e->getPath()); - $this->assertEquals('File "/foo" could not be found.', $e->getMessage(), 'A message should be generated.'); - } - - public function testGeneratedMessageWithoutPath() - { - $e = new FileNotFoundException(); - $this->assertEquals('File could not be found.', $e->getMessage(), 'A message should be generated.'); - } - - public function testCustomMessage() - { - $e = new FileNotFoundException('bar', 0, null, '/foo'); - $this->assertEquals('bar', $e->getMessage(), 'A custom message should be possible still.'); - } -} diff --git a/vendor/symfony/filesystem/Tests/FilesystemTest.php b/vendor/symfony/filesystem/Tests/FilesystemTest.php deleted file mode 100644 index e4ff91c..0000000 --- a/vendor/symfony/filesystem/Tests/FilesystemTest.php +++ /dev/null @@ -1,1638 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Tests; - -/** - * Test class for Filesystem. - */ -class FilesystemTest extends FilesystemTestCase -{ - public function testCopyCreatesNewFile() - { - $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; - $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; - - file_put_contents($sourceFilePath, 'SOURCE FILE'); - - $this->filesystem->copy($sourceFilePath, $targetFilePath); - - $this->assertFileExists($targetFilePath); - $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE'); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testCopyFails() - { - $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; - $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; - - $this->filesystem->copy($sourceFilePath, $targetFilePath); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testCopyUnreadableFileFails() - { - // skip test on Windows; PHP can't easily set file as unreadable on Windows - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test cannot run on Windows.'); - } - - $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; - $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; - - file_put_contents($sourceFilePath, 'SOURCE FILE'); - - // make sure target cannot be read - $this->filesystem->chmod($sourceFilePath, 0222); - - $this->filesystem->copy($sourceFilePath, $targetFilePath); - } - - public function testCopyOverridesExistingFileIfModified() - { - $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; - $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; - - file_put_contents($sourceFilePath, 'SOURCE FILE'); - file_put_contents($targetFilePath, 'TARGET FILE'); - touch($targetFilePath, time() - 1000); - - $this->filesystem->copy($sourceFilePath, $targetFilePath); - - $this->assertFileExists($targetFilePath); - $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE'); - } - - public function testCopyDoesNotOverrideExistingFileByDefault() - { - $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; - $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; - - file_put_contents($sourceFilePath, 'SOURCE FILE'); - file_put_contents($targetFilePath, 'TARGET FILE'); - - // make sure both files have the same modification time - $modificationTime = time() - 1000; - touch($sourceFilePath, $modificationTime); - touch($targetFilePath, $modificationTime); - - $this->filesystem->copy($sourceFilePath, $targetFilePath); - - $this->assertFileExists($targetFilePath); - $this->assertStringEqualsFile($targetFilePath, 'TARGET FILE'); - } - - public function testCopyOverridesExistingFileIfForced() - { - $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; - $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; - - file_put_contents($sourceFilePath, 'SOURCE FILE'); - file_put_contents($targetFilePath, 'TARGET FILE'); - - // make sure both files have the same modification time - $modificationTime = time() - 1000; - touch($sourceFilePath, $modificationTime); - touch($targetFilePath, $modificationTime); - - $this->filesystem->copy($sourceFilePath, $targetFilePath, true); - - $this->assertFileExists($targetFilePath); - $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE'); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testCopyWithOverrideWithReadOnlyTargetFails() - { - // skip test on Windows; PHP can't easily set file as unwritable on Windows - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test cannot run on Windows.'); - } - - $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; - $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; - - file_put_contents($sourceFilePath, 'SOURCE FILE'); - file_put_contents($targetFilePath, 'TARGET FILE'); - - // make sure both files have the same modification time - $modificationTime = time() - 1000; - touch($sourceFilePath, $modificationTime); - touch($targetFilePath, $modificationTime); - - // make sure target is read-only - $this->filesystem->chmod($targetFilePath, 0444); - - $this->filesystem->copy($sourceFilePath, $targetFilePath, true); - } - - public function testCopyCreatesTargetDirectoryIfItDoesNotExist() - { - $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; - $targetFileDirectory = $this->workspace.\DIRECTORY_SEPARATOR.'directory'; - $targetFilePath = $targetFileDirectory.\DIRECTORY_SEPARATOR.'copy_target_file'; - - file_put_contents($sourceFilePath, 'SOURCE FILE'); - - $this->filesystem->copy($sourceFilePath, $targetFilePath); - - $this->assertTrue(is_dir($targetFileDirectory)); - $this->assertFileExists($targetFilePath); - $this->assertStringEqualsFile($targetFilePath, 'SOURCE FILE'); - } - - /** - * @group network - */ - public function testCopyForOriginUrlsAndExistingLocalFileDefaultsToCopy() - { - $sourceFilePath = 'http://symfony.com/images/common/logo/logo_symfony_header.png'; - $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; - - file_put_contents($targetFilePath, 'TARGET FILE'); - - $this->filesystem->copy($sourceFilePath, $targetFilePath, false); - - $this->assertFileExists($targetFilePath); - $this->assertEquals(file_get_contents($sourceFilePath), file_get_contents($targetFilePath)); - } - - public function testMkdirCreatesDirectoriesRecursively() - { - $directory = $this->workspace - .\DIRECTORY_SEPARATOR.'directory' - .\DIRECTORY_SEPARATOR.'sub_directory'; - - $this->filesystem->mkdir($directory); - - $this->assertTrue(is_dir($directory)); - } - - public function testMkdirCreatesDirectoriesFromArray() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR; - $directories = array( - $basePath.'1', $basePath.'2', $basePath.'3', - ); - - $this->filesystem->mkdir($directories); - - $this->assertTrue(is_dir($basePath.'1')); - $this->assertTrue(is_dir($basePath.'2')); - $this->assertTrue(is_dir($basePath.'3')); - } - - public function testMkdirCreatesDirectoriesFromTraversableObject() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR; - $directories = new \ArrayObject(array( - $basePath.'1', $basePath.'2', $basePath.'3', - )); - - $this->filesystem->mkdir($directories); - - $this->assertTrue(is_dir($basePath.'1')); - $this->assertTrue(is_dir($basePath.'2')); - $this->assertTrue(is_dir($basePath.'3')); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testMkdirCreatesDirectoriesFails() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR; - $dir = $basePath.'2'; - - file_put_contents($dir, ''); - - $this->filesystem->mkdir($dir); - } - - public function testTouchCreatesEmptyFile() - { - $file = $this->workspace.\DIRECTORY_SEPARATOR.'1'; - - $this->filesystem->touch($file); - - $this->assertFileExists($file); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testTouchFails() - { - $file = $this->workspace.\DIRECTORY_SEPARATOR.'1'.\DIRECTORY_SEPARATOR.'2'; - - $this->filesystem->touch($file); - } - - public function testTouchCreatesEmptyFilesFromArray() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR; - $files = array( - $basePath.'1', $basePath.'2', $basePath.'3', - ); - - $this->filesystem->touch($files); - - $this->assertFileExists($basePath.'1'); - $this->assertFileExists($basePath.'2'); - $this->assertFileExists($basePath.'3'); - } - - public function testTouchCreatesEmptyFilesFromTraversableObject() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR; - $files = new \ArrayObject(array( - $basePath.'1', $basePath.'2', $basePath.'3', - )); - - $this->filesystem->touch($files); - - $this->assertFileExists($basePath.'1'); - $this->assertFileExists($basePath.'2'); - $this->assertFileExists($basePath.'3'); - } - - public function testRemoveCleansFilesAndDirectoriesIteratively() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR; - - mkdir($basePath); - mkdir($basePath.'dir'); - touch($basePath.'file'); - - $this->filesystem->remove($basePath); - - $this->assertFileNotExists($basePath); - } - - public function testRemoveCleansArrayOfFilesAndDirectories() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR; - - mkdir($basePath.'dir'); - touch($basePath.'file'); - - $files = array( - $basePath.'dir', $basePath.'file', - ); - - $this->filesystem->remove($files); - - $this->assertFileNotExists($basePath.'dir'); - $this->assertFileNotExists($basePath.'file'); - } - - public function testRemoveCleansTraversableObjectOfFilesAndDirectories() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR; - - mkdir($basePath.'dir'); - touch($basePath.'file'); - - $files = new \ArrayObject(array( - $basePath.'dir', $basePath.'file', - )); - - $this->filesystem->remove($files); - - $this->assertFileNotExists($basePath.'dir'); - $this->assertFileNotExists($basePath.'file'); - } - - public function testRemoveIgnoresNonExistingFiles() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR; - - mkdir($basePath.'dir'); - - $files = array( - $basePath.'dir', $basePath.'file', - ); - - $this->filesystem->remove($files); - - $this->assertFileNotExists($basePath.'dir'); - } - - public function testRemoveCleansInvalidLinks() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR; - - mkdir($basePath); - mkdir($basePath.'dir'); - // create symlink to nonexistent file - @symlink($basePath.'file', $basePath.'file-link'); - - // create symlink to dir using trailing forward slash - $this->filesystem->symlink($basePath.'dir/', $basePath.'dir-link'); - $this->assertTrue(is_dir($basePath.'dir-link')); - - // create symlink to nonexistent dir - rmdir($basePath.'dir'); - $this->assertFalse('\\' === \DIRECTORY_SEPARATOR ? @readlink($basePath.'dir-link') : is_dir($basePath.'dir-link')); - - $this->filesystem->remove($basePath); - - $this->assertFileNotExists($basePath); - } - - public function testFilesExists() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR; - - mkdir($basePath); - touch($basePath.'file1'); - mkdir($basePath.'folder'); - - $this->assertTrue($this->filesystem->exists($basePath.'file1')); - $this->assertTrue($this->filesystem->exists($basePath.'folder')); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testFilesExistsFails() - { - if ('\\' !== \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Long file names are an issue on Windows'); - } - $basePath = $this->workspace.'\\directory\\'; - $maxPathLength = PHP_MAXPATHLEN - 2; - - $oldPath = getcwd(); - mkdir($basePath); - chdir($basePath); - $file = str_repeat('T', $maxPathLength - \strlen($basePath) + 1); - $path = $basePath.$file; - exec('TYPE NUL >>'.$file); // equivalent of touch, we can not use the php touch() here because it suffers from the same limitation - $this->longPathNamesWindows[] = $path; // save this so we can clean up later - chdir($oldPath); - $this->filesystem->exists($path); - } - - public function testFilesExistsTraversableObjectOfFilesAndDirectories() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR; - - mkdir($basePath.'dir'); - touch($basePath.'file'); - - $files = new \ArrayObject(array( - $basePath.'dir', $basePath.'file', - )); - - $this->assertTrue($this->filesystem->exists($files)); - } - - public function testFilesNotExistsTraversableObjectOfFilesAndDirectories() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR; - - mkdir($basePath.'dir'); - touch($basePath.'file'); - touch($basePath.'file2'); - - $files = new \ArrayObject(array( - $basePath.'dir', $basePath.'file', $basePath.'file2', - )); - - unlink($basePath.'file'); - - $this->assertFalse($this->filesystem->exists($files)); - } - - public function testInvalidFileNotExists() - { - $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'directory'.\DIRECTORY_SEPARATOR; - - $this->assertFalse($this->filesystem->exists($basePath.time())); - } - - public function testChmodChangesFileMode() - { - $this->markAsSkippedIfChmodIsMissing(); - - $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir'; - mkdir($dir); - $file = $dir.\DIRECTORY_SEPARATOR.'file'; - touch($file); - - $this->filesystem->chmod($file, 0400); - $this->filesystem->chmod($dir, 0753); - - $this->assertFilePermissions(753, $dir); - $this->assertFilePermissions(400, $file); - } - - public function testChmodWithWrongModLeavesPreviousPermissionsUntouched() - { - $this->markAsSkippedIfChmodIsMissing(); - - if (\defined('HHVM_VERSION')) { - $this->markTestSkipped('chmod() changes permissions even when passing invalid modes on HHVM'); - } - - $dir = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - touch($dir); - - $permissions = fileperms($dir); - - $this->filesystem->chmod($dir, 'Wrongmode'); - - $this->assertSame($permissions, fileperms($dir)); - } - - public function testChmodRecursive() - { - $this->markAsSkippedIfChmodIsMissing(); - - $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir'; - mkdir($dir); - $file = $dir.\DIRECTORY_SEPARATOR.'file'; - touch($file); - - $this->filesystem->chmod($file, 0400, 0000, true); - $this->filesystem->chmod($dir, 0753, 0000, true); - - $this->assertFilePermissions(753, $dir); - $this->assertFilePermissions(753, $file); - } - - public function testChmodAppliesUmask() - { - $this->markAsSkippedIfChmodIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - touch($file); - - $this->filesystem->chmod($file, 0770, 0022); - $this->assertFilePermissions(750, $file); - } - - public function testChmodChangesModeOfArrayOfFiles() - { - $this->markAsSkippedIfChmodIsMissing(); - - $directory = $this->workspace.\DIRECTORY_SEPARATOR.'directory'; - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $files = array($directory, $file); - - mkdir($directory); - touch($file); - - $this->filesystem->chmod($files, 0753); - - $this->assertFilePermissions(753, $file); - $this->assertFilePermissions(753, $directory); - } - - public function testChmodChangesModeOfTraversableFileObject() - { - $this->markAsSkippedIfChmodIsMissing(); - - $directory = $this->workspace.\DIRECTORY_SEPARATOR.'directory'; - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $files = new \ArrayObject(array($directory, $file)); - - mkdir($directory); - touch($file); - - $this->filesystem->chmod($files, 0753); - - $this->assertFilePermissions(753, $file); - $this->assertFilePermissions(753, $directory); - } - - public function testChmodChangesZeroModeOnSubdirectoriesOnRecursive() - { - $this->markAsSkippedIfChmodIsMissing(); - - $directory = $this->workspace.\DIRECTORY_SEPARATOR.'directory'; - $subdirectory = $directory.\DIRECTORY_SEPARATOR.'subdirectory'; - - mkdir($directory); - mkdir($subdirectory); - chmod($subdirectory, 0000); - - $this->filesystem->chmod($directory, 0753, 0000, true); - - $this->assertFilePermissions(753, $subdirectory); - } - - public function testChown() - { - $this->markAsSkippedIfPosixIsMissing(); - - $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir'; - mkdir($dir); - - $owner = $this->getFileOwner($dir); - $this->filesystem->chown($dir, $owner); - - $this->assertSame($owner, $this->getFileOwner($dir)); - } - - public function testChownRecursive() - { - $this->markAsSkippedIfPosixIsMissing(); - - $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir'; - mkdir($dir); - $file = $dir.\DIRECTORY_SEPARATOR.'file'; - touch($file); - - $owner = $this->getFileOwner($dir); - $this->filesystem->chown($dir, $owner, true); - - $this->assertSame($owner, $this->getFileOwner($file)); - } - - public function testChownSymlink() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - - $this->filesystem->symlink($file, $link); - - $owner = $this->getFileOwner($link); - $this->filesystem->chown($link, $owner); - - $this->assertSame($owner, $this->getFileOwner($link)); - } - - public function testChownLink() - { - $this->markAsSkippedIfLinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - - $this->filesystem->hardlink($file, $link); - - $owner = $this->getFileOwner($link); - $this->filesystem->chown($link, $owner); - - $this->assertSame($owner, $this->getFileOwner($link)); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testChownSymlinkFails() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - - $this->filesystem->symlink($file, $link); - - $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999)); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testChownLinkFails() - { - $this->markAsSkippedIfLinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - - $this->filesystem->hardlink($file, $link); - - $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999)); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testChownFail() - { - $this->markAsSkippedIfPosixIsMissing(); - - $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir'; - mkdir($dir); - - $this->filesystem->chown($dir, 'user'.time().mt_rand(1000, 9999)); - } - - public function testChgrp() - { - $this->markAsSkippedIfPosixIsMissing(); - - $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir'; - mkdir($dir); - - $group = $this->getFileGroup($dir); - $this->filesystem->chgrp($dir, $group); - - $this->assertSame($group, $this->getFileGroup($dir)); - } - - public function testChgrpRecursive() - { - $this->markAsSkippedIfPosixIsMissing(); - - $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir'; - mkdir($dir); - $file = $dir.\DIRECTORY_SEPARATOR.'file'; - touch($file); - - $group = $this->getFileGroup($dir); - $this->filesystem->chgrp($dir, $group, true); - - $this->assertSame($group, $this->getFileGroup($file)); - } - - public function testChgrpSymlink() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - - $this->filesystem->symlink($file, $link); - - $group = $this->getFileGroup($link); - $this->filesystem->chgrp($link, $group); - - $this->assertSame($group, $this->getFileGroup($link)); - } - - public function testChgrpLink() - { - $this->markAsSkippedIfLinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - - $this->filesystem->hardlink($file, $link); - - $group = $this->getFileGroup($link); - $this->filesystem->chgrp($link, $group); - - $this->assertSame($group, $this->getFileGroup($link)); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testChgrpSymlinkFails() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - - $this->filesystem->symlink($file, $link); - - $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999)); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testChgrpLinkFails() - { - $this->markAsSkippedIfLinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - - $this->filesystem->hardlink($file, $link); - - $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999)); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testChgrpFail() - { - $this->markAsSkippedIfPosixIsMissing(); - - $dir = $this->workspace.\DIRECTORY_SEPARATOR.'dir'; - mkdir($dir); - - $this->filesystem->chgrp($dir, 'user'.time().mt_rand(1000, 9999)); - } - - public function testRename() - { - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file'; - touch($file); - - $this->filesystem->rename($file, $newPath); - - $this->assertFileNotExists($file); - $this->assertFileExists($newPath); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testRenameThrowsExceptionIfTargetAlreadyExists() - { - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file'; - - touch($file); - touch($newPath); - - $this->filesystem->rename($file, $newPath); - } - - public function testRenameOverwritesTheTargetIfItAlreadyExists() - { - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file'; - - touch($file); - touch($newPath); - - $this->filesystem->rename($file, $newPath, true); - - $this->assertFileNotExists($file); - $this->assertFileExists($newPath); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testRenameThrowsExceptionOnError() - { - $file = $this->workspace.\DIRECTORY_SEPARATOR.uniqid('fs_test_', true); - $newPath = $this->workspace.\DIRECTORY_SEPARATOR.'new_file'; - - $this->filesystem->rename($file, $newPath); - } - - public function testSymlink() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Windows does not support creating "broken" symlinks'); - } - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - // $file does not exists right now: creating "broken" links is a wanted feature - $this->filesystem->symlink($file, $link); - - $this->assertTrue(is_link($link)); - - // Create the linked file AFTER creating the link - touch($file); - - $this->assertEquals($file, readlink($link)); - } - - /** - * @depends testSymlink - */ - public function testRemoveSymlink() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - $this->filesystem->remove($link); - - $this->assertFalse(is_link($link)); - $this->assertFalse(is_file($link)); - $this->assertFalse(is_dir($link)); - } - - public function testSymlinkIsOverwrittenIfPointsToDifferentTarget() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - symlink($this->workspace, $link); - - $this->filesystem->symlink($file, $link); - - $this->assertTrue(is_link($link)); - $this->assertEquals($file, readlink($link)); - } - - public function testSymlinkIsNotOverwrittenIfAlreadyCreated() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - symlink($file, $link); - - $this->filesystem->symlink($file, $link); - - $this->assertTrue(is_link($link)); - $this->assertEquals($file, readlink($link)); - } - - public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link1 = $this->workspace.\DIRECTORY_SEPARATOR.'dir'.\DIRECTORY_SEPARATOR.'link'; - $link2 = $this->workspace.\DIRECTORY_SEPARATOR.'dir'.\DIRECTORY_SEPARATOR.'subdir'.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - - $this->filesystem->symlink($file, $link1); - $this->filesystem->symlink($file, $link2); - - $this->assertTrue(is_link($link1)); - $this->assertEquals($file, readlink($link1)); - $this->assertTrue(is_link($link2)); - $this->assertEquals($file, readlink($link2)); - } - - public function testLink() - { - $this->markAsSkippedIfLinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - $this->filesystem->hardlink($file, $link); - - $this->assertTrue(is_file($link)); - $this->assertEquals(fileinode($file), fileinode($link)); - } - - /** - * @depends testLink - */ - public function testRemoveLink() - { - $this->markAsSkippedIfLinkIsMissing(); - - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - $this->filesystem->remove($link); - - $this->assertTrue(!is_file($link)); - } - - public function testLinkIsOverwrittenIfPointsToDifferentTarget() - { - $this->markAsSkippedIfLinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $file2 = $this->workspace.\DIRECTORY_SEPARATOR.'file2'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - touch($file2); - link($file2, $link); - - $this->filesystem->hardlink($file, $link); - - $this->assertTrue(is_file($link)); - $this->assertEquals(fileinode($file), fileinode($link)); - } - - public function testLinkIsNotOverwrittenIfAlreadyCreated() - { - $this->markAsSkippedIfLinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - link($file, $link); - - $this->filesystem->hardlink($file, $link); - - $this->assertTrue(is_file($link)); - $this->assertEquals(fileinode($file), fileinode($link)); - } - - public function testLinkWithSeveralTargets() - { - $this->markAsSkippedIfLinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link1 = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - $link2 = $this->workspace.\DIRECTORY_SEPARATOR.'link2'; - - touch($file); - - $this->filesystem->hardlink($file, array($link1, $link2)); - - $this->assertTrue(is_file($link1)); - $this->assertEquals(fileinode($file), fileinode($link1)); - $this->assertTrue(is_file($link2)); - $this->assertEquals(fileinode($file), fileinode($link2)); - } - - public function testLinkWithSameTarget() - { - $this->markAsSkippedIfLinkIsMissing(); - - $file = $this->workspace.\DIRECTORY_SEPARATOR.'file'; - $link = $this->workspace.\DIRECTORY_SEPARATOR.'link'; - - touch($file); - - // practically same as testLinkIsNotOverwrittenIfAlreadyCreated - $this->filesystem->hardlink($file, array($link, $link)); - - $this->assertTrue(is_file($link)); - $this->assertEquals(fileinode($file), fileinode($link)); - } - - public function testReadRelativeLink() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Relative symbolic links are not supported on Windows'); - } - - $file = $this->workspace.'/file'; - $link1 = $this->workspace.'/dir/link'; - $link2 = $this->workspace.'/dir/link2'; - touch($file); - - $this->filesystem->symlink('../file', $link1); - $this->filesystem->symlink('link', $link2); - - $this->assertEquals($this->normalize('../file'), $this->filesystem->readlink($link1)); - $this->assertEquals('link', $this->filesystem->readlink($link2)); - $this->assertEquals($file, $this->filesystem->readlink($link1, true)); - $this->assertEquals($file, $this->filesystem->readlink($link2, true)); - $this->assertEquals($file, $this->filesystem->readlink($file, true)); - } - - public function testReadAbsoluteLink() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $file = $this->normalize($this->workspace.'/file'); - $link1 = $this->normalize($this->workspace.'/dir/link'); - $link2 = $this->normalize($this->workspace.'/dir/link2'); - touch($file); - - $this->filesystem->symlink($file, $link1); - $this->filesystem->symlink($link1, $link2); - - $this->assertEquals($file, $this->filesystem->readlink($link1)); - $this->assertEquals($link1, $this->filesystem->readlink($link2)); - $this->assertEquals($file, $this->filesystem->readlink($link1, true)); - $this->assertEquals($file, $this->filesystem->readlink($link2, true)); - $this->assertEquals($file, $this->filesystem->readlink($file, true)); - } - - public function testReadBrokenLink() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Windows does not support creating "broken" symlinks'); - } - - $file = $this->workspace.'/file'; - $link = $this->workspace.'/link'; - - $this->filesystem->symlink($file, $link); - - $this->assertEquals($file, $this->filesystem->readlink($link)); - $this->assertNull($this->filesystem->readlink($link, true)); - - touch($file); - $this->assertEquals($file, $this->filesystem->readlink($link, true)); - } - - public function testReadLinkDefaultPathDoesNotExist() - { - $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'/invalid'))); - } - - public function testReadLinkDefaultPathNotLink() - { - $file = $this->normalize($this->workspace.'/file'); - touch($file); - - $this->assertNull($this->filesystem->readlink($file)); - } - - public function testReadLinkCanonicalizePath() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $file = $this->normalize($this->workspace.'/file'); - mkdir($this->normalize($this->workspace.'/dir')); - touch($file); - - $this->assertEquals($file, $this->filesystem->readlink($this->normalize($this->workspace.'/dir/../file'), true)); - } - - public function testReadLinkCanonicalizedPathDoesNotExist() - { - $this->assertNull($this->filesystem->readlink($this->normalize($this->workspace.'invalid'), true)); - } - - /** - * @dataProvider providePathsForMakePathRelative - */ - public function testMakePathRelative($endPath, $startPath, $expectedPath) - { - $path = $this->filesystem->makePathRelative($endPath, $startPath); - - $this->assertEquals($expectedPath, $path); - } - - public function providePathsForMakePathRelative() - { - $paths = array( - array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'), - array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'), - array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'), - array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'), - array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'), - array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'), - array('/aa/bb', '/aa/bb', './'), - array('/aa/bb', '/aa/bb/', './'), - array('/aa/bb/', '/aa/bb', './'), - array('/aa/bb/', '/aa/bb/', './'), - array('/aa/bb/cc', '/aa/bb/cc/dd', '../'), - array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'), - array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'), - array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'), - array('/aa/bb/cc', '/aa', 'bb/cc/'), - array('/aa/bb/cc', '/aa/', 'bb/cc/'), - array('/aa/bb/cc/', '/aa', 'bb/cc/'), - array('/aa/bb/cc/', '/aa/', 'bb/cc/'), - array('/a/aab/bb', '/a/aa', '../aab/bb/'), - array('/a/aab/bb', '/a/aa/', '../aab/bb/'), - array('/a/aab/bb/', '/a/aa', '../aab/bb/'), - array('/a/aab/bb/', '/a/aa/', '../aab/bb/'), - array('/a/aab/bb/', '/', 'a/aab/bb/'), - array('/a/aab/bb/', '/b/aab', '../../a/aab/bb/'), - array('/aab/bb', '/aa', '../aab/bb/'), - array('/aab', '/aa', '../aab/'), - array('/aa/bb/cc', '/aa/dd/..', 'bb/cc/'), - array('/aa/../bb/cc', '/aa/dd/..', '../bb/cc/'), - array('/aa/bb/../../cc', '/aa/../dd/..', 'cc/'), - array('/../aa/bb/cc', '/aa/dd/..', 'bb/cc/'), - array('/../../aa/../bb/cc', '/aa/dd/..', '../bb/cc/'), - array('C:/aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'), - array('c:/aa/../bb/cc', 'c:/aa/dd/..', '../bb/cc/'), - array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'), - array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'), - array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'), - ); - - if ('\\' === \DIRECTORY_SEPARATOR) { - $paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/'); - } - - return $paths; - } - - /** - * @group legacy - * @dataProvider provideLegacyPathsForMakePathRelativeWithRelativePaths - * @expectedDeprecation Support for passing relative paths to Symfony\Component\Filesystem\Filesystem::makePathRelative() is deprecated since Symfony 3.4 and will be removed in 4.0. - */ - public function testMakePathRelativeWithRelativePaths($endPath, $startPath, $expectedPath) - { - $path = $this->filesystem->makePathRelative($endPath, $startPath); - - $this->assertEquals($expectedPath, $path); - } - - public function provideLegacyPathsForMakePathRelativeWithRelativePaths() - { - return array( - array('usr/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'), - array('aa/bb', 'aa/cc', '../bb/'), - array('aa/cc', 'bb/cc', '../../aa/cc/'), - array('aa/bb', 'aa/./cc', '../bb/'), - array('aa/./bb', 'aa/cc', '../bb/'), - array('aa/./bb', 'aa/./cc', '../bb/'), - array('../../', '../../', './'), - array('../aa/bb/', 'aa/bb/', '../../../aa/bb/'), - array('../../../', '../../', '../'), - array('', '', './'), - array('', 'aa/', '../'), - array('aa/', '', 'aa/'), - ); - } - - public function testMirrorCopiesFilesAndDirectoriesRecursively() - { - $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR; - $directory = $sourcePath.'directory'.\DIRECTORY_SEPARATOR; - $file1 = $directory.'file1'; - $file2 = $sourcePath.'file2'; - - mkdir($sourcePath); - mkdir($directory); - file_put_contents($file1, 'FILE1'); - file_put_contents($file2, 'FILE2'); - - $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR; - - $this->filesystem->mirror($sourcePath, $targetPath); - - $this->assertTrue(is_dir($targetPath)); - $this->assertTrue(is_dir($targetPath.'directory')); - $this->assertFileEquals($file1, $targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1'); - $this->assertFileEquals($file2, $targetPath.'file2'); - - $this->filesystem->remove($file1); - - $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => false)); - $this->assertTrue($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1')); - - $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true)); - $this->assertFalse($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1')); - - file_put_contents($file1, 'FILE1'); - - $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true)); - $this->assertTrue($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1')); - - $this->filesystem->remove($directory); - $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true)); - $this->assertFalse($this->filesystem->exists($targetPath.'directory')); - $this->assertFalse($this->filesystem->exists($targetPath.'directory'.\DIRECTORY_SEPARATOR.'file1')); - } - - public function testMirrorCreatesEmptyDirectory() - { - $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR; - - mkdir($sourcePath); - - $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR; - - $this->filesystem->mirror($sourcePath, $targetPath); - - $this->assertTrue(is_dir($targetPath)); - - $this->filesystem->remove($sourcePath); - } - - public function testMirrorCopiesLinks() - { - $this->markAsSkippedIfSymlinkIsMissing(); - - $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR; - - mkdir($sourcePath); - file_put_contents($sourcePath.'file1', 'FILE1'); - symlink($sourcePath.'file1', $sourcePath.'link1'); - - $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR; - - $this->filesystem->mirror($sourcePath, $targetPath); - - $this->assertTrue(is_dir($targetPath)); - $this->assertFileEquals($sourcePath.'file1', $targetPath.'link1'); - $this->assertTrue(is_link($targetPath.\DIRECTORY_SEPARATOR.'link1')); - } - - public function testMirrorCopiesLinkedDirectoryContents() - { - $this->markAsSkippedIfSymlinkIsMissing(true); - - $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR; - - mkdir($sourcePath.'nested/', 0777, true); - file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1'); - // Note: We symlink directory, not file - symlink($sourcePath.'nested', $sourcePath.'link1'); - - $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR; - - $this->filesystem->mirror($sourcePath, $targetPath); - - $this->assertTrue(is_dir($targetPath)); - $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.'link1/file1.txt'); - $this->assertTrue(is_link($targetPath.\DIRECTORY_SEPARATOR.'link1')); - } - - public function testMirrorCopiesRelativeLinkedContents() - { - $this->markAsSkippedIfSymlinkIsMissing(true); - - $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR; - $oldPath = getcwd(); - - mkdir($sourcePath.'nested/', 0777, true); - file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1'); - // Note: Create relative symlink - chdir($sourcePath); - symlink('nested', 'link1'); - - chdir($oldPath); - - $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR; - - $this->filesystem->mirror($sourcePath, $targetPath); - - $this->assertTrue(is_dir($targetPath)); - $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.'link1/file1.txt'); - $this->assertTrue(is_link($targetPath.\DIRECTORY_SEPARATOR.'link1')); - $this->assertEquals('\\' === \DIRECTORY_SEPARATOR ? realpath($sourcePath.'\nested') : 'nested', readlink($targetPath.\DIRECTORY_SEPARATOR.'link1')); - } - - public function testMirrorContentsWithSameNameAsSourceOrTargetWithoutDeleteOption() - { - $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR; - - mkdir($sourcePath); - touch($sourcePath.'source'); - touch($sourcePath.'target'); - - $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR; - - $oldPath = getcwd(); - chdir($this->workspace); - - $this->filesystem->mirror('source', $targetPath); - - chdir($oldPath); - - $this->assertTrue(is_dir($targetPath)); - $this->assertFileExists($targetPath.'source'); - $this->assertFileExists($targetPath.'target'); - } - - public function testMirrorContentsWithSameNameAsSourceOrTargetWithDeleteOption() - { - $sourcePath = $this->workspace.\DIRECTORY_SEPARATOR.'source'.\DIRECTORY_SEPARATOR; - - mkdir($sourcePath); - touch($sourcePath.'source'); - - $targetPath = $this->workspace.\DIRECTORY_SEPARATOR.'target'.\DIRECTORY_SEPARATOR; - - mkdir($targetPath); - touch($targetPath.'source'); - touch($targetPath.'target'); - - $oldPath = getcwd(); - chdir($this->workspace); - - $this->filesystem->mirror('source', 'target', null, array('delete' => true)); - - chdir($oldPath); - - $this->assertTrue(is_dir($targetPath)); - $this->assertFileExists($targetPath.'source'); - $this->assertFileNotExists($targetPath.'target'); - } - - /** - * @dataProvider providePathsForIsAbsolutePath - */ - public function testIsAbsolutePath($path, $expectedResult) - { - $result = $this->filesystem->isAbsolutePath($path); - - $this->assertEquals($expectedResult, $result); - } - - public function providePathsForIsAbsolutePath() - { - return array( - array('/var/lib', true), - array('c:\\\\var\\lib', true), - array('\\var\\lib', true), - array('var/lib', false), - array('../var/lib', false), - array('', false), - array(null, false), - ); - } - - public function testTempnam() - { - $dirname = $this->workspace; - - $filename = $this->filesystem->tempnam($dirname, 'foo'); - - $this->assertFileExists($filename); - } - - public function testTempnamWithFileScheme() - { - $scheme = 'file://'; - $dirname = $scheme.$this->workspace; - - $filename = $this->filesystem->tempnam($dirname, 'foo'); - - $this->assertStringStartsWith($scheme, $filename); - $this->assertFileExists($filename); - } - - public function testTempnamWithMockScheme() - { - stream_wrapper_register('mock', 'Symfony\Component\Filesystem\Tests\Fixtures\MockStream\MockStream'); - - $scheme = 'mock://'; - $dirname = $scheme.$this->workspace; - - $filename = $this->filesystem->tempnam($dirname, 'foo'); - - $this->assertStringStartsWith($scheme, $filename); - $this->assertFileExists($filename); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testTempnamWithZlibSchemeFails() - { - $scheme = 'compress.zlib://'; - $dirname = $scheme.$this->workspace; - - // The compress.zlib:// stream does not support mode x: creates the file, errors "failed to open stream: operation failed" and returns false - $this->filesystem->tempnam($dirname, 'bar'); - } - - public function testTempnamWithPHPTempSchemeFails() - { - $scheme = 'php://temp'; - $dirname = $scheme; - - $filename = $this->filesystem->tempnam($dirname, 'bar'); - - $this->assertStringStartsWith($scheme, $filename); - - // The php://temp stream deletes the file after close - $this->assertFileNotExists($filename); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testTempnamWithPharSchemeFails() - { - // Skip test if Phar disabled phar.readonly must be 0 in php.ini - if (!\Phar::canWrite()) { - $this->markTestSkipped('This test cannot run when phar.readonly is 1.'); - } - - $scheme = 'phar://'; - $dirname = $scheme.$this->workspace; - $pharname = 'foo.phar'; - - new \Phar($this->workspace.'/'.$pharname, 0, $pharname); - // The phar:// stream does not support mode x: fails to create file, errors "failed to open stream: phar error: "$filename" is not a file in phar "$pharname"" and returns false - $this->filesystem->tempnam($dirname, $pharname.'/bar'); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - */ - public function testTempnamWithHTTPSchemeFails() - { - $scheme = 'http://'; - $dirname = $scheme.$this->workspace; - - // The http:// scheme is read-only - $this->filesystem->tempnam($dirname, 'bar'); - } - - public function testTempnamOnUnwritableFallsBackToSysTmp() - { - $scheme = 'file://'; - $dirname = $scheme.$this->workspace.\DIRECTORY_SEPARATOR.'does_not_exist'; - - $filename = $this->filesystem->tempnam($dirname, 'bar'); - $realTempDir = realpath(sys_get_temp_dir()); - $this->assertStringStartsWith(rtrim($scheme.$realTempDir, \DIRECTORY_SEPARATOR), $filename); - $this->assertFileExists($filename); - - // Tear down - @unlink($filename); - } - - public function testDumpFile() - { - $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt'; - - // skip mode check on Windows - if ('\\' !== \DIRECTORY_SEPARATOR) { - $oldMask = umask(0002); - } - - $this->filesystem->dumpFile($filename, 'bar'); - $this->assertFileExists($filename); - $this->assertStringEqualsFile($filename, 'bar'); - - // skip mode check on Windows - if ('\\' !== \DIRECTORY_SEPARATOR) { - $this->assertFilePermissions(664, $filename); - umask($oldMask); - } - } - - public function testDumpFileOverwritesAnExistingFile() - { - $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo.txt'; - file_put_contents($filename, 'FOO BAR'); - - $this->filesystem->dumpFile($filename, 'bar'); - - $this->assertFileExists($filename); - $this->assertStringEqualsFile($filename, 'bar'); - } - - public function testDumpFileWithFileScheme() - { - if (\defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM does not handle the file:// scheme correctly'); - } - - $scheme = 'file://'; - $filename = $scheme.$this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt'; - - $this->filesystem->dumpFile($filename, 'bar'); - - $this->assertFileExists($filename); - $this->assertStringEqualsFile($filename, 'bar'); - } - - public function testDumpFileWithZlibScheme() - { - $scheme = 'compress.zlib://'; - $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt'; - - $this->filesystem->dumpFile($filename, 'bar'); - - // Zlib stat uses file:// wrapper so remove scheme - $this->assertFileExists(str_replace($scheme, '', $filename)); - $this->assertStringEqualsFile($filename, 'bar'); - } - - public function testAppendToFile() - { - $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'bar.txt'; - - // skip mode check on Windows - if ('\\' !== \DIRECTORY_SEPARATOR) { - $oldMask = umask(0002); - } - - $this->filesystem->dumpFile($filename, 'foo'); - - $this->filesystem->appendToFile($filename, 'bar'); - - $this->assertFileExists($filename); - $this->assertStringEqualsFile($filename, 'foobar'); - - // skip mode check on Windows - if ('\\' !== \DIRECTORY_SEPARATOR) { - $this->assertFilePermissions(664, $filename); - umask($oldMask); - } - } - - public function testAppendToFileWithScheme() - { - if (\defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM does not handle the file:// scheme correctly'); - } - - $scheme = 'file://'; - $filename = $scheme.$this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt'; - $this->filesystem->dumpFile($filename, 'foo'); - - $this->filesystem->appendToFile($filename, 'bar'); - - $this->assertFileExists($filename); - $this->assertStringEqualsFile($filename, 'foobar'); - } - - public function testAppendToFileWithZlibScheme() - { - $scheme = 'compress.zlib://'; - $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'baz.txt'; - $this->filesystem->dumpFile($filename, 'foo'); - - // Zlib stat uses file:// wrapper so remove it - $this->assertStringEqualsFile(str_replace($scheme, '', $filename), 'foo'); - - $this->filesystem->appendToFile($filename, 'bar'); - - $this->assertFileExists($filename); - $this->assertStringEqualsFile($filename, 'foobar'); - } - - public function testAppendToFileCreateTheFileIfNotExists() - { - $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo'.\DIRECTORY_SEPARATOR.'bar.txt'; - - // skip mode check on Windows - if ('\\' !== \DIRECTORY_SEPARATOR) { - $oldMask = umask(0002); - } - - $this->filesystem->appendToFile($filename, 'bar'); - - // skip mode check on Windows - if ('\\' !== \DIRECTORY_SEPARATOR) { - $this->assertFilePermissions(664, $filename); - umask($oldMask); - } - - $this->assertFileExists($filename); - $this->assertStringEqualsFile($filename, 'bar'); - } - - public function testDumpKeepsExistingPermissionsWhenOverwritingAnExistingFile() - { - $this->markAsSkippedIfChmodIsMissing(); - - $filename = $this->workspace.\DIRECTORY_SEPARATOR.'foo.txt'; - file_put_contents($filename, 'FOO BAR'); - chmod($filename, 0745); - - $this->filesystem->dumpFile($filename, 'bar', null); - - $this->assertFilePermissions(745, $filename); - } - - public function testCopyShouldKeepExecutionPermission() - { - $this->markAsSkippedIfChmodIsMissing(); - - $sourceFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_source_file'; - $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; - - file_put_contents($sourceFilePath, 'SOURCE FILE'); - chmod($sourceFilePath, 0745); - - $this->filesystem->copy($sourceFilePath, $targetFilePath); - - $this->assertFilePermissions(767, $targetFilePath); - } - - /** - * Normalize the given path (transform each blackslash into a real directory separator). - * - * @param string $path - * - * @return string - */ - private function normalize($path) - { - return str_replace('/', \DIRECTORY_SEPARATOR, $path); - } -} diff --git a/vendor/symfony/filesystem/Tests/FilesystemTestCase.php b/vendor/symfony/filesystem/Tests/FilesystemTestCase.php deleted file mode 100644 index e55c266..0000000 --- a/vendor/symfony/filesystem/Tests/FilesystemTestCase.php +++ /dev/null @@ -1,166 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Filesystem\Filesystem; - -class FilesystemTestCase extends TestCase -{ - private $umask; - - protected $longPathNamesWindows = array(); - - /** - * @var \Symfony\Component\Filesystem\Filesystem - */ - protected $filesystem = null; - - /** - * @var string - */ - protected $workspace = null; - - /** - * @var null|bool Flag for hard links on Windows - */ - private static $linkOnWindows = null; - - /** - * @var null|bool Flag for symbolic links on Windows - */ - private static $symlinkOnWindows = null; - - public static function setUpBeforeClass() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - self::$linkOnWindows = true; - $originFile = tempnam(sys_get_temp_dir(), 'li'); - $targetFile = tempnam(sys_get_temp_dir(), 'li'); - if (true !== @link($originFile, $targetFile)) { - $report = error_get_last(); - if (\is_array($report) && false !== strpos($report['message'], 'error code(1314)')) { - self::$linkOnWindows = false; - } - } else { - @unlink($targetFile); - } - - self::$symlinkOnWindows = true; - $originDir = tempnam(sys_get_temp_dir(), 'sl'); - $targetDir = tempnam(sys_get_temp_dir(), 'sl'); - if (true !== @symlink($originDir, $targetDir)) { - $report = error_get_last(); - if (\is_array($report) && false !== strpos($report['message'], 'error code(1314)')) { - self::$symlinkOnWindows = false; - } - } else { - @unlink($targetDir); - } - } - } - - protected function setUp() - { - $this->umask = umask(0); - $this->filesystem = new Filesystem(); - $this->workspace = sys_get_temp_dir().'/'.microtime(true).'.'.mt_rand(); - mkdir($this->workspace, 0777, true); - $this->workspace = realpath($this->workspace); - } - - protected function tearDown() - { - if (!empty($this->longPathNamesWindows)) { - foreach ($this->longPathNamesWindows as $path) { - exec('DEL '.$path); - } - $this->longPathNamesWindows = array(); - } - - $this->filesystem->remove($this->workspace); - umask($this->umask); - } - - /** - * @param int $expectedFilePerms Expected file permissions as three digits (i.e. 755) - * @param string $filePath - */ - protected function assertFilePermissions($expectedFilePerms, $filePath) - { - $actualFilePerms = (int) substr(sprintf('%o', fileperms($filePath)), -3); - $this->assertEquals( - $expectedFilePerms, - $actualFilePerms, - sprintf('File permissions for %s must be %s. Actual %s', $filePath, $expectedFilePerms, $actualFilePerms) - ); - } - - protected function getFileOwner($filepath) - { - $this->markAsSkippedIfPosixIsMissing(); - - $infos = stat($filepath); - if ($datas = posix_getpwuid($infos['uid'])) { - return $datas['name']; - } - } - - protected function getFileGroup($filepath) - { - $this->markAsSkippedIfPosixIsMissing(); - - $infos = stat($filepath); - if ($datas = posix_getgrgid($infos['gid'])) { - return $datas['name']; - } - - $this->markTestSkipped('Unable to retrieve file group name'); - } - - protected function markAsSkippedIfLinkIsMissing() - { - if (!\function_exists('link')) { - $this->markTestSkipped('link is not supported'); - } - - if ('\\' === \DIRECTORY_SEPARATOR && false === self::$linkOnWindows) { - $this->markTestSkipped('link requires "Create hard links" privilege on windows'); - } - } - - protected function markAsSkippedIfSymlinkIsMissing($relative = false) - { - if ('\\' === \DIRECTORY_SEPARATOR && false === self::$symlinkOnWindows) { - $this->markTestSkipped('symlink requires "Create symbolic links" privilege on Windows'); - } - - // https://bugs.php.net/bug.php?id=69473 - if ($relative && '\\' === \DIRECTORY_SEPARATOR && 1 === PHP_ZTS) { - $this->markTestSkipped('symlink does not support relative paths on thread safe Windows PHP versions'); - } - } - - protected function markAsSkippedIfChmodIsMissing() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('chmod is not supported on Windows'); - } - } - - protected function markAsSkippedIfPosixIsMissing() - { - if (!\function_exists('posix_isatty')) { - $this->markTestSkipped('Function posix_isatty is required.'); - } - } -} diff --git a/vendor/symfony/filesystem/Tests/Fixtures/MockStream/MockStream.php b/vendor/symfony/filesystem/Tests/Fixtures/MockStream/MockStream.php deleted file mode 100644 index f14420f..0000000 --- a/vendor/symfony/filesystem/Tests/Fixtures/MockStream/MockStream.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Tests\Fixtures\MockStream; - -/** - * Mock stream class to be used with stream_wrapper_register. - * stream_wrapper_register('mock', 'Symfony\Component\Filesystem\Tests\Fixtures\MockStream\MockStream'). - */ -class MockStream -{ - /** - * Opens file or URL. - * - * @param string $path Specifies the URL that was passed to the original function - * @param string $mode The mode used to open the file, as detailed for fopen() - * @param int $options Holds additional flags set by the streams API - * @param string $opened_path If the path is opened successfully, and STREAM_USE_PATH is set in options, - * opened_path should be set to the full path of the file/resource that was actually opened - * - * @return bool - */ - public function stream_open($path, $mode, $options, &$opened_path) - { - return true; - } - - /** - * @param string $path The file path or URL to stat - * @param array $flags Holds additional flags set by the streams API - * - * @return array File stats - */ - public function url_stat($path, $flags) - { - return array(); - } -} diff --git a/vendor/symfony/filesystem/Tests/LockHandlerTest.php b/vendor/symfony/filesystem/Tests/LockHandlerTest.php deleted file mode 100644 index b32e765..0000000 --- a/vendor/symfony/filesystem/Tests/LockHandlerTest.php +++ /dev/null @@ -1,144 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Filesystem\LockHandler; - -/** - * @group legacy - */ -class LockHandlerTest extends TestCase -{ - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - * @expectedExceptionMessage Failed to create "/a/b/c/d/e": mkdir(): Permission denied. - */ - public function testConstructWhenRepositoryDoesNotExist() - { - if (!getenv('USER') || 'root' === getenv('USER')) { - $this->markTestSkipped('This test will fail if run under superuser'); - } - new LockHandler('lock', '/a/b/c/d/e'); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - * @expectedExceptionMessage The directory "/" is not writable. - */ - public function testConstructWhenRepositoryIsNotWriteable() - { - if (!getenv('USER') || 'root' === getenv('USER')) { - $this->markTestSkipped('This test will fail if run under superuser'); - } - new LockHandler('lock', '/'); - } - - public function testErrorHandlingInLockIfLockPathBecomesUnwritable() - { - // skip test on Windows; PHP can't easily set file as unreadable on Windows - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test cannot run on Windows.'); - } - - $lockPath = sys_get_temp_dir().'/'.uniqid('', true); - $e = null; - $wrongMessage = null; - - try { - mkdir($lockPath); - - $lockHandler = new LockHandler('lock', $lockPath); - - chmod($lockPath, 0444); - - $lockHandler->lock(); - } catch (IOException $e) { - if (false === strpos($e->getMessage(), 'Permission denied')) { - $wrongMessage = $e->getMessage(); - } else { - $this->addToAssertionCount(1); - } - } catch (\Exception $e) { - } catch (\Throwable $e) { - } - - if (is_dir($lockPath)) { - $fs = new Filesystem(); - $fs->remove($lockPath); - } - - $this->assertInstanceOf('Symfony\Component\Filesystem\Exception\IOException', $e, sprintf('Expected IOException to be thrown, got %s instead.', \get_class($e))); - $this->assertNull($wrongMessage, sprintf('Expected exception message to contain "Permission denied", got "%s" instead.', $wrongMessage)); - } - - public function testConstructSanitizeName() - { - $lock = new LockHandler('<?php echo "% hello word ! %" ?>'); - - $file = sprintf('%s/sf.-php-echo-hello-word-.4b3d9d0d27ddef3a78a64685dda3a963e478659a9e5240feaf7b4173a8f28d5f.lock', sys_get_temp_dir()); - // ensure the file does not exist before the lock - @unlink($file); - - $lock->lock(); - - $this->assertFileExists($file); - - $lock->release(); - } - - public function testLockRelease() - { - $name = 'symfony-test-filesystem.lock'; - - $l1 = new LockHandler($name); - $l2 = new LockHandler($name); - - $this->assertTrue($l1->lock()); - $this->assertFalse($l2->lock()); - - $l1->release(); - - $this->assertTrue($l2->lock()); - $l2->release(); - } - - public function testLockTwice() - { - $name = 'symfony-test-filesystem.lock'; - - $lockHandler = new LockHandler($name); - - $this->assertTrue($lockHandler->lock()); - $this->assertTrue($lockHandler->lock()); - - $lockHandler->release(); - } - - public function testLockIsReleased() - { - $name = 'symfony-test-filesystem.lock'; - - $l1 = new LockHandler($name); - $l2 = new LockHandler($name); - - $this->assertTrue($l1->lock()); - $this->assertFalse($l2->lock()); - - $l1 = null; - - $this->assertTrue($l2->lock()); - $l2->release(); - } -} diff --git a/vendor/symfony/filesystem/composer.json b/vendor/symfony/filesystem/composer.json index 0fc8043..e756104 100644 --- a/vendor/symfony/filesystem/composer.json +++ b/vendor/symfony/filesystem/composer.json @@ -1,7 +1,7 @@ { "name": "symfony/filesystem", "type": "library", - "description": "Symfony Filesystem Component", + "description": "Provides basic utilities for the filesystem", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", @@ -16,8 +16,10 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" }, "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, @@ -25,10 +27,5 @@ "/Tests/" ] }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - } + "minimum-stability": "dev" } diff --git a/vendor/symfony/filesystem/phpunit.xml.dist b/vendor/symfony/filesystem/phpunit.xml.dist deleted file mode 100644 index 7bba6fc..0000000 --- a/vendor/symfony/filesystem/phpunit.xml.dist +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" - backupGlobals="false" - colors="true" - bootstrap="vendor/autoload.php" - failOnRisky="true" - failOnWarning="true" -> - <php> - <ini name="error_reporting" value="-1" /> - </php> - - <testsuites> - <testsuite name="Symfony Filesystem Component Test Suite"> - <directory>./Tests/</directory> - </testsuite> - </testsuites> - - <filter> - <whitelist> - <directory>./</directory> - <exclude> - <directory>./Tests</directory> - <directory>./vendor</directory> - </exclude> - </whitelist> - </filter> -</phpunit> diff --git a/vendor/symfony/finder/.gitignore b/vendor/symfony/finder/.gitignore deleted file mode 100644 index c49a5d8..0000000 --- a/vendor/symfony/finder/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/vendor/symfony/finder/CHANGELOG.md b/vendor/symfony/finder/CHANGELOG.md index 53c34be..6a44e87 100644 --- a/vendor/symfony/finder/CHANGELOG.md +++ b/vendor/symfony/finder/CHANGELOG.md @@ -1,6 +1,38 @@ CHANGELOG ========= +5.4.0 +----- + + * Deprecate `Comparator::setTarget()` and `Comparator::setOperator()` + * Add a constructor to `Comparator` that allows setting target and operator + * Finder's iterator has now `Symfony\Component\Finder\SplFileInfo` inner type specified + * Add recursive .gitignore files support + +5.0.0 +----- + + * added `$useNaturalSort` argument to `Finder::sortByName()` + +4.3.0 +----- + + * added Finder::ignoreVCSIgnored() to ignore files based on rules listed in .gitignore + +4.2.0 +----- + + * added $useNaturalSort option to Finder::sortByName() method + * the `Finder::sortByName()` method will have a new `$useNaturalSort` + argument in version 5.0, not defining it is deprecated + * added `Finder::reverseSorting()` to reverse the sorting + +4.0.0 +----- + + * removed `ExceptionInterface` + * removed `Symfony\Component\Finder\Iterator\FilterIterator` + 3.4.0 ----- diff --git a/vendor/symfony/finder/Comparator/Comparator.php b/vendor/symfony/finder/Comparator/Comparator.php index ea37566..3af551f 100644 --- a/vendor/symfony/finder/Comparator/Comparator.php +++ b/vendor/symfony/finder/Comparator/Comparator.php @@ -12,8 +12,6 @@ namespace Symfony\Component\Finder\Comparator; /** - * Comparator. - * * @author Fabien Potencier <fabien@symfony.com> */ class Comparator @@ -21,30 +19,44 @@ class Comparator private $target; private $operator = '=='; + public function __construct(string $target = null, string $operator = '==') + { + if (null === $target) { + trigger_deprecation('symfony/finder', '5.4', 'Constructing a "%s" without setting "$target" is deprecated.', __CLASS__); + } + + $this->target = $target; + $this->doSetOperator($operator); + } + /** * Gets the target value. * - * @return string The target value + * @return string */ public function getTarget() { + if (null === $this->target) { + trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" without initializing the target is deprecated.', __METHOD__); + } + return $this->target; } /** - * Sets the target value. - * - * @param string $target The target value + * @deprecated set the target via the constructor instead */ - public function setTarget($target) + public function setTarget(string $target) { + trigger_deprecation('symfony/finder', '5.4', '"%s" is deprecated. Set the target via the constructor instead.', __METHOD__); + $this->target = $target; } /** * Gets the comparison operator. * - * @return string The operator + * @return string */ public function getOperator() { @@ -54,21 +66,15 @@ public function getOperator() /** * Sets the comparison operator. * - * @param string $operator A valid operator - * * @throws \InvalidArgumentException + * + * @deprecated set the operator via the constructor instead */ - public function setOperator($operator) + public function setOperator(string $operator) { - if (!$operator) { - $operator = '=='; - } + trigger_deprecation('symfony/finder', '5.4', '"%s" is deprecated. Set the operator via the constructor instead.', __METHOD__); - if (!\in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) { - throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); - } - - $this->operator = $operator; + $this->doSetOperator('' === $operator ? '==' : $operator); } /** @@ -80,6 +86,10 @@ public function setOperator($operator) */ public function test($test) { + if (null === $this->target) { + trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" without initializing the target is deprecated.', __METHOD__); + } + switch ($this->operator) { case '>': return $test > $this->target; @@ -95,4 +105,13 @@ public function test($test) return $test == $this->target; } + + private function doSetOperator(string $operator): void + { + if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) { + throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); + } + + $this->operator = $operator; + } } diff --git a/vendor/symfony/finder/Comparator/DateComparator.php b/vendor/symfony/finder/Comparator/DateComparator.php index 3de43ef..8f651e1 100644 --- a/vendor/symfony/finder/Comparator/DateComparator.php +++ b/vendor/symfony/finder/Comparator/DateComparator.php @@ -23,7 +23,7 @@ class DateComparator extends Comparator * * @throws \InvalidArgumentException If the test is not understood */ - public function __construct($test) + public function __construct(string $test) { if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); @@ -36,7 +36,7 @@ public function __construct($test) throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); } - $operator = isset($matches[1]) ? $matches[1] : '=='; + $operator = $matches[1] ?? '=='; if ('since' === $operator || 'after' === $operator) { $operator = '>'; } @@ -45,7 +45,6 @@ public function __construct($test) $operator = '<'; } - $this->setOperator($operator); - $this->setTarget($target); + parent::__construct($target, $operator); } } diff --git a/vendor/symfony/finder/Comparator/NumberComparator.php b/vendor/symfony/finder/Comparator/NumberComparator.php index f62c0e5..dd30820 100644 --- a/vendor/symfony/finder/Comparator/NumberComparator.php +++ b/vendor/symfony/finder/Comparator/NumberComparator.php @@ -35,14 +35,14 @@ class NumberComparator extends Comparator { /** - * @param string|int $test A comparison string or an integer + * @param string|null $test A comparison string or null * * @throws \InvalidArgumentException If the test is not understood */ - public function __construct($test) + public function __construct(?string $test) { - if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test)); + if (null === $test || !preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { + throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test ?? 'null')); } $target = $matches[2]; @@ -73,7 +73,6 @@ public function __construct($test) } } - $this->setTarget($target); - $this->setOperator(isset($matches[1]) ? $matches[1] : '=='); + parent::__construct($target, $matches[1] ?: '=='); } } diff --git a/vendor/symfony/debug/Exception/OutOfMemoryException.php b/vendor/symfony/finder/Exception/DirectoryNotFoundException.php similarity index 59% rename from vendor/symfony/debug/Exception/OutOfMemoryException.php rename to vendor/symfony/finder/Exception/DirectoryNotFoundException.php index fec1979..c6cc0f2 100644 --- a/vendor/symfony/debug/Exception/OutOfMemoryException.php +++ b/vendor/symfony/finder/Exception/DirectoryNotFoundException.php @@ -9,13 +9,11 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Debug\Exception; +namespace Symfony\Component\Finder\Exception; /** - * Out of memory exception. - * - * @author Nicolas Grekas <p@tchwork.com> + * @author Andreas Erhard <andreas.erhard@i-med.ac.at> */ -class OutOfMemoryException extends FatalErrorException +class DirectoryNotFoundException extends \InvalidArgumentException { } diff --git a/vendor/symfony/finder/Exception/ExceptionInterface.php b/vendor/symfony/finder/Exception/ExceptionInterface.php deleted file mode 100644 index 161e968..0000000 --- a/vendor/symfony/finder/Exception/ExceptionInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Jean-François Simon <contact@jfsimon.fr> - * - * @deprecated since 3.3, to be removed in 4.0. - */ -interface ExceptionInterface -{ - /** - * @return \Symfony\Component\Finder\Adapter\AdapterInterface - */ - public function getAdapter(); -} diff --git a/vendor/symfony/finder/Finder.php b/vendor/symfony/finder/Finder.php index f16bfaa..8cc564c 100644 --- a/vendor/symfony/finder/Finder.php +++ b/vendor/symfony/finder/Finder.php @@ -13,12 +13,14 @@ use Symfony\Component\Finder\Comparator\DateComparator; use Symfony\Component\Finder\Comparator\NumberComparator; +use Symfony\Component\Finder\Exception\DirectoryNotFoundException; use Symfony\Component\Finder\Iterator\CustomFilterIterator; use Symfony\Component\Finder\Iterator\DateRangeFilterIterator; use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator; use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator; use Symfony\Component\Finder\Iterator\FilecontentFilterIterator; use Symfony\Component\Finder\Iterator\FilenameFilterIterator; +use Symfony\Component\Finder\Iterator\LazyIterator; use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator; use Symfony\Component\Finder\Iterator\SortableIterator; @@ -29,37 +31,41 @@ * * All rules may be invoked several times. * - * All methods return the current Finder object to allow easy chaining: + * All methods return the current Finder object to allow chaining: * - * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); + * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); * * @author Fabien Potencier <fabien@symfony.com> + * + * @implements \IteratorAggregate<string, SplFileInfo> */ class Finder implements \IteratorAggregate, \Countable { - const IGNORE_VCS_FILES = 1; - const IGNORE_DOT_FILES = 2; + public const IGNORE_VCS_FILES = 1; + public const IGNORE_DOT_FILES = 2; + public const IGNORE_VCS_IGNORED_FILES = 4; private $mode = 0; - private $names = array(); - private $notNames = array(); - private $exclude = array(); - private $filters = array(); - private $depths = array(); - private $sizes = array(); + private $names = []; + private $notNames = []; + private $exclude = []; + private $filters = []; + private $depths = []; + private $sizes = []; private $followLinks = false; + private $reverseSorting = false; private $sort = false; private $ignore = 0; - private $dirs = array(); - private $dates = array(); - private $iterators = array(); - private $contains = array(); - private $notContains = array(); - private $paths = array(); - private $notPaths = array(); + private $dirs = []; + private $dates = []; + private $iterators = []; + private $contains = []; + private $notContains = []; + private $paths = []; + private $notPaths = []; private $ignoreUnreadableDirs = false; - private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'); + private static $vcsPatterns = ['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg']; public function __construct() { @@ -105,19 +111,22 @@ public function files() * * Usage: * - * $finder->depth('> 1') // the Finder will start matching at level 1. - * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. + * $finder->depth('> 1') // the Finder will start matching at level 1. + * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. + * $finder->depth(['>= 1', '< 3']) * - * @param string|int $level The depth level expression + * @param string|int|string[]|int[] $levels The depth level expression or an array of depth levels * * @return $this * * @see DepthRangeFilterIterator * @see NumberComparator */ - public function depth($level) + public function depth($levels) { - $this->depths[] = new Comparator\NumberComparator($level); + foreach ((array) $levels as $level) { + $this->depths[] = new Comparator\NumberComparator($level); + } return $this; } @@ -127,12 +136,13 @@ public function depth($level) * * The date must be something that strtotime() is able to parse: * - * $finder->date('since yesterday'); - * $finder->date('until 2 days ago'); - * $finder->date('> now - 2 hours'); - * $finder->date('>= 2005-10-15'); + * $finder->date('since yesterday'); + * $finder->date('until 2 days ago'); + * $finder->date('> now - 2 hours'); + * $finder->date('>= 2005-10-15'); + * $finder->date(['>= 2005-10-15', '<= 2006-05-27']); * - * @param string $date A date range string + * @param string|string[] $dates A date range string or an array of date ranges * * @return $this * @@ -140,9 +150,11 @@ public function depth($level) * @see DateRangeFilterIterator * @see DateComparator */ - public function date($date) + public function date($dates) { - $this->dates[] = new Comparator\DateComparator($date); + foreach ((array) $dates as $date) { + $this->dates[] = new Comparator\DateComparator($date); + } return $this; } @@ -152,19 +164,20 @@ public function date($date) * * You can use patterns (delimited with / sign), globs or simple strings. * - * $finder->name('*.php') - * $finder->name('/\.php$/') // same as above - * $finder->name('test.php') + * $finder->name('*.php') + * $finder->name('/\.php$/') // same as above + * $finder->name('test.php') + * $finder->name(['test.py', 'test.php']) * - * @param string $pattern A pattern (a regexp, a glob, or a string) + * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns * * @return $this * * @see FilenameFilterIterator */ - public function name($pattern) + public function name($patterns) { - $this->names[] = $pattern; + $this->names = array_merge($this->names, (array) $patterns); return $this; } @@ -172,15 +185,15 @@ public function name($pattern) /** * Adds rules that files must not match. * - * @param string $pattern A pattern (a regexp, a glob, or a string) + * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns * * @return $this * * @see FilenameFilterIterator */ - public function notName($pattern) + public function notName($patterns) { - $this->notNames[] = $pattern; + $this->notNames = array_merge($this->notNames, (array) $patterns); return $this; } @@ -190,18 +203,19 @@ public function notName($pattern) * * Strings or PCRE patterns can be used: * - * $finder->contains('Lorem ipsum') - * $finder->contains('/Lorem ipsum/i') + * $finder->contains('Lorem ipsum') + * $finder->contains('/Lorem ipsum/i') + * $finder->contains(['dolor', '/ipsum/i']) * - * @param string $pattern A pattern (string or regexp) + * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns * * @return $this * * @see FilecontentFilterIterator */ - public function contains($pattern) + public function contains($patterns) { - $this->contains[] = $pattern; + $this->contains = array_merge($this->contains, (array) $patterns); return $this; } @@ -211,18 +225,19 @@ public function contains($pattern) * * Strings or PCRE patterns can be used: * - * $finder->notContains('Lorem ipsum') - * $finder->notContains('/Lorem ipsum/i') + * $finder->notContains('Lorem ipsum') + * $finder->notContains('/Lorem ipsum/i') + * $finder->notContains(['lorem', '/dolor/i']) * - * @param string $pattern A pattern (string or regexp) + * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns * * @return $this * * @see FilecontentFilterIterator */ - public function notContains($pattern) + public function notContains($patterns) { - $this->notContains[] = $pattern; + $this->notContains = array_merge($this->notContains, (array) $patterns); return $this; } @@ -232,20 +247,21 @@ public function notContains($pattern) * * You can use patterns (delimited with / sign) or simple strings. * - * $finder->path('some/special/dir') - * $finder->path('/some\/special\/dir/') // same as above + * $finder->path('some/special/dir') + * $finder->path('/some\/special\/dir/') // same as above + * $finder->path(['some dir', 'another/dir']) * * Use only / as dirname separator. * - * @param string $pattern A pattern (a regexp or a string) + * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns * * @return $this * * @see FilenameFilterIterator */ - public function path($pattern) + public function path($patterns) { - $this->paths[] = $pattern; + $this->paths = array_merge($this->paths, (array) $patterns); return $this; } @@ -255,20 +271,21 @@ public function path($pattern) * * You can use patterns (delimited with / sign) or simple strings. * - * $finder->notPath('some/special/dir') - * $finder->notPath('/some\/special\/dir/') // same as above + * $finder->notPath('some/special/dir') + * $finder->notPath('/some\/special\/dir/') // same as above + * $finder->notPath(['some/file.txt', 'another/file.log']) * * Use only / as dirname separator. * - * @param string $pattern A pattern (a regexp or a string) + * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns * * @return $this * * @see FilenameFilterIterator */ - public function notPath($pattern) + public function notPath($patterns) { - $this->notPaths[] = $pattern; + $this->notPaths = array_merge($this->notPaths, (array) $patterns); return $this; } @@ -276,20 +293,23 @@ public function notPath($pattern) /** * Adds tests for file sizes. * - * $finder->size('> 10K'); - * $finder->size('<= 1Ki'); - * $finder->size(4); + * $finder->size('> 10K'); + * $finder->size('<= 1Ki'); + * $finder->size(4); + * $finder->size(['> 10K', '< 20K']) * - * @param string|int $size A size range string or an integer + * @param string|int|string[]|int[] $sizes A size range string or an integer or an array of size ranges * * @return $this * * @see SizeRangeFilterIterator * @see NumberComparator */ - public function size($size) + public function size($sizes) { - $this->sizes[] = new Comparator\NumberComparator($size); + foreach ((array) $sizes as $size) { + $this->sizes[] = new Comparator\NumberComparator($size); + } return $this; } @@ -319,13 +339,11 @@ public function exclude($dirs) * * This option is enabled by default. * - * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not - * * @return $this * * @see ExcludeDirectoryFilterIterator */ - public function ignoreDotFiles($ignoreDotFiles) + public function ignoreDotFiles(bool $ignoreDotFiles) { if ($ignoreDotFiles) { $this->ignore |= static::IGNORE_DOT_FILES; @@ -341,13 +359,11 @@ public function ignoreDotFiles($ignoreDotFiles) * * This option is enabled by default. * - * @param bool $ignoreVCS Whether to exclude VCS files or not - * * @return $this * * @see ExcludeDirectoryFilterIterator */ - public function ignoreVCS($ignoreVCS) + public function ignoreVCS(bool $ignoreVCS) { if ($ignoreVCS) { $this->ignore |= static::IGNORE_VCS_FILES; @@ -358,6 +374,24 @@ public function ignoreVCS($ignoreVCS) return $this; } + /** + * Forces Finder to obey .gitignore and ignore files based on rules listed there. + * + * This option is disabled by default. + * + * @return $this + */ + public function ignoreVCSIgnored(bool $ignoreVCSIgnored) + { + if ($ignoreVCSIgnored) { + $this->ignore |= static::IGNORE_VCS_IGNORED_FILES; + } else { + $this->ignore &= ~static::IGNORE_VCS_IGNORED_FILES; + } + + return $this; + } + /** * Adds VCS patterns. * @@ -401,9 +435,9 @@ public function sort(\Closure $closure) * * @see SortableIterator */ - public function sortByName() + public function sortByName(bool $useNaturalSort = false) { - $this->sort = Iterator\SortableIterator::SORT_BY_NAME; + $this->sort = $useNaturalSort ? Iterator\SortableIterator::SORT_BY_NAME_NATURAL : Iterator\SortableIterator::SORT_BY_NAME; return $this; } @@ -442,6 +476,18 @@ public function sortByAccessedTime() return $this; } + /** + * Reverses the sorting. + * + * @return $this + */ + public function reverseSorting() + { + $this->reverseSorting = true; + + return $this; + } + /** * Sorts files and directories by the last inode changed time. * @@ -514,13 +560,11 @@ public function followLinks() * * By default, scanning unreadable directories content throws an AccessDeniedException. * - * @param bool $ignore - * * @return $this */ - public function ignoreUnreadableDirs($ignore = true) + public function ignoreUnreadableDirs(bool $ignore = true) { - $this->ignoreUnreadableDirs = (bool) $ignore; + $this->ignoreUnreadableDirs = $ignore; return $this; } @@ -528,27 +572,28 @@ public function ignoreUnreadableDirs($ignore = true) /** * Searches files and directories which match defined rules. * - * @param string|array $dirs A directory path or an array of directories + * @param string|string[] $dirs A directory path or an array of directories * * @return $this * - * @throws \InvalidArgumentException if one of the directories does not exist + * @throws DirectoryNotFoundException if one of the directories does not exist */ public function in($dirs) { - $resolvedDirs = array(); + $resolvedDirs = []; foreach ((array) $dirs as $dir) { if (is_dir($dir)) { - $resolvedDirs[] = $this->normalizeDir($dir); - } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) { - $resolvedDirs = array_merge($resolvedDirs, array_map(array($this, 'normalizeDir'), $glob)); + $resolvedDirs[] = [$this->normalizeDir($dir)]; + } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? \GLOB_BRACE : 0) | \GLOB_ONLYDIR | \GLOB_NOSORT)) { + sort($glob); + $resolvedDirs[] = array_map([$this, 'normalizeDir'], $glob); } else { - throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir)); + throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist.', $dir)); } } - $this->dirs = array_merge($this->dirs, $resolvedDirs); + $this->dirs = array_merge($this->dirs, ...$resolvedDirs); return $this; } @@ -558,10 +603,11 @@ public function in($dirs) * * This method implements the IteratorAggregate interface. * - * @return \Iterator|SplFileInfo[] An iterator + * @return \Iterator<string, SplFileInfo> * * @throws \LogicException if the in() method has not been called */ + #[\ReturnTypeWillChange] public function getIterator() { if (0 === \count($this->dirs) && 0 === \count($this->iterators)) { @@ -569,18 +615,30 @@ public function getIterator() } if (1 === \count($this->dirs) && 0 === \count($this->iterators)) { - return $this->searchInDirectory($this->dirs[0]); + $iterator = $this->searchInDirectory($this->dirs[0]); + + if ($this->sort || $this->reverseSorting) { + $iterator = (new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator(); + } + + return $iterator; } $iterator = new \AppendIterator(); foreach ($this->dirs as $dir) { - $iterator->append($this->searchInDirectory($dir)); + $iterator->append(new \IteratorIterator(new LazyIterator(function () use ($dir) { + return $this->searchInDirectory($dir); + }))); } foreach ($this->iterators as $it) { $iterator->append($it); } + if ($this->sort || $this->reverseSorting) { + $iterator = (new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator(); + } + return $iterator; } @@ -589,22 +647,21 @@ public function getIterator() * * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. * - * @param mixed $iterator - * * @return $this * * @throws \InvalidArgumentException when the given argument is not iterable */ - public function append($iterator) + public function append(iterable $iterator) { if ($iterator instanceof \IteratorAggregate) { $this->iterators[] = $iterator->getIterator(); } elseif ($iterator instanceof \Iterator) { $this->iterators[] = $iterator; - } elseif ($iterator instanceof \Traversable || \is_array($iterator)) { + } elseif (is_iterable($iterator)) { $it = new \ArrayIterator(); foreach ($iterator as $file) { - $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file)); + $file = $file instanceof \SplFileInfo ? $file : new \SplFileInfo($file); + $it[$file->getPathname()] = $file; } $this->iterators[] = $it; } else { @@ -615,7 +672,7 @@ public function append($iterator) } /** - * Check if the any results were found. + * Check if any results were found. * * @return bool */ @@ -633,28 +690,27 @@ public function hasResults() * * @return int */ + #[\ReturnTypeWillChange] public function count() { return iterator_count($this->getIterator()); } - /** - * @param $dir - * - * @return \Iterator - */ - private function searchInDirectory($dir) + private function searchInDirectory(string $dir): \Iterator { + $exclude = $this->exclude; + $notPaths = $this->notPaths; + if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { - $this->exclude = array_merge($this->exclude, self::$vcsPatterns); + $exclude = array_merge($exclude, self::$vcsPatterns); } if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { - $this->notPaths[] = '#(^|/)\..+(/|$)#'; + $notPaths[] = '#(^|/)\..+(/|$)#'; } $minDepth = 0; - $maxDepth = PHP_INT_MAX; + $maxDepth = \PHP_INT_MAX; foreach ($this->depths as $comparator) { switch ($comparator->getOperator()) { @@ -683,13 +739,13 @@ private function searchInDirectory($dir) $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs); - if ($this->exclude) { - $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); + if ($exclude) { + $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude); } $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); - if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) { + if ($minDepth > 0 || $maxDepth < \PHP_INT_MAX) { $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth); } @@ -717,13 +773,12 @@ private function searchInDirectory($dir) $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } - if ($this->paths || $this->notPaths) { - $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); + if ($this->paths || $notPaths) { + $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths); } - if ($this->sort) { - $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); - $iterator = $iteratorAggregate->getIterator(); + if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) { + $iterator = new Iterator\VcsIgnoredFilterIterator($iterator, $dir); } return $iterator; @@ -732,12 +787,20 @@ private function searchInDirectory($dir) /** * Normalizes given directory names by removing trailing slashes. * - * @param string $dir - * - * @return string + * Excluding: (s)ftp:// or ssh2.(s)ftp:// wrapper */ - private function normalizeDir($dir) + private function normalizeDir(string $dir): string { - return rtrim($dir, '/'.\DIRECTORY_SEPARATOR); + if ('/' === $dir) { + return $dir; + } + + $dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR); + + if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) { + $dir .= '/'; + } + + return $dir; } } diff --git a/vendor/symfony/finder/Gitignore.php b/vendor/symfony/finder/Gitignore.php new file mode 100644 index 0000000..d42cca1 --- /dev/null +++ b/vendor/symfony/finder/Gitignore.php @@ -0,0 +1,93 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder; + +/** + * Gitignore matches against text. + * + * @author Michael Voříšek <vorismi3@fel.cvut.cz> + * @author Ahmed Abdou <mail@ahmd.io> + */ +class Gitignore +{ + /** + * Returns a regexp which is the equivalent of the gitignore pattern. + * + * Format specification: https://git-scm.com/docs/gitignore#_pattern_format + */ + public static function toRegex(string $gitignoreFileContent): string + { + return self::buildRegex($gitignoreFileContent, false); + } + + public static function toRegexMatchingNegatedPatterns(string $gitignoreFileContent): string + { + return self::buildRegex($gitignoreFileContent, true); + } + + private static function buildRegex(string $gitignoreFileContent, bool $inverted): string + { + $gitignoreFileContent = preg_replace('~(?<!\\\\)#[^\n\r]*~', '', $gitignoreFileContent); + $gitignoreLines = preg_split('~\r\n?|\n~', $gitignoreFileContent); + + $res = self::lineToRegex(''); + foreach ($gitignoreLines as $line) { + $line = preg_replace('~(?<!\\\\)[ \t]+$~', '', $line); + + if ('!' === substr($line, 0, 1)) { + $line = substr($line, 1); + $isNegative = true; + } else { + $isNegative = false; + } + + if ('' !== $line) { + if ($isNegative xor $inverted) { + $res = '(?!'.self::lineToRegex($line).'$)'.$res; + } else { + $res = '(?:'.$res.'|'.self::lineToRegex($line).')'; + } + } + } + + return '~^(?:'.$res.')~s'; + } + + private static function lineToRegex(string $gitignoreLine): string + { + if ('' === $gitignoreLine) { + return '$f'; // always false + } + + $slashPos = strpos($gitignoreLine, '/'); + if (false !== $slashPos && \strlen($gitignoreLine) - 1 !== $slashPos) { + if (0 === $slashPos) { + $gitignoreLine = substr($gitignoreLine, 1); + } + $isAbsolute = true; + } else { + $isAbsolute = false; + } + + $regex = preg_quote(str_replace('\\', '', $gitignoreLine), '~'); + $regex = preg_replace_callback('~\\\\\[((?:\\\\!)?)([^\[\]]*)\\\\\]~', function (array $matches): string { + return '['.('' !== $matches[1] ? '^' : '').str_replace('\\-', '-', $matches[2]).']'; + }, $regex); + $regex = preg_replace('~(?:(?:\\\\\*){2,}(/?))+~', '(?:(?:(?!//).(?<!//))+$1)?', $regex); + $regex = preg_replace('~\\\\\*~', '[^/]*', $regex); + $regex = preg_replace('~\\\\\?~', '[^/]', $regex); + + return ($isAbsolute ? '' : '(?:[^/]+/)*') + .$regex + .(!str_ends_with($gitignoreLine, '/') ? '(?:$|/)' : ''); + } +} diff --git a/vendor/symfony/finder/Glob.php b/vendor/symfony/finder/Glob.php index d8df62b..8447932 100644 --- a/vendor/symfony/finder/Glob.php +++ b/vendor/symfony/finder/Glob.php @@ -14,14 +14,14 @@ /** * Glob matches globbing patterns against text. * - * if match_glob("foo.*", "foo.bar") echo "matched\n"; + * if match_glob("foo.*", "foo.bar") echo "matched\n"; * - * // prints foo.bar and foo.baz - * $regex = glob_to_regex("foo.*"); - * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t) - * { - * if (/$regex/) echo "matched: $car\n"; - * } + * // prints foo.bar and foo.baz + * $regex = glob_to_regex("foo.*"); + * for (['foo.bar', 'foo.baz', 'foo', 'bar'] as $t) + * { + * if (/$regex/) echo "matched: $car\n"; + * } * * Glob implements glob(3) style matching that can be used to match * against text, rather than fetching names from a filesystem. @@ -38,14 +38,9 @@ class Glob /** * Returns a regexp which is the equivalent of the glob pattern. * - * @param string $glob The glob pattern - * @param bool $strictLeadingDot - * @param bool $strictWildcardSlash - * @param string $delimiter Optional delimiter - * - * @return string regex The regexp + * @return string */ - public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#') + public static function toRegex(string $glob, bool $strictLeadingDot = true, bool $strictWildcardSlash = true, string $delimiter = '#') { $firstByte = true; $escaping = false; diff --git a/vendor/symfony/finder/Iterator/CustomFilterIterator.php b/vendor/symfony/finder/Iterator/CustomFilterIterator.php index 6666e07..f7bf19b 100644 --- a/vendor/symfony/finder/Iterator/CustomFilterIterator.php +++ b/vendor/symfony/finder/Iterator/CustomFilterIterator.php @@ -18,14 +18,16 @@ * to remove files. * * @author Fabien Potencier <fabien@symfony.com> + * + * @extends \FilterIterator<string, \SplFileInfo> */ -class CustomFilterIterator extends FilterIterator +class CustomFilterIterator extends \FilterIterator { - private $filters = array(); + private $filters = []; /** - * @param \Iterator $iterator The Iterator to filter - * @param callable[] $filters An array of PHP callbacks + * @param \Iterator<string, \SplFileInfo> $iterator The Iterator to filter + * @param callable[] $filters An array of PHP callbacks * * @throws \InvalidArgumentException */ @@ -44,14 +46,15 @@ public function __construct(\Iterator $iterator, array $filters) /** * Filters the iterator values. * - * @return bool true if the value should be kept, false otherwise + * @return bool */ + #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); foreach ($this->filters as $filter) { - if (false === \call_user_func($filter, $fileinfo)) { + if (false === $filter($fileinfo)) { return false; } } diff --git a/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php b/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php index b01e5e3..f592e19 100644 --- a/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php +++ b/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php @@ -17,14 +17,16 @@ * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). * * @author Fabien Potencier <fabien@symfony.com> + * + * @extends \FilterIterator<string, \SplFileInfo> */ -class DateRangeFilterIterator extends FilterIterator +class DateRangeFilterIterator extends \FilterIterator { - private $comparators = array(); + private $comparators = []; /** - * @param \Iterator $iterator The Iterator to filter - * @param DateComparator[] $comparators An array of DateComparator instances + * @param \Iterator<string, \SplFileInfo> $iterator + * @param DateComparator[] $comparators */ public function __construct(\Iterator $iterator, array $comparators) { @@ -36,8 +38,9 @@ public function __construct(\Iterator $iterator, array $comparators) /** * Filters the iterator values. * - * @return bool true if the value should be kept, false otherwise + * @return bool */ + #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); diff --git a/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php b/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php index ce9d3aa..f593a3f 100644 --- a/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php +++ b/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php @@ -15,20 +15,25 @@ * DepthRangeFilterIterator limits the directory depth. * * @author Fabien Potencier <fabien@symfony.com> + * + * @template-covariant TKey + * @template-covariant TValue + * + * @extends \FilterIterator<TKey, TValue> */ -class DepthRangeFilterIterator extends FilterIterator +class DepthRangeFilterIterator extends \FilterIterator { private $minDepth = 0; /** - * @param \RecursiveIteratorIterator $iterator The Iterator to filter - * @param int $minDepth The min depth - * @param int $maxDepth The max depth + * @param \RecursiveIteratorIterator<\RecursiveIterator<TKey, TValue>> $iterator The Iterator to filter + * @param int $minDepth The min depth + * @param int $maxDepth The max depth */ - public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX) + public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth = 0, int $maxDepth = \PHP_INT_MAX) { $this->minDepth = $minDepth; - $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); + $iterator->setMaxDepth(\PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); parent::__construct($iterator); } @@ -36,8 +41,9 @@ public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, /** * Filters the iterator values. * - * @return bool true if the value should be kept, false otherwise + * @return bool */ + #[\ReturnTypeWillChange] public function accept() { return $this->getInnerIterator()->getDepth() >= $this->minDepth; diff --git a/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php b/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php index c57128c..39797c8 100644 --- a/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php +++ b/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php @@ -15,26 +15,30 @@ * ExcludeDirectoryFilterIterator filters out directories. * * @author Fabien Potencier <fabien@symfony.com> + * + * @extends \FilterIterator<string, \SplFileInfo> + * + * @implements \RecursiveIterator<string, \SplFileInfo> */ -class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator +class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator { private $iterator; private $isRecursive; - private $excludedDirs = array(); + private $excludedDirs = []; private $excludedPattern; /** * @param \Iterator $iterator The Iterator to filter - * @param array $directories An array of directories to exclude + * @param string[] $directories An array of directories to exclude */ public function __construct(\Iterator $iterator, array $directories) { $this->iterator = $iterator; $this->isRecursive = $iterator instanceof \RecursiveIterator; - $patterns = array(); + $patterns = []; foreach ($directories as $directory) { $directory = rtrim($directory, '/'); - if (!$this->isRecursive || false !== strpos($directory, '/')) { + if (!$this->isRecursive || str_contains($directory, '/')) { $patterns[] = preg_quote($directory, '#'); } else { $this->excludedDirs[$directory] = true; @@ -50,8 +54,9 @@ public function __construct(\Iterator $iterator, array $directories) /** * Filters the iterator values. * - * @return bool True if the value should be kept, false otherwise + * @return bool */ + #[\ReturnTypeWillChange] public function accept() { if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) { @@ -68,14 +73,22 @@ public function accept() return true; } + /** + * @return bool + */ + #[\ReturnTypeWillChange] public function hasChildren() { return $this->isRecursive && $this->iterator->hasChildren(); } + /** + * @return self + */ + #[\ReturnTypeWillChange] public function getChildren() { - $children = new self($this->iterator->getChildren(), array()); + $children = new self($this->iterator->getChildren(), []); $children->excludedDirs = $this->excludedDirs; $children->excludedPattern = $this->excludedPattern; diff --git a/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php b/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php index e9811d4..793ae35 100644 --- a/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php +++ b/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php @@ -15,11 +15,13 @@ * FileTypeFilterIterator only keeps files, directories, or both. * * @author Fabien Potencier <fabien@symfony.com> + * + * @extends \FilterIterator<string, \SplFileInfo> */ -class FileTypeFilterIterator extends FilterIterator +class FileTypeFilterIterator extends \FilterIterator { - const ONLY_FILES = 1; - const ONLY_DIRECTORIES = 2; + public const ONLY_FILES = 1; + public const ONLY_DIRECTORIES = 2; private $mode; @@ -27,7 +29,7 @@ class FileTypeFilterIterator extends FilterIterator * @param \Iterator $iterator The Iterator to filter * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) */ - public function __construct(\Iterator $iterator, $mode) + public function __construct(\Iterator $iterator, int $mode) { $this->mode = $mode; @@ -37,8 +39,9 @@ public function __construct(\Iterator $iterator, $mode) /** * Filters the iterator values. * - * @return bool true if the value should be kept, false otherwise + * @return bool */ + #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); diff --git a/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php b/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php index 81594b8..79f8c29 100644 --- a/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php +++ b/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php @@ -16,14 +16,17 @@ * * @author Fabien Potencier <fabien@symfony.com> * @author Włodzimierz Gajda <gajdaw@gajdaw.pl> + * + * @extends MultiplePcreFilterIterator<string, \SplFileInfo> */ class FilecontentFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * - * @return bool true if the value should be kept, false otherwise + * @return bool */ + #[\ReturnTypeWillChange] public function accept() { if (!$this->matchRegexps && !$this->noMatchRegexps) { @@ -49,9 +52,9 @@ public function accept() * * @param string $str Pattern: string or regexp * - * @return string regexp corresponding to a given string or regexp + * @return string */ - protected function toRegex($str) + protected function toRegex(string $str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } diff --git a/vendor/symfony/finder/Iterator/FilenameFilterIterator.php b/vendor/symfony/finder/Iterator/FilenameFilterIterator.php index e168cd8..77b3b24 100644 --- a/vendor/symfony/finder/Iterator/FilenameFilterIterator.php +++ b/vendor/symfony/finder/Iterator/FilenameFilterIterator.php @@ -17,14 +17,17 @@ * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). * * @author Fabien Potencier <fabien@symfony.com> + * + * @extends MultiplePcreFilterIterator<string, \SplFileInfo> */ class FilenameFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * - * @return bool true if the value should be kept, false otherwise + * @return bool */ + #[\ReturnTypeWillChange] public function accept() { return $this->isAccepted($this->current()->getFilename()); @@ -38,9 +41,9 @@ public function accept() * * @param string $str Pattern: glob or regexp * - * @return string regexp corresponding to a given glob or regexp + * @return string */ - protected function toRegex($str) + protected function toRegex(string $str) { return $this->isRegex($str) ? $str : Glob::toRegex($str); } diff --git a/vendor/symfony/finder/Iterator/FilterIterator.php b/vendor/symfony/finder/Iterator/FilterIterator.php deleted file mode 100644 index c16dd8f..0000000 --- a/vendor/symfony/finder/Iterator/FilterIterator.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * This iterator just overrides the rewind method in order to correct a PHP bug, - * which existed before version 5.5.23/5.6.7. - * - * @see https://bugs.php.net/68557 - * - * @author Alex Bogomazov - * - * @deprecated since 3.4, to be removed in 4.0. - */ -abstract class FilterIterator extends \FilterIterator -{ - /** - * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after - * rewind in some cases. - * - * @see FilterIterator::rewind() - */ - public function rewind() - { - if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) { - parent::rewind(); - - return; - } - - $iterator = $this; - while ($iterator instanceof \OuterIterator) { - $innerIterator = $iterator->getInnerIterator(); - - if ($innerIterator instanceof RecursiveDirectoryIterator) { - // this condition is necessary for iterators to work properly with non-local filesystems like ftp - if ($innerIterator->isRewindable()) { - $innerIterator->next(); - $innerIterator->rewind(); - } - } elseif ($innerIterator instanceof \FilesystemIterator) { - $innerIterator->next(); - $innerIterator->rewind(); - } - - $iterator = $innerIterator; - } - - parent::rewind(); - } -} diff --git a/vendor/symfony/finder/Iterator/LazyIterator.php b/vendor/symfony/finder/Iterator/LazyIterator.php new file mode 100644 index 0000000..32cc37f --- /dev/null +++ b/vendor/symfony/finder/Iterator/LazyIterator.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * @author Jérémy Derussé <jeremy@derusse.com> + * + * @internal + */ +class LazyIterator implements \IteratorAggregate +{ + private $iteratorFactory; + + public function __construct(callable $iteratorFactory) + { + $this->iteratorFactory = $iteratorFactory; + } + + public function getIterator(): \Traversable + { + yield from ($this->iteratorFactory)(); + } +} diff --git a/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php b/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php index fc88540..564765d 100644 --- a/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php +++ b/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php @@ -15,16 +15,21 @@ * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). * * @author Fabien Potencier <fabien@symfony.com> + * + * @template-covariant TKey + * @template-covariant TValue + * + * @extends \FilterIterator<TKey, TValue> */ -abstract class MultiplePcreFilterIterator extends FilterIterator +abstract class MultiplePcreFilterIterator extends \FilterIterator { - protected $matchRegexps = array(); - protected $noMatchRegexps = array(); + protected $matchRegexps = []; + protected $noMatchRegexps = []; /** * @param \Iterator $iterator The Iterator to filter - * @param array $matchPatterns An array of patterns that need to match - * @param array $noMatchPatterns An array of patterns that need to not match + * @param string[] $matchPatterns An array of patterns that need to match + * @param string[] $noMatchPatterns An array of patterns that need to not match */ public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) { @@ -46,11 +51,9 @@ public function __construct(\Iterator $iterator, array $matchPatterns, array $no * Such case can be handled by child classes before calling the method if they want to * apply a different behavior. * - * @param string $string The string to be matched against filters - * * @return bool */ - protected function isAccepted($string) + protected function isAccepted(string $string) { // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { @@ -77,13 +80,17 @@ protected function isAccepted($string) /** * Checks whether the string is a regex. * - * @param string $str - * - * @return bool Whether the given string is a regex + * @return bool */ - protected function isRegex($str) + protected function isRegex(string $str) { - if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) { + $availableModifiers = 'imsxuADU'; + + if (\PHP_VERSION_ID >= 80200) { + $availableModifiers .= 'n'; + } + + if (preg_match('/^(.{3,}?)['.$availableModifiers.']*$/', $str, $m)) { $start = substr($m[1], 0, 1); $end = substr($m[1], -1); @@ -91,7 +98,7 @@ protected function isRegex($str) return !preg_match('/[*?[:alnum:] \\\\]/', $start); } - foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) { + foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) { if ($start === $delimiters[0] && $end === $delimiters[1]) { return true; } @@ -104,9 +111,7 @@ protected function isRegex($str) /** * Converts string into regexp. * - * @param string $str Pattern - * - * @return string regexp corresponding to a given string + * @return string */ - abstract protected function toRegex($str); + abstract protected function toRegex(string $str); } diff --git a/vendor/symfony/finder/Iterator/PathFilterIterator.php b/vendor/symfony/finder/Iterator/PathFilterIterator.php index 3fda557..7974c4e 100644 --- a/vendor/symfony/finder/Iterator/PathFilterIterator.php +++ b/vendor/symfony/finder/Iterator/PathFilterIterator.php @@ -16,14 +16,17 @@ * * @author Fabien Potencier <fabien@symfony.com> * @author Włodzimierz Gajda <gajdaw@gajdaw.pl> + * + * @extends MultiplePcreFilterIterator<string, \SplFileInfo> */ class PathFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * - * @return bool true if the value should be kept, false otherwise + * @return bool */ + #[\ReturnTypeWillChange] public function accept() { $filename = $this->current()->getRelativePathname(); @@ -47,9 +50,9 @@ public function accept() * * @param string $str Pattern: regexp or dirname * - * @return string regexp corresponding to a given string or regexp + * @return string */ - protected function toRegex($str) + protected function toRegex(string $str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } diff --git a/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php b/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php index 3e6ef86..27589cd 100644 --- a/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php +++ b/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php @@ -37,13 +37,9 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator private $directorySeparator = '/'; /** - * @param string $path - * @param int $flags - * @param bool $ignoreUnreadableDirs - * * @throws \RuntimeException */ - public function __construct($path, $flags, $ignoreUnreadableDirs = false) + public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = false) { if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { throw new \RuntimeException('This iterator only support returning current as fileinfo.'); @@ -60,28 +56,58 @@ public function __construct($path, $flags, $ignoreUnreadableDirs = false) /** * Return an instance of SplFileInfo with support for relative paths. * - * @return SplFileInfo File information + * @return SplFileInfo */ + #[\ReturnTypeWillChange] public function current() { // the logic here avoids redoing the same work in all iterations if (null === $subPathname = $this->subPath) { - $subPathname = $this->subPath = (string) $this->getSubPath(); + $subPathname = $this->subPath = $this->getSubPath(); } if ('' !== $subPathname) { $subPathname .= $this->directorySeparator; } $subPathname .= $this->getFilename(); - return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname); + if ('/' !== $basePath = $this->rootPath) { + $basePath .= $this->directorySeparator; + } + + return new SplFileInfo($basePath.$subPathname, $this->subPath, $subPathname); + } + + /** + * @param bool $allowLinks + * + * @return bool + */ + #[\ReturnTypeWillChange] + public function hasChildren($allowLinks = false) + { + $hasChildren = parent::hasChildren($allowLinks); + + if (!$hasChildren || !$this->ignoreUnreadableDirs) { + return $hasChildren; + } + + try { + parent::getChildren(); + + return true; + } catch (\UnexpectedValueException $e) { + // If directory is unreadable and finder is set to ignore it, skip children + return false; + } } /** - * @return \RecursiveIterator + * @return \RecursiveDirectoryIterator * * @throws AccessDeniedException */ + #[\ReturnTypeWillChange] public function getChildren() { try { @@ -98,36 +124,29 @@ public function getChildren() return $children; } catch (\UnexpectedValueException $e) { - if ($this->ignoreUnreadableDirs) { - // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. - return new \RecursiveArrayIterator(array()); - } else { - throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); - } + throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); } } /** * Do nothing for non rewindable stream. + * + * @return void */ + #[\ReturnTypeWillChange] public function rewind() { if (false === $this->isRewindable()) { return; } - // @see https://bugs.php.net/68557 - if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) { - parent::next(); - } - parent::rewind(); } /** * Checks if the stream is rewindable. * - * @return bool true when the stream is rewindable, false otherwise + * @return bool */ public function isRewindable() { @@ -135,11 +154,6 @@ public function isRewindable() return $this->rewindable; } - // workaround for an HHVM bug, should be removed when https://github.com/facebook/hhvm/issues/7281 is fixed - if ('' === $this->getPath()) { - return $this->rewindable = false; - } - if (false !== $stream = @opendir($this->getPath())) { $infos = stream_get_meta_data($stream); closedir($stream); diff --git a/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php b/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php index bd1a7fb..575bf29 100644 --- a/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php +++ b/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php @@ -17,14 +17,16 @@ * SizeRangeFilterIterator filters out files that are not in the given size range. * * @author Fabien Potencier <fabien@symfony.com> + * + * @extends \FilterIterator<string, \SplFileInfo> */ -class SizeRangeFilterIterator extends FilterIterator +class SizeRangeFilterIterator extends \FilterIterator { - private $comparators = array(); + private $comparators = []; /** - * @param \Iterator $iterator The Iterator to filter - * @param NumberComparator[] $comparators An array of NumberComparator instances + * @param \Iterator<string, \SplFileInfo> $iterator + * @param NumberComparator[] $comparators */ public function __construct(\Iterator $iterator, array $comparators) { @@ -36,8 +38,9 @@ public function __construct(\Iterator $iterator, array $comparators) /** * Filters the iterator values. * - * @return bool true if the value should be kept, false otherwise + * @return bool */ + #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); diff --git a/vendor/symfony/finder/Iterator/SortableIterator.php b/vendor/symfony/finder/Iterator/SortableIterator.php index 53f8e31..9afde5c 100644 --- a/vendor/symfony/finder/Iterator/SortableIterator.php +++ b/vendor/symfony/finder/Iterator/SortableIterator.php @@ -15,65 +15,89 @@ * SortableIterator applies a sort on a given Iterator. * * @author Fabien Potencier <fabien@symfony.com> + * + * @implements \IteratorAggregate<string, \SplFileInfo> */ class SortableIterator implements \IteratorAggregate { - const SORT_BY_NAME = 1; - const SORT_BY_TYPE = 2; - const SORT_BY_ACCESSED_TIME = 3; - const SORT_BY_CHANGED_TIME = 4; - const SORT_BY_MODIFIED_TIME = 5; + public const SORT_BY_NONE = 0; + public const SORT_BY_NAME = 1; + public const SORT_BY_TYPE = 2; + public const SORT_BY_ACCESSED_TIME = 3; + public const SORT_BY_CHANGED_TIME = 4; + public const SORT_BY_MODIFIED_TIME = 5; + public const SORT_BY_NAME_NATURAL = 6; private $iterator; private $sort; /** - * @param \Traversable $iterator The Iterator to filter - * @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) + * @param \Traversable<string, \SplFileInfo> $iterator + * @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) * * @throws \InvalidArgumentException */ - public function __construct(\Traversable $iterator, $sort) + public function __construct(\Traversable $iterator, $sort, bool $reverseOrder = false) { $this->iterator = $iterator; + $order = $reverseOrder ? -1 : 1; if (self::SORT_BY_NAME === $sort) { - $this->sort = function ($a, $b) { - return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname()); + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); + }; + } elseif (self::SORT_BY_NAME_NATURAL === $sort) { + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); }; } elseif (self::SORT_BY_TYPE === $sort) { - $this->sort = function ($a, $b) { + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { if ($a->isDir() && $b->isFile()) { - return -1; + return -$order; } elseif ($a->isFile() && $b->isDir()) { - return 1; + return $order; } - return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname()); + return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); }; } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { - $this->sort = function ($a, $b) { - return $a->getATime() - $b->getATime(); + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * ($a->getATime() - $b->getATime()); }; } elseif (self::SORT_BY_CHANGED_TIME === $sort) { - $this->sort = function ($a, $b) { - return $a->getCTime() - $b->getCTime(); + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * ($a->getCTime() - $b->getCTime()); }; } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { - $this->sort = function ($a, $b) { - return $a->getMTime() - $b->getMTime(); + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * ($a->getMTime() - $b->getMTime()); }; + } elseif (self::SORT_BY_NONE === $sort) { + $this->sort = $order; } elseif (\is_callable($sort)) { - $this->sort = $sort; + $this->sort = $reverseOrder ? static function (\SplFileInfo $a, \SplFileInfo $b) use ($sort) { return -$sort($a, $b); } : $sort; } else { throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.'); } } + /** + * @return \Traversable<string, \SplFileInfo> + */ + #[\ReturnTypeWillChange] public function getIterator() { + if (1 === $this->sort) { + return $this->iterator; + } + $array = iterator_to_array($this->iterator, true); - uasort($array, $this->sort); + + if (-1 === $this->sort) { + $array = array_reverse($array); + } else { + uasort($array, $this->sort); + } return new \ArrayIterator($array); } diff --git a/vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php b/vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php new file mode 100644 index 0000000..e27158c --- /dev/null +++ b/vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php @@ -0,0 +1,151 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +use Symfony\Component\Finder\Gitignore; + +final class VcsIgnoredFilterIterator extends \FilterIterator +{ + /** + * @var string + */ + private $baseDir; + + /** + * @var array<string, array{0: string, 1: string}|null> + */ + private $gitignoreFilesCache = []; + + /** + * @var array<string, bool> + */ + private $ignoredPathsCache = []; + + public function __construct(\Iterator $iterator, string $baseDir) + { + $this->baseDir = $this->normalizePath($baseDir); + + parent::__construct($iterator); + } + + public function accept(): bool + { + $file = $this->current(); + + $fileRealPath = $this->normalizePath($file->getRealPath()); + + return !$this->isIgnored($fileRealPath); + } + + private function isIgnored(string $fileRealPath): bool + { + if (is_dir($fileRealPath) && !str_ends_with($fileRealPath, '/')) { + $fileRealPath .= '/'; + } + + if (isset($this->ignoredPathsCache[$fileRealPath])) { + return $this->ignoredPathsCache[$fileRealPath]; + } + + $ignored = false; + + foreach ($this->parentsDirectoryDownward($fileRealPath) as $parentDirectory) { + if ($this->isIgnored($parentDirectory)) { + // rules in ignored directories are ignored, no need to check further. + break; + } + + $fileRelativePath = substr($fileRealPath, \strlen($parentDirectory) + 1); + + if (null === $regexps = $this->readGitignoreFile("{$parentDirectory}/.gitignore")) { + continue; + } + + [$exclusionRegex, $inclusionRegex] = $regexps; + + if (preg_match($exclusionRegex, $fileRelativePath)) { + $ignored = true; + + continue; + } + + if (preg_match($inclusionRegex, $fileRelativePath)) { + $ignored = false; + } + } + + return $this->ignoredPathsCache[$fileRealPath] = $ignored; + } + + /** + * @return list<string> + */ + private function parentsDirectoryDownward(string $fileRealPath): array + { + $parentDirectories = []; + + $parentDirectory = $fileRealPath; + + while (true) { + $newParentDirectory = \dirname($parentDirectory); + + // dirname('/') = '/' + if ($newParentDirectory === $parentDirectory) { + break; + } + + $parentDirectory = $newParentDirectory; + + if (0 !== strpos($parentDirectory, $this->baseDir)) { + break; + } + + $parentDirectories[] = $parentDirectory; + } + + return array_reverse($parentDirectories); + } + + /** + * @return array{0: string, 1: string}|null + */ + private function readGitignoreFile(string $path): ?array + { + if (\array_key_exists($path, $this->gitignoreFilesCache)) { + return $this->gitignoreFilesCache[$path]; + } + + if (!file_exists($path)) { + return $this->gitignoreFilesCache[$path] = null; + } + + if (!is_file($path) || !is_readable($path)) { + throw new \RuntimeException("The \"ignoreVCSIgnored\" option cannot be used by the Finder as the \"{$path}\" file is not readable."); + } + + $gitignoreFileContent = file_get_contents($path); + + return $this->gitignoreFilesCache[$path] = [ + Gitignore::toRegex($gitignoreFileContent), + Gitignore::toRegexMatchingNegatedPatterns($gitignoreFileContent), + ]; + } + + private function normalizePath(string $path): string + { + if ('\\' === \DIRECTORY_SEPARATOR) { + return str_replace('\\', '/', $path); + } + + return $path; + } +} diff --git a/vendor/symfony/finder/LICENSE b/vendor/symfony/finder/LICENSE index 21d7fb9..0138f8f 100644 --- a/vendor/symfony/finder/LICENSE +++ b/vendor/symfony/finder/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/finder/README.md b/vendor/symfony/finder/README.md index 0b19c75..22bdeb9 100644 --- a/vendor/symfony/finder/README.md +++ b/vendor/symfony/finder/README.md @@ -7,8 +7,8 @@ interface. Resources --------- - * [Documentation](https://symfony.com/doc/current/components/finder.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) + * [Documentation](https://symfony.com/doc/current/components/finder.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/finder/SplFileInfo.php b/vendor/symfony/finder/SplFileInfo.php index 0f4e025..11604a2 100644 --- a/vendor/symfony/finder/SplFileInfo.php +++ b/vendor/symfony/finder/SplFileInfo.php @@ -26,7 +26,7 @@ class SplFileInfo extends \SplFileInfo * @param string $relativePath The relative path * @param string $relativePathname The relative path name */ - public function __construct($file, $relativePath, $relativePathname) + public function __construct(string $file, string $relativePath, string $relativePathname) { parent::__construct($file); $this->relativePath = $relativePath; @@ -38,7 +38,7 @@ public function __construct($file, $relativePath, $relativePathname) * * This path does not contain the file name. * - * @return string the relative path + * @return string */ public function getRelativePath() { @@ -50,25 +50,35 @@ public function getRelativePath() * * This path contains the file name. * - * @return string the relative path name + * @return string */ public function getRelativePathname() { return $this->relativePathname; } + public function getFilenameWithoutExtension(): string + { + $filename = $this->getFilename(); + + return pathinfo($filename, \PATHINFO_FILENAME); + } + /** * Returns the contents of the file. * - * @return string the contents of the file + * @return string * * @throws \RuntimeException */ public function getContents() { set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - $content = file_get_contents($this->getPathname()); - restore_error_handler(); + try { + $content = file_get_contents($this->getPathname()); + } finally { + restore_error_handler(); + } if (false === $content) { throw new \RuntimeException($error); } diff --git a/vendor/symfony/finder/Tests/Comparator/ComparatorTest.php b/vendor/symfony/finder/Tests/Comparator/ComparatorTest.php deleted file mode 100644 index 656fc57..0000000 --- a/vendor/symfony/finder/Tests/Comparator/ComparatorTest.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Comparator; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Finder\Comparator\Comparator; - -class ComparatorTest extends TestCase -{ - public function testGetSetOperator() - { - $comparator = new Comparator(); - try { - $comparator->setOperator('foo'); - $this->fail('->setOperator() throws an \InvalidArgumentException if the operator is not valid.'); - } catch (\Exception $e) { - $this->assertInstanceOf('InvalidArgumentException', $e, '->setOperator() throws an \InvalidArgumentException if the operator is not valid.'); - } - - $comparator = new Comparator(); - $comparator->setOperator('>'); - $this->assertEquals('>', $comparator->getOperator(), '->getOperator() returns the current operator'); - } - - public function testGetSetTarget() - { - $comparator = new Comparator(); - $comparator->setTarget(8); - $this->assertEquals(8, $comparator->getTarget(), '->getTarget() returns the target'); - } - - /** - * @dataProvider getTestData - */ - public function testTest($operator, $target, $match, $noMatch) - { - $c = new Comparator(); - $c->setOperator($operator); - $c->setTarget($target); - - foreach ($match as $m) { - $this->assertTrue($c->test($m), '->test() tests a string against the expression'); - } - - foreach ($noMatch as $m) { - $this->assertFalse($c->test($m), '->test() tests a string against the expression'); - } - } - - public function getTestData() - { - return array( - array('<', '1000', array('500', '999'), array('1000', '1500')), - ); - } -} diff --git a/vendor/symfony/finder/Tests/Comparator/DateComparatorTest.php b/vendor/symfony/finder/Tests/Comparator/DateComparatorTest.php deleted file mode 100644 index 8a6c1dd..0000000 --- a/vendor/symfony/finder/Tests/Comparator/DateComparatorTest.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Comparator; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Finder\Comparator\DateComparator; - -class DateComparatorTest extends TestCase -{ - public function testConstructor() - { - try { - new DateComparator('foobar'); - $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.'); - } catch (\Exception $e) { - $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.'); - } - - try { - new DateComparator(''); - $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.'); - } catch (\Exception $e) { - $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.'); - } - } - - /** - * @dataProvider getTestData - */ - public function testTest($test, $match, $noMatch) - { - $c = new DateComparator($test); - - foreach ($match as $m) { - $this->assertTrue($c->test($m), '->test() tests a string against the expression'); - } - - foreach ($noMatch as $m) { - $this->assertFalse($c->test($m), '->test() tests a string against the expression'); - } - } - - public function getTestData() - { - return array( - array('< 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))), - array('until 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))), - array('before 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))), - array('> 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))), - array('after 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))), - array('since 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))), - array('!= 2005-10-10', array(strtotime('2005-10-11')), array(strtotime('2005-10-10'))), - ); - } -} diff --git a/vendor/symfony/finder/Tests/Comparator/NumberComparatorTest.php b/vendor/symfony/finder/Tests/Comparator/NumberComparatorTest.php deleted file mode 100644 index 30a75c7..0000000 --- a/vendor/symfony/finder/Tests/Comparator/NumberComparatorTest.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Comparator; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Finder\Comparator\NumberComparator; - -class NumberComparatorTest extends TestCase -{ - /** - * @dataProvider getConstructorTestData - */ - public function testConstructor($successes, $failures) - { - foreach ($successes as $s) { - new NumberComparator($s); - } - - foreach ($failures as $f) { - try { - new NumberComparator($f); - $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.'); - } catch (\Exception $e) { - $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.'); - } - } - } - - /** - * @dataProvider getTestData - */ - public function testTest($test, $match, $noMatch) - { - $c = new NumberComparator($test); - - foreach ($match as $m) { - $this->assertTrue($c->test($m), '->test() tests a string against the expression'); - } - - foreach ($noMatch as $m) { - $this->assertFalse($c->test($m), '->test() tests a string against the expression'); - } - } - - public function getTestData() - { - return array( - array('< 1000', array('500', '999'), array('1000', '1500')), - - array('< 1K', array('500', '999'), array('1000', '1500')), - array('<1k', array('500', '999'), array('1000', '1500')), - array(' < 1 K ', array('500', '999'), array('1000', '1500')), - array('<= 1K', array('1000'), array('1001')), - array('> 1K', array('1001'), array('1000')), - array('>= 1K', array('1000'), array('999')), - - array('< 1KI', array('500', '1023'), array('1024', '1500')), - array('<= 1KI', array('1024'), array('1025')), - array('> 1KI', array('1025'), array('1024')), - array('>= 1KI', array('1024'), array('1023')), - - array('1KI', array('1024'), array('1023', '1025')), - array('==1KI', array('1024'), array('1023', '1025')), - - array('==1m', array('1000000'), array('999999', '1000001')), - array('==1mi', array(1024 * 1024), array(1024 * 1024 - 1, 1024 * 1024 + 1)), - - array('==1g', array('1000000000'), array('999999999', '1000000001')), - array('==1gi', array(1024 * 1024 * 1024), array(1024 * 1024 * 1024 - 1, 1024 * 1024 * 1024 + 1)), - - array('!= 1000', array('500', '999'), array('1000')), - ); - } - - public function getConstructorTestData() - { - return array( - array( - array( - '1', '0', - '3.5', '33.55', '123.456', '123456.78', - '.1', '.123', - '.0', '0.0', - '1.', '0.', '123.', - '==1', '!=1', '<1', '>1', '<=1', '>=1', - '==1k', '==1ki', '==1m', '==1mi', '==1g', '==1gi', - '1k', '1ki', '1m', '1mi', '1g', '1gi', - ), - array( - false, null, '', - ' ', 'foobar', - '=1', '===1', - '0 . 1', '123 .45', '234. 567', - '..', '.0.', '0.1.2', - ), - ), - ); - } -} diff --git a/vendor/symfony/finder/Tests/FinderTest.php b/vendor/symfony/finder/Tests/FinderTest.php deleted file mode 100644 index fbdcc36..0000000 --- a/vendor/symfony/finder/Tests/FinderTest.php +++ /dev/null @@ -1,737 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests; - -use Symfony\Component\Finder\Finder; - -class FinderTest extends Iterator\RealIteratorTestCase -{ - public function testCreate() - { - $this->assertInstanceOf('Symfony\Component\Finder\Finder', Finder::create()); - } - - public function testDirectories() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->directories()); - $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->directories(); - $finder->files(); - $finder->directories(); - $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testFiles() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->files()); - $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->files(); - $finder->directories(); - $finder->files(); - $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testRemoveTrailingSlash() - { - $finder = $this->buildFinder(); - - $expected = $this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')); - $in = self::$tmpDir.'//'; - - $this->assertIterator($expected, $finder->in($in)->files()->getIterator()); - } - - public function testSymlinksNotResolved() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('symlinks are not supported on Windows'); - } - - $finder = $this->buildFinder(); - - symlink($this->toAbsolute('foo'), $this->toAbsolute('baz')); - $expected = $this->toAbsolute(array('baz/bar.tmp')); - $in = self::$tmpDir.'/baz/'; - try { - $this->assertIterator($expected, $finder->in($in)->files()->getIterator()); - unlink($this->toAbsolute('baz')); - } catch (\Exception $e) { - unlink($this->toAbsolute('baz')); - throw $e; - } - } - - public function testBackPathNotNormalized() - { - $finder = $this->buildFinder(); - - $expected = $this->toAbsolute(array('foo/../foo/bar.tmp')); - $in = self::$tmpDir.'/foo/../foo/'; - $this->assertIterator($expected, $finder->in($in)->files()->getIterator()); - } - - public function testDepth() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->depth('< 1')); - $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->depth('<= 0')); - $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->depth('>= 1')); - $this->assertIterator($this->toAbsolute(array('foo/bar.tmp')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->depth('< 1')->depth('>= 1'); - $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testName() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->name('*.php')); - $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->name('test.ph*'); - $finder->name('test.py'); - $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->name('~^test~i'); - $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->name('~\\.php$~i'); - $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->name('test.p{hp,y}'); - $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testNotName() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->notName('*.php')); - $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->notName('*.php'); - $finder->notName('*.py'); - $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->name('test.ph*'); - $finder->name('test.py'); - $finder->notName('*.php'); - $finder->notName('*.py'); - $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->name('test.ph*'); - $finder->name('test.py'); - $finder->notName('*.p{hp,y}'); - $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator()); - } - - /** - * @dataProvider getRegexNameTestData - */ - public function testRegexName($regex) - { - $finder = $this->buildFinder(); - $finder->name($regex); - $this->assertIterator($this->toAbsolute(array('test.py', 'test.php')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testSize() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->files()->size('< 1K')->size('> 500')); - $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testDate() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->files()->date('until last month')); - $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testExclude() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->exclude('foo')); - $this->assertIterator($this->toAbsolute(array('test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testIgnoreVCS() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false)); - $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false); - $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false)); - $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testIgnoreDotFiles() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false)); - $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false); - $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false)); - $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testSortByName() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->sortByName()); - $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testSortByType() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->sortByType()); - $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'toto', 'foo/bar.tmp', 'test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testSortByAccessedTime() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->sortByAccessedTime()); - $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testSortByChangedTime() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->sortByChangedTime()); - $this->assertIterator($this->toAbsolute(array('toto', 'test.py', 'test.php', 'foo/bar.tmp', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testSortByModifiedTime() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->sortByModifiedTime()); - $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testSort() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealPath(), $b->getRealPath()); })); - $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testFilter() - { - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->filter(function (\SplFileInfo $f) { return false !== strpos($f, 'test'); })); - $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testFollowLinks() - { - if ('\\' == \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('symlinks are not supported on Windows'); - } - - $finder = $this->buildFinder(); - $this->assertSame($finder, $finder->followLinks()); - $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - } - - public function testIn() - { - $finder = $this->buildFinder(); - $iterator = $finder->files()->name('*.php')->depth('< 1')->in(array(self::$tmpDir, __DIR__))->getIterator(); - - $expected = array( - self::$tmpDir.\DIRECTORY_SEPARATOR.'test.php', - __DIR__.\DIRECTORY_SEPARATOR.'FinderTest.php', - __DIR__.\DIRECTORY_SEPARATOR.'GlobTest.php', - ); - - $this->assertIterator($expected, $iterator); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testInWithNonExistentDirectory() - { - $finder = new Finder(); - $finder->in('foobar'); - } - - public function testInWithGlob() - { - $finder = $this->buildFinder(); - $finder->in(array(__DIR__.'/Fixtures/*/B/C/', __DIR__.'/Fixtures/*/*/B/C/'))->getIterator(); - - $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testInWithNonDirectoryGlob() - { - $finder = new Finder(); - $finder->in(__DIR__.'/Fixtures/A/a*'); - } - - public function testInWithGlobBrace() - { - $finder = $this->buildFinder(); - $finder->in(array(__DIR__.'/Fixtures/{A,copy/A}/B/C'))->getIterator(); - - $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder); - } - - /** - * @expectedException \LogicException - */ - public function testGetIteratorWithoutIn() - { - $finder = Finder::create(); - $finder->getIterator(); - } - - public function testGetIterator() - { - $finder = $this->buildFinder(); - $dirs = array(); - foreach ($finder->directories()->in(self::$tmpDir) as $dir) { - $dirs[] = (string) $dir; - } - - $expected = $this->toAbsolute(array('foo', 'toto')); - - sort($dirs); - sort($expected); - - $this->assertEquals($expected, $dirs, 'implements the \IteratorAggregate interface'); - - $finder = $this->buildFinder(); - $this->assertEquals(2, iterator_count($finder->directories()->in(self::$tmpDir)), 'implements the \IteratorAggregate interface'); - - $finder = $this->buildFinder(); - $a = iterator_to_array($finder->directories()->in(self::$tmpDir)); - $a = array_values(array_map('strval', $a)); - sort($a); - $this->assertEquals($expected, $a, 'implements the \IteratorAggregate interface'); - } - - public function testRelativePath() - { - $finder = $this->buildFinder()->in(self::$tmpDir); - - $paths = array(); - - foreach ($finder as $file) { - $paths[] = $file->getRelativePath(); - } - - $ref = array('', '', '', '', 'foo', ''); - - sort($ref); - sort($paths); - - $this->assertEquals($ref, $paths); - } - - public function testRelativePathname() - { - $finder = $this->buildFinder()->in(self::$tmpDir)->sortByName(); - - $paths = array(); - - foreach ($finder as $file) { - $paths[] = $file->getRelativePathname(); - } - - $ref = array('test.php', 'toto', 'test.py', 'foo', 'foo'.\DIRECTORY_SEPARATOR.'bar.tmp', 'foo bar'); - - sort($paths); - sort($ref); - - $this->assertEquals($ref, $paths); - } - - public function testAppendWithAFinder() - { - $finder = $this->buildFinder(); - $finder->files()->in(self::$tmpDir.\DIRECTORY_SEPARATOR.'foo'); - - $finder1 = $this->buildFinder(); - $finder1->directories()->in(self::$tmpDir); - - $finder = $finder->append($finder1); - - $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator()); - } - - public function testAppendWithAnArray() - { - $finder = $this->buildFinder(); - $finder->files()->in(self::$tmpDir.\DIRECTORY_SEPARATOR.'foo'); - - $finder->append($this->toAbsolute(array('foo', 'toto'))); - - $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator()); - } - - public function testAppendReturnsAFinder() - { - $this->assertInstanceOf('Symfony\\Component\\Finder\\Finder', Finder::create()->append(array())); - } - - public function testAppendDoesNotRequireIn() - { - $finder = $this->buildFinder(); - $finder->in(self::$tmpDir.\DIRECTORY_SEPARATOR.'foo'); - - $finder1 = Finder::create()->append($finder); - - $this->assertIterator(iterator_to_array($finder->getIterator()), $finder1->getIterator()); - } - - public function testCountDirectories() - { - $directory = Finder::create()->directories()->in(self::$tmpDir); - $i = 0; - - foreach ($directory as $dir) { - ++$i; - } - - $this->assertCount($i, $directory); - } - - public function testCountFiles() - { - $files = Finder::create()->files()->in(__DIR__.\DIRECTORY_SEPARATOR.'Fixtures'); - $i = 0; - - foreach ($files as $file) { - ++$i; - } - - $this->assertCount($i, $files); - } - - /** - * @expectedException \LogicException - */ - public function testCountWithoutIn() - { - $finder = Finder::create()->files(); - \count($finder); - } - - public function testHasResults() - { - $finder = $this->buildFinder(); - $finder->in(__DIR__); - $this->assertTrue($finder->hasResults()); - } - - public function testNoResults() - { - $finder = $this->buildFinder(); - $finder->in(__DIR__)->name('DoesNotExist'); - $this->assertFalse($finder->hasResults()); - } - - /** - * @dataProvider getContainsTestData - */ - public function testContains($matchPatterns, $noMatchPatterns, $expected) - { - $finder = $this->buildFinder(); - $finder->in(__DIR__.\DIRECTORY_SEPARATOR.'Fixtures') - ->name('*.txt')->sortByName() - ->contains($matchPatterns) - ->notContains($noMatchPatterns); - - $this->assertIterator($this->toAbsoluteFixtures($expected), $finder); - } - - public function testContainsOnDirectory() - { - $finder = $this->buildFinder(); - $finder->in(__DIR__) - ->directories() - ->name('Fixtures') - ->contains('abc'); - $this->assertIterator(array(), $finder); - } - - public function testNotContainsOnDirectory() - { - $finder = $this->buildFinder(); - $finder->in(__DIR__) - ->directories() - ->name('Fixtures') - ->notContains('abc'); - $this->assertIterator(array(), $finder); - } - - /** - * Searching in multiple locations involves AppendIterator which does an unnecessary rewind which leaves FilterIterator - * with inner FilesystemIterator in an invalid state. - * - * @see https://bugs.php.net/68557 - */ - public function testMultipleLocations() - { - $locations = array( - self::$tmpDir.'/', - self::$tmpDir.'/toto/', - ); - - // it is expected that there are test.py test.php in the tmpDir - $finder = new Finder(); - $finder->in($locations) - // the default flag IGNORE_DOT_FILES fixes the problem indirectly - // so we set it to false for better isolation - ->ignoreDotFiles(false) - ->depth('< 1')->name('test.php'); - - $this->assertCount(1, $finder); - } - - /** - * Searching in multiple locations with sub directories involves - * AppendIterator which does an unnecessary rewind which leaves - * FilterIterator with inner FilesystemIterator in an invalid state. - * - * @see https://bugs.php.net/68557 - */ - public function testMultipleLocationsWithSubDirectories() - { - $locations = array( - __DIR__.'/Fixtures/one', - self::$tmpDir.\DIRECTORY_SEPARATOR.'toto', - ); - - $finder = $this->buildFinder(); - $finder->in($locations)->depth('< 10')->name('*.neon'); - - $expected = array( - __DIR__.'/Fixtures/one'.\DIRECTORY_SEPARATOR.'b'.\DIRECTORY_SEPARATOR.'c.neon', - __DIR__.'/Fixtures/one'.\DIRECTORY_SEPARATOR.'b'.\DIRECTORY_SEPARATOR.'d.neon', - ); - - $this->assertIterator($expected, $finder); - $this->assertIteratorInForeach($expected, $finder); - } - - /** - * Iterator keys must be the file pathname. - */ - public function testIteratorKeys() - { - $finder = $this->buildFinder()->in(self::$tmpDir); - foreach ($finder as $key => $file) { - $this->assertEquals($file->getPathname(), $key); - } - } - - public function testRegexSpecialCharsLocationWithPathRestrictionContainingStartFlag() - { - $finder = $this->buildFinder(); - $finder->in(__DIR__.\DIRECTORY_SEPARATOR.'Fixtures'.\DIRECTORY_SEPARATOR.'r+e.gex[c]a(r)s') - ->path('/^dir/'); - - $expected = array('r+e.gex[c]a(r)s'.\DIRECTORY_SEPARATOR.'dir', 'r+e.gex[c]a(r)s'.\DIRECTORY_SEPARATOR.'dir'.\DIRECTORY_SEPARATOR.'bar.dat'); - $this->assertIterator($this->toAbsoluteFixtures($expected), $finder); - } - - public function getContainsTestData() - { - return array( - array('', '', array()), - array('foo', 'bar', array()), - array('', 'foobar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')), - array('lorem ipsum dolor sit amet', 'foobar', array('lorem.txt')), - array('sit', 'bar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')), - array('dolor sit amet', '@^L@m', array('dolor.txt', 'ipsum.txt')), - array('/^lorem ipsum dolor sit amet$/m', 'foobar', array('lorem.txt')), - array('lorem', 'foobar', array('lorem.txt')), - array('', 'lorem', array('dolor.txt', 'ipsum.txt')), - array('ipsum dolor sit amet', '/^IPSUM/m', array('lorem.txt')), - ); - } - - public function getRegexNameTestData() - { - return array( - array('~.+\\.p.+~i'), - array('~t.*s~i'), - ); - } - - /** - * @dataProvider getTestPathData - */ - public function testPath($matchPatterns, $noMatchPatterns, array $expected) - { - $finder = $this->buildFinder(); - $finder->in(__DIR__.\DIRECTORY_SEPARATOR.'Fixtures') - ->path($matchPatterns) - ->notPath($noMatchPatterns); - - $this->assertIterator($this->toAbsoluteFixtures($expected), $finder); - } - - public function getTestPathData() - { - return array( - array('', '', array()), - array('/^A\/B\/C/', '/C$/', - array('A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C'.\DIRECTORY_SEPARATOR.'abc.dat'), - ), - array('/^A\/B/', 'foobar', - array( - 'A'.\DIRECTORY_SEPARATOR.'B', - 'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C', - 'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'ab.dat', - 'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C'.\DIRECTORY_SEPARATOR.'abc.dat', - ), - ), - array('A/B/C', 'foobar', - array( - 'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C', - 'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C'.\DIRECTORY_SEPARATOR.'abc.dat', - 'copy'.\DIRECTORY_SEPARATOR.'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C', - 'copy'.\DIRECTORY_SEPARATOR.'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C'.\DIRECTORY_SEPARATOR.'abc.dat.copy', - ), - ), - array('A/B', 'foobar', - array( - //dirs - 'A'.\DIRECTORY_SEPARATOR.'B', - 'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C', - 'copy'.\DIRECTORY_SEPARATOR.'A'.\DIRECTORY_SEPARATOR.'B', - 'copy'.\DIRECTORY_SEPARATOR.'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C', - //files - 'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'ab.dat', - 'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C'.\DIRECTORY_SEPARATOR.'abc.dat', - 'copy'.\DIRECTORY_SEPARATOR.'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'ab.dat.copy', - 'copy'.\DIRECTORY_SEPARATOR.'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C'.\DIRECTORY_SEPARATOR.'abc.dat.copy', - ), - ), - array('/^with space\//', 'foobar', - array( - 'with space'.\DIRECTORY_SEPARATOR.'foo.txt', - ), - ), - ); - } - - public function testAccessDeniedException() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('chmod is not supported on Windows'); - } - - $finder = $this->buildFinder(); - $finder->files()->in(self::$tmpDir); - - // make 'foo' directory non-readable - $testDir = self::$tmpDir.\DIRECTORY_SEPARATOR.'foo'; - chmod($testDir, 0333); - - if (false === $couldRead = is_readable($testDir)) { - try { - $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator()); - $this->fail('Finder should throw an exception when opening a non-readable directory.'); - } catch (\Exception $e) { - $expectedExceptionClass = 'Symfony\\Component\\Finder\\Exception\\AccessDeniedException'; - if ($e instanceof \PHPUnit_Framework_ExpectationFailedException) { - $this->fail(sprintf("Expected exception:\n%s\nGot:\n%s\nWith comparison failure:\n%s", $expectedExceptionClass, 'PHPUnit_Framework_ExpectationFailedException', $e->getComparisonFailure()->getExpectedAsString())); - } - - if ($e instanceof \PHPUnit\Framework\ExpectationFailedException) { - $this->fail(sprintf("Expected exception:\n%s\nGot:\n%s\nWith comparison failure:\n%s", $expectedExceptionClass, '\PHPUnit\Framework\ExpectationFailedException', $e->getComparisonFailure()->getExpectedAsString())); - } - - $this->assertInstanceOf($expectedExceptionClass, $e); - } - } - - // restore original permissions - chmod($testDir, 0777); - clearstatcache($testDir); - - if ($couldRead) { - $this->markTestSkipped('could read test files while test requires unreadable'); - } - } - - public function testIgnoredAccessDeniedException() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('chmod is not supported on Windows'); - } - - $finder = $this->buildFinder(); - $finder->files()->ignoreUnreadableDirs()->in(self::$tmpDir); - - // make 'foo' directory non-readable - $testDir = self::$tmpDir.\DIRECTORY_SEPARATOR.'foo'; - chmod($testDir, 0333); - - if (false === ($couldRead = is_readable($testDir))) { - $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator()); - } - - // restore original permissions - chmod($testDir, 0777); - clearstatcache($testDir); - - if ($couldRead) { - $this->markTestSkipped('could read test files while test requires unreadable'); - } - } - - protected function buildFinder() - { - return Finder::create(); - } -} diff --git a/vendor/symfony/finder/Tests/Fixtures/.dot/a b/vendor/symfony/finder/Tests/Fixtures/.dot/a deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/.dot/b/c.neon b/vendor/symfony/finder/Tests/Fixtures/.dot/b/c.neon deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/.dot/b/d.neon b/vendor/symfony/finder/Tests/Fixtures/.dot/b/d.neon deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/A/B/C/abc.dat b/vendor/symfony/finder/Tests/Fixtures/A/B/C/abc.dat deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/A/B/ab.dat b/vendor/symfony/finder/Tests/Fixtures/A/B/ab.dat deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/A/a.dat b/vendor/symfony/finder/Tests/Fixtures/A/a.dat deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy b/vendor/symfony/finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/copy/A/B/ab.dat.copy b/vendor/symfony/finder/Tests/Fixtures/copy/A/B/ab.dat.copy deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/copy/A/a.dat.copy b/vendor/symfony/finder/Tests/Fixtures/copy/A/a.dat.copy deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/dolor.txt b/vendor/symfony/finder/Tests/Fixtures/dolor.txt deleted file mode 100644 index 658bec6..0000000 --- a/vendor/symfony/finder/Tests/Fixtures/dolor.txt +++ /dev/null @@ -1,2 +0,0 @@ -dolor sit amet -DOLOR SIT AMET \ No newline at end of file diff --git a/vendor/symfony/finder/Tests/Fixtures/ipsum.txt b/vendor/symfony/finder/Tests/Fixtures/ipsum.txt deleted file mode 100644 index c7f392d..0000000 --- a/vendor/symfony/finder/Tests/Fixtures/ipsum.txt +++ /dev/null @@ -1,2 +0,0 @@ -ipsum dolor sit amet -IPSUM DOLOR SIT AMET \ No newline at end of file diff --git a/vendor/symfony/finder/Tests/Fixtures/lorem.txt b/vendor/symfony/finder/Tests/Fixtures/lorem.txt deleted file mode 100644 index 2991a2c..0000000 --- a/vendor/symfony/finder/Tests/Fixtures/lorem.txt +++ /dev/null @@ -1,2 +0,0 @@ -lorem ipsum dolor sit amet -LOREM IPSUM DOLOR SIT AMET \ No newline at end of file diff --git a/vendor/symfony/finder/Tests/Fixtures/one/.dot b/vendor/symfony/finder/Tests/Fixtures/one/.dot deleted file mode 100644 index 1028065..0000000 --- a/vendor/symfony/finder/Tests/Fixtures/one/.dot +++ /dev/null @@ -1 +0,0 @@ -.dot \ No newline at end of file diff --git a/vendor/symfony/finder/Tests/Fixtures/one/a b/vendor/symfony/finder/Tests/Fixtures/one/a deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/one/b/c.neon b/vendor/symfony/finder/Tests/Fixtures/one/b/c.neon deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/one/b/d.neon b/vendor/symfony/finder/Tests/Fixtures/one/b/d.neon deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/r+e.gex[c]a(r)s/dir/bar.dat b/vendor/symfony/finder/Tests/Fixtures/r+e.gex[c]a(r)s/dir/bar.dat deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/Fixtures/with space/foo.txt b/vendor/symfony/finder/Tests/Fixtures/with space/foo.txt deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/symfony/finder/Tests/GlobTest.php b/vendor/symfony/finder/Tests/GlobTest.php deleted file mode 100644 index 3a5aab3..0000000 --- a/vendor/symfony/finder/Tests/GlobTest.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Finder\Finder; -use Symfony\Component\Finder\Glob; - -class GlobTest extends TestCase -{ - public function testGlobToRegexDelimiters() - { - $this->assertEquals('#^(?=[^\.])\#$#', Glob::toRegex('#')); - $this->assertEquals('#^\.[^/]*$#', Glob::toRegex('.*')); - $this->assertEquals('^\.[^/]*$', Glob::toRegex('.*', true, true, '')); - $this->assertEquals('/^\.[^/]*$/', Glob::toRegex('.*', true, true, '/')); - } - - public function testGlobToRegexDoubleStarStrictDots() - { - $finder = new Finder(); - $finder->ignoreDotFiles(false); - $regex = Glob::toRegex('/**/*.neon'); - - foreach ($finder->in(__DIR__) as $k => $v) { - $k = str_replace(\DIRECTORY_SEPARATOR, '/', $k); - if (preg_match($regex, substr($k, \strlen(__DIR__)))) { - $match[] = substr($k, 10 + \strlen(__DIR__)); - } - } - sort($match); - - $this->assertSame(array('one/b/c.neon', 'one/b/d.neon'), $match); - } - - public function testGlobToRegexDoubleStarNonStrictDots() - { - $finder = new Finder(); - $finder->ignoreDotFiles(false); - $regex = Glob::toRegex('/**/*.neon', false); - - foreach ($finder->in(__DIR__) as $k => $v) { - $k = str_replace(\DIRECTORY_SEPARATOR, '/', $k); - if (preg_match($regex, substr($k, \strlen(__DIR__)))) { - $match[] = substr($k, 10 + \strlen(__DIR__)); - } - } - sort($match); - - $this->assertSame(array('.dot/b/c.neon', '.dot/b/d.neon', 'one/b/c.neon', 'one/b/d.neon'), $match); - } - - public function testGlobToRegexDoubleStarWithoutLeadingSlash() - { - $finder = new Finder(); - $finder->ignoreDotFiles(false); - $regex = Glob::toRegex('/Fixtures/one/**'); - - foreach ($finder->in(__DIR__) as $k => $v) { - $k = str_replace(\DIRECTORY_SEPARATOR, '/', $k); - if (preg_match($regex, substr($k, \strlen(__DIR__)))) { - $match[] = substr($k, 10 + \strlen(__DIR__)); - } - } - sort($match); - - $this->assertSame(array('one/a', 'one/b', 'one/b/c.neon', 'one/b/d.neon'), $match); - } - - public function testGlobToRegexDoubleStarWithoutLeadingSlashNotStrictLeadingDot() - { - $finder = new Finder(); - $finder->ignoreDotFiles(false); - $regex = Glob::toRegex('/Fixtures/one/**', false); - - foreach ($finder->in(__DIR__) as $k => $v) { - $k = str_replace(\DIRECTORY_SEPARATOR, '/', $k); - if (preg_match($regex, substr($k, \strlen(__DIR__)))) { - $match[] = substr($k, 10 + \strlen(__DIR__)); - } - } - sort($match); - - $this->assertSame(array('one/.dot', 'one/a', 'one/b', 'one/b/c.neon', 'one/b/d.neon'), $match); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/CustomFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/CustomFilterIteratorTest.php deleted file mode 100644 index b036ad1..0000000 --- a/vendor/symfony/finder/Tests/Iterator/CustomFilterIteratorTest.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Iterator\CustomFilterIterator; - -class CustomFilterIteratorTest extends IteratorTestCase -{ - /** - * @expectedException \InvalidArgumentException - */ - public function testWithInvalidFilter() - { - new CustomFilterIterator(new Iterator(), array('foo')); - } - - /** - * @dataProvider getAcceptData - */ - public function testAccept($filters, $expected) - { - $inner = new Iterator(array('test.php', 'test.py', 'foo.php')); - - $iterator = new CustomFilterIterator($inner, $filters); - - $this->assertIterator($expected, $iterator); - } - - public function getAcceptData() - { - return array( - array(array(function (\SplFileInfo $fileinfo) { return false; }), array()), - array(array(function (\SplFileInfo $fileinfo) { return 0 === strpos($fileinfo, 'test'); }), array('test.php', 'test.py')), - array(array('is_dir'), array()), - ); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/DateRangeFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/DateRangeFilterIteratorTest.php deleted file mode 100644 index 3226f70..0000000 --- a/vendor/symfony/finder/Tests/Iterator/DateRangeFilterIteratorTest.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Comparator\DateComparator; -use Symfony\Component\Finder\Iterator\DateRangeFilterIterator; - -class DateRangeFilterIteratorTest extends RealIteratorTestCase -{ - /** - * @dataProvider getAcceptData - */ - public function testAccept($size, $expected) - { - $files = self::$files; - $files[] = self::toAbsolute('doesnotexist'); - $inner = new Iterator($files); - - $iterator = new DateRangeFilterIterator($inner, $size); - - $this->assertIterator($expected, $iterator); - } - - public function getAcceptData() - { - $since20YearsAgo = array( - '.git', - 'test.py', - 'foo', - 'foo/bar.tmp', - 'test.php', - 'toto', - 'toto/.git', - '.bar', - '.foo', - '.foo/.bar', - 'foo bar', - '.foo/bar', - ); - - $since2MonthsAgo = array( - '.git', - 'test.py', - 'foo', - 'toto', - 'toto/.git', - '.bar', - '.foo', - '.foo/.bar', - 'foo bar', - '.foo/bar', - ); - - $untilLastMonth = array( - 'foo/bar.tmp', - 'test.php', - ); - - return array( - array(array(new DateComparator('since 20 years ago')), $this->toAbsolute($since20YearsAgo)), - array(array(new DateComparator('since 2 months ago')), $this->toAbsolute($since2MonthsAgo)), - array(array(new DateComparator('until last month')), $this->toAbsolute($untilLastMonth)), - ); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/DepthRangeFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/DepthRangeFilterIteratorTest.php deleted file mode 100644 index 2e90140..0000000 --- a/vendor/symfony/finder/Tests/Iterator/DepthRangeFilterIteratorTest.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator; - -class DepthRangeFilterIteratorTest extends RealIteratorTestCase -{ - /** - * @dataProvider getAcceptData - */ - public function testAccept($minDepth, $maxDepth, $expected) - { - $inner = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->toAbsolute(), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST); - - $iterator = new DepthRangeFilterIterator($inner, $minDepth, $maxDepth); - - $actual = array_keys(iterator_to_array($iterator)); - sort($expected); - sort($actual); - $this->assertEquals($expected, $actual); - } - - public function getAcceptData() - { - $lessThan1 = array( - '.git', - 'test.py', - 'foo', - 'test.php', - 'toto', - '.foo', - '.bar', - 'foo bar', - ); - - $lessThanOrEqualTo1 = array( - '.git', - 'test.py', - 'foo', - 'foo/bar.tmp', - 'test.php', - 'toto', - 'toto/.git', - '.foo', - '.foo/.bar', - '.bar', - 'foo bar', - '.foo/bar', - ); - - $graterThanOrEqualTo1 = array( - 'toto/.git', - 'foo/bar.tmp', - '.foo/.bar', - '.foo/bar', - ); - - $equalTo1 = array( - 'toto/.git', - 'foo/bar.tmp', - '.foo/.bar', - '.foo/bar', - ); - - return array( - array(0, 0, $this->toAbsolute($lessThan1)), - array(0, 1, $this->toAbsolute($lessThanOrEqualTo1)), - array(2, PHP_INT_MAX, array()), - array(1, PHP_INT_MAX, $this->toAbsolute($graterThanOrEqualTo1)), - array(1, 1, $this->toAbsolute($equalTo1)), - ); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php deleted file mode 100644 index fa192c3..0000000 --- a/vendor/symfony/finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator; -use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator; - -class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase -{ - /** - * @dataProvider getAcceptData - */ - public function testAccept($directories, $expected) - { - $inner = new \RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->toAbsolute(), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST); - - $iterator = new ExcludeDirectoryFilterIterator($inner, $directories); - - $this->assertIterator($expected, $iterator); - } - - public function getAcceptData() - { - $foo = array( - '.bar', - '.foo', - '.foo/.bar', - '.foo/bar', - '.git', - 'test.py', - 'test.php', - 'toto', - 'toto/.git', - 'foo bar', - ); - - $fo = array( - '.bar', - '.foo', - '.foo/.bar', - '.foo/bar', - '.git', - 'test.py', - 'foo', - 'foo/bar.tmp', - 'test.php', - 'toto', - 'toto/.git', - 'foo bar', - ); - - $toto = array( - '.bar', - '.foo', - '.foo/.bar', - '.foo/bar', - '.git', - 'test.py', - 'foo', - 'foo/bar.tmp', - 'test.php', - 'foo bar', - ); - - return array( - array(array('foo'), $this->toAbsolute($foo)), - array(array('fo'), $this->toAbsolute($fo)), - array(array('toto/'), $this->toAbsolute($toto)), - ); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/FileTypeFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/FileTypeFilterIteratorTest.php deleted file mode 100644 index 4350b00..0000000 --- a/vendor/symfony/finder/Tests/Iterator/FileTypeFilterIteratorTest.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Iterator\FileTypeFilterIterator; - -class FileTypeFilterIteratorTest extends RealIteratorTestCase -{ - /** - * @dataProvider getAcceptData - */ - public function testAccept($mode, $expected) - { - $inner = new InnerTypeIterator(self::$files); - - $iterator = new FileTypeFilterIterator($inner, $mode); - - $this->assertIterator($expected, $iterator); - } - - public function getAcceptData() - { - $onlyFiles = array( - 'test.py', - 'foo/bar.tmp', - 'test.php', - '.bar', - '.foo/.bar', - '.foo/bar', - 'foo bar', - ); - - $onlyDirectories = array( - '.git', - 'foo', - 'toto', - 'toto/.git', - '.foo', - ); - - return array( - array(FileTypeFilterIterator::ONLY_FILES, $this->toAbsolute($onlyFiles)), - array(FileTypeFilterIterator::ONLY_DIRECTORIES, $this->toAbsolute($onlyDirectories)), - ); - } -} - -class InnerTypeIterator extends \ArrayIterator -{ - public function current() - { - return new \SplFileInfo(parent::current()); - } - - public function isFile() - { - return $this->current()->isFile(); - } - - public function isDir() - { - return $this->current()->isDir(); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/FilecontentFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/FilecontentFilterIteratorTest.php deleted file mode 100644 index 744bdae..0000000 --- a/vendor/symfony/finder/Tests/Iterator/FilecontentFilterIteratorTest.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Iterator\FilecontentFilterIterator; - -class FilecontentFilterIteratorTest extends IteratorTestCase -{ - public function testAccept() - { - $inner = new MockFileListIterator(array('test.txt')); - $iterator = new FilecontentFilterIterator($inner, array(), array()); - $this->assertIterator(array('test.txt'), $iterator); - } - - public function testDirectory() - { - $inner = new MockFileListIterator(array('directory')); - $iterator = new FilecontentFilterIterator($inner, array('directory'), array()); - $this->assertIterator(array(), $iterator); - } - - public function testUnreadableFile() - { - $inner = new MockFileListIterator(array('file r-')); - $iterator = new FilecontentFilterIterator($inner, array('file r-'), array()); - $this->assertIterator(array(), $iterator); - } - - /** - * @dataProvider getTestFilterData - */ - public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray) - { - $iterator = new FilecontentFilterIterator($inner, $matchPatterns, $noMatchPatterns); - $this->assertIterator($resultArray, $iterator); - } - - public function getTestFilterData() - { - $inner = new MockFileListIterator(); - - $inner[] = new MockSplFileInfo(array( - 'name' => 'a.txt', - 'contents' => 'Lorem ipsum...', - 'type' => 'file', - 'mode' => 'r+', ) - ); - - $inner[] = new MockSplFileInfo(array( - 'name' => 'b.yml', - 'contents' => 'dolor sit...', - 'type' => 'file', - 'mode' => 'r+', ) - ); - - $inner[] = new MockSplFileInfo(array( - 'name' => 'some/other/dir/third.php', - 'contents' => 'amet...', - 'type' => 'file', - 'mode' => 'r+', ) - ); - - $inner[] = new MockSplFileInfo(array( - 'name' => 'unreadable-file.txt', - 'contents' => false, - 'type' => 'file', - 'mode' => 'r+', ) - ); - - return array( - array($inner, array('.'), array(), array('a.txt', 'b.yml', 'some/other/dir/third.php')), - array($inner, array('ipsum'), array(), array('a.txt')), - array($inner, array('i', 'amet'), array('Lorem', 'amet'), array('b.yml')), - ); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/FilenameFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/FilenameFilterIteratorTest.php deleted file mode 100644 index c4b9795..0000000 --- a/vendor/symfony/finder/Tests/Iterator/FilenameFilterIteratorTest.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Iterator\FilenameFilterIterator; - -class FilenameFilterIteratorTest extends IteratorTestCase -{ - /** - * @dataProvider getAcceptData - */ - public function testAccept($matchPatterns, $noMatchPatterns, $expected) - { - $inner = new InnerNameIterator(array('test.php', 'test.py', 'foo.php')); - - $iterator = new FilenameFilterIterator($inner, $matchPatterns, $noMatchPatterns); - - $this->assertIterator($expected, $iterator); - } - - public function getAcceptData() - { - return array( - array(array('test.*'), array(), array('test.php', 'test.py')), - array(array(), array('test.*'), array('foo.php')), - array(array('*.php'), array('test.*'), array('foo.php')), - array(array('*.php', '*.py'), array('foo.*'), array('test.php', 'test.py')), - array(array('/\.php$/'), array(), array('test.php', 'foo.php')), - array(array(), array('/\.php$/'), array('test.py')), - ); - } -} - -class InnerNameIterator extends \ArrayIterator -{ - public function current() - { - return new \SplFileInfo(parent::current()); - } - - public function getFilename() - { - return parent::current(); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/FilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/FilterIteratorTest.php deleted file mode 100644 index 8b1a448..0000000 --- a/vendor/symfony/finder/Tests/Iterator/FilterIteratorTest.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -/** - * @author Alex Bogomazov - * - * @group legacy - */ -class FilterIteratorTest extends RealIteratorTestCase -{ - public function testFilterFilesystemIterators() - { - $i = new \FilesystemIterator($this->toAbsolute()); - - // it is expected that there are test.py test.php in the tmpDir - $i = $this->getMockForAbstractClass('Symfony\Component\Finder\Iterator\FilterIterator', array($i)); - $i->expects($this->any()) - ->method('accept') - ->will($this->returnCallback(function () use ($i) { - return (bool) preg_match('/\.php/', (string) $i->current()); - }) - ); - - $c = 0; - foreach ($i as $item) { - ++$c; - } - - $this->assertEquals(1, $c); - - $i->rewind(); - - $c = 0; - foreach ($i as $item) { - ++$c; - } - - // This would fail in php older than 5.5.23/5.6.7 with \FilterIterator - // but works with Symfony\Component\Finder\Iterator\FilterIterator - // see https://bugs.php.net/68557 - $this->assertEquals(1, $c); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/Iterator.php b/vendor/symfony/finder/Tests/Iterator/Iterator.php deleted file mode 100644 index 849bf08..0000000 --- a/vendor/symfony/finder/Tests/Iterator/Iterator.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -class Iterator implements \Iterator -{ - protected $values = array(); - - public function __construct(array $values = array()) - { - foreach ($values as $value) { - $this->attach(new \SplFileInfo($value)); - } - $this->rewind(); - } - - public function attach(\SplFileInfo $fileinfo) - { - $this->values[] = $fileinfo; - } - - public function rewind() - { - reset($this->values); - } - - public function valid() - { - return false !== $this->current(); - } - - public function next() - { - next($this->values); - } - - public function current() - { - return current($this->values); - } - - public function key() - { - return key($this->values); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/IteratorTestCase.php b/vendor/symfony/finder/Tests/Iterator/IteratorTestCase.php deleted file mode 100644 index 89f042a..0000000 --- a/vendor/symfony/finder/Tests/Iterator/IteratorTestCase.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use PHPUnit\Framework\TestCase; - -abstract class IteratorTestCase extends TestCase -{ - protected function assertIterator($expected, \Traversable $iterator) - { - // set iterator_to_array $use_key to false to avoid values merge - // this made FinderTest::testAppendWithAnArray() fail with GnuFinderAdapter - $values = array_map(function (\SplFileInfo $fileinfo) { return str_replace('/', \DIRECTORY_SEPARATOR, $fileinfo->getPathname()); }, iterator_to_array($iterator, false)); - - $expected = array_map(function ($path) { return str_replace('/', \DIRECTORY_SEPARATOR, $path); }, $expected); - - sort($values); - sort($expected); - - $this->assertEquals($expected, array_values($values)); - } - - protected function assertOrderedIterator($expected, \Traversable $iterator) - { - $values = array_map(function (\SplFileInfo $fileinfo) { return $fileinfo->getPathname(); }, iterator_to_array($iterator)); - - $this->assertEquals($expected, array_values($values)); - } - - /** - * Same as assertOrderedIterator, but checks the order of groups of - * array elements. - * - * @param array $expected - an array of arrays. For any two subarrays - * $a and $b such that $a goes before $b in $expected, the method - * asserts that any element of $a goes before any element of $b - * in the sequence generated by $iterator - * @param \Traversable $iterator - */ - protected function assertOrderedIteratorForGroups($expected, \Traversable $iterator) - { - $values = array_values(array_map(function (\SplFileInfo $fileinfo) { return $fileinfo->getPathname(); }, iterator_to_array($iterator))); - - foreach ($expected as $subarray) { - $temp = array(); - while (\count($values) && \count($temp) < \count($subarray)) { - $temp[] = array_shift($values); - } - sort($temp); - sort($subarray); - $this->assertEquals($subarray, $temp); - } - } - - /** - * Same as IteratorTestCase::assertIterator with foreach usage. - * - * @param array $expected - * @param \Traversable $iterator - */ - protected function assertIteratorInForeach($expected, \Traversable $iterator) - { - $values = array(); - foreach ($iterator as $file) { - $this->assertInstanceOf('Symfony\\Component\\Finder\\SplFileInfo', $file); - $values[] = $file->getPathname(); - } - - sort($values); - sort($expected); - - $this->assertEquals($expected, array_values($values)); - } - - /** - * Same as IteratorTestCase::assertOrderedIterator with foreach usage. - * - * @param array $expected - * @param \Traversable $iterator - */ - protected function assertOrderedIteratorInForeach($expected, \Traversable $iterator) - { - $values = array(); - foreach ($iterator as $file) { - $this->assertInstanceOf('Symfony\\Component\\Finder\\SplFileInfo', $file); - $values[] = $file->getPathname(); - } - - $this->assertEquals($expected, array_values($values)); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/MockFileListIterator.php b/vendor/symfony/finder/Tests/Iterator/MockFileListIterator.php deleted file mode 100644 index eb0adfa..0000000 --- a/vendor/symfony/finder/Tests/Iterator/MockFileListIterator.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -class MockFileListIterator extends \ArrayIterator -{ - public function __construct(array $filesArray = array()) - { - $files = array_map(function ($file) { return new MockSplFileInfo($file); }, $filesArray); - parent::__construct($files); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/MockSplFileInfo.php b/vendor/symfony/finder/Tests/Iterator/MockSplFileInfo.php deleted file mode 100644 index 36e6528..0000000 --- a/vendor/symfony/finder/Tests/Iterator/MockSplFileInfo.php +++ /dev/null @@ -1,132 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -class MockSplFileInfo extends \SplFileInfo -{ - const TYPE_DIRECTORY = 1; - const TYPE_FILE = 2; - const TYPE_UNKNOWN = 3; - - private $contents = null; - private $mode = null; - private $type = null; - private $relativePath = null; - private $relativePathname = null; - - public function __construct($param) - { - if (\is_string($param)) { - parent::__construct($param); - } elseif (\is_array($param)) { - $defaults = array( - 'name' => 'file.txt', - 'contents' => null, - 'mode' => null, - 'type' => null, - 'relativePath' => null, - 'relativePathname' => null, - ); - $defaults = array_merge($defaults, $param); - parent::__construct($defaults['name']); - $this->setContents($defaults['contents']); - $this->setMode($defaults['mode']); - $this->setType($defaults['type']); - $this->setRelativePath($defaults['relativePath']); - $this->setRelativePathname($defaults['relativePathname']); - } else { - throw new \RuntimeException(sprintf('Incorrect parameter "%s"', $param)); - } - } - - public function isFile() - { - if (null === $this->type) { - return false !== strpos($this->getFilename(), 'file'); - } - - return self::TYPE_FILE === $this->type; - } - - public function isDir() - { - if (null === $this->type) { - return false !== strpos($this->getFilename(), 'directory'); - } - - return self::TYPE_DIRECTORY === $this->type; - } - - public function isReadable() - { - if (null === $this->mode) { - return preg_match('/r\+/', $this->getFilename()); - } - - return preg_match('/r\+/', $this->mode); - } - - public function getContents() - { - return $this->contents; - } - - public function setContents($contents) - { - $this->contents = $contents; - } - - public function setMode($mode) - { - $this->mode = $mode; - } - - public function setType($type) - { - if (\is_string($type)) { - switch ($type) { - case 'directory': - case 'd': - $this->type = self::TYPE_DIRECTORY; - break; - case 'file': - case 'f': - $this->type = self::TYPE_FILE; - break; - default: - $this->type = self::TYPE_UNKNOWN; - } - } else { - $this->type = $type; - } - } - - public function setRelativePath($relativePath) - { - $this->relativePath = $relativePath; - } - - public function setRelativePathname($relativePathname) - { - $this->relativePathname = $relativePathname; - } - - public function getRelativePath() - { - return $this->relativePath; - } - - public function getRelativePathname() - { - return $this->relativePathname; - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php deleted file mode 100644 index f2c1cd2..0000000 --- a/vendor/symfony/finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php +++ /dev/null @@ -1,71 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Finder\Iterator\MultiplePcreFilterIterator; - -class MultiplePcreFilterIteratorTest extends TestCase -{ - /** - * @dataProvider getIsRegexFixtures - */ - public function testIsRegex($string, $isRegex, $message) - { - $testIterator = new TestMultiplePcreFilterIterator(); - $this->assertEquals($isRegex, $testIterator->isRegex($string), $message); - } - - public function getIsRegexFixtures() - { - return array( - array('foo', false, 'string'), - array(' foo ', false, '" " is not a valid delimiter'), - array('\\foo\\', false, '"\\" is not a valid delimiter'), - array('afooa', false, '"a" is not a valid delimiter'), - array('//', false, 'the pattern should contain at least 1 character'), - array('/a/', true, 'valid regex'), - array('/foo/', true, 'valid regex'), - array('/foo/i', true, 'valid regex with a single modifier'), - array('/foo/imsxu', true, 'valid regex with multiple modifiers'), - array('#foo#', true, '"#" is a valid delimiter'), - array('{foo}', true, '"{,}" is a valid delimiter pair'), - array('[foo]', true, '"[,]" is a valid delimiter pair'), - array('(foo)', true, '"(,)" is a valid delimiter pair'), - array('<foo>', true, '"<,>" is a valid delimiter pair'), - array('*foo.*', false, '"*" is not considered as a valid delimiter'), - array('?foo.?', false, '"?" is not considered as a valid delimiter'), - ); - } -} - -class TestMultiplePcreFilterIterator extends MultiplePcreFilterIterator -{ - public function __construct() - { - } - - public function accept() - { - throw new \BadFunctionCallException('Not implemented'); - } - - public function isRegex($str) - { - return parent::isRegex($str); - } - - public function toRegex($str) - { - throw new \BadFunctionCallException('Not implemented'); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/PathFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/PathFilterIteratorTest.php deleted file mode 100644 index 38ed966..0000000 --- a/vendor/symfony/finder/Tests/Iterator/PathFilterIteratorTest.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Iterator\PathFilterIterator; - -class PathFilterIteratorTest extends IteratorTestCase -{ - /** - * @dataProvider getTestFilterData - */ - public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray) - { - $iterator = new PathFilterIterator($inner, $matchPatterns, $noMatchPatterns); - $this->assertIterator($resultArray, $iterator); - } - - public function getTestFilterData() - { - $inner = new MockFileListIterator(); - - //PATH: A/B/C/abc.dat - $inner[] = new MockSplFileInfo(array( - 'name' => 'abc.dat', - 'relativePathname' => 'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C'.\DIRECTORY_SEPARATOR.'abc.dat', - )); - - //PATH: A/B/ab.dat - $inner[] = new MockSplFileInfo(array( - 'name' => 'ab.dat', - 'relativePathname' => 'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'ab.dat', - )); - - //PATH: A/a.dat - $inner[] = new MockSplFileInfo(array( - 'name' => 'a.dat', - 'relativePathname' => 'A'.\DIRECTORY_SEPARATOR.'a.dat', - )); - - //PATH: copy/A/B/C/abc.dat.copy - $inner[] = new MockSplFileInfo(array( - 'name' => 'abc.dat.copy', - 'relativePathname' => 'copy'.\DIRECTORY_SEPARATOR.'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'C'.\DIRECTORY_SEPARATOR.'abc.dat', - )); - - //PATH: copy/A/B/ab.dat.copy - $inner[] = new MockSplFileInfo(array( - 'name' => 'ab.dat.copy', - 'relativePathname' => 'copy'.\DIRECTORY_SEPARATOR.'A'.\DIRECTORY_SEPARATOR.'B'.\DIRECTORY_SEPARATOR.'ab.dat', - )); - - //PATH: copy/A/a.dat.copy - $inner[] = new MockSplFileInfo(array( - 'name' => 'a.dat.copy', - 'relativePathname' => 'copy'.\DIRECTORY_SEPARATOR.'A'.\DIRECTORY_SEPARATOR.'a.dat', - )); - - return array( - array($inner, array('/^A/'), array(), array('abc.dat', 'ab.dat', 'a.dat')), - array($inner, array('/^A\/B/'), array(), array('abc.dat', 'ab.dat')), - array($inner, array('/^A\/B\/C/'), array(), array('abc.dat')), - array($inner, array('/A\/B\/C/'), array(), array('abc.dat', 'abc.dat.copy')), - - array($inner, array('A'), array(), array('abc.dat', 'ab.dat', 'a.dat', 'abc.dat.copy', 'ab.dat.copy', 'a.dat.copy')), - array($inner, array('A/B'), array(), array('abc.dat', 'ab.dat', 'abc.dat.copy', 'ab.dat.copy')), - array($inner, array('A/B/C'), array(), array('abc.dat', 'abc.dat.copy')), - - array($inner, array('copy/A'), array(), array('abc.dat.copy', 'ab.dat.copy', 'a.dat.copy')), - array($inner, array('copy/A/B'), array(), array('abc.dat.copy', 'ab.dat.copy')), - array($inner, array('copy/A/B/C'), array(), array('abc.dat.copy')), - ); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php b/vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php deleted file mode 100644 index b0223b7..0000000 --- a/vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -abstract class RealIteratorTestCase extends IteratorTestCase -{ - protected static $tmpDir; - protected static $files; - - public static function setUpBeforeClass() - { - self::$tmpDir = realpath(sys_get_temp_dir()).\DIRECTORY_SEPARATOR.'symfony_finder'; - - self::$files = array( - '.git/', - '.foo/', - '.foo/.bar', - '.foo/bar', - '.bar', - 'test.py', - 'foo/', - 'foo/bar.tmp', - 'test.php', - 'toto/', - 'toto/.git/', - 'foo bar', - ); - - self::$files = self::toAbsolute(self::$files); - - if (is_dir(self::$tmpDir)) { - self::tearDownAfterClass(); - } else { - mkdir(self::$tmpDir); - } - - foreach (self::$files as $file) { - if (\DIRECTORY_SEPARATOR === $file[\strlen($file) - 1]) { - mkdir($file); - } else { - touch($file); - } - } - - file_put_contents(self::toAbsolute('test.php'), str_repeat(' ', 800)); - file_put_contents(self::toAbsolute('test.py'), str_repeat(' ', 2000)); - - touch(self::toAbsolute('foo/bar.tmp'), strtotime('2005-10-15')); - touch(self::toAbsolute('test.php'), strtotime('2005-10-15')); - } - - public static function tearDownAfterClass() - { - $paths = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator(self::$tmpDir, \RecursiveDirectoryIterator::SKIP_DOTS), - \RecursiveIteratorIterator::CHILD_FIRST - ); - - foreach ($paths as $path) { - if ($path->isDir()) { - if ($path->isLink()) { - @unlink($path); - } else { - @rmdir($path); - } - } else { - @unlink($path); - } - } - } - - protected static function toAbsolute($files = null) - { - /* - * Without the call to setUpBeforeClass() property can be null. - */ - if (!self::$tmpDir) { - self::$tmpDir = realpath(sys_get_temp_dir()).\DIRECTORY_SEPARATOR.'symfony_finder'; - } - - if (\is_array($files)) { - $f = array(); - foreach ($files as $file) { - if (\is_array($file)) { - $f[] = self::toAbsolute($file); - } else { - $f[] = self::$tmpDir.\DIRECTORY_SEPARATOR.str_replace('/', \DIRECTORY_SEPARATOR, $file); - } - } - - return $f; - } - - if (\is_string($files)) { - return self::$tmpDir.\DIRECTORY_SEPARATOR.str_replace('/', \DIRECTORY_SEPARATOR, $files); - } - - return self::$tmpDir; - } - - protected static function toAbsoluteFixtures($files) - { - $f = array(); - foreach ($files as $file) { - $f[] = realpath(__DIR__.\DIRECTORY_SEPARATOR.'..'.\DIRECTORY_SEPARATOR.'Fixtures'.\DIRECTORY_SEPARATOR.$file); - } - - return $f; - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php deleted file mode 100644 index 0c9aca2..0000000 --- a/vendor/symfony/finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator; - -class RecursiveDirectoryIteratorTest extends IteratorTestCase -{ - /** - * @group network - */ - public function testRewindOnFtp() - { - try { - $i = new RecursiveDirectoryIterator('ftp://speedtest.tele2.net/', \RecursiveDirectoryIterator::SKIP_DOTS); - } catch (\UnexpectedValueException $e) { - $this->markTestSkipped('Unsupported stream "ftp".'); - } - - $i->rewind(); - - $this->assertTrue(true); - } - - /** - * @group network - */ - public function testSeekOnFtp() - { - try { - $i = new RecursiveDirectoryIterator('ftp://speedtest.tele2.net/', \RecursiveDirectoryIterator::SKIP_DOTS); - } catch (\UnexpectedValueException $e) { - $this->markTestSkipped('Unsupported stream "ftp".'); - } - - $contains = array( - 'ftp://speedtest.tele2.net'.\DIRECTORY_SEPARATOR.'1000GB.zip', - 'ftp://speedtest.tele2.net'.\DIRECTORY_SEPARATOR.'100GB.zip', - ); - $actual = array(); - - $i->seek(0); - $actual[] = $i->getPathname(); - - $i->seek(1); - $actual[] = $i->getPathname(); - - $this->assertEquals($contains, $actual); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/SizeRangeFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/SizeRangeFilterIteratorTest.php deleted file mode 100644 index 068fc7b..0000000 --- a/vendor/symfony/finder/Tests/Iterator/SizeRangeFilterIteratorTest.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Comparator\NumberComparator; -use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator; - -class SizeRangeFilterIteratorTest extends RealIteratorTestCase -{ - /** - * @dataProvider getAcceptData - */ - public function testAccept($size, $expected) - { - $inner = new InnerSizeIterator(self::$files); - - $iterator = new SizeRangeFilterIterator($inner, $size); - - $this->assertIterator($expected, $iterator); - } - - public function getAcceptData() - { - $lessThan1KGreaterThan05K = array( - '.foo', - '.git', - 'foo', - 'test.php', - 'toto', - 'toto/.git', - ); - - return array( - array(array(new NumberComparator('< 1K'), new NumberComparator('> 0.5K')), $this->toAbsolute($lessThan1KGreaterThan05K)), - ); - } -} - -class InnerSizeIterator extends \ArrayIterator -{ - public function current() - { - return new \SplFileInfo(parent::current()); - } - - public function getFilename() - { - return parent::current(); - } - - public function isFile() - { - return $this->current()->isFile(); - } - - public function getSize() - { - return $this->current()->getSize(); - } -} diff --git a/vendor/symfony/finder/Tests/Iterator/SortableIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/SortableIteratorTest.php deleted file mode 100644 index a35a12b..0000000 --- a/vendor/symfony/finder/Tests/Iterator/SortableIteratorTest.php +++ /dev/null @@ -1,183 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -use Symfony\Component\Finder\Iterator\SortableIterator; - -class SortableIteratorTest extends RealIteratorTestCase -{ - public function testConstructor() - { - try { - new SortableIterator(new Iterator(array()), 'foobar'); - $this->fail('__construct() throws an \InvalidArgumentException exception if the mode is not valid'); - } catch (\Exception $e) { - $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException exception if the mode is not valid'); - } - } - - /** - * @dataProvider getAcceptData - */ - public function testAccept($mode, $expected) - { - if (!\is_callable($mode)) { - switch ($mode) { - case SortableIterator::SORT_BY_ACCESSED_TIME: - if ('\\' === \DIRECTORY_SEPARATOR) { - touch(self::toAbsolute('.git')); - } else { - file_get_contents(self::toAbsolute('.git')); - } - sleep(1); - file_get_contents(self::toAbsolute('.bar')); - break; - case SortableIterator::SORT_BY_CHANGED_TIME: - file_put_contents(self::toAbsolute('test.php'), 'foo'); - sleep(1); - file_put_contents(self::toAbsolute('test.py'), 'foo'); - break; - case SortableIterator::SORT_BY_MODIFIED_TIME: - file_put_contents(self::toAbsolute('test.php'), 'foo'); - sleep(1); - file_put_contents(self::toAbsolute('test.py'), 'foo'); - break; - } - } - - $inner = new Iterator(self::$files); - - $iterator = new SortableIterator($inner, $mode); - - if (SortableIterator::SORT_BY_ACCESSED_TIME === $mode - || SortableIterator::SORT_BY_CHANGED_TIME === $mode - || SortableIterator::SORT_BY_MODIFIED_TIME === $mode - ) { - if ('\\' === \DIRECTORY_SEPARATOR && SortableIterator::SORT_BY_MODIFIED_TIME !== $mode) { - $this->markTestSkipped('Sorting by atime or ctime is not supported on Windows'); - } - $this->assertOrderedIteratorForGroups($expected, $iterator); - } else { - $this->assertOrderedIterator($expected, $iterator); - } - } - - public function getAcceptData() - { - $sortByName = array( - '.bar', - '.foo', - '.foo/.bar', - '.foo/bar', - '.git', - 'foo', - 'foo bar', - 'foo/bar.tmp', - 'test.php', - 'test.py', - 'toto', - 'toto/.git', - ); - - $sortByType = array( - '.foo', - '.git', - 'foo', - 'toto', - 'toto/.git', - '.bar', - '.foo/.bar', - '.foo/bar', - 'foo bar', - 'foo/bar.tmp', - 'test.php', - 'test.py', - ); - - $customComparison = array( - '.bar', - '.foo', - '.foo/.bar', - '.foo/bar', - '.git', - 'foo', - 'foo bar', - 'foo/bar.tmp', - 'test.php', - 'test.py', - 'toto', - 'toto/.git', - ); - - $sortByAccessedTime = array( - // For these two files the access time was set to 2005-10-15 - array('foo/bar.tmp', 'test.php'), - // These files were created more or less at the same time - array( - '.git', - '.foo', - '.foo/.bar', - '.foo/bar', - 'test.py', - 'foo', - 'toto', - 'toto/.git', - 'foo bar', - ), - // This file was accessed after sleeping for 1 sec - array('.bar'), - ); - - $sortByChangedTime = array( - array( - '.git', - '.foo', - '.foo/.bar', - '.foo/bar', - '.bar', - 'foo', - 'foo/bar.tmp', - 'toto', - 'toto/.git', - 'foo bar', - ), - array('test.php'), - array('test.py'), - ); - - $sortByModifiedTime = array( - array( - '.git', - '.foo', - '.foo/.bar', - '.foo/bar', - '.bar', - 'foo', - 'foo/bar.tmp', - 'toto', - 'toto/.git', - 'foo bar', - ), - array('test.php'), - array('test.py'), - ); - - return array( - array(SortableIterator::SORT_BY_NAME, $this->toAbsolute($sortByName)), - array(SortableIterator::SORT_BY_TYPE, $this->toAbsolute($sortByType)), - array(SortableIterator::SORT_BY_ACCESSED_TIME, $this->toAbsolute($sortByAccessedTime)), - array(SortableIterator::SORT_BY_CHANGED_TIME, $this->toAbsolute($sortByChangedTime)), - array(SortableIterator::SORT_BY_MODIFIED_TIME, $this->toAbsolute($sortByModifiedTime)), - array(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealPath(), $b->getRealPath()); }, $this->toAbsolute($customComparison)), - ); - } -} diff --git a/vendor/symfony/finder/composer.json b/vendor/symfony/finder/composer.json index de19826..ef19911 100644 --- a/vendor/symfony/finder/composer.json +++ b/vendor/symfony/finder/composer.json @@ -1,7 +1,7 @@ { "name": "symfony/finder", "type": "library", - "description": "Symfony Finder Component", + "description": "Finds files and directories via an intuitive fluent interface", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", @@ -16,7 +16,9 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" }, "autoload": { "psr-4": { "Symfony\\Component\\Finder\\": "" }, @@ -24,10 +26,5 @@ "/Tests/" ] }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - } + "minimum-stability": "dev" } diff --git a/vendor/symfony/finder/phpunit.xml.dist b/vendor/symfony/finder/phpunit.xml.dist deleted file mode 100644 index 0e1a866..0000000 --- a/vendor/symfony/finder/phpunit.xml.dist +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" - backupGlobals="false" - colors="true" - bootstrap="vendor/autoload.php" - failOnRisky="true" - failOnWarning="true" -> - <php> - <ini name="error_reporting" value="-1" /> - </php> - - <testsuites> - <testsuite name="Symfony Finder Component Test Suite"> - <directory>./Tests/</directory> - </testsuite> - </testsuites> - - <filter> - <whitelist> - <directory>./</directory> - <exclude> - <directory>./Tests</directory> - <directory>./vendor</directory> - </exclude> - </whitelist> - </filter> -</phpunit> diff --git a/vendor/symfony/options-resolver/CHANGELOG.md b/vendor/symfony/options-resolver/CHANGELOG.md new file mode 100644 index 0000000..84c4594 --- /dev/null +++ b/vendor/symfony/options-resolver/CHANGELOG.md @@ -0,0 +1,81 @@ +CHANGELOG +========= + +5.3 +--- + + * Add prototype definition for nested options + +5.1.0 +----- + + * added fluent configuration of options using `OptionResolver::define()` + * added `setInfo()` and `getInfo()` methods + * updated the signature of method `OptionsResolver::setDeprecated()` to `OptionsResolver::setDeprecation(string $option, string $package, string $version, $message)` + * deprecated `OptionsResolverIntrospector::getDeprecationMessage()`, use `OptionsResolverIntrospector::getDeprecation()` instead + +5.0.0 +----- + + * added argument `$triggerDeprecation` to `OptionsResolver::offsetGet()` + +4.3.0 +----- + + * added `OptionsResolver::addNormalizer` method + +4.2.0 +----- + + * added support for nested options definition + * added `setDeprecated` and `isDeprecated` methods + +3.4.0 +----- + + * added `OptionsResolverIntrospector` to inspect options definitions inside an `OptionsResolver` instance + * added array of types support in allowed types (e.g int[]) + +2.6.0 +----- + + * deprecated OptionsResolverInterface + * [BC BREAK] removed "array" type hint from OptionsResolverInterface methods + setRequired(), setAllowedValues(), addAllowedValues(), setAllowedTypes() and + addAllowedTypes() + * added OptionsResolver::setDefault() + * added OptionsResolver::hasDefault() + * added OptionsResolver::setNormalizer() + * added OptionsResolver::isRequired() + * added OptionsResolver::getRequiredOptions() + * added OptionsResolver::isMissing() + * added OptionsResolver::getMissingOptions() + * added OptionsResolver::setDefined() + * added OptionsResolver::isDefined() + * added OptionsResolver::getDefinedOptions() + * added OptionsResolver::remove() + * added OptionsResolver::clear() + * deprecated OptionsResolver::replaceDefaults() + * deprecated OptionsResolver::setOptional() in favor of setDefined() + * deprecated OptionsResolver::isKnown() in favor of isDefined() + * [BC BREAK] OptionsResolver::isRequired() returns true now if a required + option has a default value set + * [BC BREAK] merged Options into OptionsResolver and turned Options into an + interface + * deprecated Options::overload() (now in OptionsResolver) + * deprecated Options::set() (now in OptionsResolver) + * deprecated Options::get() (now in OptionsResolver) + * deprecated Options::has() (now in OptionsResolver) + * deprecated Options::replace() (now in OptionsResolver) + * [BC BREAK] Options::get() (now in OptionsResolver) can only be used within + lazy option/normalizer closures now + * [BC BREAK] removed Traversable interface from Options since using within + lazy option/normalizer closures resulted in exceptions + * [BC BREAK] removed Options::all() since using within lazy option/normalizer + closures resulted in exceptions + * [BC BREAK] OptionDefinitionException now extends LogicException instead of + RuntimeException + * [BC BREAK] normalizers are not executed anymore for unset options + * normalizers are executed after validating the options now + * [BC BREAK] an UndefinedOptionsException is now thrown instead of an + InvalidOptionsException when non-existing options are passed diff --git a/vendor/symfony/options-resolver/Debug/OptionsResolverIntrospector.php b/vendor/symfony/options-resolver/Debug/OptionsResolverIntrospector.php new file mode 100644 index 0000000..95909f3 --- /dev/null +++ b/vendor/symfony/options-resolver/Debug/OptionsResolverIntrospector.php @@ -0,0 +1,120 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Debug; + +use Symfony\Component\OptionsResolver\Exception\NoConfigurationException; +use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException; +use Symfony\Component\OptionsResolver\OptionsResolver; + +/** + * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> + * + * @final + */ +class OptionsResolverIntrospector +{ + private $get; + + public function __construct(OptionsResolver $optionsResolver) + { + $this->get = \Closure::bind(function ($property, $option, $message) { + /** @var OptionsResolver $this */ + if (!$this->isDefined($option)) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist.', $option)); + } + + if (!\array_key_exists($option, $this->{$property})) { + throw new NoConfigurationException($message); + } + + return $this->{$property}[$option]; + }, $optionsResolver, $optionsResolver); + } + + /** + * @return mixed + * + * @throws NoConfigurationException on no configured value + */ + public function getDefault(string $option) + { + return ($this->get)('defaults', $option, sprintf('No default value was set for the "%s" option.', $option)); + } + + /** + * @return \Closure[] + * + * @throws NoConfigurationException on no configured closures + */ + public function getLazyClosures(string $option): array + { + return ($this->get)('lazy', $option, sprintf('No lazy closures were set for the "%s" option.', $option)); + } + + /** + * @return string[] + * + * @throws NoConfigurationException on no configured types + */ + public function getAllowedTypes(string $option): array + { + return ($this->get)('allowedTypes', $option, sprintf('No allowed types were set for the "%s" option.', $option)); + } + + /** + * @return mixed[] + * + * @throws NoConfigurationException on no configured values + */ + public function getAllowedValues(string $option): array + { + return ($this->get)('allowedValues', $option, sprintf('No allowed values were set for the "%s" option.', $option)); + } + + /** + * @throws NoConfigurationException on no configured normalizer + */ + public function getNormalizer(string $option): \Closure + { + return current($this->getNormalizers($option)); + } + + /** + * @throws NoConfigurationException when no normalizer is configured + */ + public function getNormalizers(string $option): array + { + return ($this->get)('normalizers', $option, sprintf('No normalizer was set for the "%s" option.', $option)); + } + + /** + * @return string|\Closure + * + * @throws NoConfigurationException on no configured deprecation + * + * @deprecated since Symfony 5.1, use "getDeprecation()" instead. + */ + public function getDeprecationMessage(string $option) + { + trigger_deprecation('symfony/options-resolver', '5.1', 'The "%s()" method is deprecated, use "getDeprecation()" instead.', __METHOD__); + + return $this->getDeprecation($option)['message']; + } + + /** + * @throws NoConfigurationException on no configured deprecation + */ + public function getDeprecation(string $option): array + { + return ($this->get)('deprecated', $option, sprintf('No deprecation was set for the "%s" option.', $option)); + } +} diff --git a/vendor/symfony/options-resolver/Exception/AccessException.php b/vendor/symfony/options-resolver/Exception/AccessException.php new file mode 100644 index 0000000..c12b680 --- /dev/null +++ b/vendor/symfony/options-resolver/Exception/AccessException.php @@ -0,0 +1,22 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Exception; + +/** + * Thrown when trying to read an option outside of or write it inside of + * {@link \Symfony\Component\OptionsResolver\Options::resolve()}. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class AccessException extends \LogicException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/options-resolver/Exception/ExceptionInterface.php b/vendor/symfony/options-resolver/Exception/ExceptionInterface.php new file mode 100644 index 0000000..ea99d05 --- /dev/null +++ b/vendor/symfony/options-resolver/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Exception; + +/** + * Marker interface for all exceptions thrown by the OptionsResolver component. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +interface ExceptionInterface extends \Throwable +{ +} diff --git a/vendor/symfony/options-resolver/Exception/InvalidArgumentException.php b/vendor/symfony/options-resolver/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..6d421d6 --- /dev/null +++ b/vendor/symfony/options-resolver/Exception/InvalidArgumentException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Exception; + +/** + * Thrown when an argument is invalid. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/options-resolver/Exception/InvalidOptionsException.php b/vendor/symfony/options-resolver/Exception/InvalidOptionsException.php new file mode 100644 index 0000000..6fd4f12 --- /dev/null +++ b/vendor/symfony/options-resolver/Exception/InvalidOptionsException.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Exception; + +/** + * Thrown when the value of an option does not match its validation rules. + * + * You should make sure a valid value is passed to the option. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class InvalidOptionsException extends InvalidArgumentException +{ +} diff --git a/vendor/symfony/options-resolver/Exception/MissingOptionsException.php b/vendor/symfony/options-resolver/Exception/MissingOptionsException.php new file mode 100644 index 0000000..faa487f --- /dev/null +++ b/vendor/symfony/options-resolver/Exception/MissingOptionsException.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Exception; + +/** + * Exception thrown when a required option is missing. + * + * Add the option to the passed options array. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class MissingOptionsException extends InvalidArgumentException +{ +} diff --git a/vendor/symfony/options-resolver/Exception/NoConfigurationException.php b/vendor/symfony/options-resolver/Exception/NoConfigurationException.php new file mode 100644 index 0000000..6693ec1 --- /dev/null +++ b/vendor/symfony/options-resolver/Exception/NoConfigurationException.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Exception; + +use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector; + +/** + * Thrown when trying to introspect an option definition property + * for which no value was configured inside the OptionsResolver instance. + * + * @see OptionsResolverIntrospector + * + * @author Maxime Steinhausser <maxime.steinhausser@gmail.com> + */ +class NoConfigurationException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/options-resolver/Exception/NoSuchOptionException.php b/vendor/symfony/options-resolver/Exception/NoSuchOptionException.php new file mode 100644 index 0000000..4c3280f --- /dev/null +++ b/vendor/symfony/options-resolver/Exception/NoSuchOptionException.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Exception; + +/** + * Thrown when trying to read an option that has no value set. + * + * When accessing optional options from within a lazy option or normalizer you should first + * check whether the optional option is set. You can do this with `isset($options['optional'])`. + * In contrast to the {@link UndefinedOptionsException}, this is a runtime exception that can + * occur when evaluating lazy options. + * + * @author Tobias Schultze <http://tobion.de> + */ +class NoSuchOptionException extends \OutOfBoundsException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/options-resolver/Exception/OptionDefinitionException.php b/vendor/symfony/options-resolver/Exception/OptionDefinitionException.php new file mode 100644 index 0000000..e8e339d --- /dev/null +++ b/vendor/symfony/options-resolver/Exception/OptionDefinitionException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Exception; + +/** + * Thrown when two lazy options have a cyclic dependency. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class OptionDefinitionException extends \LogicException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/options-resolver/Exception/UndefinedOptionsException.php b/vendor/symfony/options-resolver/Exception/UndefinedOptionsException.php new file mode 100644 index 0000000..6ca3fce --- /dev/null +++ b/vendor/symfony/options-resolver/Exception/UndefinedOptionsException.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Exception; + +/** + * Exception thrown when an undefined option is passed. + * + * You should remove the options in question from your code or define them + * beforehand. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class UndefinedOptionsException extends InvalidArgumentException +{ +} diff --git a/vendor/symfony/options-resolver/LICENSE b/vendor/symfony/options-resolver/LICENSE new file mode 100644 index 0000000..0138f8f --- /dev/null +++ b/vendor/symfony/options-resolver/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +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/vendor/symfony/options-resolver/OptionConfigurator.php b/vendor/symfony/options-resolver/OptionConfigurator.php new file mode 100644 index 0000000..62f03d0 --- /dev/null +++ b/vendor/symfony/options-resolver/OptionConfigurator.php @@ -0,0 +1,139 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver; + +use Symfony\Component\OptionsResolver\Exception\AccessException; + +final class OptionConfigurator +{ + private $name; + private $resolver; + + public function __construct(string $name, OptionsResolver $resolver) + { + $this->name = $name; + $this->resolver = $resolver; + $this->resolver->setDefined($name); + } + + /** + * Adds allowed types for this option. + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function allowedTypes(string ...$types): self + { + $this->resolver->setAllowedTypes($this->name, $types); + + return $this; + } + + /** + * Sets allowed values for this option. + * + * @param mixed ...$values One or more acceptable values/closures + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function allowedValues(...$values): self + { + $this->resolver->setAllowedValues($this->name, $values); + + return $this; + } + + /** + * Sets the default value for this option. + * + * @param mixed $value The default value of the option + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function default($value): self + { + $this->resolver->setDefault($this->name, $value); + + return $this; + } + + /** + * Defines an option configurator with the given name. + */ + public function define(string $option): self + { + return $this->resolver->define($option); + } + + /** + * Marks this option as deprecated. + * + * @param string $package The name of the composer package that is triggering the deprecation + * @param string $version The version of the package that introduced the deprecation + * @param string|\Closure $message The deprecation message to use + * + * @return $this + */ + public function deprecated(string $package, string $version, $message = 'The option "%name%" is deprecated.'): self + { + $this->resolver->setDeprecated($this->name, $package, $version, $message); + + return $this; + } + + /** + * Sets the normalizer for this option. + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function normalize(\Closure $normalizer): self + { + $this->resolver->setNormalizer($this->name, $normalizer); + + return $this; + } + + /** + * Marks this option as required. + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function required(): self + { + $this->resolver->setRequired($this->name); + + return $this; + } + + /** + * Sets an info message for an option. + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function info(string $info): self + { + $this->resolver->setInfo($this->name, $info); + + return $this; + } +} diff --git a/vendor/symfony/options-resolver/Options.php b/vendor/symfony/options-resolver/Options.php new file mode 100644 index 0000000..d444ec4 --- /dev/null +++ b/vendor/symfony/options-resolver/Options.php @@ -0,0 +1,22 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver; + +/** + * Contains resolved option values. + * + * @author Bernhard Schussek <bschussek@gmail.com> + * @author Tobias Schultze <http://tobion.de> + */ +interface Options extends \ArrayAccess, \Countable +{ +} diff --git a/vendor/symfony/options-resolver/OptionsResolver.php b/vendor/symfony/options-resolver/OptionsResolver.php new file mode 100644 index 0000000..3db291f --- /dev/null +++ b/vendor/symfony/options-resolver/OptionsResolver.php @@ -0,0 +1,1347 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver; + +use Symfony\Component\OptionsResolver\Exception\AccessException; +use Symfony\Component\OptionsResolver\Exception\InvalidArgumentException; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; +use Symfony\Component\OptionsResolver\Exception\MissingOptionsException; +use Symfony\Component\OptionsResolver\Exception\NoSuchOptionException; +use Symfony\Component\OptionsResolver\Exception\OptionDefinitionException; +use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException; + +/** + * Validates options and merges them with default values. + * + * @author Bernhard Schussek <bschussek@gmail.com> + * @author Tobias Schultze <http://tobion.de> + */ +class OptionsResolver implements Options +{ + private const VALIDATION_FUNCTIONS = [ + 'bool' => 'is_bool', + 'boolean' => 'is_bool', + 'int' => 'is_int', + 'integer' => 'is_int', + 'long' => 'is_int', + 'float' => 'is_float', + 'double' => 'is_float', + 'real' => 'is_float', + 'numeric' => 'is_numeric', + 'string' => 'is_string', + 'scalar' => 'is_scalar', + 'array' => 'is_array', + 'iterable' => 'is_iterable', + 'countable' => 'is_countable', + 'callable' => 'is_callable', + 'object' => 'is_object', + 'resource' => 'is_resource', + ]; + + /** + * The names of all defined options. + */ + private $defined = []; + + /** + * The default option values. + */ + private $defaults = []; + + /** + * A list of closure for nested options. + * + * @var \Closure[][] + */ + private $nested = []; + + /** + * The names of required options. + */ + private $required = []; + + /** + * The resolved option values. + */ + private $resolved = []; + + /** + * A list of normalizer closures. + * + * @var \Closure[][] + */ + private $normalizers = []; + + /** + * A list of accepted values for each option. + */ + private $allowedValues = []; + + /** + * A list of accepted types for each option. + */ + private $allowedTypes = []; + + /** + * A list of info messages for each option. + */ + private $info = []; + + /** + * A list of closures for evaluating lazy options. + */ + private $lazy = []; + + /** + * A list of lazy options whose closure is currently being called. + * + * This list helps detecting circular dependencies between lazy options. + */ + private $calling = []; + + /** + * A list of deprecated options. + */ + private $deprecated = []; + + /** + * The list of options provided by the user. + */ + private $given = []; + + /** + * Whether the instance is locked for reading. + * + * Once locked, the options cannot be changed anymore. This is + * necessary in order to avoid inconsistencies during the resolving + * process. If any option is changed after being read, all evaluated + * lazy options that depend on this option would become invalid. + */ + private $locked = false; + + private $parentsOptions = []; + + /** + * Whether the whole options definition is marked as array prototype. + */ + private $prototype; + + /** + * The prototype array's index that is being read. + */ + private $prototypeIndex; + + /** + * Sets the default value of a given option. + * + * If the default value should be set based on other options, you can pass + * a closure with the following signature: + * + * function (Options $options) { + * // ... + * } + * + * The closure will be evaluated when {@link resolve()} is called. The + * closure has access to the resolved values of other options through the + * passed {@link Options} instance: + * + * function (Options $options) { + * if (isset($options['port'])) { + * // ... + * } + * } + * + * If you want to access the previously set default value, add a second + * argument to the closure's signature: + * + * $options->setDefault('name', 'Default Name'); + * + * $options->setDefault('name', function (Options $options, $previousValue) { + * // 'Default Name' === $previousValue + * }); + * + * This is mostly useful if the configuration of the {@link Options} object + * is spread across different locations of your code, such as base and + * sub-classes. + * + * If you want to define nested options, you can pass a closure with the + * following signature: + * + * $options->setDefault('database', function (OptionsResolver $resolver) { + * $resolver->setDefined(['dbname', 'host', 'port', 'user', 'pass']); + * } + * + * To get access to the parent options, add a second argument to the closure's + * signature: + * + * function (OptionsResolver $resolver, Options $parent) { + * // 'default' === $parent['connection'] + * } + * + * @param string $option The name of the option + * @param mixed $value The default value of the option + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function setDefault(string $option, $value) + { + // Setting is not possible once resolving starts, because then lazy + // options could manipulate the state of the object, leading to + // inconsistent results. + if ($this->locked) { + throw new AccessException('Default values cannot be set from a lazy option or normalizer.'); + } + + // If an option is a closure that should be evaluated lazily, store it + // in the "lazy" property. + if ($value instanceof \Closure) { + $reflClosure = new \ReflectionFunction($value); + $params = $reflClosure->getParameters(); + + if (isset($params[0]) && Options::class === $this->getParameterClassName($params[0])) { + // Initialize the option if no previous value exists + if (!isset($this->defaults[$option])) { + $this->defaults[$option] = null; + } + + // Ignore previous lazy options if the closure has no second parameter + if (!isset($this->lazy[$option]) || !isset($params[1])) { + $this->lazy[$option] = []; + } + + // Store closure for later evaluation + $this->lazy[$option][] = $value; + $this->defined[$option] = true; + + // Make sure the option is processed and is not nested anymore + unset($this->resolved[$option], $this->nested[$option]); + + return $this; + } + + if (isset($params[0]) && null !== ($type = $params[0]->getType()) && self::class === $type->getName() && (!isset($params[1]) || (($type = $params[1]->getType()) instanceof \ReflectionNamedType && Options::class === $type->getName()))) { + // Store closure for later evaluation + $this->nested[$option][] = $value; + $this->defaults[$option] = []; + $this->defined[$option] = true; + + // Make sure the option is processed and is not lazy anymore + unset($this->resolved[$option], $this->lazy[$option]); + + return $this; + } + } + + // This option is not lazy nor nested anymore + unset($this->lazy[$option], $this->nested[$option]); + + // Yet undefined options can be marked as resolved, because we only need + // to resolve options with lazy closures, normalizers or validation + // rules, none of which can exist for undefined options + // If the option was resolved before, update the resolved value + if (!isset($this->defined[$option]) || \array_key_exists($option, $this->resolved)) { + $this->resolved[$option] = $value; + } + + $this->defaults[$option] = $value; + $this->defined[$option] = true; + + return $this; + } + + /** + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function setDefaults(array $defaults) + { + foreach ($defaults as $option => $value) { + $this->setDefault($option, $value); + } + + return $this; + } + + /** + * Returns whether a default value is set for an option. + * + * Returns true if {@link setDefault()} was called for this option. + * An option is also considered set if it was set to null. + * + * @return bool + */ + public function hasDefault(string $option) + { + return \array_key_exists($option, $this->defaults); + } + + /** + * Marks one or more options as required. + * + * @param string|string[] $optionNames One or more option names + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function setRequired($optionNames) + { + if ($this->locked) { + throw new AccessException('Options cannot be made required from a lazy option or normalizer.'); + } + + foreach ((array) $optionNames as $option) { + $this->defined[$option] = true; + $this->required[$option] = true; + } + + return $this; + } + + /** + * Returns whether an option is required. + * + * An option is required if it was passed to {@link setRequired()}. + * + * @return bool + */ + public function isRequired(string $option) + { + return isset($this->required[$option]); + } + + /** + * Returns the names of all required options. + * + * @return string[] + * + * @see isRequired() + */ + public function getRequiredOptions() + { + return array_keys($this->required); + } + + /** + * Returns whether an option is missing a default value. + * + * An option is missing if it was passed to {@link setRequired()}, but not + * to {@link setDefault()}. This option must be passed explicitly to + * {@link resolve()}, otherwise an exception will be thrown. + * + * @return bool + */ + public function isMissing(string $option) + { + return isset($this->required[$option]) && !\array_key_exists($option, $this->defaults); + } + + /** + * Returns the names of all options missing a default value. + * + * @return string[] + */ + public function getMissingOptions() + { + return array_keys(array_diff_key($this->required, $this->defaults)); + } + + /** + * Defines a valid option name. + * + * Defines an option name without setting a default value. The option will + * be accepted when passed to {@link resolve()}. When not passed, the + * option will not be included in the resolved options. + * + * @param string|string[] $optionNames One or more option names + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function setDefined($optionNames) + { + if ($this->locked) { + throw new AccessException('Options cannot be defined from a lazy option or normalizer.'); + } + + foreach ((array) $optionNames as $option) { + $this->defined[$option] = true; + } + + return $this; + } + + /** + * Returns whether an option is defined. + * + * Returns true for any option passed to {@link setDefault()}, + * {@link setRequired()} or {@link setDefined()}. + * + * @return bool + */ + public function isDefined(string $option) + { + return isset($this->defined[$option]); + } + + /** + * Returns the names of all defined options. + * + * @return string[] + * + * @see isDefined() + */ + public function getDefinedOptions() + { + return array_keys($this->defined); + } + + public function isNested(string $option): bool + { + return isset($this->nested[$option]); + } + + /** + * Deprecates an option, allowed types or values. + * + * Instead of passing the message, you may also pass a closure with the + * following signature: + * + * function (Options $options, $value): string { + * // ... + * } + * + * The closure receives the value as argument and should return a string. + * Return an empty string to ignore the option deprecation. + * + * The closure is invoked when {@link resolve()} is called. The parameter + * passed to the closure is the value of the option after validating it + * and before normalizing it. + * + * @param string $package The name of the composer package that is triggering the deprecation + * @param string $version The version of the package that introduced the deprecation + * @param string|\Closure $message The deprecation message to use + * + * @return $this + */ + public function setDeprecated(string $option/* , string $package, string $version, $message = 'The option "%name%" is deprecated.' */): self + { + if ($this->locked) { + throw new AccessException('Options cannot be deprecated from a lazy option or normalizer.'); + } + + if (!isset($this->defined[$option])) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist, defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); + } + + $args = \func_get_args(); + + if (\func_num_args() < 3) { + trigger_deprecation('symfony/options-resolver', '5.1', 'The signature of method "%s()" requires 2 new arguments: "string $package, string $version", not defining them is deprecated.', __METHOD__); + + $message = $args[1] ?? 'The option "%name%" is deprecated.'; + $package = $version = ''; + } else { + $package = $args[1]; + $version = $args[2]; + $message = $args[3] ?? 'The option "%name%" is deprecated.'; + } + + if (!\is_string($message) && !$message instanceof \Closure) { + throw new InvalidArgumentException(sprintf('Invalid type for deprecation message argument, expected string or \Closure, but got "%s".', get_debug_type($message))); + } + + // ignore if empty string + if ('' === $message) { + return $this; + } + + $this->deprecated[$option] = [ + 'package' => $package, + 'version' => $version, + 'message' => $message, + ]; + + // Make sure the option is processed + unset($this->resolved[$option]); + + return $this; + } + + public function isDeprecated(string $option): bool + { + return isset($this->deprecated[$option]); + } + + /** + * Sets the normalizer for an option. + * + * The normalizer should be a closure with the following signature: + * + * function (Options $options, $value) { + * // ... + * } + * + * The closure is invoked when {@link resolve()} is called. The closure + * has access to the resolved values of other options through the passed + * {@link Options} instance. + * + * The second parameter passed to the closure is the value of + * the option. + * + * The resolved option value is set to the return value of the closure. + * + * @return $this + * + * @throws UndefinedOptionsException If the option is undefined + * @throws AccessException If called from a lazy option or normalizer + */ + public function setNormalizer(string $option, \Closure $normalizer) + { + if ($this->locked) { + throw new AccessException('Normalizers cannot be set from a lazy option or normalizer.'); + } + + if (!isset($this->defined[$option])) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); + } + + $this->normalizers[$option] = [$normalizer]; + + // Make sure the option is processed + unset($this->resolved[$option]); + + return $this; + } + + /** + * Adds a normalizer for an option. + * + * The normalizer should be a closure with the following signature: + * + * function (Options $options, $value): mixed { + * // ... + * } + * + * The closure is invoked when {@link resolve()} is called. The closure + * has access to the resolved values of other options through the passed + * {@link Options} instance. + * + * The second parameter passed to the closure is the value of + * the option. + * + * The resolved option value is set to the return value of the closure. + * + * @return $this + * + * @throws UndefinedOptionsException If the option is undefined + * @throws AccessException If called from a lazy option or normalizer + */ + public function addNormalizer(string $option, \Closure $normalizer, bool $forcePrepend = false): self + { + if ($this->locked) { + throw new AccessException('Normalizers cannot be set from a lazy option or normalizer.'); + } + + if (!isset($this->defined[$option])) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); + } + + if ($forcePrepend) { + $this->normalizers[$option] = $this->normalizers[$option] ?? []; + array_unshift($this->normalizers[$option], $normalizer); + } else { + $this->normalizers[$option][] = $normalizer; + } + + // Make sure the option is processed + unset($this->resolved[$option]); + + return $this; + } + + /** + * Sets allowed values for an option. + * + * Instead of passing values, you may also pass a closures with the + * following signature: + * + * function ($value) { + * // return true or false + * } + * + * The closure receives the value as argument and should return true to + * accept the value and false to reject the value. + * + * @param string $option The option name + * @param mixed $allowedValues One or more acceptable values/closures + * + * @return $this + * + * @throws UndefinedOptionsException If the option is undefined + * @throws AccessException If called from a lazy option or normalizer + */ + public function setAllowedValues(string $option, $allowedValues) + { + if ($this->locked) { + throw new AccessException('Allowed values cannot be set from a lazy option or normalizer.'); + } + + if (!isset($this->defined[$option])) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); + } + + $this->allowedValues[$option] = \is_array($allowedValues) ? $allowedValues : [$allowedValues]; + + // Make sure the option is processed + unset($this->resolved[$option]); + + return $this; + } + + /** + * Adds allowed values for an option. + * + * The values are merged with the allowed values defined previously. + * + * Instead of passing values, you may also pass a closures with the + * following signature: + * + * function ($value) { + * // return true or false + * } + * + * The closure receives the value as argument and should return true to + * accept the value and false to reject the value. + * + * @param string $option The option name + * @param mixed $allowedValues One or more acceptable values/closures + * + * @return $this + * + * @throws UndefinedOptionsException If the option is undefined + * @throws AccessException If called from a lazy option or normalizer + */ + public function addAllowedValues(string $option, $allowedValues) + { + if ($this->locked) { + throw new AccessException('Allowed values cannot be added from a lazy option or normalizer.'); + } + + if (!isset($this->defined[$option])) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); + } + + if (!\is_array($allowedValues)) { + $allowedValues = [$allowedValues]; + } + + if (!isset($this->allowedValues[$option])) { + $this->allowedValues[$option] = $allowedValues; + } else { + $this->allowedValues[$option] = array_merge($this->allowedValues[$option], $allowedValues); + } + + // Make sure the option is processed + unset($this->resolved[$option]); + + return $this; + } + + /** + * Sets allowed types for an option. + * + * Any type for which a corresponding is_<type>() function exists is + * acceptable. Additionally, fully-qualified class or interface names may + * be passed. + * + * @param string|string[] $allowedTypes One or more accepted types + * + * @return $this + * + * @throws UndefinedOptionsException If the option is undefined + * @throws AccessException If called from a lazy option or normalizer + */ + public function setAllowedTypes(string $option, $allowedTypes) + { + if ($this->locked) { + throw new AccessException('Allowed types cannot be set from a lazy option or normalizer.'); + } + + if (!isset($this->defined[$option])) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); + } + + $this->allowedTypes[$option] = (array) $allowedTypes; + + // Make sure the option is processed + unset($this->resolved[$option]); + + return $this; + } + + /** + * Adds allowed types for an option. + * + * The types are merged with the allowed types defined previously. + * + * Any type for which a corresponding is_<type>() function exists is + * acceptable. Additionally, fully-qualified class or interface names may + * be passed. + * + * @param string|string[] $allowedTypes One or more accepted types + * + * @return $this + * + * @throws UndefinedOptionsException If the option is undefined + * @throws AccessException If called from a lazy option or normalizer + */ + public function addAllowedTypes(string $option, $allowedTypes) + { + if ($this->locked) { + throw new AccessException('Allowed types cannot be added from a lazy option or normalizer.'); + } + + if (!isset($this->defined[$option])) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); + } + + if (!isset($this->allowedTypes[$option])) { + $this->allowedTypes[$option] = (array) $allowedTypes; + } else { + $this->allowedTypes[$option] = array_merge($this->allowedTypes[$option], (array) $allowedTypes); + } + + // Make sure the option is processed + unset($this->resolved[$option]); + + return $this; + } + + /** + * Defines an option configurator with the given name. + */ + public function define(string $option): OptionConfigurator + { + if (isset($this->defined[$option])) { + throw new OptionDefinitionException(sprintf('The option "%s" is already defined.', $option)); + } + + return new OptionConfigurator($option, $this); + } + + /** + * Sets an info message for an option. + * + * @return $this + * + * @throws UndefinedOptionsException If the option is undefined + * @throws AccessException If called from a lazy option or normalizer + */ + public function setInfo(string $option, string $info): self + { + if ($this->locked) { + throw new AccessException('The Info message cannot be set from a lazy option or normalizer.'); + } + + if (!isset($this->defined[$option])) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); + } + + $this->info[$option] = $info; + + return $this; + } + + /** + * Gets the info message for an option. + */ + public function getInfo(string $option): ?string + { + if (!isset($this->defined[$option])) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); + } + + return $this->info[$option] ?? null; + } + + /** + * Marks the whole options definition as array prototype. + * + * @return $this + * + * @throws AccessException If called from a lazy option, a normalizer or a root definition + */ + public function setPrototype(bool $prototype): self + { + if ($this->locked) { + throw new AccessException('The prototype property cannot be set from a lazy option or normalizer.'); + } + + if (null === $this->prototype && $prototype) { + throw new AccessException('The prototype property cannot be set from a root definition.'); + } + + $this->prototype = $prototype; + + return $this; + } + + public function isPrototype(): bool + { + return $this->prototype ?? false; + } + + /** + * Removes the option with the given name. + * + * Undefined options are ignored. + * + * @param string|string[] $optionNames One or more option names + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function remove($optionNames) + { + if ($this->locked) { + throw new AccessException('Options cannot be removed from a lazy option or normalizer.'); + } + + foreach ((array) $optionNames as $option) { + unset($this->defined[$option], $this->defaults[$option], $this->required[$option], $this->resolved[$option]); + unset($this->lazy[$option], $this->normalizers[$option], $this->allowedTypes[$option], $this->allowedValues[$option], $this->info[$option]); + } + + return $this; + } + + /** + * Removes all options. + * + * @return $this + * + * @throws AccessException If called from a lazy option or normalizer + */ + public function clear() + { + if ($this->locked) { + throw new AccessException('Options cannot be cleared from a lazy option or normalizer.'); + } + + $this->defined = []; + $this->defaults = []; + $this->nested = []; + $this->required = []; + $this->resolved = []; + $this->lazy = []; + $this->normalizers = []; + $this->allowedTypes = []; + $this->allowedValues = []; + $this->deprecated = []; + $this->info = []; + + return $this; + } + + /** + * Merges options with the default values stored in the container and + * validates them. + * + * Exceptions are thrown if: + * + * - Undefined options are passed; + * - Required options are missing; + * - Options have invalid types; + * - Options have invalid values. + * + * @return array + * + * @throws UndefinedOptionsException If an option name is undefined + * @throws InvalidOptionsException If an option doesn't fulfill the + * specified validation rules + * @throws MissingOptionsException If a required option is missing + * @throws OptionDefinitionException If there is a cyclic dependency between + * lazy options and/or normalizers + * @throws NoSuchOptionException If a lazy option reads an unavailable option + * @throws AccessException If called from a lazy option or normalizer + */ + public function resolve(array $options = []) + { + if ($this->locked) { + throw new AccessException('Options cannot be resolved from a lazy option or normalizer.'); + } + + // Allow this method to be called multiple times + $clone = clone $this; + + // Make sure that no unknown options are passed + $diff = array_diff_key($options, $clone->defined); + + if (\count($diff) > 0) { + ksort($clone->defined); + ksort($diff); + + throw new UndefinedOptionsException(sprintf((\count($diff) > 1 ? 'The options "%s" do not exist.' : 'The option "%s" does not exist.').' Defined options are: "%s".', $this->formatOptions(array_keys($diff)), implode('", "', array_keys($clone->defined)))); + } + + // Override options set by the user + foreach ($options as $option => $value) { + $clone->given[$option] = true; + $clone->defaults[$option] = $value; + unset($clone->resolved[$option], $clone->lazy[$option]); + } + + // Check whether any required option is missing + $diff = array_diff_key($clone->required, $clone->defaults); + + if (\count($diff) > 0) { + ksort($diff); + + throw new MissingOptionsException(sprintf(\count($diff) > 1 ? 'The required options "%s" are missing.' : 'The required option "%s" is missing.', $this->formatOptions(array_keys($diff)))); + } + + // Lock the container + $clone->locked = true; + + // Now process the individual options. Use offsetGet(), which resolves + // the option itself and any options that the option depends on + foreach ($clone->defaults as $option => $_) { + $clone->offsetGet($option); + } + + return $clone->resolved; + } + + /** + * Returns the resolved value of an option. + * + * @param bool $triggerDeprecation Whether to trigger the deprecation or not (true by default) + * + * @return mixed + * + * @throws AccessException If accessing this method outside of + * {@link resolve()} + * @throws NoSuchOptionException If the option is not set + * @throws InvalidOptionsException If the option doesn't fulfill the + * specified validation rules + * @throws OptionDefinitionException If there is a cyclic dependency between + * lazy options and/or normalizers + */ + #[\ReturnTypeWillChange] + public function offsetGet($option, bool $triggerDeprecation = true) + { + if (!$this->locked) { + throw new AccessException('Array access is only supported within closures of lazy options and normalizers.'); + } + + // Shortcut for resolved options + if (isset($this->resolved[$option]) || \array_key_exists($option, $this->resolved)) { + if ($triggerDeprecation && isset($this->deprecated[$option]) && (isset($this->given[$option]) || $this->calling) && \is_string($this->deprecated[$option]['message'])) { + trigger_deprecation($this->deprecated[$option]['package'], $this->deprecated[$option]['version'], strtr($this->deprecated[$option]['message'], ['%name%' => $option])); + } + + return $this->resolved[$option]; + } + + // Check whether the option is set at all + if (!isset($this->defaults[$option]) && !\array_key_exists($option, $this->defaults)) { + if (!isset($this->defined[$option])) { + throw new NoSuchOptionException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined)))); + } + + throw new NoSuchOptionException(sprintf('The optional option "%s" has no value set. You should make sure it is set with "isset" before reading it.', $this->formatOptions([$option]))); + } + + $value = $this->defaults[$option]; + + // Resolve the option if it is a nested definition + if (isset($this->nested[$option])) { + // If the closure is already being called, we have a cyclic dependency + if (isset($this->calling[$option])) { + throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling)))); + } + + if (!\is_array($value)) { + throw new InvalidOptionsException(sprintf('The nested option "%s" with value %s is expected to be of type array, but is of type "%s".', $this->formatOptions([$option]), $this->formatValue($value), get_debug_type($value))); + } + + // The following section must be protected from cyclic calls. + $this->calling[$option] = true; + try { + $resolver = new self(); + $resolver->prototype = false; + $resolver->parentsOptions = $this->parentsOptions; + $resolver->parentsOptions[] = $option; + foreach ($this->nested[$option] as $closure) { + $closure($resolver, $this); + } + + if ($resolver->prototype) { + $values = []; + foreach ($value as $index => $prototypeValue) { + if (!\is_array($prototypeValue)) { + throw new InvalidOptionsException(sprintf('The value of the option "%s" is expected to be of type array of array, but is of type array of "%s".', $this->formatOptions([$option]), get_debug_type($prototypeValue))); + } + + $resolver->prototypeIndex = $index; + $values[$index] = $resolver->resolve($prototypeValue); + } + $value = $values; + } else { + $value = $resolver->resolve($value); + } + } finally { + $resolver->prototypeIndex = null; + unset($this->calling[$option]); + } + } + + // Resolve the option if the default value is lazily evaluated + if (isset($this->lazy[$option])) { + // If the closure is already being called, we have a cyclic + // dependency + if (isset($this->calling[$option])) { + throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling)))); + } + + // The following section must be protected from cyclic + // calls. Set $calling for the current $option to detect a cyclic + // dependency + // BEGIN + $this->calling[$option] = true; + try { + foreach ($this->lazy[$option] as $closure) { + $value = $closure($this, $value); + } + } finally { + unset($this->calling[$option]); + } + // END + } + + // Validate the type of the resolved option + if (isset($this->allowedTypes[$option])) { + $valid = true; + $invalidTypes = []; + + foreach ($this->allowedTypes[$option] as $type) { + if ($valid = $this->verifyTypes($type, $value, $invalidTypes)) { + break; + } + } + + if (!$valid) { + $fmtActualValue = $this->formatValue($value); + $fmtAllowedTypes = implode('" or "', $this->allowedTypes[$option]); + $fmtProvidedTypes = implode('|', array_keys($invalidTypes)); + $allowedContainsArrayType = \count(array_filter($this->allowedTypes[$option], static function ($item) { + return str_ends_with($item, '[]'); + })) > 0; + + if (\is_array($value) && $allowedContainsArrayType) { + throw new InvalidOptionsException(sprintf('The option "%s" with value %s is expected to be of type "%s", but one of the elements is of type "%s".', $this->formatOptions([$option]), $fmtActualValue, $fmtAllowedTypes, $fmtProvidedTypes)); + } + + throw new InvalidOptionsException(sprintf('The option "%s" with value %s is expected to be of type "%s", but is of type "%s".', $this->formatOptions([$option]), $fmtActualValue, $fmtAllowedTypes, $fmtProvidedTypes)); + } + } + + // Validate the value of the resolved option + if (isset($this->allowedValues[$option])) { + $success = false; + $printableAllowedValues = []; + + foreach ($this->allowedValues[$option] as $allowedValue) { + if ($allowedValue instanceof \Closure) { + if ($allowedValue($value)) { + $success = true; + break; + } + + // Don't include closures in the exception message + continue; + } + + if ($value === $allowedValue) { + $success = true; + break; + } + + $printableAllowedValues[] = $allowedValue; + } + + if (!$success) { + $message = sprintf( + 'The option "%s" with value %s is invalid.', + $option, + $this->formatValue($value) + ); + + if (\count($printableAllowedValues) > 0) { + $message .= sprintf( + ' Accepted values are: %s.', + $this->formatValues($printableAllowedValues) + ); + } + + if (isset($this->info[$option])) { + $message .= sprintf(' Info: %s.', $this->info[$option]); + } + + throw new InvalidOptionsException($message); + } + } + + // Check whether the option is deprecated + // and it is provided by the user or is being called from a lazy evaluation + if ($triggerDeprecation && isset($this->deprecated[$option]) && (isset($this->given[$option]) || ($this->calling && \is_string($this->deprecated[$option]['message'])))) { + $deprecation = $this->deprecated[$option]; + $message = $this->deprecated[$option]['message']; + + if ($message instanceof \Closure) { + // If the closure is already being called, we have a cyclic dependency + if (isset($this->calling[$option])) { + throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling)))); + } + + $this->calling[$option] = true; + try { + if (!\is_string($message = $message($this, $value))) { + throw new InvalidOptionsException(sprintf('Invalid type for deprecation message, expected string but got "%s", return an empty string to ignore.', get_debug_type($message))); + } + } finally { + unset($this->calling[$option]); + } + } + + if ('' !== $message) { + trigger_deprecation($deprecation['package'], $deprecation['version'], strtr($message, ['%name%' => $option])); + } + } + + // Normalize the validated option + if (isset($this->normalizers[$option])) { + // If the closure is already being called, we have a cyclic + // dependency + if (isset($this->calling[$option])) { + throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling)))); + } + + // The following section must be protected from cyclic + // calls. Set $calling for the current $option to detect a cyclic + // dependency + // BEGIN + $this->calling[$option] = true; + try { + foreach ($this->normalizers[$option] as $normalizer) { + $value = $normalizer($this, $value); + } + } finally { + unset($this->calling[$option]); + } + // END + } + + // Mark as resolved + $this->resolved[$option] = $value; + + return $value; + } + + private function verifyTypes(string $type, $value, array &$invalidTypes, int $level = 0): bool + { + if (\is_array($value) && '[]' === substr($type, -2)) { + $type = substr($type, 0, -2); + $valid = true; + + foreach ($value as $val) { + if (!$this->verifyTypes($type, $val, $invalidTypes, $level + 1)) { + $valid = false; + } + } + + return $valid; + } + + if (('null' === $type && null === $value) || (isset(self::VALIDATION_FUNCTIONS[$type]) ? self::VALIDATION_FUNCTIONS[$type]($value) : $value instanceof $type)) { + return true; + } + + if (!$invalidTypes || $level > 0) { + $invalidTypes[get_debug_type($value)] = true; + } + + return false; + } + + /** + * Returns whether a resolved option with the given name exists. + * + * @param string $option The option name + * + * @return bool + * + * @throws AccessException If accessing this method outside of {@link resolve()} + * + * @see \ArrayAccess::offsetExists() + */ + #[\ReturnTypeWillChange] + public function offsetExists($option) + { + if (!$this->locked) { + throw new AccessException('Array access is only supported within closures of lazy options and normalizers.'); + } + + return \array_key_exists($option, $this->defaults); + } + + /** + * Not supported. + * + * @return void + * + * @throws AccessException + */ + #[\ReturnTypeWillChange] + public function offsetSet($option, $value) + { + throw new AccessException('Setting options via array access is not supported. Use setDefault() instead.'); + } + + /** + * Not supported. + * + * @return void + * + * @throws AccessException + */ + #[\ReturnTypeWillChange] + public function offsetUnset($option) + { + throw new AccessException('Removing options via array access is not supported. Use remove() instead.'); + } + + /** + * Returns the number of set options. + * + * This may be only a subset of the defined options. + * + * @return int + * + * @throws AccessException If accessing this method outside of {@link resolve()} + * + * @see \Countable::count() + */ + #[\ReturnTypeWillChange] + public function count() + { + if (!$this->locked) { + throw new AccessException('Counting is only supported within closures of lazy options and normalizers.'); + } + + return \count($this->defaults); + } + + /** + * Returns a string representation of the value. + * + * This method returns the equivalent PHP tokens for most scalar types + * (i.e. "false" for false, "1" for 1 etc.). Strings are always wrapped + * in double quotes ("). + * + * @param mixed $value The value to format as string + */ + private function formatValue($value): string + { + if (\is_object($value)) { + return \get_class($value); + } + + if (\is_array($value)) { + return 'array'; + } + + if (\is_string($value)) { + return '"'.$value.'"'; + } + + if (\is_resource($value)) { + return 'resource'; + } + + if (null === $value) { + return 'null'; + } + + if (false === $value) { + return 'false'; + } + + if (true === $value) { + return 'true'; + } + + return (string) $value; + } + + /** + * Returns a string representation of a list of values. + * + * Each of the values is converted to a string using + * {@link formatValue()}. The values are then concatenated with commas. + * + * @see formatValue() + */ + private function formatValues(array $values): string + { + foreach ($values as $key => $value) { + $values[$key] = $this->formatValue($value); + } + + return implode(', ', $values); + } + + private function formatOptions(array $options): string + { + if ($this->parentsOptions) { + $prefix = array_shift($this->parentsOptions); + if ($this->parentsOptions) { + $prefix .= sprintf('[%s]', implode('][', $this->parentsOptions)); + } + + if ($this->prototype && null !== $this->prototypeIndex) { + $prefix .= sprintf('[%s]', $this->prototypeIndex); + } + + $options = array_map(static function (string $option) use ($prefix): string { + return sprintf('%s[%s]', $prefix, $option); + }, $options); + } + + return implode('", "', $options); + } + + private function getParameterClassName(\ReflectionParameter $parameter): ?string + { + if (!($type = $parameter->getType()) instanceof \ReflectionNamedType || $type->isBuiltin()) { + return null; + } + + return $type->getName(); + } +} diff --git a/vendor/symfony/options-resolver/README.md b/vendor/symfony/options-resolver/README.md new file mode 100644 index 0000000..c63b900 --- /dev/null +++ b/vendor/symfony/options-resolver/README.md @@ -0,0 +1,15 @@ +OptionsResolver Component +========================= + +The OptionsResolver component is `array_replace` on steroids. It allows you to +create an options system with required options, defaults, validation (type, +value), normalization and more. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/options_resolver.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/options-resolver/composer.json b/vendor/symfony/options-resolver/composer.json new file mode 100644 index 0000000..a38d1bd --- /dev/null +++ b/vendor/symfony/options-resolver/composer.json @@ -0,0 +1,31 @@ +{ + "name": "symfony/options-resolver", + "type": "library", + "description": "Provides an improved replacement for the array_replace PHP function", + "keywords": ["options", "config", "configuration"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.16" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\OptionsResolver\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/vendor/symfony/polyfill-ctype/Ctype.php b/vendor/symfony/polyfill-ctype/Ctype.php index 58414dc..ba75a2c 100644 --- a/vendor/symfony/polyfill-ctype/Ctype.php +++ b/vendor/symfony/polyfill-ctype/Ctype.php @@ -25,13 +25,13 @@ final class Ctype * * @see https://php.net/ctype-alnum * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_alnum($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text); } @@ -41,13 +41,13 @@ public static function ctype_alnum($text) * * @see https://php.net/ctype-alpha * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_alpha($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text); } @@ -57,13 +57,13 @@ public static function ctype_alpha($text) * * @see https://php.net/ctype-cntrl * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_cntrl($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text); } @@ -73,13 +73,13 @@ public static function ctype_cntrl($text) * * @see https://php.net/ctype-digit * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_digit($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text); } @@ -89,13 +89,13 @@ public static function ctype_digit($text) * * @see https://php.net/ctype-graph * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_graph($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text); } @@ -105,13 +105,13 @@ public static function ctype_graph($text) * * @see https://php.net/ctype-lower * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_lower($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text); } @@ -121,13 +121,13 @@ public static function ctype_lower($text) * * @see https://php.net/ctype-print * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_print($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text); } @@ -137,13 +137,13 @@ public static function ctype_print($text) * * @see https://php.net/ctype-punct * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_punct($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text); } @@ -153,13 +153,13 @@ public static function ctype_punct($text) * * @see https://php.net/ctype-space * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_space($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text); } @@ -169,13 +169,13 @@ public static function ctype_space($text) * * @see https://php.net/ctype-upper * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_upper($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text); } @@ -185,13 +185,13 @@ public static function ctype_upper($text) * * @see https://php.net/ctype-xdigit * - * @param string|int $text + * @param mixed $text * * @return bool */ public static function ctype_xdigit($text) { - $text = self::convert_int_to_char_for_ctype($text); + $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__); return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text); } @@ -204,11 +204,12 @@ public static function ctype_xdigit($text) * (negative values have 256 added in order to allow characters in the Extended ASCII range). * Any other integer is interpreted as a string containing the decimal digits of the integer. * - * @param string|int $int + * @param mixed $int + * @param string $function * * @return mixed */ - private static function convert_int_to_char_for_ctype($int) + private static function convert_int_to_char_for_ctype($int, $function) { if (!\is_int($int)) { return $int; @@ -218,6 +219,10 @@ private static function convert_int_to_char_for_ctype($int) return (string) $int; } + if (\PHP_VERSION_ID >= 80100) { + @trigger_error($function.'(): Argument of type int will be interpreted as string in the future', \E_USER_DEPRECATED); + } + if ($int < 0) { $int += 256; } diff --git a/vendor/symfony/polyfill-ctype/LICENSE b/vendor/symfony/polyfill-ctype/LICENSE index ad399a7..3f853aa 100644 --- a/vendor/symfony/polyfill-ctype/LICENSE +++ b/vendor/symfony/polyfill-ctype/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018 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/vendor/symfony/polyfill-ctype/README.md b/vendor/symfony/polyfill-ctype/README.md index 8add1ab..b144d03 100644 --- a/vendor/symfony/polyfill-ctype/README.md +++ b/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/master/README.md). +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). License ======= diff --git a/vendor/symfony/polyfill-ctype/bootstrap.php b/vendor/symfony/polyfill-ctype/bootstrap.php index 14d1d0f..d54524b 100644 --- a/vendor/symfony/polyfill-ctype/bootstrap.php +++ b/vendor/symfony/polyfill-ctype/bootstrap.php @@ -11,16 +11,40 @@ use Symfony\Polyfill\Ctype as p; +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + if (!function_exists('ctype_alnum')) { function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); } +} +if (!function_exists('ctype_alpha')) { function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); } +} +if (!function_exists('ctype_cntrl')) { function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); } +} +if (!function_exists('ctype_digit')) { function ctype_digit($text) { return p\Ctype::ctype_digit($text); } +} +if (!function_exists('ctype_graph')) { function ctype_graph($text) { return p\Ctype::ctype_graph($text); } +} +if (!function_exists('ctype_lower')) { function ctype_lower($text) { return p\Ctype::ctype_lower($text); } +} +if (!function_exists('ctype_print')) { function ctype_print($text) { return p\Ctype::ctype_print($text); } +} +if (!function_exists('ctype_punct')) { function ctype_punct($text) { return p\Ctype::ctype_punct($text); } +} +if (!function_exists('ctype_space')) { function ctype_space($text) { return p\Ctype::ctype_space($text); } +} +if (!function_exists('ctype_upper')) { function ctype_upper($text) { return p\Ctype::ctype_upper($text); } +} +if (!function_exists('ctype_xdigit')) { function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); } } diff --git a/vendor/symfony/polyfill-ctype/bootstrap80.php b/vendor/symfony/polyfill-ctype/bootstrap80.php new file mode 100644 index 0000000..ab2f861 --- /dev/null +++ b/vendor/symfony/polyfill-ctype/bootstrap80.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Ctype as p; + +if (!function_exists('ctype_alnum')) { + function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); } +} +if (!function_exists('ctype_alpha')) { + function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); } +} +if (!function_exists('ctype_cntrl')) { + function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); } +} +if (!function_exists('ctype_digit')) { + function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); } +} +if (!function_exists('ctype_graph')) { + function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); } +} +if (!function_exists('ctype_lower')) { + function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); } +} +if (!function_exists('ctype_print')) { + function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); } +} +if (!function_exists('ctype_punct')) { + function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); } +} +if (!function_exists('ctype_space')) { + function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); } +} +if (!function_exists('ctype_upper')) { + function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); } +} +if (!function_exists('ctype_xdigit')) { + function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); } +} diff --git a/vendor/symfony/polyfill-ctype/composer.json b/vendor/symfony/polyfill-ctype/composer.json index 0504dda..1b3efff 100644 --- a/vendor/symfony/polyfill-ctype/composer.json +++ b/vendor/symfony/polyfill-ctype/composer.json @@ -16,16 +16,26 @@ } ], "require": { - "php": ">=5.3.3" + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" }, "files": [ "bootstrap.php" ] }, + "suggest": { + "ext-ctype": "For best performance" + }, "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.8-dev" + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } } } diff --git a/vendor/symfony/polyfill-intl-grapheme/Grapheme.php b/vendor/symfony/polyfill-intl-grapheme/Grapheme.php new file mode 100644 index 0000000..5373f16 --- /dev/null +++ b/vendor/symfony/polyfill-intl-grapheme/Grapheme.php @@ -0,0 +1,247 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Intl\Grapheme; + +\define('SYMFONY_GRAPHEME_CLUSTER_RX', ((float) \PCRE_VERSION < 10 ? (float) \PCRE_VERSION >= 8.32 : (float) \PCRE_VERSION >= 10.39) ? '\X' : Grapheme::GRAPHEME_CLUSTER_RX); + +/** + * Partial intl implementation in pure PHP. + * + * Implemented: + * - grapheme_extract - Extract a sequence of grapheme clusters from a text buffer, which must be encoded in UTF-8 + * - grapheme_stripos - Find position (in grapheme units) of first occurrence of a case-insensitive string + * - grapheme_stristr - Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack + * - grapheme_strlen - Get string length in grapheme units + * - grapheme_strpos - Find position (in grapheme units) of first occurrence of a string + * - grapheme_strripos - Find position (in grapheme units) of last occurrence of a case-insensitive string + * - grapheme_strrpos - Find position (in grapheme units) of last occurrence of a string + * - grapheme_strstr - Returns part of haystack string from the first occurrence of needle to the end of haystack + * - grapheme_substr - Return part of a string + * + * @author Nicolas Grekas <p@tchwork.com> + * + * @internal + */ +final class Grapheme +{ + // (CRLF|([ZWNJ-ZWJ]|T+|L*(LV?V+|LV|LVT)T*|L+|[^Control])[Extend]*|[Control]) + // This regular expression is a work around for http://bugs.exim.org/1279 + public const GRAPHEME_CLUSTER_RX = '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])'; + + 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", 'ι'], + ]; + + public static function grapheme_extract($s, $size, $type = \GRAPHEME_EXTR_COUNT, $start = 0, &$next = 0) + { + if (0 > $start) { + $start = \strlen($s) + $start; + } + + if (!\is_scalar($s)) { + $hasError = false; + set_error_handler(function () use (&$hasError) { $hasError = true; }); + $next = substr($s, $start); + restore_error_handler(); + if ($hasError) { + substr($s, $start); + $s = ''; + } else { + $s = $next; + } + } else { + $s = substr($s, $start); + } + $size = (int) $size; + $type = (int) $type; + $start = (int) $start; + + if (\GRAPHEME_EXTR_COUNT !== $type && \GRAPHEME_EXTR_MAXBYTES !== $type && \GRAPHEME_EXTR_MAXCHARS !== $type) { + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError('grapheme_extract(): Argument #3 ($type) must be one of GRAPHEME_EXTR_COUNT, GRAPHEME_EXTR_MAXBYTES, or GRAPHEME_EXTR_MAXCHARS'); + } + + if (!isset($s[0]) || 0 > $size || 0 > $start) { + return false; + } + if (0 === $size) { + return ''; + } + + $next = $start; + + $s = preg_split('/('.SYMFONY_GRAPHEME_CLUSTER_RX.')/u', "\r\n".$s, $size + 1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE); + + if (!isset($s[1])) { + return false; + } + + $i = 1; + $ret = ''; + + do { + if (\GRAPHEME_EXTR_COUNT === $type) { + --$size; + } elseif (\GRAPHEME_EXTR_MAXBYTES === $type) { + $size -= \strlen($s[$i]); + } else { + $size -= iconv_strlen($s[$i], 'UTF-8//IGNORE'); + } + + if ($size >= 0) { + $ret .= $s[$i]; + } + } while (isset($s[++$i]) && $size > 0); + + $next += \strlen($ret); + + return $ret; + } + + public static function grapheme_strlen($s) + { + preg_replace('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', '', $s, -1, $len); + + return 0 === $len && '' !== $s ? null : $len; + } + + public static function grapheme_substr($s, $start, $len = null) + { + if (null === $len) { + $len = 2147483647; + } + + preg_match_all('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', $s, $s); + + $slen = \count($s[0]); + $start = (int) $start; + + if (0 > $start) { + $start += $slen; + } + if (0 > $start) { + if (\PHP_VERSION_ID < 80000) { + return false; + } + + $start = 0; + } + if ($start >= $slen) { + return \PHP_VERSION_ID >= 80000 ? '' : false; + } + + $rem = $slen - $start; + + if (0 > $len) { + $len += $rem; + } + if (0 === $len) { + return ''; + } + if (0 > $len) { + return \PHP_VERSION_ID >= 80000 ? '' : false; + } + if ($len > $rem) { + $len = $rem; + } + + return implode('', \array_slice($s[0], $start, $len)); + } + + public static function grapheme_strpos($s, $needle, $offset = 0) + { + return self::grapheme_position($s, $needle, $offset, 0); + } + + public static function grapheme_stripos($s, $needle, $offset = 0) + { + return self::grapheme_position($s, $needle, $offset, 1); + } + + public static function grapheme_strrpos($s, $needle, $offset = 0) + { + return self::grapheme_position($s, $needle, $offset, 2); + } + + public static function grapheme_strripos($s, $needle, $offset = 0) + { + return self::grapheme_position($s, $needle, $offset, 3); + } + + public static function grapheme_stristr($s, $needle, $beforeNeedle = false) + { + return mb_stristr($s, $needle, $beforeNeedle, 'UTF-8'); + } + + public static function grapheme_strstr($s, $needle, $beforeNeedle = false) + { + return mb_strstr($s, $needle, $beforeNeedle, 'UTF-8'); + } + + private static function grapheme_position($s, $needle, $offset, $mode) + { + $needle = (string) $needle; + if (80000 > \PHP_VERSION_ID && !preg_match('/./us', $needle)) { + return false; + } + $s = (string) $s; + if (!preg_match('/./us', $s)) { + return false; + } + if ($offset > 0) { + $s = self::grapheme_substr($s, $offset); + } elseif ($offset < 0) { + if (2 > $mode) { + $offset += self::grapheme_strlen($s); + $s = self::grapheme_substr($s, $offset); + if (0 > $offset) { + $offset = 0; + } + } elseif (0 > $offset += self::grapheme_strlen($needle)) { + $s = self::grapheme_substr($s, 0, $offset); + $offset = 0; + } else { + $offset = 0; + } + } + + // As UTF-8 is self-synchronizing, and we have ensured the strings are valid UTF-8, + // we can use normal binary string functions here. For case-insensitive searches, + // case fold the strings first. + $caseInsensitive = $mode & 1; + $reverse = $mode & 2; + if ($caseInsensitive) { + // Use the same case folding mode as mbstring does for mb_stripos(). + // Stick to SIMPLE case folding to avoid changing the length of the string, which + // might result in offsets being shifted. + $mode = \defined('MB_CASE_FOLD_SIMPLE') ? \MB_CASE_FOLD_SIMPLE : \MB_CASE_LOWER; + $s = mb_convert_case($s, $mode, 'UTF-8'); + $needle = mb_convert_case($needle, $mode, 'UTF-8'); + + if (!\defined('MB_CASE_FOLD_SIMPLE')) { + $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s); + $needle = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $needle); + } + } + if ($reverse) { + $needlePos = strrpos($s, $needle); + } else { + $needlePos = strpos($s, $needle); + } + + return false !== $needlePos ? self::grapheme_strlen(substr($s, 0, $needlePos)) + $offset : false; + } +} diff --git a/vendor/symfony/polyfill-intl-grapheme/LICENSE b/vendor/symfony/polyfill-intl-grapheme/LICENSE new file mode 100644 index 0000000..4cd8bdd --- /dev/null +++ b/vendor/symfony/polyfill-intl-grapheme/LICENSE @@ -0,0 +1,19 @@ +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 +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/vendor/symfony/polyfill-intl-grapheme/README.md b/vendor/symfony/polyfill-intl-grapheme/README.md new file mode 100644 index 0000000..f55d92c --- /dev/null +++ b/vendor/symfony/polyfill-intl-grapheme/README.md @@ -0,0 +1,31 @@ +Symfony Polyfill / Intl: Grapheme +================================= + +This component provides a partial, native PHP implementation of the +[Grapheme functions](https://php.net/intl.grapheme) from the +[Intl](https://php.net/intl) extension. + +- [`grapheme_extract`](https://php.net/grapheme_extract): Extract a sequence of grapheme + clusters from a text buffer, which must be encoded in UTF-8 +- [`grapheme_stripos`](https://php.net/grapheme_stripos): Find position (in grapheme units) + of first occurrence of a case-insensitive string +- [`grapheme_stristr`](https://php.net/grapheme_stristr): Returns part of haystack string + from the first occurrence of case-insensitive needle to the end of haystack +- [`grapheme_strlen`](https://php.net/grapheme_strlen): Get string length in grapheme units +- [`grapheme_strpos`](https://php.net/grapheme_strpos): Find position (in grapheme units) + of first occurrence of a string +- [`grapheme_strripos`](https://php.net/grapheme_strripos): Find position (in grapheme units) + of last occurrence of a case-insensitive string +- [`grapheme_strrpos`](https://php.net/grapheme_strrpos): Find position (in grapheme units) + of last occurrence of a string +- [`grapheme_strstr`](https://php.net/grapheme_strstr): Returns part of haystack string from + the first occurrence of needle to the end of haystack +- [`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). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-intl-grapheme/bootstrap.php b/vendor/symfony/polyfill-intl-grapheme/bootstrap.php new file mode 100644 index 0000000..a9ea03c --- /dev/null +++ b/vendor/symfony/polyfill-intl-grapheme/bootstrap.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Grapheme as p; + +if (extension_loaded('intl')) { + return; +} + +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + +if (!defined('GRAPHEME_EXTR_COUNT')) { + define('GRAPHEME_EXTR_COUNT', 0); +} +if (!defined('GRAPHEME_EXTR_MAXBYTES')) { + define('GRAPHEME_EXTR_MAXBYTES', 1); +} +if (!defined('GRAPHEME_EXTR_MAXCHARS')) { + define('GRAPHEME_EXTR_MAXCHARS', 2); +} + +if (!function_exists('grapheme_extract')) { + function grapheme_extract($haystack, $size, $type = 0, $start = 0, &$next = 0) { return p\Grapheme::grapheme_extract($haystack, $size, $type, $start, $next); } +} +if (!function_exists('grapheme_stripos')) { + function grapheme_stripos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_stripos($haystack, $needle, $offset); } +} +if (!function_exists('grapheme_stristr')) { + function grapheme_stristr($haystack, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_stristr($haystack, $needle, $beforeNeedle); } +} +if (!function_exists('grapheme_strlen')) { + function grapheme_strlen($input) { return p\Grapheme::grapheme_strlen($input); } +} +if (!function_exists('grapheme_strpos')) { + function grapheme_strpos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strpos($haystack, $needle, $offset); } +} +if (!function_exists('grapheme_strripos')) { + function grapheme_strripos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strripos($haystack, $needle, $offset); } +} +if (!function_exists('grapheme_strrpos')) { + function grapheme_strrpos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strrpos($haystack, $needle, $offset); } +} +if (!function_exists('grapheme_strstr')) { + function grapheme_strstr($haystack, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_strstr($haystack, $needle, $beforeNeedle); } +} +if (!function_exists('grapheme_substr')) { + function grapheme_substr($string, $offset, $length = null) { return p\Grapheme::grapheme_substr($string, $offset, $length); } +} diff --git a/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php b/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php new file mode 100644 index 0000000..b8c0786 --- /dev/null +++ b/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php @@ -0,0 +1,50 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Grapheme as p; + +if (!defined('GRAPHEME_EXTR_COUNT')) { + define('GRAPHEME_EXTR_COUNT', 0); +} +if (!defined('GRAPHEME_EXTR_MAXBYTES')) { + define('GRAPHEME_EXTR_MAXBYTES', 1); +} +if (!defined('GRAPHEME_EXTR_MAXCHARS')) { + define('GRAPHEME_EXTR_MAXCHARS', 2); +} + +if (!function_exists('grapheme_extract')) { + function grapheme_extract(?string $haystack, ?int $size, ?int $type = GRAPHEME_EXTR_COUNT, ?int $offset = 0, &$next = null): string|false { return p\Grapheme::grapheme_extract((string) $haystack, (int) $size, (int) $type, (int) $offset, $next); } +} +if (!function_exists('grapheme_stripos')) { + function grapheme_stripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_stripos((string) $haystack, (string) $needle, (int) $offset); } +} +if (!function_exists('grapheme_stristr')) { + function grapheme_stristr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_stristr((string) $haystack, (string) $needle, (bool) $beforeNeedle); } +} +if (!function_exists('grapheme_strlen')) { + function grapheme_strlen(?string $string): int|false|null { return p\Grapheme::grapheme_strlen((string) $string); } +} +if (!function_exists('grapheme_strpos')) { + function grapheme_strpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strpos((string) $haystack, (string) $needle, (int) $offset); } +} +if (!function_exists('grapheme_strripos')) { + function grapheme_strripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strripos((string) $haystack, (string) $needle, (int) $offset); } +} +if (!function_exists('grapheme_strrpos')) { + function grapheme_strrpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strrpos((string) $haystack, (string) $needle, (int) $offset); } +} +if (!function_exists('grapheme_strstr')) { + function grapheme_strstr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_strstr((string) $haystack, (string) $needle, (bool) $beforeNeedle); } +} +if (!function_exists('grapheme_substr')) { + function grapheme_substr(?string $string, ?int $offset, ?int $length = null): string|false { return p\Grapheme::grapheme_substr((string) $string, (int) $offset, $length); } +} diff --git a/vendor/symfony/polyfill-intl-grapheme/composer.json b/vendor/symfony/polyfill-intl-grapheme/composer.json new file mode 100644 index 0000000..fde5537 --- /dev/null +++ b/vendor/symfony/polyfill-intl-grapheme/composer.json @@ -0,0 +1,38 @@ +{ + "name": "symfony/polyfill-intl-grapheme", + "type": "library", + "description": "Symfony polyfill for intl's grapheme_* functions", + "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "grapheme"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-intl": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/vendor/symfony/polyfill-intl-normalizer/LICENSE b/vendor/symfony/polyfill-intl-normalizer/LICENSE new file mode 100644 index 0000000..4cd8bdd --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/LICENSE @@ -0,0 +1,19 @@ +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 +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/vendor/symfony/polyfill-intl-normalizer/Normalizer.php b/vendor/symfony/polyfill-intl-normalizer/Normalizer.php new file mode 100644 index 0000000..81704ab --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/Normalizer.php @@ -0,0 +1,310 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Intl\Normalizer; + +/** + * Normalizer is a PHP fallback implementation of the Normalizer class provided by the intl extension. + * + * It has been validated with Unicode 6.3 Normalization Conformance Test. + * See http://www.unicode.org/reports/tr15/ for detailed info about Unicode normalizations. + * + * @author Nicolas Grekas <p@tchwork.com> + * + * @internal + */ +class Normalizer +{ + public const FORM_D = \Normalizer::FORM_D; + public const FORM_KD = \Normalizer::FORM_KD; + public const FORM_C = \Normalizer::FORM_C; + public const FORM_KC = \Normalizer::FORM_KC; + public const NFD = \Normalizer::NFD; + public const NFKD = \Normalizer::NFKD; + public const NFC = \Normalizer::NFC; + public const NFKC = \Normalizer::NFKC; + + private static $C; + private static $D; + private static $KD; + private static $cC; + private static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; + private static $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"; + + public static function isNormalized(string $s, int $form = self::FORM_C) + { + if (!\in_array($form, [self::NFD, self::NFKD, self::NFC, self::NFKC])) { + return false; + } + if (!isset($s[strspn($s, self::$ASCII)])) { + return true; + } + if (self::NFC == $form && preg_match('//u', $s) && !preg_match('/[^\x00-\x{2FF}]/u', $s)) { + return true; + } + + return self::normalize($s, $form) === $s; + } + + public static function normalize(string $s, int $form = self::FORM_C) + { + if (!preg_match('//u', $s)) { + return false; + } + + switch ($form) { + case self::NFC: $C = true; $K = false; break; + case self::NFD: $C = false; $K = false; break; + case self::NFKC: $C = true; $K = true; break; + case self::NFKD: $C = false; $K = true; break; + default: + if (\defined('Normalizer::NONE') && \Normalizer::NONE == $form) { + return $s; + } + + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError('normalizer_normalize(): Argument #2 ($form) must be a a valid normalization form'); + } + + if ('' === $s) { + return ''; + } + + if ($K && null === self::$KD) { + self::$KD = self::getData('compatibilityDecomposition'); + } + + if (null === self::$D) { + self::$D = self::getData('canonicalDecomposition'); + self::$cC = self::getData('combiningClass'); + } + + if (null !== $mbEncoding = (2 /* MB_OVERLOAD_STRING */ & (int) \ini_get('mbstring.func_overload')) ? mb_internal_encoding() : null) { + mb_internal_encoding('8bit'); + } + + $r = self::decompose($s, $K); + + if ($C) { + if (null === self::$C) { + self::$C = self::getData('canonicalComposition'); + } + + $r = self::recompose($r); + } + if (null !== $mbEncoding) { + mb_internal_encoding($mbEncoding); + } + + return $r; + } + + private static function recompose($s) + { + $ASCII = self::$ASCII; + $compMap = self::$C; + $combClass = self::$cC; + $ulenMask = self::$ulenMask; + + $result = $tail = ''; + + $i = $s[0] < "\x80" ? 1 : $ulenMask[$s[0] & "\xF0"]; + $len = \strlen($s); + + $lastUchr = substr($s, 0, $i); + $lastUcls = isset($combClass[$lastUchr]) ? 256 : 0; + + while ($i < $len) { + if ($s[$i] < "\x80") { + // ASCII chars + + if ($tail) { + $lastUchr .= $tail; + $tail = ''; + } + + if ($j = strspn($s, $ASCII, $i + 1)) { + $lastUchr .= substr($s, $i, $j); + $i += $j; + } + + $result .= $lastUchr; + $lastUchr = $s[$i]; + $lastUcls = 0; + ++$i; + continue; + } + + $ulen = $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + + if ($lastUchr < "\xE1\x84\x80" || "\xE1\x84\x92" < $lastUchr + || $uchr < "\xE1\x85\xA1" || "\xE1\x85\xB5" < $uchr + || $lastUcls) { + // Table lookup and combining chars composition + + $ucls = $combClass[$uchr] ?? 0; + + if (isset($compMap[$lastUchr.$uchr]) && (!$lastUcls || $lastUcls < $ucls)) { + $lastUchr = $compMap[$lastUchr.$uchr]; + } elseif ($lastUcls = $ucls) { + $tail .= $uchr; + } else { + if ($tail) { + $lastUchr .= $tail; + $tail = ''; + } + + $result .= $lastUchr; + $lastUchr = $uchr; + } + } else { + // Hangul chars + + $L = \ord($lastUchr[2]) - 0x80; + $V = \ord($uchr[2]) - 0xA1; + $T = 0; + + $uchr = substr($s, $i + $ulen, 3); + + if ("\xE1\x86\xA7" <= $uchr && $uchr <= "\xE1\x87\x82") { + $T = \ord($uchr[2]) - 0xA7; + 0 > $T && $T += 0x40; + $ulen += 3; + } + + $L = 0xAC00 + ($L * 21 + $V) * 28 + $T; + $lastUchr = \chr(0xE0 | $L >> 12).\chr(0x80 | $L >> 6 & 0x3F).\chr(0x80 | $L & 0x3F); + } + + $i += $ulen; + } + + return $result.$lastUchr.$tail; + } + + private static function decompose($s, $c) + { + $result = ''; + + $ASCII = self::$ASCII; + $decompMap = self::$D; + $combClass = self::$cC; + $ulenMask = self::$ulenMask; + if ($c) { + $compatMap = self::$KD; + } + + $c = []; + $i = 0; + $len = \strlen($s); + + while ($i < $len) { + if ($s[$i] < "\x80") { + // ASCII chars + + if ($c) { + ksort($c); + $result .= implode('', $c); + $c = []; + } + + $j = 1 + strspn($s, $ASCII, $i + 1); + $result .= substr($s, $i, $j); + $i += $j; + continue; + } + + $ulen = $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + $i += $ulen; + + if ($uchr < "\xEA\xB0\x80" || "\xED\x9E\xA3" < $uchr) { + // Table lookup + + if ($uchr !== $j = $compatMap[$uchr] ?? ($decompMap[$uchr] ?? $uchr)) { + $uchr = $j; + + $j = \strlen($uchr); + $ulen = $uchr[0] < "\x80" ? 1 : $ulenMask[$uchr[0] & "\xF0"]; + + if ($ulen != $j) { + // Put trailing chars in $s + + $j -= $ulen; + $i -= $j; + + if (0 > $i) { + $s = str_repeat(' ', -$i).$s; + $len -= $i; + $i = 0; + } + + while ($j--) { + $s[$i + $j] = $uchr[$ulen + $j]; + } + + $uchr = substr($uchr, 0, $ulen); + } + } + if (isset($combClass[$uchr])) { + // Combining chars, for sorting + + if (!isset($c[$combClass[$uchr]])) { + $c[$combClass[$uchr]] = ''; + } + $c[$combClass[$uchr]] .= $uchr; + continue; + } + } else { + // Hangul chars + + $uchr = unpack('C*', $uchr); + $j = (($uchr[1] - 224) << 12) + (($uchr[2] - 128) << 6) + $uchr[3] - 0xAC80; + + $uchr = "\xE1\x84".\chr(0x80 + (int) ($j / 588)) + ."\xE1\x85".\chr(0xA1 + (int) (($j % 588) / 28)); + + if ($j %= 28) { + $uchr .= $j < 25 + ? ("\xE1\x86".\chr(0xA7 + $j)) + : ("\xE1\x87".\chr(0x67 + $j)); + } + } + if ($c) { + ksort($c); + $result .= implode('', $c); + $c = []; + } + + $result .= $uchr; + } + + if ($c) { + ksort($c); + $result .= implode('', $c); + } + + return $result; + } + + private static function getData($file) + { + if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { + return require $file; + } + + return false; + } +} diff --git a/vendor/symfony/polyfill-intl-normalizer/README.md b/vendor/symfony/polyfill-intl-normalizer/README.md new file mode 100644 index 0000000..b9b762e --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/README.md @@ -0,0 +1,14 @@ +Symfony Polyfill / Intl: Normalizer +=================================== + +This component provides a fallback implementation for the +[`Normalizer`](https://php.net/Normalizer) class provided +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). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php b/vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php new file mode 100644 index 0000000..0fdfc89 --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php @@ -0,0 +1,17 @@ +<?php + +class Normalizer extends Symfony\Polyfill\Intl\Normalizer\Normalizer +{ + /** + * @deprecated since ICU 56 and removed in PHP 8 + */ + public const NONE = 2; + public const FORM_D = 4; + public const FORM_KD = 8; + public const FORM_C = 16; + public const FORM_KC = 32; + public const NFD = 4; + public const NFKD = 8; + public const NFC = 16; + public const NFKC = 32; +} diff --git a/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php b/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php new file mode 100644 index 0000000..db47644 --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php @@ -0,0 +1,945 @@ +<?php + +return array ( + 'À' => 'À', + 'Á' => 'Á', + 'Â' => 'Â', + 'Ã' => 'Ã', + 'Ä' => 'Ä', + 'Å' => 'Å', + 'Ç' => 'Ç', + 'È' => 'È', + 'É' => 'É', + 'Ê' => 'Ê', + 'Ë' => 'Ë', + 'Ì' => 'Ì', + 'Í' => 'Í', + 'Î' => 'Î', + 'Ï' => 'Ï', + 'Ñ' => 'Ñ', + 'Ò' => 'Ò', + 'Ó' => 'Ó', + 'Ô' => 'Ô', + 'Õ' => 'Õ', + 'Ö' => 'Ö', + 'Ù' => 'Ù', + 'Ú' => 'Ú', + 'Û' => 'Û', + 'Ü' => 'Ü', + 'Ý' => 'Ý', + 'à' => 'à', + 'á' => 'á', + 'â' => 'â', + 'ã' => 'ã', + 'ä' => 'ä', + 'å' => 'å', + 'ç' => 'ç', + 'è' => 'è', + 'é' => 'é', + 'ê' => 'ê', + 'ë' => 'ë', + 'ì' => 'ì', + 'í' => 'í', + 'î' => 'î', + 'ï' => 'ï', + 'ñ' => 'ñ', + 'ò' => 'ò', + 'ó' => 'ó', + 'ô' => 'ô', + 'õ' => 'õ', + 'ö' => 'ö', + 'ù' => 'ù', + 'ú' => 'ú', + 'û' => 'û', + 'ü' => 'ü', + 'ý' => 'ý', + 'ÿ' => 'ÿ', + 'Ā' => 'Ā', + 'ā' => 'ā', + 'Ă' => 'Ă', + 'ă' => 'ă', + 'Ą' => 'Ą', + 'ą' => 'ą', + 'Ć' => 'Ć', + 'ć' => 'ć', + 'Ĉ' => 'Ĉ', + 'ĉ' => 'ĉ', + 'Ċ' => 'Ċ', + 'ċ' => 'ċ', + 'Č' => 'Č', + 'č' => 'č', + 'Ď' => 'Ď', + 'ď' => 'ď', + 'Ē' => 'Ē', + 'ē' => 'ē', + 'Ĕ' => 'Ĕ', + 'ĕ' => 'ĕ', + 'Ė' => 'Ė', + 'ė' => 'ė', + 'Ę' => 'Ę', + 'ę' => 'ę', + 'Ě' => 'Ě', + 'ě' => 'ě', + 'Ĝ' => 'Ĝ', + 'ĝ' => 'ĝ', + 'Ğ' => 'Ğ', + 'ğ' => 'ğ', + 'Ġ' => 'Ġ', + 'ġ' => 'ġ', + 'Ģ' => 'Ģ', + 'ģ' => 'ģ', + 'Ĥ' => 'Ĥ', + 'ĥ' => 'ĥ', + 'Ĩ' => 'Ĩ', + 'ĩ' => 'ĩ', + 'Ī' => 'Ī', + 'ī' => 'ī', + 'Ĭ' => 'Ĭ', + 'ĭ' => 'ĭ', + 'Į' => 'Į', + 'į' => 'į', + 'İ' => 'İ', + 'Ĵ' => 'Ĵ', + 'ĵ' => 'ĵ', + 'Ķ' => 'Ķ', + 'ķ' => 'ķ', + 'Ĺ' => 'Ĺ', + 'ĺ' => 'ĺ', + 'Ļ' => 'Ļ', + 'ļ' => 'ļ', + 'Ľ' => 'Ľ', + 'ľ' => 'ľ', + 'Ń' => 'Ń', + 'ń' => 'ń', + 'Ņ' => 'Ņ', + 'ņ' => 'ņ', + 'Ň' => 'Ň', + 'ň' => 'ň', + 'Ō' => 'Ō', + 'ō' => 'ō', + 'Ŏ' => 'Ŏ', + 'ŏ' => 'ŏ', + 'Ő' => 'Ő', + 'ő' => 'ő', + 'Ŕ' => 'Ŕ', + 'ŕ' => 'ŕ', + 'Ŗ' => 'Ŗ', + 'ŗ' => 'ŗ', + 'Ř' => 'Ř', + 'ř' => 'ř', + 'Ś' => 'Ś', + 'ś' => 'ś', + 'Ŝ' => 'Ŝ', + 'ŝ' => 'ŝ', + 'Ş' => 'Ş', + 'ş' => 'ş', + 'Š' => 'Š', + 'š' => 'š', + 'Ţ' => 'Ţ', + 'ţ' => 'ţ', + 'Ť' => 'Ť', + 'ť' => 'ť', + 'Ũ' => 'Ũ', + 'ũ' => 'ũ', + 'Ū' => 'Ū', + 'ū' => 'ū', + 'Ŭ' => 'Ŭ', + 'ŭ' => 'ŭ', + 'Ů' => 'Ů', + 'ů' => 'ů', + 'Ű' => 'Ű', + 'ű' => 'ű', + 'Ų' => 'Ų', + 'ų' => 'ų', + 'Ŵ' => 'Ŵ', + 'ŵ' => 'ŵ', + 'Ŷ' => 'Ŷ', + 'ŷ' => 'ŷ', + 'Ÿ' => 'Ÿ', + 'Ź' => 'Ź', + 'ź' => 'ź', + 'Ż' => 'Ż', + 'ż' => 'ż', + 'Ž' => 'Ž', + 'ž' => 'ž', + 'Ơ' => 'Ơ', + 'ơ' => 'ơ', + 'Ư' => 'Ư', + 'ư' => 'ư', + 'Ǎ' => 'Ǎ', + 'ǎ' => 'ǎ', + 'Ǐ' => 'Ǐ', + 'ǐ' => 'ǐ', + 'Ǒ' => 'Ǒ', + 'ǒ' => 'ǒ', + 'Ǔ' => 'Ǔ', + 'ǔ' => 'ǔ', + 'Ǖ' => 'Ǖ', + 'ǖ' => 'ǖ', + 'Ǘ' => 'Ǘ', + 'ǘ' => 'ǘ', + 'Ǚ' => 'Ǚ', + 'ǚ' => 'ǚ', + 'Ǜ' => 'Ǜ', + 'ǜ' => 'ǜ', + 'Ǟ' => 'Ǟ', + 'ǟ' => 'ǟ', + 'Ǡ' => 'Ǡ', + 'ǡ' => 'ǡ', + 'Ǣ' => 'Ǣ', + 'ǣ' => 'ǣ', + 'Ǧ' => 'Ǧ', + 'ǧ' => 'ǧ', + 'Ǩ' => 'Ǩ', + 'ǩ' => 'ǩ', + 'Ǫ' => 'Ǫ', + 'ǫ' => 'ǫ', + 'Ǭ' => 'Ǭ', + 'ǭ' => 'ǭ', + 'Ǯ' => 'Ǯ', + 'ǯ' => 'ǯ', + 'ǰ' => 'ǰ', + 'Ǵ' => 'Ǵ', + 'ǵ' => 'ǵ', + 'Ǹ' => 'Ǹ', + 'ǹ' => 'ǹ', + 'Ǻ' => 'Ǻ', + 'ǻ' => 'ǻ', + 'Ǽ' => 'Ǽ', + 'ǽ' => 'ǽ', + 'Ǿ' => 'Ǿ', + 'ǿ' => 'ǿ', + 'Ȁ' => 'Ȁ', + 'ȁ' => 'ȁ', + 'Ȃ' => 'Ȃ', + 'ȃ' => 'ȃ', + 'Ȅ' => 'Ȅ', + 'ȅ' => 'ȅ', + 'Ȇ' => 'Ȇ', + 'ȇ' => 'ȇ', + 'Ȉ' => 'Ȉ', + 'ȉ' => 'ȉ', + 'Ȋ' => 'Ȋ', + 'ȋ' => 'ȋ', + 'Ȍ' => 'Ȍ', + 'ȍ' => 'ȍ', + 'Ȏ' => 'Ȏ', + 'ȏ' => 'ȏ', + 'Ȑ' => 'Ȑ', + 'ȑ' => 'ȑ', + 'Ȓ' => 'Ȓ', + 'ȓ' => 'ȓ', + 'Ȕ' => 'Ȕ', + 'ȕ' => 'ȕ', + 'Ȗ' => 'Ȗ', + 'ȗ' => 'ȗ', + 'Ș' => 'Ș', + 'ș' => 'ș', + 'Ț' => 'Ț', + 'ț' => 'ț', + 'Ȟ' => 'Ȟ', + 'ȟ' => 'ȟ', + 'Ȧ' => 'Ȧ', + 'ȧ' => 'ȧ', + 'Ȩ' => 'Ȩ', + 'ȩ' => 'ȩ', + 'Ȫ' => 'Ȫ', + 'ȫ' => 'ȫ', + 'Ȭ' => 'Ȭ', + 'ȭ' => 'ȭ', + 'Ȯ' => 'Ȯ', + 'ȯ' => 'ȯ', + 'Ȱ' => 'Ȱ', + 'ȱ' => 'ȱ', + 'Ȳ' => 'Ȳ', + 'ȳ' => 'ȳ', + '΅' => '΅', + 'Ά' => 'Ά', + 'Έ' => 'Έ', + 'Ή' => 'Ή', + 'Ί' => 'Ί', + 'Ό' => 'Ό', + 'Ύ' => 'Ύ', + 'Ώ' => 'Ώ', + 'ΐ' => 'ΐ', + 'Ϊ' => 'Ϊ', + 'Ϋ' => 'Ϋ', + 'ά' => 'ά', + 'έ' => 'έ', + 'ή' => 'ή', + 'ί' => 'ί', + 'ΰ' => 'ΰ', + 'ϊ' => 'ϊ', + 'ϋ' => 'ϋ', + 'ό' => 'ό', + 'ύ' => 'ύ', + 'ώ' => 'ώ', + 'ϓ' => 'ϓ', + 'ϔ' => 'ϔ', + 'Ѐ' => 'Ѐ', + 'Ё' => 'Ё', + 'Ѓ' => 'Ѓ', + 'Ї' => 'Ї', + 'Ќ' => 'Ќ', + 'Ѝ' => 'Ѝ', + 'Ў' => 'Ў', + 'Й' => 'Й', + 'й' => 'й', + 'ѐ' => 'ѐ', + 'ё' => 'ё', + 'ѓ' => 'ѓ', + 'ї' => 'ї', + 'ќ' => 'ќ', + 'ѝ' => 'ѝ', + 'ў' => 'ў', + 'Ѷ' => 'Ѷ', + 'ѷ' => 'ѷ', + 'Ӂ' => 'Ӂ', + 'ӂ' => 'ӂ', + 'Ӑ' => 'Ӑ', + 'ӑ' => 'ӑ', + 'Ӓ' => 'Ӓ', + 'ӓ' => 'ӓ', + 'Ӗ' => 'Ӗ', + 'ӗ' => 'ӗ', + 'Ӛ' => 'Ӛ', + 'ӛ' => 'ӛ', + 'Ӝ' => 'Ӝ', + 'ӝ' => 'ӝ', + 'Ӟ' => 'Ӟ', + 'ӟ' => 'ӟ', + 'Ӣ' => 'Ӣ', + 'ӣ' => 'ӣ', + 'Ӥ' => 'Ӥ', + 'ӥ' => 'ӥ', + 'Ӧ' => 'Ӧ', + 'ӧ' => 'ӧ', + 'Ӫ' => 'Ӫ', + 'ӫ' => 'ӫ', + 'Ӭ' => 'Ӭ', + 'ӭ' => 'ӭ', + 'Ӯ' => 'Ӯ', + 'ӯ' => 'ӯ', + 'Ӱ' => 'Ӱ', + 'ӱ' => 'ӱ', + 'Ӳ' => 'Ӳ', + 'ӳ' => 'ӳ', + 'Ӵ' => 'Ӵ', + 'ӵ' => 'ӵ', + 'Ӹ' => 'Ӹ', + 'ӹ' => 'ӹ', + 'آ' => 'آ', + 'أ' => 'أ', + 'ؤ' => 'ؤ', + 'إ' => 'إ', + 'ئ' => 'ئ', + 'ۀ' => 'ۀ', + 'ۂ' => 'ۂ', + 'ۓ' => 'ۓ', + 'ऩ' => 'ऩ', + 'ऱ' => 'ऱ', + 'ऴ' => 'ऴ', + 'ো' => 'ো', + 'ৌ' => 'ৌ', + 'ୈ' => 'ୈ', + 'ୋ' => 'ୋ', + 'ୌ' => 'ୌ', + 'ஔ' => 'ஔ', + 'ொ' => 'ொ', + 'ோ' => 'ோ', + 'ௌ' => 'ௌ', + 'ై' => 'ై', + 'ೀ' => 'ೀ', + 'ೇ' => 'ೇ', + 'ೈ' => 'ೈ', + 'ೊ' => 'ೊ', + 'ೋ' => 'ೋ', + 'ൊ' => 'ൊ', + 'ോ' => 'ോ', + 'ൌ' => 'ൌ', + 'ේ' => 'ේ', + 'ො' => 'ො', + 'ෝ' => 'ෝ', + 'ෞ' => 'ෞ', + 'ဦ' => 'ဦ', + 'ᬆ' => 'ᬆ', + 'ᬈ' => 'ᬈ', + 'ᬊ' => 'ᬊ', + 'ᬌ' => 'ᬌ', + 'ᬎ' => 'ᬎ', + 'ᬒ' => 'ᬒ', + 'ᬻ' => 'ᬻ', + 'ᬽ' => 'ᬽ', + 'ᭀ' => 'ᭀ', + 'ᭁ' => 'ᭁ', + 'ᭃ' => 'ᭃ', + 'Ḁ' => 'Ḁ', + 'ḁ' => 'ḁ', + 'Ḃ' => 'Ḃ', + 'ḃ' => 'ḃ', + 'Ḅ' => 'Ḅ', + 'ḅ' => 'ḅ', + 'Ḇ' => 'Ḇ', + 'ḇ' => 'ḇ', + 'Ḉ' => 'Ḉ', + 'ḉ' => 'ḉ', + 'Ḋ' => 'Ḋ', + 'ḋ' => 'ḋ', + 'Ḍ' => 'Ḍ', + 'ḍ' => 'ḍ', + 'Ḏ' => 'Ḏ', + 'ḏ' => 'ḏ', + 'Ḑ' => 'Ḑ', + 'ḑ' => 'ḑ', + 'Ḓ' => 'Ḓ', + 'ḓ' => 'ḓ', + 'Ḕ' => 'Ḕ', + 'ḕ' => 'ḕ', + 'Ḗ' => 'Ḗ', + 'ḗ' => 'ḗ', + 'Ḙ' => 'Ḙ', + 'ḙ' => 'ḙ', + 'Ḛ' => 'Ḛ', + 'ḛ' => 'ḛ', + 'Ḝ' => 'Ḝ', + 'ḝ' => 'ḝ', + 'Ḟ' => 'Ḟ', + 'ḟ' => 'ḟ', + 'Ḡ' => 'Ḡ', + 'ḡ' => 'ḡ', + 'Ḣ' => 'Ḣ', + 'ḣ' => 'ḣ', + 'Ḥ' => 'Ḥ', + 'ḥ' => 'ḥ', + 'Ḧ' => 'Ḧ', + 'ḧ' => 'ḧ', + 'Ḩ' => 'Ḩ', + 'ḩ' => 'ḩ', + 'Ḫ' => 'Ḫ', + 'ḫ' => 'ḫ', + 'Ḭ' => 'Ḭ', + 'ḭ' => 'ḭ', + 'Ḯ' => 'Ḯ', + 'ḯ' => 'ḯ', + 'Ḱ' => 'Ḱ', + 'ḱ' => 'ḱ', + 'Ḳ' => 'Ḳ', + 'ḳ' => 'ḳ', + 'Ḵ' => 'Ḵ', + 'ḵ' => 'ḵ', + 'Ḷ' => 'Ḷ', + 'ḷ' => 'ḷ', + 'Ḹ' => 'Ḹ', + 'ḹ' => 'ḹ', + 'Ḻ' => 'Ḻ', + 'ḻ' => 'ḻ', + 'Ḽ' => 'Ḽ', + 'ḽ' => 'ḽ', + 'Ḿ' => 'Ḿ', + 'ḿ' => 'ḿ', + 'Ṁ' => 'Ṁ', + 'ṁ' => 'ṁ', + 'Ṃ' => 'Ṃ', + 'ṃ' => 'ṃ', + 'Ṅ' => 'Ṅ', + 'ṅ' => 'ṅ', + 'Ṇ' => 'Ṇ', + 'ṇ' => 'ṇ', + 'Ṉ' => 'Ṉ', + 'ṉ' => 'ṉ', + 'Ṋ' => 'Ṋ', + 'ṋ' => 'ṋ', + 'Ṍ' => 'Ṍ', + 'ṍ' => 'ṍ', + 'Ṏ' => 'Ṏ', + 'ṏ' => 'ṏ', + 'Ṑ' => 'Ṑ', + 'ṑ' => 'ṑ', + 'Ṓ' => 'Ṓ', + 'ṓ' => 'ṓ', + 'Ṕ' => 'Ṕ', + 'ṕ' => 'ṕ', + 'Ṗ' => 'Ṗ', + 'ṗ' => 'ṗ', + 'Ṙ' => 'Ṙ', + 'ṙ' => 'ṙ', + 'Ṛ' => 'Ṛ', + 'ṛ' => 'ṛ', + 'Ṝ' => 'Ṝ', + 'ṝ' => 'ṝ', + 'Ṟ' => 'Ṟ', + 'ṟ' => 'ṟ', + 'Ṡ' => 'Ṡ', + 'ṡ' => 'ṡ', + 'Ṣ' => 'Ṣ', + 'ṣ' => 'ṣ', + 'Ṥ' => 'Ṥ', + 'ṥ' => 'ṥ', + 'Ṧ' => 'Ṧ', + 'ṧ' => 'ṧ', + 'Ṩ' => 'Ṩ', + 'ṩ' => 'ṩ', + 'Ṫ' => 'Ṫ', + 'ṫ' => 'ṫ', + 'Ṭ' => 'Ṭ', + 'ṭ' => 'ṭ', + 'Ṯ' => 'Ṯ', + 'ṯ' => 'ṯ', + 'Ṱ' => 'Ṱ', + 'ṱ' => 'ṱ', + 'Ṳ' => 'Ṳ', + 'ṳ' => 'ṳ', + 'Ṵ' => 'Ṵ', + 'ṵ' => 'ṵ', + 'Ṷ' => 'Ṷ', + 'ṷ' => 'ṷ', + 'Ṹ' => 'Ṹ', + 'ṹ' => 'ṹ', + 'Ṻ' => 'Ṻ', + 'ṻ' => 'ṻ', + 'Ṽ' => 'Ṽ', + 'ṽ' => 'ṽ', + 'Ṿ' => 'Ṿ', + 'ṿ' => 'ṿ', + 'Ẁ' => 'Ẁ', + 'ẁ' => 'ẁ', + 'Ẃ' => 'Ẃ', + 'ẃ' => 'ẃ', + 'Ẅ' => 'Ẅ', + 'ẅ' => 'ẅ', + 'Ẇ' => 'Ẇ', + 'ẇ' => 'ẇ', + 'Ẉ' => 'Ẉ', + 'ẉ' => 'ẉ', + 'Ẋ' => 'Ẋ', + 'ẋ' => 'ẋ', + 'Ẍ' => 'Ẍ', + 'ẍ' => 'ẍ', + 'Ẏ' => 'Ẏ', + 'ẏ' => 'ẏ', + 'Ẑ' => 'Ẑ', + 'ẑ' => 'ẑ', + 'Ẓ' => 'Ẓ', + 'ẓ' => 'ẓ', + 'Ẕ' => 'Ẕ', + 'ẕ' => 'ẕ', + 'ẖ' => 'ẖ', + 'ẗ' => 'ẗ', + 'ẘ' => 'ẘ', + 'ẙ' => 'ẙ', + 'ẛ' => 'ẛ', + 'Ạ' => 'Ạ', + 'ạ' => 'ạ', + 'Ả' => 'Ả', + 'ả' => 'ả', + 'Ấ' => 'Ấ', + 'ấ' => 'ấ', + 'Ầ' => 'Ầ', + 'ầ' => 'ầ', + 'Ẩ' => 'Ẩ', + 'ẩ' => 'ẩ', + 'Ẫ' => 'Ẫ', + 'ẫ' => 'ẫ', + 'Ậ' => 'Ậ', + 'ậ' => 'ậ', + 'Ắ' => 'Ắ', + 'ắ' => 'ắ', + 'Ằ' => 'Ằ', + 'ằ' => 'ằ', + 'Ẳ' => 'Ẳ', + 'ẳ' => 'ẳ', + 'Ẵ' => 'Ẵ', + 'ẵ' => 'ẵ', + 'Ặ' => 'Ặ', + 'ặ' => 'ặ', + 'Ẹ' => 'Ẹ', + 'ẹ' => 'ẹ', + 'Ẻ' => 'Ẻ', + 'ẻ' => 'ẻ', + 'Ẽ' => 'Ẽ', + 'ẽ' => 'ẽ', + 'Ế' => 'Ế', + 'ế' => 'ế', + 'Ề' => 'Ề', + 'ề' => 'ề', + 'Ể' => 'Ể', + 'ể' => 'ể', + 'Ễ' => 'Ễ', + 'ễ' => 'ễ', + 'Ệ' => 'Ệ', + 'ệ' => 'ệ', + 'Ỉ' => 'Ỉ', + 'ỉ' => 'ỉ', + 'Ị' => 'Ị', + 'ị' => 'ị', + 'Ọ' => 'Ọ', + 'ọ' => 'ọ', + 'Ỏ' => 'Ỏ', + 'ỏ' => 'ỏ', + 'Ố' => 'Ố', + 'ố' => 'ố', + 'Ồ' => 'Ồ', + 'ồ' => 'ồ', + 'Ổ' => 'Ổ', + 'ổ' => 'ổ', + 'Ỗ' => 'Ỗ', + 'ỗ' => 'ỗ', + 'Ộ' => 'Ộ', + 'ộ' => 'ộ', + 'Ớ' => 'Ớ', + 'ớ' => 'ớ', + 'Ờ' => 'Ờ', + 'ờ' => 'ờ', + 'Ở' => 'Ở', + 'ở' => 'ở', + 'Ỡ' => 'Ỡ', + 'ỡ' => 'ỡ', + 'Ợ' => 'Ợ', + 'ợ' => 'ợ', + 'Ụ' => 'Ụ', + 'ụ' => 'ụ', + 'Ủ' => 'Ủ', + 'ủ' => 'ủ', + 'Ứ' => 'Ứ', + 'ứ' => 'ứ', + 'Ừ' => 'Ừ', + 'ừ' => 'ừ', + 'Ử' => 'Ử', + 'ử' => 'ử', + 'Ữ' => 'Ữ', + 'ữ' => 'ữ', + 'Ự' => 'Ự', + 'ự' => 'ự', + 'Ỳ' => 'Ỳ', + 'ỳ' => 'ỳ', + 'Ỵ' => 'Ỵ', + 'ỵ' => 'ỵ', + 'Ỷ' => 'Ỷ', + 'ỷ' => 'ỷ', + 'Ỹ' => 'Ỹ', + 'ỹ' => 'ỹ', + 'ἀ' => 'ἀ', + 'ἁ' => 'ἁ', + 'ἂ' => 'ἂ', + 'ἃ' => 'ἃ', + 'ἄ' => 'ἄ', + 'ἅ' => 'ἅ', + 'ἆ' => 'ἆ', + 'ἇ' => 'ἇ', + 'Ἀ' => 'Ἀ', + 'Ἁ' => 'Ἁ', + 'Ἂ' => 'Ἂ', + 'Ἃ' => 'Ἃ', + 'Ἄ' => 'Ἄ', + 'Ἅ' => 'Ἅ', + 'Ἆ' => 'Ἆ', + 'Ἇ' => 'Ἇ', + 'ἐ' => 'ἐ', + 'ἑ' => 'ἑ', + 'ἒ' => 'ἒ', + 'ἓ' => 'ἓ', + 'ἔ' => 'ἔ', + 'ἕ' => 'ἕ', + 'Ἐ' => 'Ἐ', + 'Ἑ' => 'Ἑ', + 'Ἒ' => 'Ἒ', + 'Ἓ' => 'Ἓ', + 'Ἔ' => 'Ἔ', + 'Ἕ' => 'Ἕ', + 'ἠ' => 'ἠ', + 'ἡ' => 'ἡ', + 'ἢ' => 'ἢ', + 'ἣ' => 'ἣ', + 'ἤ' => 'ἤ', + 'ἥ' => 'ἥ', + 'ἦ' => 'ἦ', + 'ἧ' => 'ἧ', + 'Ἠ' => 'Ἠ', + 'Ἡ' => 'Ἡ', + 'Ἢ' => 'Ἢ', + 'Ἣ' => 'Ἣ', + 'Ἤ' => 'Ἤ', + 'Ἥ' => 'Ἥ', + 'Ἦ' => 'Ἦ', + 'Ἧ' => 'Ἧ', + 'ἰ' => 'ἰ', + 'ἱ' => 'ἱ', + 'ἲ' => 'ἲ', + 'ἳ' => 'ἳ', + 'ἴ' => 'ἴ', + 'ἵ' => 'ἵ', + 'ἶ' => 'ἶ', + 'ἷ' => 'ἷ', + 'Ἰ' => 'Ἰ', + 'Ἱ' => 'Ἱ', + 'Ἲ' => 'Ἲ', + 'Ἳ' => 'Ἳ', + 'Ἴ' => 'Ἴ', + 'Ἵ' => 'Ἵ', + 'Ἶ' => 'Ἶ', + 'Ἷ' => 'Ἷ', + 'ὀ' => 'ὀ', + 'ὁ' => 'ὁ', + 'ὂ' => 'ὂ', + 'ὃ' => 'ὃ', + 'ὄ' => 'ὄ', + 'ὅ' => 'ὅ', + 'Ὀ' => 'Ὀ', + 'Ὁ' => 'Ὁ', + 'Ὂ' => 'Ὂ', + 'Ὃ' => 'Ὃ', + 'Ὄ' => 'Ὄ', + 'Ὅ' => 'Ὅ', + 'ὐ' => 'ὐ', + 'ὑ' => 'ὑ', + 'ὒ' => 'ὒ', + 'ὓ' => 'ὓ', + 'ὔ' => 'ὔ', + 'ὕ' => 'ὕ', + 'ὖ' => 'ὖ', + 'ὗ' => 'ὗ', + 'Ὑ' => 'Ὑ', + 'Ὓ' => 'Ὓ', + 'Ὕ' => 'Ὕ', + 'Ὗ' => 'Ὗ', + 'ὠ' => 'ὠ', + 'ὡ' => 'ὡ', + 'ὢ' => 'ὢ', + 'ὣ' => 'ὣ', + 'ὤ' => 'ὤ', + 'ὥ' => 'ὥ', + 'ὦ' => 'ὦ', + 'ὧ' => 'ὧ', + 'Ὠ' => 'Ὠ', + 'Ὡ' => 'Ὡ', + 'Ὢ' => 'Ὢ', + 'Ὣ' => 'Ὣ', + 'Ὤ' => 'Ὤ', + 'Ὥ' => 'Ὥ', + 'Ὦ' => 'Ὦ', + 'Ὧ' => 'Ὧ', + 'ὰ' => 'ὰ', + 'ὲ' => 'ὲ', + 'ὴ' => 'ὴ', + 'ὶ' => 'ὶ', + 'ὸ' => 'ὸ', + 'ὺ' => 'ὺ', + 'ὼ' => 'ὼ', + 'ᾀ' => 'ᾀ', + 'ᾁ' => 'ᾁ', + 'ᾂ' => 'ᾂ', + 'ᾃ' => 'ᾃ', + 'ᾄ' => 'ᾄ', + 'ᾅ' => 'ᾅ', + 'ᾆ' => 'ᾆ', + 'ᾇ' => 'ᾇ', + 'ᾈ' => 'ᾈ', + 'ᾉ' => 'ᾉ', + 'ᾊ' => 'ᾊ', + 'ᾋ' => 'ᾋ', + 'ᾌ' => 'ᾌ', + 'ᾍ' => 'ᾍ', + 'ᾎ' => 'ᾎ', + 'ᾏ' => 'ᾏ', + 'ᾐ' => 'ᾐ', + 'ᾑ' => 'ᾑ', + 'ᾒ' => 'ᾒ', + 'ᾓ' => 'ᾓ', + 'ᾔ' => 'ᾔ', + 'ᾕ' => 'ᾕ', + 'ᾖ' => 'ᾖ', + 'ᾗ' => 'ᾗ', + 'ᾘ' => 'ᾘ', + 'ᾙ' => 'ᾙ', + 'ᾚ' => 'ᾚ', + 'ᾛ' => 'ᾛ', + 'ᾜ' => 'ᾜ', + 'ᾝ' => 'ᾝ', + 'ᾞ' => 'ᾞ', + 'ᾟ' => 'ᾟ', + 'ᾠ' => 'ᾠ', + 'ᾡ' => 'ᾡ', + 'ᾢ' => 'ᾢ', + 'ᾣ' => 'ᾣ', + 'ᾤ' => 'ᾤ', + 'ᾥ' => 'ᾥ', + 'ᾦ' => 'ᾦ', + 'ᾧ' => 'ᾧ', + 'ᾨ' => 'ᾨ', + 'ᾩ' => 'ᾩ', + 'ᾪ' => 'ᾪ', + 'ᾫ' => 'ᾫ', + 'ᾬ' => 'ᾬ', + 'ᾭ' => 'ᾭ', + 'ᾮ' => 'ᾮ', + 'ᾯ' => 'ᾯ', + 'ᾰ' => 'ᾰ', + 'ᾱ' => 'ᾱ', + 'ᾲ' => 'ᾲ', + 'ᾳ' => 'ᾳ', + 'ᾴ' => 'ᾴ', + 'ᾶ' => 'ᾶ', + 'ᾷ' => 'ᾷ', + 'Ᾰ' => 'Ᾰ', + 'Ᾱ' => 'Ᾱ', + 'Ὰ' => 'Ὰ', + 'ᾼ' => 'ᾼ', + '῁' => '῁', + 'ῂ' => 'ῂ', + 'ῃ' => 'ῃ', + 'ῄ' => 'ῄ', + 'ῆ' => 'ῆ', + 'ῇ' => 'ῇ', + 'Ὲ' => 'Ὲ', + 'Ὴ' => 'Ὴ', + 'ῌ' => 'ῌ', + '῍' => '῍', + '῎' => '῎', + '῏' => '῏', + 'ῐ' => 'ῐ', + 'ῑ' => 'ῑ', + 'ῒ' => 'ῒ', + 'ῖ' => 'ῖ', + 'ῗ' => 'ῗ', + 'Ῐ' => 'Ῐ', + 'Ῑ' => 'Ῑ', + 'Ὶ' => 'Ὶ', + '῝' => '῝', + '῞' => '῞', + '῟' => '῟', + 'ῠ' => 'ῠ', + 'ῡ' => 'ῡ', + 'ῢ' => 'ῢ', + 'ῤ' => 'ῤ', + 'ῥ' => 'ῥ', + 'ῦ' => 'ῦ', + 'ῧ' => 'ῧ', + 'Ῠ' => 'Ῠ', + 'Ῡ' => 'Ῡ', + 'Ὺ' => 'Ὺ', + 'Ῥ' => 'Ῥ', + '῭' => '῭', + 'ῲ' => 'ῲ', + 'ῳ' => 'ῳ', + 'ῴ' => 'ῴ', + 'ῶ' => 'ῶ', + 'ῷ' => 'ῷ', + 'Ὸ' => 'Ὸ', + 'Ὼ' => 'Ὼ', + 'ῼ' => 'ῼ', + '↚' => '↚', + '↛' => '↛', + '↮' => '↮', + '⇍' => '⇍', + '⇎' => '⇎', + '⇏' => '⇏', + '∄' => '∄', + '∉' => '∉', + '∌' => '∌', + '∤' => '∤', + '∦' => '∦', + '≁' => '≁', + '≄' => '≄', + '≇' => '≇', + '≉' => '≉', + '≠' => '≠', + '≢' => '≢', + '≭' => '≭', + '≮' => '≮', + '≯' => '≯', + '≰' => '≰', + '≱' => '≱', + '≴' => '≴', + '≵' => '≵', + '≸' => '≸', + '≹' => '≹', + '⊀' => '⊀', + '⊁' => '⊁', + '⊄' => '⊄', + '⊅' => '⊅', + '⊈' => '⊈', + '⊉' => '⊉', + '⊬' => '⊬', + '⊭' => '⊭', + '⊮' => '⊮', + '⊯' => '⊯', + '⋠' => '⋠', + '⋡' => '⋡', + '⋢' => '⋢', + '⋣' => '⋣', + '⋪' => '⋪', + '⋫' => '⋫', + '⋬' => '⋬', + '⋭' => '⋭', + 'が' => 'が', + 'ぎ' => 'ぎ', + 'ぐ' => 'ぐ', + 'げ' => 'げ', + 'ご' => 'ご', + 'ざ' => 'ざ', + 'じ' => 'じ', + 'ず' => 'ず', + 'ぜ' => 'ぜ', + 'ぞ' => 'ぞ', + 'だ' => 'だ', + 'ぢ' => 'ぢ', + 'づ' => 'づ', + 'で' => 'で', + 'ど' => 'ど', + 'ば' => 'ば', + 'ぱ' => 'ぱ', + 'び' => 'び', + 'ぴ' => 'ぴ', + 'ぶ' => 'ぶ', + 'ぷ' => 'ぷ', + 'べ' => 'べ', + 'ぺ' => 'ぺ', + 'ぼ' => 'ぼ', + 'ぽ' => 'ぽ', + 'ゔ' => 'ゔ', + 'ゞ' => 'ゞ', + 'ガ' => 'ガ', + 'ギ' => 'ギ', + 'グ' => 'グ', + 'ゲ' => 'ゲ', + 'ゴ' => 'ゴ', + 'ザ' => 'ザ', + 'ジ' => 'ジ', + 'ズ' => 'ズ', + 'ゼ' => 'ゼ', + 'ゾ' => 'ゾ', + 'ダ' => 'ダ', + 'ヂ' => 'ヂ', + 'ヅ' => 'ヅ', + 'デ' => 'デ', + 'ド' => 'ド', + 'バ' => 'バ', + 'パ' => 'パ', + 'ビ' => 'ビ', + 'ピ' => 'ピ', + 'ブ' => 'ブ', + 'プ' => 'プ', + 'ベ' => 'ベ', + 'ペ' => 'ペ', + 'ボ' => 'ボ', + 'ポ' => 'ポ', + 'ヴ' => 'ヴ', + 'ヷ' => 'ヷ', + 'ヸ' => 'ヸ', + 'ヹ' => 'ヹ', + 'ヺ' => 'ヺ', + 'ヾ' => 'ヾ', + '𑂚' => '𑂚', + '𑂜' => '𑂜', + '𑂫' => '𑂫', + '𑄮' => '𑄮', + '𑄯' => '𑄯', + '𑍋' => '𑍋', + '𑍌' => '𑍌', + '𑒻' => '𑒻', + '𑒼' => '𑒼', + '𑒾' => '𑒾', + '𑖺' => '𑖺', + '𑖻' => '𑖻', + '𑤸' => '𑤸', +); diff --git a/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php b/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php new file mode 100644 index 0000000..5a3e8e0 --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php @@ -0,0 +1,2065 @@ +<?php + +return array ( + 'À' => 'À', + 'Á' => 'Á', + 'Â' => 'Â', + 'Ã' => 'Ã', + 'Ä' => 'Ä', + 'Å' => 'Å', + 'Ç' => 'Ç', + 'È' => 'È', + 'É' => 'É', + 'Ê' => 'Ê', + 'Ë' => 'Ë', + 'Ì' => 'Ì', + 'Í' => 'Í', + 'Î' => 'Î', + 'Ï' => 'Ï', + 'Ñ' => 'Ñ', + 'Ò' => 'Ò', + 'Ó' => 'Ó', + 'Ô' => 'Ô', + 'Õ' => 'Õ', + 'Ö' => 'Ö', + 'Ù' => 'Ù', + 'Ú' => 'Ú', + 'Û' => 'Û', + 'Ü' => 'Ü', + 'Ý' => 'Ý', + 'à' => 'à', + 'á' => 'á', + 'â' => 'â', + 'ã' => 'ã', + 'ä' => 'ä', + 'å' => 'å', + 'ç' => 'ç', + 'è' => 'è', + 'é' => 'é', + 'ê' => 'ê', + 'ë' => 'ë', + 'ì' => 'ì', + 'í' => 'í', + 'î' => 'î', + 'ï' => 'ï', + 'ñ' => 'ñ', + 'ò' => 'ò', + 'ó' => 'ó', + 'ô' => 'ô', + 'õ' => 'õ', + 'ö' => 'ö', + 'ù' => 'ù', + 'ú' => 'ú', + 'û' => 'û', + 'ü' => 'ü', + 'ý' => 'ý', + 'ÿ' => 'ÿ', + 'Ā' => 'Ā', + 'ā' => 'ā', + 'Ă' => 'Ă', + 'ă' => 'ă', + 'Ą' => 'Ą', + 'ą' => 'ą', + 'Ć' => 'Ć', + 'ć' => 'ć', + 'Ĉ' => 'Ĉ', + 'ĉ' => 'ĉ', + 'Ċ' => 'Ċ', + 'ċ' => 'ċ', + 'Č' => 'Č', + 'č' => 'č', + 'Ď' => 'Ď', + 'ď' => 'ď', + 'Ē' => 'Ē', + 'ē' => 'ē', + 'Ĕ' => 'Ĕ', + 'ĕ' => 'ĕ', + 'Ė' => 'Ė', + 'ė' => 'ė', + 'Ę' => 'Ę', + 'ę' => 'ę', + 'Ě' => 'Ě', + 'ě' => 'ě', + 'Ĝ' => 'Ĝ', + 'ĝ' => 'ĝ', + 'Ğ' => 'Ğ', + 'ğ' => 'ğ', + 'Ġ' => 'Ġ', + 'ġ' => 'ġ', + 'Ģ' => 'Ģ', + 'ģ' => 'ģ', + 'Ĥ' => 'Ĥ', + 'ĥ' => 'ĥ', + 'Ĩ' => 'Ĩ', + 'ĩ' => 'ĩ', + 'Ī' => 'Ī', + 'ī' => 'ī', + 'Ĭ' => 'Ĭ', + 'ĭ' => 'ĭ', + 'Į' => 'Į', + 'į' => 'į', + 'İ' => 'İ', + 'Ĵ' => 'Ĵ', + 'ĵ' => 'ĵ', + 'Ķ' => 'Ķ', + 'ķ' => 'ķ', + 'Ĺ' => 'Ĺ', + 'ĺ' => 'ĺ', + 'Ļ' => 'Ļ', + 'ļ' => 'ļ', + 'Ľ' => 'Ľ', + 'ľ' => 'ľ', + 'Ń' => 'Ń', + 'ń' => 'ń', + 'Ņ' => 'Ņ', + 'ņ' => 'ņ', + 'Ň' => 'Ň', + 'ň' => 'ň', + 'Ō' => 'Ō', + 'ō' => 'ō', + 'Ŏ' => 'Ŏ', + 'ŏ' => 'ŏ', + 'Ő' => 'Ő', + 'ő' => 'ő', + 'Ŕ' => 'Ŕ', + 'ŕ' => 'ŕ', + 'Ŗ' => 'Ŗ', + 'ŗ' => 'ŗ', + 'Ř' => 'Ř', + 'ř' => 'ř', + 'Ś' => 'Ś', + 'ś' => 'ś', + 'Ŝ' => 'Ŝ', + 'ŝ' => 'ŝ', + 'Ş' => 'Ş', + 'ş' => 'ş', + 'Š' => 'Š', + 'š' => 'š', + 'Ţ' => 'Ţ', + 'ţ' => 'ţ', + 'Ť' => 'Ť', + 'ť' => 'ť', + 'Ũ' => 'Ũ', + 'ũ' => 'ũ', + 'Ū' => 'Ū', + 'ū' => 'ū', + 'Ŭ' => 'Ŭ', + 'ŭ' => 'ŭ', + 'Ů' => 'Ů', + 'ů' => 'ů', + 'Ű' => 'Ű', + 'ű' => 'ű', + 'Ų' => 'Ų', + 'ų' => 'ų', + 'Ŵ' => 'Ŵ', + 'ŵ' => 'ŵ', + 'Ŷ' => 'Ŷ', + 'ŷ' => 'ŷ', + 'Ÿ' => 'Ÿ', + 'Ź' => 'Ź', + 'ź' => 'ź', + 'Ż' => 'Ż', + 'ż' => 'ż', + 'Ž' => 'Ž', + 'ž' => 'ž', + 'Ơ' => 'Ơ', + 'ơ' => 'ơ', + 'Ư' => 'Ư', + 'ư' => 'ư', + 'Ǎ' => 'Ǎ', + 'ǎ' => 'ǎ', + 'Ǐ' => 'Ǐ', + 'ǐ' => 'ǐ', + 'Ǒ' => 'Ǒ', + 'ǒ' => 'ǒ', + 'Ǔ' => 'Ǔ', + 'ǔ' => 'ǔ', + 'Ǖ' => 'Ǖ', + 'ǖ' => 'ǖ', + 'Ǘ' => 'Ǘ', + 'ǘ' => 'ǘ', + 'Ǚ' => 'Ǚ', + 'ǚ' => 'ǚ', + 'Ǜ' => 'Ǜ', + 'ǜ' => 'ǜ', + 'Ǟ' => 'Ǟ', + 'ǟ' => 'ǟ', + 'Ǡ' => 'Ǡ', + 'ǡ' => 'ǡ', + 'Ǣ' => 'Ǣ', + 'ǣ' => 'ǣ', + 'Ǧ' => 'Ǧ', + 'ǧ' => 'ǧ', + 'Ǩ' => 'Ǩ', + 'ǩ' => 'ǩ', + 'Ǫ' => 'Ǫ', + 'ǫ' => 'ǫ', + 'Ǭ' => 'Ǭ', + 'ǭ' => 'ǭ', + 'Ǯ' => 'Ǯ', + 'ǯ' => 'ǯ', + 'ǰ' => 'ǰ', + 'Ǵ' => 'Ǵ', + 'ǵ' => 'ǵ', + 'Ǹ' => 'Ǹ', + 'ǹ' => 'ǹ', + 'Ǻ' => 'Ǻ', + 'ǻ' => 'ǻ', + 'Ǽ' => 'Ǽ', + 'ǽ' => 'ǽ', + 'Ǿ' => 'Ǿ', + 'ǿ' => 'ǿ', + 'Ȁ' => 'Ȁ', + 'ȁ' => 'ȁ', + 'Ȃ' => 'Ȃ', + 'ȃ' => 'ȃ', + 'Ȅ' => 'Ȅ', + 'ȅ' => 'ȅ', + 'Ȇ' => 'Ȇ', + 'ȇ' => 'ȇ', + 'Ȉ' => 'Ȉ', + 'ȉ' => 'ȉ', + 'Ȋ' => 'Ȋ', + 'ȋ' => 'ȋ', + 'Ȍ' => 'Ȍ', + 'ȍ' => 'ȍ', + 'Ȏ' => 'Ȏ', + 'ȏ' => 'ȏ', + 'Ȑ' => 'Ȑ', + 'ȑ' => 'ȑ', + 'Ȓ' => 'Ȓ', + 'ȓ' => 'ȓ', + 'Ȕ' => 'Ȕ', + 'ȕ' => 'ȕ', + 'Ȗ' => 'Ȗ', + 'ȗ' => 'ȗ', + 'Ș' => 'Ș', + 'ș' => 'ș', + 'Ț' => 'Ț', + 'ț' => 'ț', + 'Ȟ' => 'Ȟ', + 'ȟ' => 'ȟ', + 'Ȧ' => 'Ȧ', + 'ȧ' => 'ȧ', + 'Ȩ' => 'Ȩ', + 'ȩ' => 'ȩ', + 'Ȫ' => 'Ȫ', + 'ȫ' => 'ȫ', + 'Ȭ' => 'Ȭ', + 'ȭ' => 'ȭ', + 'Ȯ' => 'Ȯ', + 'ȯ' => 'ȯ', + 'Ȱ' => 'Ȱ', + 'ȱ' => 'ȱ', + 'Ȳ' => 'Ȳ', + 'ȳ' => 'ȳ', + '̀' => '̀', + '́' => '́', + '̓' => '̓', + '̈́' => '̈́', + 'ʹ' => 'ʹ', + ';' => ';', + '΅' => '΅', + 'Ά' => 'Ά', + '·' => '·', + 'Έ' => 'Έ', + 'Ή' => 'Ή', + 'Ί' => 'Ί', + 'Ό' => 'Ό', + 'Ύ' => 'Ύ', + 'Ώ' => 'Ώ', + 'ΐ' => 'ΐ', + 'Ϊ' => 'Ϊ', + 'Ϋ' => 'Ϋ', + 'ά' => 'ά', + 'έ' => 'έ', + 'ή' => 'ή', + 'ί' => 'ί', + 'ΰ' => 'ΰ', + 'ϊ' => 'ϊ', + 'ϋ' => 'ϋ', + 'ό' => 'ό', + 'ύ' => 'ύ', + 'ώ' => 'ώ', + 'ϓ' => 'ϓ', + 'ϔ' => 'ϔ', + 'Ѐ' => 'Ѐ', + 'Ё' => 'Ё', + 'Ѓ' => 'Ѓ', + 'Ї' => 'Ї', + 'Ќ' => 'Ќ', + 'Ѝ' => 'Ѝ', + 'Ў' => 'Ў', + 'Й' => 'Й', + 'й' => 'й', + 'ѐ' => 'ѐ', + 'ё' => 'ё', + 'ѓ' => 'ѓ', + 'ї' => 'ї', + 'ќ' => 'ќ', + 'ѝ' => 'ѝ', + 'ў' => 'ў', + 'Ѷ' => 'Ѷ', + 'ѷ' => 'ѷ', + 'Ӂ' => 'Ӂ', + 'ӂ' => 'ӂ', + 'Ӑ' => 'Ӑ', + 'ӑ' => 'ӑ', + 'Ӓ' => 'Ӓ', + 'ӓ' => 'ӓ', + 'Ӗ' => 'Ӗ', + 'ӗ' => 'ӗ', + 'Ӛ' => 'Ӛ', + 'ӛ' => 'ӛ', + 'Ӝ' => 'Ӝ', + 'ӝ' => 'ӝ', + 'Ӟ' => 'Ӟ', + 'ӟ' => 'ӟ', + 'Ӣ' => 'Ӣ', + 'ӣ' => 'ӣ', + 'Ӥ' => 'Ӥ', + 'ӥ' => 'ӥ', + 'Ӧ' => 'Ӧ', + 'ӧ' => 'ӧ', + 'Ӫ' => 'Ӫ', + 'ӫ' => 'ӫ', + 'Ӭ' => 'Ӭ', + 'ӭ' => 'ӭ', + 'Ӯ' => 'Ӯ', + 'ӯ' => 'ӯ', + 'Ӱ' => 'Ӱ', + 'ӱ' => 'ӱ', + 'Ӳ' => 'Ӳ', + 'ӳ' => 'ӳ', + 'Ӵ' => 'Ӵ', + 'ӵ' => 'ӵ', + 'Ӹ' => 'Ӹ', + 'ӹ' => 'ӹ', + 'آ' => 'آ', + 'أ' => 'أ', + 'ؤ' => 'ؤ', + 'إ' => 'إ', + 'ئ' => 'ئ', + 'ۀ' => 'ۀ', + 'ۂ' => 'ۂ', + 'ۓ' => 'ۓ', + 'ऩ' => 'ऩ', + 'ऱ' => 'ऱ', + 'ऴ' => 'ऴ', + 'क़' => 'क़', + 'ख़' => 'ख़', + 'ग़' => 'ग़', + 'ज़' => 'ज़', + 'ड़' => 'ड़', + 'ढ़' => 'ढ़', + 'फ़' => 'फ़', + 'य़' => 'य़', + 'ো' => 'ো', + 'ৌ' => 'ৌ', + 'ড়' => 'ড়', + 'ঢ়' => 'ঢ়', + 'য়' => 'য়', + 'ਲ਼' => 'ਲ਼', + 'ਸ਼' => 'ਸ਼', + 'ਖ਼' => 'ਖ਼', + 'ਗ਼' => 'ਗ਼', + 'ਜ਼' => 'ਜ਼', + 'ਫ਼' => 'ਫ਼', + 'ୈ' => 'ୈ', + 'ୋ' => 'ୋ', + 'ୌ' => 'ୌ', + 'ଡ଼' => 'ଡ଼', + 'ଢ଼' => 'ଢ଼', + 'ஔ' => 'ஔ', + 'ொ' => 'ொ', + 'ோ' => 'ோ', + 'ௌ' => 'ௌ', + 'ై' => 'ై', + 'ೀ' => 'ೀ', + 'ೇ' => 'ೇ', + 'ೈ' => 'ೈ', + 'ೊ' => 'ೊ', + 'ೋ' => 'ೋ', + 'ൊ' => 'ൊ', + 'ോ' => 'ോ', + 'ൌ' => 'ൌ', + 'ේ' => 'ේ', + 'ො' => 'ො', + 'ෝ' => 'ෝ', + 'ෞ' => 'ෞ', + 'གྷ' => 'གྷ', + 'ཌྷ' => 'ཌྷ', + 'དྷ' => 'དྷ', + 'བྷ' => 'བྷ', + 'ཛྷ' => 'ཛྷ', + 'ཀྵ' => 'ཀྵ', + 'ཱི' => 'ཱི', + 'ཱུ' => 'ཱུ', + 'ྲྀ' => 'ྲྀ', + 'ླྀ' => 'ླྀ', + 'ཱྀ' => 'ཱྀ', + 'ྒྷ' => 'ྒྷ', + 'ྜྷ' => 'ྜྷ', + 'ྡྷ' => 'ྡྷ', + 'ྦྷ' => 'ྦྷ', + 'ྫྷ' => 'ྫྷ', + 'ྐྵ' => 'ྐྵ', + 'ဦ' => 'ဦ', + 'ᬆ' => 'ᬆ', + 'ᬈ' => 'ᬈ', + 'ᬊ' => 'ᬊ', + 'ᬌ' => 'ᬌ', + 'ᬎ' => 'ᬎ', + 'ᬒ' => 'ᬒ', + 'ᬻ' => 'ᬻ', + 'ᬽ' => 'ᬽ', + 'ᭀ' => 'ᭀ', + 'ᭁ' => 'ᭁ', + 'ᭃ' => 'ᭃ', + 'Ḁ' => 'Ḁ', + 'ḁ' => 'ḁ', + 'Ḃ' => 'Ḃ', + 'ḃ' => 'ḃ', + 'Ḅ' => 'Ḅ', + 'ḅ' => 'ḅ', + 'Ḇ' => 'Ḇ', + 'ḇ' => 'ḇ', + 'Ḉ' => 'Ḉ', + 'ḉ' => 'ḉ', + 'Ḋ' => 'Ḋ', + 'ḋ' => 'ḋ', + 'Ḍ' => 'Ḍ', + 'ḍ' => 'ḍ', + 'Ḏ' => 'Ḏ', + 'ḏ' => 'ḏ', + 'Ḑ' => 'Ḑ', + 'ḑ' => 'ḑ', + 'Ḓ' => 'Ḓ', + 'ḓ' => 'ḓ', + 'Ḕ' => 'Ḕ', + 'ḕ' => 'ḕ', + 'Ḗ' => 'Ḗ', + 'ḗ' => 'ḗ', + 'Ḙ' => 'Ḙ', + 'ḙ' => 'ḙ', + 'Ḛ' => 'Ḛ', + 'ḛ' => 'ḛ', + 'Ḝ' => 'Ḝ', + 'ḝ' => 'ḝ', + 'Ḟ' => 'Ḟ', + 'ḟ' => 'ḟ', + 'Ḡ' => 'Ḡ', + 'ḡ' => 'ḡ', + 'Ḣ' => 'Ḣ', + 'ḣ' => 'ḣ', + 'Ḥ' => 'Ḥ', + 'ḥ' => 'ḥ', + 'Ḧ' => 'Ḧ', + 'ḧ' => 'ḧ', + 'Ḩ' => 'Ḩ', + 'ḩ' => 'ḩ', + 'Ḫ' => 'Ḫ', + 'ḫ' => 'ḫ', + 'Ḭ' => 'Ḭ', + 'ḭ' => 'ḭ', + 'Ḯ' => 'Ḯ', + 'ḯ' => 'ḯ', + 'Ḱ' => 'Ḱ', + 'ḱ' => 'ḱ', + 'Ḳ' => 'Ḳ', + 'ḳ' => 'ḳ', + 'Ḵ' => 'Ḵ', + 'ḵ' => 'ḵ', + 'Ḷ' => 'Ḷ', + 'ḷ' => 'ḷ', + 'Ḹ' => 'Ḹ', + 'ḹ' => 'ḹ', + 'Ḻ' => 'Ḻ', + 'ḻ' => 'ḻ', + 'Ḽ' => 'Ḽ', + 'ḽ' => 'ḽ', + 'Ḿ' => 'Ḿ', + 'ḿ' => 'ḿ', + 'Ṁ' => 'Ṁ', + 'ṁ' => 'ṁ', + 'Ṃ' => 'Ṃ', + 'ṃ' => 'ṃ', + 'Ṅ' => 'Ṅ', + 'ṅ' => 'ṅ', + 'Ṇ' => 'Ṇ', + 'ṇ' => 'ṇ', + 'Ṉ' => 'Ṉ', + 'ṉ' => 'ṉ', + 'Ṋ' => 'Ṋ', + 'ṋ' => 'ṋ', + 'Ṍ' => 'Ṍ', + 'ṍ' => 'ṍ', + 'Ṏ' => 'Ṏ', + 'ṏ' => 'ṏ', + 'Ṑ' => 'Ṑ', + 'ṑ' => 'ṑ', + 'Ṓ' => 'Ṓ', + 'ṓ' => 'ṓ', + 'Ṕ' => 'Ṕ', + 'ṕ' => 'ṕ', + 'Ṗ' => 'Ṗ', + 'ṗ' => 'ṗ', + 'Ṙ' => 'Ṙ', + 'ṙ' => 'ṙ', + 'Ṛ' => 'Ṛ', + 'ṛ' => 'ṛ', + 'Ṝ' => 'Ṝ', + 'ṝ' => 'ṝ', + 'Ṟ' => 'Ṟ', + 'ṟ' => 'ṟ', + 'Ṡ' => 'Ṡ', + 'ṡ' => 'ṡ', + 'Ṣ' => 'Ṣ', + 'ṣ' => 'ṣ', + 'Ṥ' => 'Ṥ', + 'ṥ' => 'ṥ', + 'Ṧ' => 'Ṧ', + 'ṧ' => 'ṧ', + 'Ṩ' => 'Ṩ', + 'ṩ' => 'ṩ', + 'Ṫ' => 'Ṫ', + 'ṫ' => 'ṫ', + 'Ṭ' => 'Ṭ', + 'ṭ' => 'ṭ', + 'Ṯ' => 'Ṯ', + 'ṯ' => 'ṯ', + 'Ṱ' => 'Ṱ', + 'ṱ' => 'ṱ', + 'Ṳ' => 'Ṳ', + 'ṳ' => 'ṳ', + 'Ṵ' => 'Ṵ', + 'ṵ' => 'ṵ', + 'Ṷ' => 'Ṷ', + 'ṷ' => 'ṷ', + 'Ṹ' => 'Ṹ', + 'ṹ' => 'ṹ', + 'Ṻ' => 'Ṻ', + 'ṻ' => 'ṻ', + 'Ṽ' => 'Ṽ', + 'ṽ' => 'ṽ', + 'Ṿ' => 'Ṿ', + 'ṿ' => 'ṿ', + 'Ẁ' => 'Ẁ', + 'ẁ' => 'ẁ', + 'Ẃ' => 'Ẃ', + 'ẃ' => 'ẃ', + 'Ẅ' => 'Ẅ', + 'ẅ' => 'ẅ', + 'Ẇ' => 'Ẇ', + 'ẇ' => 'ẇ', + 'Ẉ' => 'Ẉ', + 'ẉ' => 'ẉ', + 'Ẋ' => 'Ẋ', + 'ẋ' => 'ẋ', + 'Ẍ' => 'Ẍ', + 'ẍ' => 'ẍ', + 'Ẏ' => 'Ẏ', + 'ẏ' => 'ẏ', + 'Ẑ' => 'Ẑ', + 'ẑ' => 'ẑ', + 'Ẓ' => 'Ẓ', + 'ẓ' => 'ẓ', + 'Ẕ' => 'Ẕ', + 'ẕ' => 'ẕ', + 'ẖ' => 'ẖ', + 'ẗ' => 'ẗ', + 'ẘ' => 'ẘ', + 'ẙ' => 'ẙ', + 'ẛ' => 'ẛ', + 'Ạ' => 'Ạ', + 'ạ' => 'ạ', + 'Ả' => 'Ả', + 'ả' => 'ả', + 'Ấ' => 'Ấ', + 'ấ' => 'ấ', + 'Ầ' => 'Ầ', + 'ầ' => 'ầ', + 'Ẩ' => 'Ẩ', + 'ẩ' => 'ẩ', + 'Ẫ' => 'Ẫ', + 'ẫ' => 'ẫ', + 'Ậ' => 'Ậ', + 'ậ' => 'ậ', + 'Ắ' => 'Ắ', + 'ắ' => 'ắ', + 'Ằ' => 'Ằ', + 'ằ' => 'ằ', + 'Ẳ' => 'Ẳ', + 'ẳ' => 'ẳ', + 'Ẵ' => 'Ẵ', + 'ẵ' => 'ẵ', + 'Ặ' => 'Ặ', + 'ặ' => 'ặ', + 'Ẹ' => 'Ẹ', + 'ẹ' => 'ẹ', + 'Ẻ' => 'Ẻ', + 'ẻ' => 'ẻ', + 'Ẽ' => 'Ẽ', + 'ẽ' => 'ẽ', + 'Ế' => 'Ế', + 'ế' => 'ế', + 'Ề' => 'Ề', + 'ề' => 'ề', + 'Ể' => 'Ể', + 'ể' => 'ể', + 'Ễ' => 'Ễ', + 'ễ' => 'ễ', + 'Ệ' => 'Ệ', + 'ệ' => 'ệ', + 'Ỉ' => 'Ỉ', + 'ỉ' => 'ỉ', + 'Ị' => 'Ị', + 'ị' => 'ị', + 'Ọ' => 'Ọ', + 'ọ' => 'ọ', + 'Ỏ' => 'Ỏ', + 'ỏ' => 'ỏ', + 'Ố' => 'Ố', + 'ố' => 'ố', + 'Ồ' => 'Ồ', + 'ồ' => 'ồ', + 'Ổ' => 'Ổ', + 'ổ' => 'ổ', + 'Ỗ' => 'Ỗ', + 'ỗ' => 'ỗ', + 'Ộ' => 'Ộ', + 'ộ' => 'ộ', + 'Ớ' => 'Ớ', + 'ớ' => 'ớ', + 'Ờ' => 'Ờ', + 'ờ' => 'ờ', + 'Ở' => 'Ở', + 'ở' => 'ở', + 'Ỡ' => 'Ỡ', + 'ỡ' => 'ỡ', + 'Ợ' => 'Ợ', + 'ợ' => 'ợ', + 'Ụ' => 'Ụ', + 'ụ' => 'ụ', + 'Ủ' => 'Ủ', + 'ủ' => 'ủ', + 'Ứ' => 'Ứ', + 'ứ' => 'ứ', + 'Ừ' => 'Ừ', + 'ừ' => 'ừ', + 'Ử' => 'Ử', + 'ử' => 'ử', + 'Ữ' => 'Ữ', + 'ữ' => 'ữ', + 'Ự' => 'Ự', + 'ự' => 'ự', + 'Ỳ' => 'Ỳ', + 'ỳ' => 'ỳ', + 'Ỵ' => 'Ỵ', + 'ỵ' => 'ỵ', + 'Ỷ' => 'Ỷ', + 'ỷ' => 'ỷ', + 'Ỹ' => 'Ỹ', + 'ỹ' => 'ỹ', + 'ἀ' => 'ἀ', + 'ἁ' => 'ἁ', + 'ἂ' => 'ἂ', + 'ἃ' => 'ἃ', + 'ἄ' => 'ἄ', + 'ἅ' => 'ἅ', + 'ἆ' => 'ἆ', + 'ἇ' => 'ἇ', + 'Ἀ' => 'Ἀ', + 'Ἁ' => 'Ἁ', + 'Ἂ' => 'Ἂ', + 'Ἃ' => 'Ἃ', + 'Ἄ' => 'Ἄ', + 'Ἅ' => 'Ἅ', + 'Ἆ' => 'Ἆ', + 'Ἇ' => 'Ἇ', + 'ἐ' => 'ἐ', + 'ἑ' => 'ἑ', + 'ἒ' => 'ἒ', + 'ἓ' => 'ἓ', + 'ἔ' => 'ἔ', + 'ἕ' => 'ἕ', + 'Ἐ' => 'Ἐ', + 'Ἑ' => 'Ἑ', + 'Ἒ' => 'Ἒ', + 'Ἓ' => 'Ἓ', + 'Ἔ' => 'Ἔ', + 'Ἕ' => 'Ἕ', + 'ἠ' => 'ἠ', + 'ἡ' => 'ἡ', + 'ἢ' => 'ἢ', + 'ἣ' => 'ἣ', + 'ἤ' => 'ἤ', + 'ἥ' => 'ἥ', + 'ἦ' => 'ἦ', + 'ἧ' => 'ἧ', + 'Ἠ' => 'Ἠ', + 'Ἡ' => 'Ἡ', + 'Ἢ' => 'Ἢ', + 'Ἣ' => 'Ἣ', + 'Ἤ' => 'Ἤ', + 'Ἥ' => 'Ἥ', + 'Ἦ' => 'Ἦ', + 'Ἧ' => 'Ἧ', + 'ἰ' => 'ἰ', + 'ἱ' => 'ἱ', + 'ἲ' => 'ἲ', + 'ἳ' => 'ἳ', + 'ἴ' => 'ἴ', + 'ἵ' => 'ἵ', + 'ἶ' => 'ἶ', + 'ἷ' => 'ἷ', + 'Ἰ' => 'Ἰ', + 'Ἱ' => 'Ἱ', + 'Ἲ' => 'Ἲ', + 'Ἳ' => 'Ἳ', + 'Ἴ' => 'Ἴ', + 'Ἵ' => 'Ἵ', + 'Ἶ' => 'Ἶ', + 'Ἷ' => 'Ἷ', + 'ὀ' => 'ὀ', + 'ὁ' => 'ὁ', + 'ὂ' => 'ὂ', + 'ὃ' => 'ὃ', + 'ὄ' => 'ὄ', + 'ὅ' => 'ὅ', + 'Ὀ' => 'Ὀ', + 'Ὁ' => 'Ὁ', + 'Ὂ' => 'Ὂ', + 'Ὃ' => 'Ὃ', + 'Ὄ' => 'Ὄ', + 'Ὅ' => 'Ὅ', + 'ὐ' => 'ὐ', + 'ὑ' => 'ὑ', + 'ὒ' => 'ὒ', + 'ὓ' => 'ὓ', + 'ὔ' => 'ὔ', + 'ὕ' => 'ὕ', + 'ὖ' => 'ὖ', + 'ὗ' => 'ὗ', + 'Ὑ' => 'Ὑ', + 'Ὓ' => 'Ὓ', + 'Ὕ' => 'Ὕ', + 'Ὗ' => 'Ὗ', + 'ὠ' => 'ὠ', + 'ὡ' => 'ὡ', + 'ὢ' => 'ὢ', + 'ὣ' => 'ὣ', + 'ὤ' => 'ὤ', + 'ὥ' => 'ὥ', + 'ὦ' => 'ὦ', + 'ὧ' => 'ὧ', + 'Ὠ' => 'Ὠ', + 'Ὡ' => 'Ὡ', + 'Ὢ' => 'Ὢ', + 'Ὣ' => 'Ὣ', + 'Ὤ' => 'Ὤ', + 'Ὥ' => 'Ὥ', + 'Ὦ' => 'Ὦ', + 'Ὧ' => 'Ὧ', + 'ὰ' => 'ὰ', + 'ά' => 'ά', + 'ὲ' => 'ὲ', + 'έ' => 'έ', + 'ὴ' => 'ὴ', + 'ή' => 'ή', + 'ὶ' => 'ὶ', + 'ί' => 'ί', + 'ὸ' => 'ὸ', + 'ό' => 'ό', + 'ὺ' => 'ὺ', + 'ύ' => 'ύ', + 'ὼ' => 'ὼ', + 'ώ' => 'ώ', + 'ᾀ' => 'ᾀ', + 'ᾁ' => 'ᾁ', + 'ᾂ' => 'ᾂ', + 'ᾃ' => 'ᾃ', + 'ᾄ' => 'ᾄ', + 'ᾅ' => 'ᾅ', + 'ᾆ' => 'ᾆ', + 'ᾇ' => 'ᾇ', + 'ᾈ' => 'ᾈ', + 'ᾉ' => 'ᾉ', + 'ᾊ' => 'ᾊ', + 'ᾋ' => 'ᾋ', + 'ᾌ' => 'ᾌ', + 'ᾍ' => 'ᾍ', + 'ᾎ' => 'ᾎ', + 'ᾏ' => 'ᾏ', + 'ᾐ' => 'ᾐ', + 'ᾑ' => 'ᾑ', + 'ᾒ' => 'ᾒ', + 'ᾓ' => 'ᾓ', + 'ᾔ' => 'ᾔ', + 'ᾕ' => 'ᾕ', + 'ᾖ' => 'ᾖ', + 'ᾗ' => 'ᾗ', + 'ᾘ' => 'ᾘ', + 'ᾙ' => 'ᾙ', + 'ᾚ' => 'ᾚ', + 'ᾛ' => 'ᾛ', + 'ᾜ' => 'ᾜ', + 'ᾝ' => 'ᾝ', + 'ᾞ' => 'ᾞ', + 'ᾟ' => 'ᾟ', + 'ᾠ' => 'ᾠ', + 'ᾡ' => 'ᾡ', + 'ᾢ' => 'ᾢ', + 'ᾣ' => 'ᾣ', + 'ᾤ' => 'ᾤ', + 'ᾥ' => 'ᾥ', + 'ᾦ' => 'ᾦ', + 'ᾧ' => 'ᾧ', + 'ᾨ' => 'ᾨ', + 'ᾩ' => 'ᾩ', + 'ᾪ' => 'ᾪ', + 'ᾫ' => 'ᾫ', + 'ᾬ' => 'ᾬ', + 'ᾭ' => 'ᾭ', + 'ᾮ' => 'ᾮ', + 'ᾯ' => 'ᾯ', + 'ᾰ' => 'ᾰ', + 'ᾱ' => 'ᾱ', + 'ᾲ' => 'ᾲ', + 'ᾳ' => 'ᾳ', + 'ᾴ' => 'ᾴ', + 'ᾶ' => 'ᾶ', + 'ᾷ' => 'ᾷ', + 'Ᾰ' => 'Ᾰ', + 'Ᾱ' => 'Ᾱ', + 'Ὰ' => 'Ὰ', + 'Ά' => 'Ά', + 'ᾼ' => 'ᾼ', + 'ι' => 'ι', + '῁' => '῁', + 'ῂ' => 'ῂ', + 'ῃ' => 'ῃ', + 'ῄ' => 'ῄ', + 'ῆ' => 'ῆ', + 'ῇ' => 'ῇ', + 'Ὲ' => 'Ὲ', + 'Έ' => 'Έ', + 'Ὴ' => 'Ὴ', + 'Ή' => 'Ή', + 'ῌ' => 'ῌ', + '῍' => '῍', + '῎' => '῎', + '῏' => '῏', + 'ῐ' => 'ῐ', + 'ῑ' => 'ῑ', + 'ῒ' => 'ῒ', + 'ΐ' => 'ΐ', + 'ῖ' => 'ῖ', + 'ῗ' => 'ῗ', + 'Ῐ' => 'Ῐ', + 'Ῑ' => 'Ῑ', + 'Ὶ' => 'Ὶ', + 'Ί' => 'Ί', + '῝' => '῝', + '῞' => '῞', + '῟' => '῟', + 'ῠ' => 'ῠ', + 'ῡ' => 'ῡ', + 'ῢ' => 'ῢ', + 'ΰ' => 'ΰ', + 'ῤ' => 'ῤ', + 'ῥ' => 'ῥ', + 'ῦ' => 'ῦ', + 'ῧ' => 'ῧ', + 'Ῠ' => 'Ῠ', + 'Ῡ' => 'Ῡ', + 'Ὺ' => 'Ὺ', + 'Ύ' => 'Ύ', + 'Ῥ' => 'Ῥ', + '῭' => '῭', + '΅' => '΅', + '`' => '`', + 'ῲ' => 'ῲ', + 'ῳ' => 'ῳ', + 'ῴ' => 'ῴ', + 'ῶ' => 'ῶ', + 'ῷ' => 'ῷ', + 'Ὸ' => 'Ὸ', + 'Ό' => 'Ό', + 'Ὼ' => 'Ὼ', + 'Ώ' => 'Ώ', + 'ῼ' => 'ῼ', + '´' => '´', + ' ' => ' ', + ' ' => ' ', + 'Ω' => 'Ω', + 'K' => 'K', + 'Å' => 'Å', + '↚' => '↚', + '↛' => '↛', + '↮' => '↮', + '⇍' => '⇍', + '⇎' => '⇎', + '⇏' => '⇏', + '∄' => '∄', + '∉' => '∉', + '∌' => '∌', + '∤' => '∤', + '∦' => '∦', + '≁' => '≁', + '≄' => '≄', + '≇' => '≇', + '≉' => '≉', + '≠' => '≠', + '≢' => '≢', + '≭' => '≭', + '≮' => '≮', + '≯' => '≯', + '≰' => '≰', + '≱' => '≱', + '≴' => '≴', + '≵' => '≵', + '≸' => '≸', + '≹' => '≹', + '⊀' => '⊀', + '⊁' => '⊁', + '⊄' => '⊄', + '⊅' => '⊅', + '⊈' => '⊈', + '⊉' => '⊉', + '⊬' => '⊬', + '⊭' => '⊭', + '⊮' => '⊮', + '⊯' => '⊯', + '⋠' => '⋠', + '⋡' => '⋡', + '⋢' => '⋢', + '⋣' => '⋣', + '⋪' => '⋪', + '⋫' => '⋫', + '⋬' => '⋬', + '⋭' => '⋭', + '〈' => '〈', + '〉' => '〉', + '⫝̸' => '⫝̸', + 'が' => 'が', + 'ぎ' => 'ぎ', + 'ぐ' => 'ぐ', + 'げ' => 'げ', + 'ご' => 'ご', + 'ざ' => 'ざ', + 'じ' => 'じ', + 'ず' => 'ず', + 'ぜ' => 'ぜ', + 'ぞ' => 'ぞ', + 'だ' => 'だ', + 'ぢ' => 'ぢ', + 'づ' => 'づ', + 'で' => 'で', + 'ど' => 'ど', + 'ば' => 'ば', + 'ぱ' => 'ぱ', + 'び' => 'び', + 'ぴ' => 'ぴ', + 'ぶ' => 'ぶ', + 'ぷ' => 'ぷ', + 'べ' => 'べ', + 'ぺ' => 'ぺ', + 'ぼ' => 'ぼ', + 'ぽ' => 'ぽ', + 'ゔ' => 'ゔ', + 'ゞ' => 'ゞ', + 'ガ' => 'ガ', + 'ギ' => 'ギ', + 'グ' => 'グ', + 'ゲ' => 'ゲ', + 'ゴ' => 'ゴ', + 'ザ' => 'ザ', + 'ジ' => 'ジ', + 'ズ' => 'ズ', + 'ゼ' => 'ゼ', + 'ゾ' => 'ゾ', + 'ダ' => 'ダ', + 'ヂ' => 'ヂ', + 'ヅ' => 'ヅ', + 'デ' => 'デ', + 'ド' => 'ド', + 'バ' => 'バ', + 'パ' => 'パ', + 'ビ' => 'ビ', + 'ピ' => 'ピ', + 'ブ' => 'ブ', + 'プ' => 'プ', + 'ベ' => 'ベ', + 'ペ' => 'ペ', + 'ボ' => 'ボ', + 'ポ' => 'ポ', + 'ヴ' => 'ヴ', + 'ヷ' => 'ヷ', + 'ヸ' => 'ヸ', + 'ヹ' => 'ヹ', + 'ヺ' => 'ヺ', + 'ヾ' => 'ヾ', + '豈' => '豈', + '更' => '更', + '車' => '車', + '賈' => '賈', + '滑' => '滑', + '串' => '串', + '句' => '句', + '龜' => '龜', + '龜' => '龜', + '契' => '契', + '金' => '金', + '喇' => '喇', + '奈' => '奈', + '懶' => '懶', + '癩' => '癩', + '羅' => '羅', + '蘿' => '蘿', + '螺' => '螺', + '裸' => '裸', + '邏' => '邏', + '樂' => '樂', + '洛' => '洛', + '烙' => '烙', + '珞' => '珞', + '落' => '落', + '酪' => '酪', + '駱' => '駱', + '亂' => '亂', + '卵' => '卵', + '欄' => '欄', + '爛' => '爛', + '蘭' => '蘭', + '鸞' => '鸞', + '嵐' => '嵐', + '濫' => '濫', + '藍' => '藍', + '襤' => '襤', + '拉' => '拉', + '臘' => '臘', + '蠟' => '蠟', + '廊' => '廊', + '朗' => '朗', + '浪' => '浪', + '狼' => '狼', + '郎' => '郎', + '來' => '來', + '冷' => '冷', + '勞' => '勞', + '擄' => '擄', + '櫓' => '櫓', + '爐' => '爐', + '盧' => '盧', + '老' => '老', + '蘆' => '蘆', + '虜' => '虜', + '路' => '路', + '露' => '露', + '魯' => '魯', + '鷺' => '鷺', + '碌' => '碌', + '祿' => '祿', + '綠' => '綠', + '菉' => '菉', + '錄' => '錄', + '鹿' => '鹿', + '論' => '論', + '壟' => '壟', + '弄' => '弄', + '籠' => '籠', + '聾' => '聾', + '牢' => '牢', + '磊' => '磊', + '賂' => '賂', + '雷' => '雷', + '壘' => '壘', + '屢' => '屢', + '樓' => '樓', + '淚' => '淚', + '漏' => '漏', + '累' => '累', + '縷' => '縷', + '陋' => '陋', + '勒' => '勒', + '肋' => '肋', + '凜' => '凜', + '凌' => '凌', + '稜' => '稜', + '綾' => '綾', + '菱' => '菱', + '陵' => '陵', + '讀' => '讀', + '拏' => '拏', + '樂' => '樂', + '諾' => '諾', + '丹' => '丹', + '寧' => '寧', + '怒' => '怒', + '率' => '率', + '異' => '異', + '北' => '北', + '磻' => '磻', + '便' => '便', + '復' => '復', + '不' => '不', + '泌' => '泌', + '數' => '數', + '索' => '索', + '參' => '參', + '塞' => '塞', + '省' => '省', + '葉' => '葉', + '說' => '說', + '殺' => '殺', + '辰' => '辰', + '沈' => '沈', + '拾' => '拾', + '若' => '若', + '掠' => '掠', + '略' => '略', + '亮' => '亮', + '兩' => '兩', + '凉' => '凉', + '梁' => '梁', + '糧' => '糧', + '良' => '良', + '諒' => '諒', + '量' => '量', + '勵' => '勵', + '呂' => '呂', + '女' => '女', + '廬' => '廬', + '旅' => '旅', + '濾' => '濾', + '礪' => '礪', + '閭' => '閭', + '驪' => '驪', + '麗' => '麗', + '黎' => '黎', + '力' => '力', + '曆' => '曆', + '歷' => '歷', + '轢' => '轢', + '年' => '年', + '憐' => '憐', + '戀' => '戀', + '撚' => '撚', + '漣' => '漣', + '煉' => '煉', + '璉' => '璉', + '秊' => '秊', + '練' => '練', + '聯' => '聯', + '輦' => '輦', + '蓮' => '蓮', + '連' => '連', + '鍊' => '鍊', + '列' => '列', + '劣' => '劣', + '咽' => '咽', + '烈' => '烈', + '裂' => '裂', + '說' => '說', + '廉' => '廉', + '念' => '念', + '捻' => '捻', + '殮' => '殮', + '簾' => '簾', + '獵' => '獵', + '令' => '令', + '囹' => '囹', + '寧' => '寧', + '嶺' => '嶺', + '怜' => '怜', + '玲' => '玲', + '瑩' => '瑩', + '羚' => '羚', + '聆' => '聆', + '鈴' => '鈴', + '零' => '零', + '靈' => '靈', + '領' => '領', + '例' => '例', + '禮' => '禮', + '醴' => '醴', + '隸' => '隸', + '惡' => '惡', + '了' => '了', + '僚' => '僚', + '寮' => '寮', + '尿' => '尿', + '料' => '料', + '樂' => '樂', + '燎' => '燎', + '療' => '療', + '蓼' => '蓼', + '遼' => '遼', + '龍' => '龍', + '暈' => '暈', + '阮' => '阮', + '劉' => '劉', + '杻' => '杻', + '柳' => '柳', + '流' => '流', + '溜' => '溜', + '琉' => '琉', + '留' => '留', + '硫' => '硫', + '紐' => '紐', + '類' => '類', + '六' => '六', + '戮' => '戮', + '陸' => '陸', + '倫' => '倫', + '崙' => '崙', + '淪' => '淪', + '輪' => '輪', + '律' => '律', + '慄' => '慄', + '栗' => '栗', + '率' => '率', + '隆' => '隆', + '利' => '利', + '吏' => '吏', + '履' => '履', + '易' => '易', + '李' => '李', + '梨' => '梨', + '泥' => '泥', + '理' => '理', + '痢' => '痢', + '罹' => '罹', + '裏' => '裏', + '裡' => '裡', + '里' => '里', + '離' => '離', + '匿' => '匿', + '溺' => '溺', + '吝' => '吝', + '燐' => '燐', + '璘' => '璘', + '藺' => '藺', + '隣' => '隣', + '鱗' => '鱗', + '麟' => '麟', + '林' => '林', + '淋' => '淋', + '臨' => '臨', + '立' => '立', + '笠' => '笠', + '粒' => '粒', + '狀' => '狀', + '炙' => '炙', + '識' => '識', + '什' => '什', + '茶' => '茶', + '刺' => '刺', + '切' => '切', + '度' => '度', + '拓' => '拓', + '糖' => '糖', + '宅' => '宅', + '洞' => '洞', + '暴' => '暴', + '輻' => '輻', + '行' => '行', + '降' => '降', + '見' => '見', + '廓' => '廓', + '兀' => '兀', + '嗀' => '嗀', + '塚' => '塚', + '晴' => '晴', + '凞' => '凞', + '猪' => '猪', + '益' => '益', + '礼' => '礼', + '神' => '神', + '祥' => '祥', + '福' => '福', + '靖' => '靖', + '精' => '精', + '羽' => '羽', + '蘒' => '蘒', + '諸' => '諸', + '逸' => '逸', + '都' => '都', + '飯' => '飯', + '飼' => '飼', + '館' => '館', + '鶴' => '鶴', + '郞' => '郞', + '隷' => '隷', + '侮' => '侮', + '僧' => '僧', + '免' => '免', + '勉' => '勉', + '勤' => '勤', + '卑' => '卑', + '喝' => '喝', + '嘆' => '嘆', + '器' => '器', + '塀' => '塀', + '墨' => '墨', + '層' => '層', + '屮' => '屮', + '悔' => '悔', + '慨' => '慨', + '憎' => '憎', + '懲' => '懲', + '敏' => '敏', + '既' => '既', + '暑' => '暑', + '梅' => '梅', + '海' => '海', + '渚' => '渚', + '漢' => '漢', + '煮' => '煮', + '爫' => '爫', + '琢' => '琢', + '碑' => '碑', + '社' => '社', + '祉' => '祉', + '祈' => '祈', + '祐' => '祐', + '祖' => '祖', + '祝' => '祝', + '禍' => '禍', + '禎' => '禎', + '穀' => '穀', + '突' => '突', + '節' => '節', + '練' => '練', + '縉' => '縉', + '繁' => '繁', + '署' => '署', + '者' => '者', + '臭' => '臭', + '艹' => '艹', + '艹' => '艹', + '著' => '著', + '褐' => '褐', + '視' => '視', + '謁' => '謁', + '謹' => '謹', + '賓' => '賓', + '贈' => '贈', + '辶' => '辶', + '逸' => '逸', + '難' => '難', + '響' => '響', + '頻' => '頻', + '恵' => '恵', + '𤋮' => '𤋮', + '舘' => '舘', + '並' => '並', + '况' => '况', + '全' => '全', + '侀' => '侀', + '充' => '充', + '冀' => '冀', + '勇' => '勇', + '勺' => '勺', + '喝' => '喝', + '啕' => '啕', + '喙' => '喙', + '嗢' => '嗢', + '塚' => '塚', + '墳' => '墳', + '奄' => '奄', + '奔' => '奔', + '婢' => '婢', + '嬨' => '嬨', + '廒' => '廒', + '廙' => '廙', + '彩' => '彩', + '徭' => '徭', + '惘' => '惘', + '慎' => '慎', + '愈' => '愈', + '憎' => '憎', + '慠' => '慠', + '懲' => '懲', + '戴' => '戴', + '揄' => '揄', + '搜' => '搜', + '摒' => '摒', + '敖' => '敖', + '晴' => '晴', + '朗' => '朗', + '望' => '望', + '杖' => '杖', + '歹' => '歹', + '殺' => '殺', + '流' => '流', + '滛' => '滛', + '滋' => '滋', + '漢' => '漢', + '瀞' => '瀞', + '煮' => '煮', + '瞧' => '瞧', + '爵' => '爵', + '犯' => '犯', + '猪' => '猪', + '瑱' => '瑱', + '甆' => '甆', + '画' => '画', + '瘝' => '瘝', + '瘟' => '瘟', + '益' => '益', + '盛' => '盛', + '直' => '直', + '睊' => '睊', + '着' => '着', + '磌' => '磌', + '窱' => '窱', + '節' => '節', + '类' => '类', + '絛' => '絛', + '練' => '練', + '缾' => '缾', + '者' => '者', + '荒' => '荒', + '華' => '華', + '蝹' => '蝹', + '襁' => '襁', + '覆' => '覆', + '視' => '視', + '調' => '調', + '諸' => '諸', + '請' => '請', + '謁' => '謁', + '諾' => '諾', + '諭' => '諭', + '謹' => '謹', + '變' => '變', + '贈' => '贈', + '輸' => '輸', + '遲' => '遲', + '醙' => '醙', + '鉶' => '鉶', + '陼' => '陼', + '難' => '難', + '靖' => '靖', + '韛' => '韛', + '響' => '響', + '頋' => '頋', + '頻' => '頻', + '鬒' => '鬒', + '龜' => '龜', + '𢡊' => '𢡊', + '𢡄' => '𢡄', + '𣏕' => '𣏕', + '㮝' => '㮝', + '䀘' => '䀘', + '䀹' => '䀹', + '𥉉' => '𥉉', + '𥳐' => '𥳐', + '𧻓' => '𧻓', + '齃' => '齃', + '龎' => '龎', + 'יִ' => 'יִ', + 'ײַ' => 'ײַ', + 'שׁ' => 'שׁ', + 'שׂ' => 'שׂ', + 'שּׁ' => 'שּׁ', + 'שּׂ' => 'שּׂ', + 'אַ' => 'אַ', + 'אָ' => 'אָ', + 'אּ' => 'אּ', + 'בּ' => 'בּ', + 'גּ' => 'גּ', + 'דּ' => 'דּ', + 'הּ' => 'הּ', + 'וּ' => 'וּ', + 'זּ' => 'זּ', + 'טּ' => 'טּ', + 'יּ' => 'יּ', + 'ךּ' => 'ךּ', + 'כּ' => 'כּ', + 'לּ' => 'לּ', + 'מּ' => 'מּ', + 'נּ' => 'נּ', + 'סּ' => 'סּ', + 'ףּ' => 'ףּ', + 'פּ' => 'פּ', + 'צּ' => 'צּ', + 'קּ' => 'קּ', + 'רּ' => 'רּ', + 'שּ' => 'שּ', + 'תּ' => 'תּ', + 'וֹ' => 'וֹ', + 'בֿ' => 'בֿ', + 'כֿ' => 'כֿ', + 'פֿ' => 'פֿ', + '𑂚' => '𑂚', + '𑂜' => '𑂜', + '𑂫' => '𑂫', + '𑄮' => '𑄮', + '𑄯' => '𑄯', + '𑍋' => '𑍋', + '𑍌' => '𑍌', + '𑒻' => '𑒻', + '𑒼' => '𑒼', + '𑒾' => '𑒾', + '𑖺' => '𑖺', + '𑖻' => '𑖻', + '𑤸' => '𑤸', + '𝅗𝅥' => '𝅗𝅥', + '𝅘𝅥' => '𝅘𝅥', + '𝅘𝅥𝅮' => '𝅘𝅥𝅮', + '𝅘𝅥𝅯' => '𝅘𝅥𝅯', + '𝅘𝅥𝅰' => '𝅘𝅥𝅰', + '𝅘𝅥𝅱' => '𝅘𝅥𝅱', + '𝅘𝅥𝅲' => '𝅘𝅥𝅲', + '𝆹𝅥' => '𝆹𝅥', + '𝆺𝅥' => '𝆺𝅥', + '𝆹𝅥𝅮' => '𝆹𝅥𝅮', + '𝆺𝅥𝅮' => '𝆺𝅥𝅮', + '𝆹𝅥𝅯' => '𝆹𝅥𝅯', + '𝆺𝅥𝅯' => '𝆺𝅥𝅯', + '丽' => '丽', + '丸' => '丸', + '乁' => '乁', + '𠄢' => '𠄢', + '你' => '你', + '侮' => '侮', + '侻' => '侻', + '倂' => '倂', + '偺' => '偺', + '備' => '備', + '僧' => '僧', + '像' => '像', + '㒞' => '㒞', + '𠘺' => '𠘺', + '免' => '免', + '兔' => '兔', + '兤' => '兤', + '具' => '具', + '𠔜' => '𠔜', + '㒹' => '㒹', + '內' => '內', + '再' => '再', + '𠕋' => '𠕋', + '冗' => '冗', + '冤' => '冤', + '仌' => '仌', + '冬' => '冬', + '况' => '况', + '𩇟' => '𩇟', + '凵' => '凵', + '刃' => '刃', + '㓟' => '㓟', + '刻' => '刻', + '剆' => '剆', + '割' => '割', + '剷' => '剷', + '㔕' => '㔕', + '勇' => '勇', + '勉' => '勉', + '勤' => '勤', + '勺' => '勺', + '包' => '包', + '匆' => '匆', + '北' => '北', + '卉' => '卉', + '卑' => '卑', + '博' => '博', + '即' => '即', + '卽' => '卽', + '卿' => '卿', + '卿' => '卿', + '卿' => '卿', + '𠨬' => '𠨬', + '灰' => '灰', + '及' => '及', + '叟' => '叟', + '𠭣' => '𠭣', + '叫' => '叫', + '叱' => '叱', + '吆' => '吆', + '咞' => '咞', + '吸' => '吸', + '呈' => '呈', + '周' => '周', + '咢' => '咢', + '哶' => '哶', + '唐' => '唐', + '啓' => '啓', + '啣' => '啣', + '善' => '善', + '善' => '善', + '喙' => '喙', + '喫' => '喫', + '喳' => '喳', + '嗂' => '嗂', + '圖' => '圖', + '嘆' => '嘆', + '圗' => '圗', + '噑' => '噑', + '噴' => '噴', + '切' => '切', + '壮' => '壮', + '城' => '城', + '埴' => '埴', + '堍' => '堍', + '型' => '型', + '堲' => '堲', + '報' => '報', + '墬' => '墬', + '𡓤' => '𡓤', + '売' => '売', + '壷' => '壷', + '夆' => '夆', + '多' => '多', + '夢' => '夢', + '奢' => '奢', + '𡚨' => '𡚨', + '𡛪' => '𡛪', + '姬' => '姬', + '娛' => '娛', + '娧' => '娧', + '姘' => '姘', + '婦' => '婦', + '㛮' => '㛮', + '㛼' => '㛼', + '嬈' => '嬈', + '嬾' => '嬾', + '嬾' => '嬾', + '𡧈' => '𡧈', + '寃' => '寃', + '寘' => '寘', + '寧' => '寧', + '寳' => '寳', + '𡬘' => '𡬘', + '寿' => '寿', + '将' => '将', + '当' => '当', + '尢' => '尢', + '㞁' => '㞁', + '屠' => '屠', + '屮' => '屮', + '峀' => '峀', + '岍' => '岍', + '𡷤' => '𡷤', + '嵃' => '嵃', + '𡷦' => '𡷦', + '嵮' => '嵮', + '嵫' => '嵫', + '嵼' => '嵼', + '巡' => '巡', + '巢' => '巢', + '㠯' => '㠯', + '巽' => '巽', + '帨' => '帨', + '帽' => '帽', + '幩' => '幩', + '㡢' => '㡢', + '𢆃' => '𢆃', + '㡼' => '㡼', + '庰' => '庰', + '庳' => '庳', + '庶' => '庶', + '廊' => '廊', + '𪎒' => '𪎒', + '廾' => '廾', + '𢌱' => '𢌱', + '𢌱' => '𢌱', + '舁' => '舁', + '弢' => '弢', + '弢' => '弢', + '㣇' => '㣇', + '𣊸' => '𣊸', + '𦇚' => '𦇚', + '形' => '形', + '彫' => '彫', + '㣣' => '㣣', + '徚' => '徚', + '忍' => '忍', + '志' => '志', + '忹' => '忹', + '悁' => '悁', + '㤺' => '㤺', + '㤜' => '㤜', + '悔' => '悔', + '𢛔' => '𢛔', + '惇' => '惇', + '慈' => '慈', + '慌' => '慌', + '慎' => '慎', + '慌' => '慌', + '慺' => '慺', + '憎' => '憎', + '憲' => '憲', + '憤' => '憤', + '憯' => '憯', + '懞' => '懞', + '懲' => '懲', + '懶' => '懶', + '成' => '成', + '戛' => '戛', + '扝' => '扝', + '抱' => '抱', + '拔' => '拔', + '捐' => '捐', + '𢬌' => '𢬌', + '挽' => '挽', + '拼' => '拼', + '捨' => '捨', + '掃' => '掃', + '揤' => '揤', + '𢯱' => '𢯱', + '搢' => '搢', + '揅' => '揅', + '掩' => '掩', + '㨮' => '㨮', + '摩' => '摩', + '摾' => '摾', + '撝' => '撝', + '摷' => '摷', + '㩬' => '㩬', + '敏' => '敏', + '敬' => '敬', + '𣀊' => '𣀊', + '旣' => '旣', + '書' => '書', + '晉' => '晉', + '㬙' => '㬙', + '暑' => '暑', + '㬈' => '㬈', + '㫤' => '㫤', + '冒' => '冒', + '冕' => '冕', + '最' => '最', + '暜' => '暜', + '肭' => '肭', + '䏙' => '䏙', + '朗' => '朗', + '望' => '望', + '朡' => '朡', + '杞' => '杞', + '杓' => '杓', + '𣏃' => '𣏃', + '㭉' => '㭉', + '柺' => '柺', + '枅' => '枅', + '桒' => '桒', + '梅' => '梅', + '𣑭' => '𣑭', + '梎' => '梎', + '栟' => '栟', + '椔' => '椔', + '㮝' => '㮝', + '楂' => '楂', + '榣' => '榣', + '槪' => '槪', + '檨' => '檨', + '𣚣' => '𣚣', + '櫛' => '櫛', + '㰘' => '㰘', + '次' => '次', + '𣢧' => '𣢧', + '歔' => '歔', + '㱎' => '㱎', + '歲' => '歲', + '殟' => '殟', + '殺' => '殺', + '殻' => '殻', + '𣪍' => '𣪍', + '𡴋' => '𡴋', + '𣫺' => '𣫺', + '汎' => '汎', + '𣲼' => '𣲼', + '沿' => '沿', + '泍' => '泍', + '汧' => '汧', + '洖' => '洖', + '派' => '派', + '海' => '海', + '流' => '流', + '浩' => '浩', + '浸' => '浸', + '涅' => '涅', + '𣴞' => '𣴞', + '洴' => '洴', + '港' => '港', + '湮' => '湮', + '㴳' => '㴳', + '滋' => '滋', + '滇' => '滇', + '𣻑' => '𣻑', + '淹' => '淹', + '潮' => '潮', + '𣽞' => '𣽞', + '𣾎' => '𣾎', + '濆' => '濆', + '瀹' => '瀹', + '瀞' => '瀞', + '瀛' => '瀛', + '㶖' => '㶖', + '灊' => '灊', + '災' => '災', + '灷' => '灷', + '炭' => '炭', + '𠔥' => '𠔥', + '煅' => '煅', + '𤉣' => '𤉣', + '熜' => '熜', + '𤎫' => '𤎫', + '爨' => '爨', + '爵' => '爵', + '牐' => '牐', + '𤘈' => '𤘈', + '犀' => '犀', + '犕' => '犕', + '𤜵' => '𤜵', + '𤠔' => '𤠔', + '獺' => '獺', + '王' => '王', + '㺬' => '㺬', + '玥' => '玥', + '㺸' => '㺸', + '㺸' => '㺸', + '瑇' => '瑇', + '瑜' => '瑜', + '瑱' => '瑱', + '璅' => '璅', + '瓊' => '瓊', + '㼛' => '㼛', + '甤' => '甤', + '𤰶' => '𤰶', + '甾' => '甾', + '𤲒' => '𤲒', + '異' => '異', + '𢆟' => '𢆟', + '瘐' => '瘐', + '𤾡' => '𤾡', + '𤾸' => '𤾸', + '𥁄' => '𥁄', + '㿼' => '㿼', + '䀈' => '䀈', + '直' => '直', + '𥃳' => '𥃳', + '𥃲' => '𥃲', + '𥄙' => '𥄙', + '𥄳' => '𥄳', + '眞' => '眞', + '真' => '真', + '真' => '真', + '睊' => '睊', + '䀹' => '䀹', + '瞋' => '瞋', + '䁆' => '䁆', + '䂖' => '䂖', + '𥐝' => '𥐝', + '硎' => '硎', + '碌' => '碌', + '磌' => '磌', + '䃣' => '䃣', + '𥘦' => '𥘦', + '祖' => '祖', + '𥚚' => '𥚚', + '𥛅' => '𥛅', + '福' => '福', + '秫' => '秫', + '䄯' => '䄯', + '穀' => '穀', + '穊' => '穊', + '穏' => '穏', + '𥥼' => '𥥼', + '𥪧' => '𥪧', + '𥪧' => '𥪧', + '竮' => '竮', + '䈂' => '䈂', + '𥮫' => '𥮫', + '篆' => '篆', + '築' => '築', + '䈧' => '䈧', + '𥲀' => '𥲀', + '糒' => '糒', + '䊠' => '䊠', + '糨' => '糨', + '糣' => '糣', + '紀' => '紀', + '𥾆' => '𥾆', + '絣' => '絣', + '䌁' => '䌁', + '緇' => '緇', + '縂' => '縂', + '繅' => '繅', + '䌴' => '䌴', + '𦈨' => '𦈨', + '𦉇' => '𦉇', + '䍙' => '䍙', + '𦋙' => '𦋙', + '罺' => '罺', + '𦌾' => '𦌾', + '羕' => '羕', + '翺' => '翺', + '者' => '者', + '𦓚' => '𦓚', + '𦔣' => '𦔣', + '聠' => '聠', + '𦖨' => '𦖨', + '聰' => '聰', + '𣍟' => '𣍟', + '䏕' => '䏕', + '育' => '育', + '脃' => '脃', + '䐋' => '䐋', + '脾' => '脾', + '媵' => '媵', + '𦞧' => '𦞧', + '𦞵' => '𦞵', + '𣎓' => '𣎓', + '𣎜' => '𣎜', + '舁' => '舁', + '舄' => '舄', + '辞' => '辞', + '䑫' => '䑫', + '芑' => '芑', + '芋' => '芋', + '芝' => '芝', + '劳' => '劳', + '花' => '花', + '芳' => '芳', + '芽' => '芽', + '苦' => '苦', + '𦬼' => '𦬼', + '若' => '若', + '茝' => '茝', + '荣' => '荣', + '莭' => '莭', + '茣' => '茣', + '莽' => '莽', + '菧' => '菧', + '著' => '著', + '荓' => '荓', + '菊' => '菊', + '菌' => '菌', + '菜' => '菜', + '𦰶' => '𦰶', + '𦵫' => '𦵫', + '𦳕' => '𦳕', + '䔫' => '䔫', + '蓱' => '蓱', + '蓳' => '蓳', + '蔖' => '蔖', + '𧏊' => '𧏊', + '蕤' => '蕤', + '𦼬' => '𦼬', + '䕝' => '䕝', + '䕡' => '䕡', + '𦾱' => '𦾱', + '𧃒' => '𧃒', + '䕫' => '䕫', + '虐' => '虐', + '虜' => '虜', + '虧' => '虧', + '虩' => '虩', + '蚩' => '蚩', + '蚈' => '蚈', + '蜎' => '蜎', + '蛢' => '蛢', + '蝹' => '蝹', + '蜨' => '蜨', + '蝫' => '蝫', + '螆' => '螆', + '䗗' => '䗗', + '蟡' => '蟡', + '蠁' => '蠁', + '䗹' => '䗹', + '衠' => '衠', + '衣' => '衣', + '𧙧' => '𧙧', + '裗' => '裗', + '裞' => '裞', + '䘵' => '䘵', + '裺' => '裺', + '㒻' => '㒻', + '𧢮' => '𧢮', + '𧥦' => '𧥦', + '䚾' => '䚾', + '䛇' => '䛇', + '誠' => '誠', + '諭' => '諭', + '變' => '變', + '豕' => '豕', + '𧲨' => '𧲨', + '貫' => '貫', + '賁' => '賁', + '贛' => '贛', + '起' => '起', + '𧼯' => '𧼯', + '𠠄' => '𠠄', + '跋' => '跋', + '趼' => '趼', + '跰' => '跰', + '𠣞' => '𠣞', + '軔' => '軔', + '輸' => '輸', + '𨗒' => '𨗒', + '𨗭' => '𨗭', + '邔' => '邔', + '郱' => '郱', + '鄑' => '鄑', + '𨜮' => '𨜮', + '鄛' => '鄛', + '鈸' => '鈸', + '鋗' => '鋗', + '鋘' => '鋘', + '鉼' => '鉼', + '鏹' => '鏹', + '鐕' => '鐕', + '𨯺' => '𨯺', + '開' => '開', + '䦕' => '䦕', + '閷' => '閷', + '𨵷' => '𨵷', + '䧦' => '䧦', + '雃' => '雃', + '嶲' => '嶲', + '霣' => '霣', + '𩅅' => '𩅅', + '𩈚' => '𩈚', + '䩮' => '䩮', + '䩶' => '䩶', + '韠' => '韠', + '𩐊' => '𩐊', + '䪲' => '䪲', + '𩒖' => '𩒖', + '頋' => '頋', + '頋' => '頋', + '頩' => '頩', + '𩖶' => '𩖶', + '飢' => '飢', + '䬳' => '䬳', + '餩' => '餩', + '馧' => '馧', + '駂' => '駂', + '駾' => '駾', + '䯎' => '䯎', + '𩬰' => '𩬰', + '鬒' => '鬒', + '鱀' => '鱀', + '鳽' => '鳽', + '䳎' => '䳎', + '䳭' => '䳭', + '鵧' => '鵧', + '𪃎' => '𪃎', + '䳸' => '䳸', + '𪄅' => '𪄅', + '𪈎' => '𪈎', + '𪊑' => '𪊑', + '麻' => '麻', + '䵖' => '䵖', + '黹' => '黹', + '黾' => '黾', + '鼅' => '鼅', + '鼏' => '鼏', + '鼖' => '鼖', + '鼻' => '鼻', + '𪘀' => '𪘀', +); diff --git a/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php b/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php new file mode 100644 index 0000000..ec90f36 --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php @@ -0,0 +1,876 @@ +<?php + +return array ( + '̀' => 230, + '́' => 230, + '̂' => 230, + '̃' => 230, + '̄' => 230, + '̅' => 230, + '̆' => 230, + '̇' => 230, + '̈' => 230, + '̉' => 230, + '̊' => 230, + '̋' => 230, + '̌' => 230, + '̍' => 230, + '̎' => 230, + '̏' => 230, + '̐' => 230, + '̑' => 230, + '̒' => 230, + '̓' => 230, + '̔' => 230, + '̕' => 232, + '̖' => 220, + '̗' => 220, + '̘' => 220, + '̙' => 220, + '̚' => 232, + '̛' => 216, + '̜' => 220, + '̝' => 220, + '̞' => 220, + '̟' => 220, + '̠' => 220, + '̡' => 202, + '̢' => 202, + '̣' => 220, + '̤' => 220, + '̥' => 220, + '̦' => 220, + '̧' => 202, + '̨' => 202, + '̩' => 220, + '̪' => 220, + '̫' => 220, + '̬' => 220, + '̭' => 220, + '̮' => 220, + '̯' => 220, + '̰' => 220, + '̱' => 220, + '̲' => 220, + '̳' => 220, + '̴' => 1, + '̵' => 1, + '̶' => 1, + '̷' => 1, + '̸' => 1, + '̹' => 220, + '̺' => 220, + '̻' => 220, + '̼' => 220, + '̽' => 230, + '̾' => 230, + '̿' => 230, + '̀' => 230, + '́' => 230, + '͂' => 230, + '̓' => 230, + '̈́' => 230, + 'ͅ' => 240, + '͆' => 230, + '͇' => 220, + '͈' => 220, + '͉' => 220, + '͊' => 230, + '͋' => 230, + '͌' => 230, + '͍' => 220, + '͎' => 220, + '͐' => 230, + '͑' => 230, + '͒' => 230, + '͓' => 220, + '͔' => 220, + '͕' => 220, + '͖' => 220, + '͗' => 230, + '͘' => 232, + '͙' => 220, + '͚' => 220, + '͛' => 230, + '͜' => 233, + '͝' => 234, + '͞' => 234, + '͟' => 233, + '͠' => 234, + '͡' => 234, + '͢' => 233, + 'ͣ' => 230, + 'ͤ' => 230, + 'ͥ' => 230, + 'ͦ' => 230, + 'ͧ' => 230, + 'ͨ' => 230, + 'ͩ' => 230, + 'ͪ' => 230, + 'ͫ' => 230, + 'ͬ' => 230, + 'ͭ' => 230, + 'ͮ' => 230, + 'ͯ' => 230, + '҃' => 230, + '҄' => 230, + '҅' => 230, + '҆' => 230, + '҇' => 230, + '֑' => 220, + '֒' => 230, + '֓' => 230, + '֔' => 230, + '֕' => 230, + '֖' => 220, + '֗' => 230, + '֘' => 230, + '֙' => 230, + '֚' => 222, + '֛' => 220, + '֜' => 230, + '֝' => 230, + '֞' => 230, + '֟' => 230, + '֠' => 230, + '֡' => 230, + '֢' => 220, + '֣' => 220, + '֤' => 220, + '֥' => 220, + '֦' => 220, + '֧' => 220, + '֨' => 230, + '֩' => 230, + '֪' => 220, + '֫' => 230, + '֬' => 230, + '֭' => 222, + '֮' => 228, + '֯' => 230, + 'ְ' => 10, + 'ֱ' => 11, + 'ֲ' => 12, + 'ֳ' => 13, + 'ִ' => 14, + 'ֵ' => 15, + 'ֶ' => 16, + 'ַ' => 17, + 'ָ' => 18, + 'ֹ' => 19, + 'ֺ' => 19, + 'ֻ' => 20, + 'ּ' => 21, + 'ֽ' => 22, + 'ֿ' => 23, + 'ׁ' => 24, + 'ׂ' => 25, + 'ׄ' => 230, + 'ׅ' => 220, + 'ׇ' => 18, + 'ؐ' => 230, + 'ؑ' => 230, + 'ؒ' => 230, + 'ؓ' => 230, + 'ؔ' => 230, + 'ؕ' => 230, + 'ؖ' => 230, + 'ؗ' => 230, + 'ؘ' => 30, + 'ؙ' => 31, + 'ؚ' => 32, + 'ً' => 27, + 'ٌ' => 28, + 'ٍ' => 29, + 'َ' => 30, + 'ُ' => 31, + 'ِ' => 32, + 'ّ' => 33, + 'ْ' => 34, + 'ٓ' => 230, + 'ٔ' => 230, + 'ٕ' => 220, + 'ٖ' => 220, + 'ٗ' => 230, + '٘' => 230, + 'ٙ' => 230, + 'ٚ' => 230, + 'ٛ' => 230, + 'ٜ' => 220, + 'ٝ' => 230, + 'ٞ' => 230, + 'ٟ' => 220, + 'ٰ' => 35, + 'ۖ' => 230, + 'ۗ' => 230, + 'ۘ' => 230, + 'ۙ' => 230, + 'ۚ' => 230, + 'ۛ' => 230, + 'ۜ' => 230, + '۟' => 230, + '۠' => 230, + 'ۡ' => 230, + 'ۢ' => 230, + 'ۣ' => 220, + 'ۤ' => 230, + 'ۧ' => 230, + 'ۨ' => 230, + '۪' => 220, + '۫' => 230, + '۬' => 230, + 'ۭ' => 220, + 'ܑ' => 36, + 'ܰ' => 230, + 'ܱ' => 220, + 'ܲ' => 230, + 'ܳ' => 230, + 'ܴ' => 220, + 'ܵ' => 230, + 'ܶ' => 230, + 'ܷ' => 220, + 'ܸ' => 220, + 'ܹ' => 220, + 'ܺ' => 230, + 'ܻ' => 220, + 'ܼ' => 220, + 'ܽ' => 230, + 'ܾ' => 220, + 'ܿ' => 230, + '݀' => 230, + '݁' => 230, + '݂' => 220, + '݃' => 230, + '݄' => 220, + '݅' => 230, + '݆' => 220, + '݇' => 230, + '݈' => 220, + '݉' => 230, + '݊' => 230, + '߫' => 230, + '߬' => 230, + '߭' => 230, + '߮' => 230, + '߯' => 230, + '߰' => 230, + '߱' => 230, + '߲' => 220, + '߳' => 230, + '߽' => 220, + 'ࠖ' => 230, + 'ࠗ' => 230, + '࠘' => 230, + '࠙' => 230, + 'ࠛ' => 230, + 'ࠜ' => 230, + 'ࠝ' => 230, + 'ࠞ' => 230, + 'ࠟ' => 230, + 'ࠠ' => 230, + 'ࠡ' => 230, + 'ࠢ' => 230, + 'ࠣ' => 230, + 'ࠥ' => 230, + 'ࠦ' => 230, + 'ࠧ' => 230, + 'ࠩ' => 230, + 'ࠪ' => 230, + 'ࠫ' => 230, + 'ࠬ' => 230, + '࠭' => 230, + '࡙' => 220, + '࡚' => 220, + '࡛' => 220, + '࣓' => 220, + 'ࣔ' => 230, + 'ࣕ' => 230, + 'ࣖ' => 230, + 'ࣗ' => 230, + 'ࣘ' => 230, + 'ࣙ' => 230, + 'ࣚ' => 230, + 'ࣛ' => 230, + 'ࣜ' => 230, + 'ࣝ' => 230, + 'ࣞ' => 230, + 'ࣟ' => 230, + '࣠' => 230, + '࣡' => 230, + 'ࣣ' => 220, + 'ࣤ' => 230, + 'ࣥ' => 230, + 'ࣦ' => 220, + 'ࣧ' => 230, + 'ࣨ' => 230, + 'ࣩ' => 220, + '࣪' => 230, + '࣫' => 230, + '࣬' => 230, + '࣭' => 220, + '࣮' => 220, + '࣯' => 220, + 'ࣰ' => 27, + 'ࣱ' => 28, + 'ࣲ' => 29, + 'ࣳ' => 230, + 'ࣴ' => 230, + 'ࣵ' => 230, + 'ࣶ' => 220, + 'ࣷ' => 230, + 'ࣸ' => 230, + 'ࣹ' => 220, + 'ࣺ' => 220, + 'ࣻ' => 230, + 'ࣼ' => 230, + 'ࣽ' => 230, + 'ࣾ' => 230, + 'ࣿ' => 230, + '़' => 7, + '्' => 9, + '॑' => 230, + '॒' => 220, + '॓' => 230, + '॔' => 230, + '়' => 7, + '্' => 9, + '৾' => 230, + '਼' => 7, + '੍' => 9, + '઼' => 7, + '્' => 9, + '଼' => 7, + '୍' => 9, + '்' => 9, + '్' => 9, + 'ౕ' => 84, + 'ౖ' => 91, + '಼' => 7, + '್' => 9, + '഻' => 9, + '഼' => 9, + '്' => 9, + '්' => 9, + 'ุ' => 103, + 'ู' => 103, + 'ฺ' => 9, + '่' => 107, + '้' => 107, + '๊' => 107, + '๋' => 107, + 'ຸ' => 118, + 'ູ' => 118, + '຺' => 9, + '່' => 122, + '້' => 122, + '໊' => 122, + '໋' => 122, + '༘' => 220, + '༙' => 220, + '༵' => 220, + '༷' => 220, + '༹' => 216, + 'ཱ' => 129, + 'ི' => 130, + 'ུ' => 132, + 'ེ' => 130, + 'ཻ' => 130, + 'ོ' => 130, + 'ཽ' => 130, + 'ྀ' => 130, + 'ྂ' => 230, + 'ྃ' => 230, + '྄' => 9, + '྆' => 230, + '྇' => 230, + '࿆' => 220, + '့' => 7, + '္' => 9, + '်' => 9, + 'ႍ' => 220, + '፝' => 230, + '፞' => 230, + '፟' => 230, + '᜔' => 9, + '᜴' => 9, + '្' => 9, + '៝' => 230, + 'ᢩ' => 228, + '᤹' => 222, + '᤺' => 230, + '᤻' => 220, + 'ᨗ' => 230, + 'ᨘ' => 220, + '᩠' => 9, + '᩵' => 230, + '᩶' => 230, + '᩷' => 230, + '᩸' => 230, + '᩹' => 230, + '᩺' => 230, + '᩻' => 230, + '᩼' => 230, + '᩿' => 220, + '᪰' => 230, + '᪱' => 230, + '᪲' => 230, + '᪳' => 230, + '᪴' => 230, + '᪵' => 220, + '᪶' => 220, + '᪷' => 220, + '᪸' => 220, + '᪹' => 220, + '᪺' => 220, + '᪻' => 230, + '᪼' => 230, + '᪽' => 220, + 'ᪿ' => 220, + 'ᫀ' => 220, + '᬴' => 7, + '᭄' => 9, + '᭫' => 230, + '᭬' => 220, + '᭭' => 230, + '᭮' => 230, + '᭯' => 230, + '᭰' => 230, + '᭱' => 230, + '᭲' => 230, + '᭳' => 230, + '᮪' => 9, + '᮫' => 9, + '᯦' => 7, + '᯲' => 9, + '᯳' => 9, + '᰷' => 7, + '᳐' => 230, + '᳑' => 230, + '᳒' => 230, + '᳔' => 1, + '᳕' => 220, + '᳖' => 220, + '᳗' => 220, + '᳘' => 220, + '᳙' => 220, + '᳚' => 230, + '᳛' => 230, + '᳜' => 220, + '᳝' => 220, + '᳞' => 220, + '᳟' => 220, + '᳠' => 230, + '᳢' => 1, + '᳣' => 1, + '᳤' => 1, + '᳥' => 1, + '᳦' => 1, + '᳧' => 1, + '᳨' => 1, + '᳭' => 220, + '᳴' => 230, + '᳸' => 230, + '᳹' => 230, + '᷀' => 230, + '᷁' => 230, + '᷂' => 220, + '᷃' => 230, + '᷄' => 230, + '᷅' => 230, + '᷆' => 230, + '᷇' => 230, + '᷈' => 230, + '᷉' => 230, + '᷊' => 220, + '᷋' => 230, + '᷌' => 230, + '᷍' => 234, + '᷎' => 214, + '᷏' => 220, + '᷐' => 202, + '᷑' => 230, + '᷒' => 230, + 'ᷓ' => 230, + 'ᷔ' => 230, + 'ᷕ' => 230, + 'ᷖ' => 230, + 'ᷗ' => 230, + 'ᷘ' => 230, + 'ᷙ' => 230, + 'ᷚ' => 230, + 'ᷛ' => 230, + 'ᷜ' => 230, + 'ᷝ' => 230, + 'ᷞ' => 230, + 'ᷟ' => 230, + 'ᷠ' => 230, + 'ᷡ' => 230, + 'ᷢ' => 230, + 'ᷣ' => 230, + 'ᷤ' => 230, + 'ᷥ' => 230, + 'ᷦ' => 230, + 'ᷧ' => 230, + 'ᷨ' => 230, + 'ᷩ' => 230, + 'ᷪ' => 230, + 'ᷫ' => 230, + 'ᷬ' => 230, + 'ᷭ' => 230, + 'ᷮ' => 230, + 'ᷯ' => 230, + 'ᷰ' => 230, + 'ᷱ' => 230, + 'ᷲ' => 230, + 'ᷳ' => 230, + 'ᷴ' => 230, + '᷵' => 230, + '᷶' => 232, + '᷷' => 228, + '᷸' => 228, + '᷹' => 220, + '᷻' => 230, + '᷼' => 233, + '᷽' => 220, + '᷾' => 230, + '᷿' => 220, + '⃐' => 230, + '⃑' => 230, + '⃒' => 1, + '⃓' => 1, + '⃔' => 230, + '⃕' => 230, + '⃖' => 230, + '⃗' => 230, + '⃘' => 1, + '⃙' => 1, + '⃚' => 1, + '⃛' => 230, + '⃜' => 230, + '⃡' => 230, + '⃥' => 1, + '⃦' => 1, + '⃧' => 230, + '⃨' => 220, + '⃩' => 230, + '⃪' => 1, + '⃫' => 1, + '⃬' => 220, + '⃭' => 220, + '⃮' => 220, + '⃯' => 220, + '⃰' => 230, + '⳯' => 230, + '⳰' => 230, + '⳱' => 230, + '⵿' => 9, + 'ⷠ' => 230, + 'ⷡ' => 230, + 'ⷢ' => 230, + 'ⷣ' => 230, + 'ⷤ' => 230, + 'ⷥ' => 230, + 'ⷦ' => 230, + 'ⷧ' => 230, + 'ⷨ' => 230, + 'ⷩ' => 230, + 'ⷪ' => 230, + 'ⷫ' => 230, + 'ⷬ' => 230, + 'ⷭ' => 230, + 'ⷮ' => 230, + 'ⷯ' => 230, + 'ⷰ' => 230, + 'ⷱ' => 230, + 'ⷲ' => 230, + 'ⷳ' => 230, + 'ⷴ' => 230, + 'ⷵ' => 230, + 'ⷶ' => 230, + 'ⷷ' => 230, + 'ⷸ' => 230, + 'ⷹ' => 230, + 'ⷺ' => 230, + 'ⷻ' => 230, + 'ⷼ' => 230, + 'ⷽ' => 230, + 'ⷾ' => 230, + 'ⷿ' => 230, + '〪' => 218, + '〫' => 228, + '〬' => 232, + '〭' => 222, + '〮' => 224, + '〯' => 224, + '゙' => 8, + '゚' => 8, + '꙯' => 230, + 'ꙴ' => 230, + 'ꙵ' => 230, + 'ꙶ' => 230, + 'ꙷ' => 230, + 'ꙸ' => 230, + 'ꙹ' => 230, + 'ꙺ' => 230, + 'ꙻ' => 230, + '꙼' => 230, + '꙽' => 230, + 'ꚞ' => 230, + 'ꚟ' => 230, + '꛰' => 230, + '꛱' => 230, + '꠆' => 9, + '꠬' => 9, + '꣄' => 9, + '꣠' => 230, + '꣡' => 230, + '꣢' => 230, + '꣣' => 230, + '꣤' => 230, + '꣥' => 230, + '꣦' => 230, + '꣧' => 230, + '꣨' => 230, + '꣩' => 230, + '꣪' => 230, + '꣫' => 230, + '꣬' => 230, + '꣭' => 230, + '꣮' => 230, + '꣯' => 230, + '꣰' => 230, + '꣱' => 230, + '꤫' => 220, + '꤬' => 220, + '꤭' => 220, + '꥓' => 9, + '꦳' => 7, + '꧀' => 9, + 'ꪰ' => 230, + 'ꪲ' => 230, + 'ꪳ' => 230, + 'ꪴ' => 220, + 'ꪷ' => 230, + 'ꪸ' => 230, + 'ꪾ' => 230, + '꪿' => 230, + '꫁' => 230, + '꫶' => 9, + '꯭' => 9, + 'ﬞ' => 26, + '︠' => 230, + '︡' => 230, + '︢' => 230, + '︣' => 230, + '︤' => 230, + '︥' => 230, + '︦' => 230, + '︧' => 220, + '︨' => 220, + '︩' => 220, + '︪' => 220, + '︫' => 220, + '︬' => 220, + '︭' => 220, + '︮' => 230, + '︯' => 230, + '𐇽' => 220, + '𐋠' => 220, + '𐍶' => 230, + '𐍷' => 230, + '𐍸' => 230, + '𐍹' => 230, + '𐍺' => 230, + '𐨍' => 220, + '𐨏' => 230, + '𐨸' => 230, + '𐨹' => 1, + '𐨺' => 220, + '𐨿' => 9, + '𐫥' => 230, + '𐫦' => 220, + '𐴤' => 230, + '𐴥' => 230, + '𐴦' => 230, + '𐴧' => 230, + '𐺫' => 230, + '𐺬' => 230, + '𐽆' => 220, + '𐽇' => 220, + '𐽈' => 230, + '𐽉' => 230, + '𐽊' => 230, + '𐽋' => 220, + '𐽌' => 230, + '𐽍' => 220, + '𐽎' => 220, + '𐽏' => 220, + '𐽐' => 220, + '𑁆' => 9, + '𑁿' => 9, + '𑂹' => 9, + '𑂺' => 7, + '𑄀' => 230, + '𑄁' => 230, + '𑄂' => 230, + '𑄳' => 9, + '𑄴' => 9, + '𑅳' => 7, + '𑇀' => 9, + '𑇊' => 7, + '𑈵' => 9, + '𑈶' => 7, + '𑋩' => 7, + '𑋪' => 9, + '𑌻' => 7, + '𑌼' => 7, + '𑍍' => 9, + '𑍦' => 230, + '𑍧' => 230, + '𑍨' => 230, + '𑍩' => 230, + '𑍪' => 230, + '𑍫' => 230, + '𑍬' => 230, + '𑍰' => 230, + '𑍱' => 230, + '𑍲' => 230, + '𑍳' => 230, + '𑍴' => 230, + '𑑂' => 9, + '𑑆' => 7, + '𑑞' => 230, + '𑓂' => 9, + '𑓃' => 7, + '𑖿' => 9, + '𑗀' => 7, + '𑘿' => 9, + '𑚶' => 9, + '𑚷' => 7, + '𑜫' => 9, + '𑠹' => 9, + '𑠺' => 7, + '𑤽' => 9, + '𑤾' => 9, + '𑥃' => 7, + '𑧠' => 9, + '𑨴' => 9, + '𑩇' => 9, + '𑪙' => 9, + '𑰿' => 9, + '𑵂' => 7, + '𑵄' => 9, + '𑵅' => 9, + '𑶗' => 9, + '𖫰' => 1, + '𖫱' => 1, + '𖫲' => 1, + '𖫳' => 1, + '𖫴' => 1, + '𖬰' => 230, + '𖬱' => 230, + '𖬲' => 230, + '𖬳' => 230, + '𖬴' => 230, + '𖬵' => 230, + '𖬶' => 230, + '𖿰' => 6, + '𖿱' => 6, + '𛲞' => 1, + '𝅥' => 216, + '𝅦' => 216, + '𝅧' => 1, + '𝅨' => 1, + '𝅩' => 1, + '𝅭' => 226, + '𝅮' => 216, + '𝅯' => 216, + '𝅰' => 216, + '𝅱' => 216, + '𝅲' => 216, + '𝅻' => 220, + '𝅼' => 220, + '𝅽' => 220, + '𝅾' => 220, + '𝅿' => 220, + '𝆀' => 220, + '𝆁' => 220, + '𝆂' => 220, + '𝆅' => 230, + '𝆆' => 230, + '𝆇' => 230, + '𝆈' => 230, + '𝆉' => 230, + '𝆊' => 220, + '𝆋' => 220, + '𝆪' => 230, + '𝆫' => 230, + '𝆬' => 230, + '𝆭' => 230, + '𝉂' => 230, + '𝉃' => 230, + '𝉄' => 230, + '𞀀' => 230, + '𞀁' => 230, + '𞀂' => 230, + '𞀃' => 230, + '𞀄' => 230, + '𞀅' => 230, + '𞀆' => 230, + '𞀈' => 230, + '𞀉' => 230, + '𞀊' => 230, + '𞀋' => 230, + '𞀌' => 230, + '𞀍' => 230, + '𞀎' => 230, + '𞀏' => 230, + '𞀐' => 230, + '𞀑' => 230, + '𞀒' => 230, + '𞀓' => 230, + '𞀔' => 230, + '𞀕' => 230, + '𞀖' => 230, + '𞀗' => 230, + '𞀘' => 230, + '𞀛' => 230, + '𞀜' => 230, + '𞀝' => 230, + '𞀞' => 230, + '𞀟' => 230, + '𞀠' => 230, + '𞀡' => 230, + '𞀣' => 230, + '𞀤' => 230, + '𞀦' => 230, + '𞀧' => 230, + '𞀨' => 230, + '𞀩' => 230, + '𞀪' => 230, + '𞄰' => 230, + '𞄱' => 230, + '𞄲' => 230, + '𞄳' => 230, + '𞄴' => 230, + '𞄵' => 230, + '𞄶' => 230, + '𞋬' => 230, + '𞋭' => 230, + '𞋮' => 230, + '𞋯' => 230, + '𞣐' => 220, + '𞣑' => 220, + '𞣒' => 220, + '𞣓' => 220, + '𞣔' => 220, + '𞣕' => 220, + '𞣖' => 220, + '𞥄' => 230, + '𞥅' => 230, + '𞥆' => 230, + '𞥇' => 230, + '𞥈' => 230, + '𞥉' => 230, + '𞥊' => 7, +); diff --git a/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php b/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php new file mode 100644 index 0000000..1574902 --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php @@ -0,0 +1,3695 @@ +<?php + +return array ( + ' ' => ' ', + '¨' => ' ̈', + 'ª' => 'a', + '¯' => ' ̄', + '²' => '2', + '³' => '3', + '´' => ' ́', + 'µ' => 'μ', + '¸' => ' ̧', + '¹' => '1', + 'º' => 'o', + '¼' => '1⁄4', + '½' => '1⁄2', + '¾' => '3⁄4', + 'IJ' => 'IJ', + 'ij' => 'ij', + 'Ŀ' => 'L·', + 'ŀ' => 'l·', + 'ʼn' => 'ʼn', + 'ſ' => 's', + 'DŽ' => 'DŽ', + 'Dž' => 'Dž', + 'dž' => 'dž', + 'LJ' => 'LJ', + 'Lj' => 'Lj', + 'lj' => 'lj', + 'NJ' => 'NJ', + 'Nj' => 'Nj', + 'nj' => 'nj', + 'DZ' => 'DZ', + 'Dz' => 'Dz', + 'dz' => 'dz', + 'ʰ' => 'h', + 'ʱ' => 'ɦ', + 'ʲ' => 'j', + 'ʳ' => 'r', + 'ʴ' => 'ɹ', + 'ʵ' => 'ɻ', + 'ʶ' => 'ʁ', + 'ʷ' => 'w', + 'ʸ' => 'y', + '˘' => ' ̆', + '˙' => ' ̇', + '˚' => ' ̊', + '˛' => ' ̨', + '˜' => ' ̃', + '˝' => ' ̋', + 'ˠ' => 'ɣ', + 'ˡ' => 'l', + 'ˢ' => 's', + 'ˣ' => 'x', + 'ˤ' => 'ʕ', + 'ͺ' => ' ͅ', + '΄' => ' ́', + '΅' => ' ̈́', + 'ϐ' => 'β', + 'ϑ' => 'θ', + 'ϒ' => 'Υ', + 'ϓ' => 'Ύ', + 'ϔ' => 'Ϋ', + 'ϕ' => 'φ', + 'ϖ' => 'π', + 'ϰ' => 'κ', + 'ϱ' => 'ρ', + 'ϲ' => 'ς', + 'ϴ' => 'Θ', + 'ϵ' => 'ε', + 'Ϲ' => 'Σ', + 'և' => 'եւ', + 'ٵ' => 'اٴ', + 'ٶ' => 'وٴ', + 'ٷ' => 'ۇٴ', + 'ٸ' => 'يٴ', + 'ำ' => 'ํา', + 'ຳ' => 'ໍາ', + 'ໜ' => 'ຫນ', + 'ໝ' => 'ຫມ', + '༌' => '་', + 'ཷ' => 'ྲཱྀ', + 'ཹ' => 'ླཱྀ', + 'ჼ' => 'ნ', + 'ᴬ' => 'A', + 'ᴭ' => 'Æ', + 'ᴮ' => 'B', + 'ᴰ' => 'D', + 'ᴱ' => 'E', + 'ᴲ' => 'Ǝ', + 'ᴳ' => 'G', + 'ᴴ' => 'H', + 'ᴵ' => 'I', + 'ᴶ' => 'J', + 'ᴷ' => 'K', + 'ᴸ' => 'L', + 'ᴹ' => 'M', + 'ᴺ' => 'N', + 'ᴼ' => 'O', + 'ᴽ' => 'Ȣ', + 'ᴾ' => 'P', + 'ᴿ' => 'R', + 'ᵀ' => 'T', + 'ᵁ' => 'U', + 'ᵂ' => 'W', + 'ᵃ' => 'a', + 'ᵄ' => 'ɐ', + 'ᵅ' => 'ɑ', + 'ᵆ' => 'ᴂ', + 'ᵇ' => 'b', + 'ᵈ' => 'd', + 'ᵉ' => 'e', + 'ᵊ' => 'ə', + 'ᵋ' => 'ɛ', + 'ᵌ' => 'ɜ', + 'ᵍ' => 'g', + 'ᵏ' => 'k', + 'ᵐ' => 'm', + 'ᵑ' => 'ŋ', + 'ᵒ' => 'o', + 'ᵓ' => 'ɔ', + 'ᵔ' => 'ᴖ', + 'ᵕ' => 'ᴗ', + 'ᵖ' => 'p', + 'ᵗ' => 't', + 'ᵘ' => 'u', + 'ᵙ' => 'ᴝ', + 'ᵚ' => 'ɯ', + 'ᵛ' => 'v', + 'ᵜ' => 'ᴥ', + 'ᵝ' => 'β', + 'ᵞ' => 'γ', + 'ᵟ' => 'δ', + 'ᵠ' => 'φ', + 'ᵡ' => 'χ', + 'ᵢ' => 'i', + 'ᵣ' => 'r', + 'ᵤ' => 'u', + 'ᵥ' => 'v', + 'ᵦ' => 'β', + 'ᵧ' => 'γ', + 'ᵨ' => 'ρ', + 'ᵩ' => 'φ', + 'ᵪ' => 'χ', + 'ᵸ' => 'н', + 'ᶛ' => 'ɒ', + 'ᶜ' => 'c', + 'ᶝ' => 'ɕ', + 'ᶞ' => 'ð', + 'ᶟ' => 'ɜ', + 'ᶠ' => 'f', + 'ᶡ' => 'ɟ', + 'ᶢ' => 'ɡ', + 'ᶣ' => 'ɥ', + 'ᶤ' => 'ɨ', + 'ᶥ' => 'ɩ', + 'ᶦ' => 'ɪ', + 'ᶧ' => 'ᵻ', + 'ᶨ' => 'ʝ', + 'ᶩ' => 'ɭ', + 'ᶪ' => 'ᶅ', + 'ᶫ' => 'ʟ', + 'ᶬ' => 'ɱ', + 'ᶭ' => 'ɰ', + 'ᶮ' => 'ɲ', + 'ᶯ' => 'ɳ', + 'ᶰ' => 'ɴ', + 'ᶱ' => 'ɵ', + 'ᶲ' => 'ɸ', + 'ᶳ' => 'ʂ', + 'ᶴ' => 'ʃ', + 'ᶵ' => 'ƫ', + 'ᶶ' => 'ʉ', + 'ᶷ' => 'ʊ', + 'ᶸ' => 'ᴜ', + 'ᶹ' => 'ʋ', + 'ᶺ' => 'ʌ', + 'ᶻ' => 'z', + 'ᶼ' => 'ʐ', + 'ᶽ' => 'ʑ', + 'ᶾ' => 'ʒ', + 'ᶿ' => 'θ', + 'ẚ' => 'aʾ', + 'ẛ' => 'ṡ', + '᾽' => ' ̓', + '᾿' => ' ̓', + '῀' => ' ͂', + '῁' => ' ̈͂', + '῍' => ' ̓̀', + '῎' => ' ̓́', + '῏' => ' ̓͂', + '῝' => ' ̔̀', + '῞' => ' ̔́', + '῟' => ' ̔͂', + '῭' => ' ̈̀', + '΅' => ' ̈́', + '´' => ' ́', + '῾' => ' ̔', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + '‑' => '‐', + '‗' => ' ̳', + '․' => '.', + '‥' => '..', + '…' => '...', + ' ' => ' ', + '″' => '′′', + '‴' => '′′′', + '‶' => '‵‵', + '‷' => '‵‵‵', + '‼' => '!!', + '‾' => ' ̅', + '⁇' => '??', + '⁈' => '?!', + '⁉' => '!?', + '⁗' => '′′′′', + ' ' => ' ', + '⁰' => '0', + 'ⁱ' => 'i', + '⁴' => '4', + '⁵' => '5', + '⁶' => '6', + '⁷' => '7', + '⁸' => '8', + '⁹' => '9', + '⁺' => '+', + '⁻' => '−', + '⁼' => '=', + '⁽' => '(', + '⁾' => ')', + 'ⁿ' => 'n', + '₀' => '0', + '₁' => '1', + '₂' => '2', + '₃' => '3', + '₄' => '4', + '₅' => '5', + '₆' => '6', + '₇' => '7', + '₈' => '8', + '₉' => '9', + '₊' => '+', + '₋' => '−', + '₌' => '=', + '₍' => '(', + '₎' => ')', + 'ₐ' => 'a', + 'ₑ' => 'e', + 'ₒ' => 'o', + 'ₓ' => 'x', + 'ₔ' => 'ə', + 'ₕ' => 'h', + 'ₖ' => 'k', + 'ₗ' => 'l', + 'ₘ' => 'm', + 'ₙ' => 'n', + 'ₚ' => 'p', + 'ₛ' => 's', + 'ₜ' => 't', + '₨' => 'Rs', + '℀' => 'a/c', + '℁' => 'a/s', + 'ℂ' => 'C', + '℃' => '°C', + '℅' => 'c/o', + '℆' => 'c/u', + 'ℇ' => 'Ɛ', + '℉' => '°F', + 'ℊ' => 'g', + 'ℋ' => 'H', + 'ℌ' => 'H', + 'ℍ' => 'H', + 'ℎ' => 'h', + 'ℏ' => 'ħ', + 'ℐ' => 'I', + 'ℑ' => 'I', + 'ℒ' => 'L', + 'ℓ' => 'l', + 'ℕ' => 'N', + '№' => 'No', + 'ℙ' => 'P', + 'ℚ' => 'Q', + 'ℛ' => 'R', + 'ℜ' => 'R', + 'ℝ' => 'R', + '℠' => 'SM', + '℡' => 'TEL', + '™' => 'TM', + 'ℤ' => 'Z', + 'ℨ' => 'Z', + 'ℬ' => 'B', + 'ℭ' => 'C', + 'ℯ' => 'e', + 'ℰ' => 'E', + 'ℱ' => 'F', + 'ℳ' => 'M', + 'ℴ' => 'o', + 'ℵ' => 'א', + 'ℶ' => 'ב', + 'ℷ' => 'ג', + 'ℸ' => 'ד', + 'ℹ' => 'i', + '℻' => 'FAX', + 'ℼ' => 'π', + 'ℽ' => 'γ', + 'ℾ' => 'Γ', + 'ℿ' => 'Π', + '⅀' => '∑', + 'ⅅ' => 'D', + 'ⅆ' => 'd', + 'ⅇ' => 'e', + 'ⅈ' => 'i', + 'ⅉ' => 'j', + '⅐' => '1⁄7', + '⅑' => '1⁄9', + '⅒' => '1⁄10', + '⅓' => '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⁄', + 'Ⅰ' => 'I', + 'Ⅱ' => 'II', + 'Ⅲ' => 'III', + 'Ⅳ' => 'IV', + 'Ⅴ' => 'V', + 'Ⅵ' => 'VI', + 'Ⅶ' => 'VII', + 'Ⅷ' => 'VIII', + 'Ⅸ' => 'IX', + 'Ⅹ' => 'X', + 'Ⅺ' => 'XI', + 'Ⅻ' => 'XII', + 'Ⅼ' => 'L', + 'Ⅽ' => 'C', + 'Ⅾ' => 'D', + 'Ⅿ' => 'M', + 'ⅰ' => 'i', + 'ⅱ' => 'ii', + 'ⅲ' => 'iii', + 'ⅳ' => 'iv', + 'ⅴ' => 'v', + 'ⅵ' => 'vi', + 'ⅶ' => 'vii', + 'ⅷ' => 'viii', + 'ⅸ' => 'ix', + 'ⅹ' => 'x', + 'ⅺ' => 'xi', + 'ⅻ' => 'xii', + 'ⅼ' => 'l', + 'ⅽ' => 'c', + 'ⅾ' => 'd', + 'ⅿ' => 'm', + '↉' => '0⁄3', + '∬' => '∫∫', + '∭' => '∫∫∫', + '∯' => '∮∮', + '∰' => '∮∮∮', + '①' => '1', + '②' => '2', + '③' => '3', + '④' => '4', + '⑤' => '5', + '⑥' => '6', + '⑦' => '7', + '⑧' => '8', + '⑨' => '9', + '⑩' => '10', + '⑪' => '11', + '⑫' => '12', + '⑬' => '13', + '⑭' => '14', + '⑮' => '15', + '⑯' => '16', + '⑰' => '17', + '⑱' => '18', + '⑲' => '19', + '⑳' => '20', + '⑴' => '(1)', + '⑵' => '(2)', + '⑶' => '(3)', + '⑷' => '(4)', + '⑸' => '(5)', + '⑹' => '(6)', + '⑺' => '(7)', + '⑻' => '(8)', + '⑼' => '(9)', + '⑽' => '(10)', + '⑾' => '(11)', + '⑿' => '(12)', + '⒀' => '(13)', + '⒁' => '(14)', + '⒂' => '(15)', + '⒃' => '(16)', + '⒄' => '(17)', + '⒅' => '(18)', + '⒆' => '(19)', + '⒇' => '(20)', + '⒈' => '1.', + '⒉' => '2.', + '⒊' => '3.', + '⒋' => '4.', + '⒌' => '5.', + '⒍' => '6.', + '⒎' => '7.', + '⒏' => '8.', + '⒐' => '9.', + '⒑' => '10.', + '⒒' => '11.', + '⒓' => '12.', + '⒔' => '13.', + '⒕' => '14.', + '⒖' => '15.', + '⒗' => '16.', + '⒘' => '17.', + '⒙' => '18.', + '⒚' => '19.', + '⒛' => '20.', + '⒜' => '(a)', + '⒝' => '(b)', + '⒞' => '(c)', + '⒟' => '(d)', + '⒠' => '(e)', + '⒡' => '(f)', + '⒢' => '(g)', + '⒣' => '(h)', + '⒤' => '(i)', + '⒥' => '(j)', + '⒦' => '(k)', + '⒧' => '(l)', + '⒨' => '(m)', + '⒩' => '(n)', + '⒪' => '(o)', + '⒫' => '(p)', + '⒬' => '(q)', + '⒭' => '(r)', + '⒮' => '(s)', + '⒯' => '(t)', + '⒰' => '(u)', + '⒱' => '(v)', + '⒲' => '(w)', + '⒳' => '(x)', + '⒴' => '(y)', + '⒵' => '(z)', + 'Ⓐ' => 'A', + 'Ⓑ' => 'B', + 'Ⓒ' => 'C', + 'Ⓓ' => 'D', + 'Ⓔ' => 'E', + 'Ⓕ' => 'F', + 'Ⓖ' => 'G', + 'Ⓗ' => 'H', + 'Ⓘ' => 'I', + 'Ⓙ' => 'J', + 'Ⓚ' => 'K', + 'Ⓛ' => 'L', + 'Ⓜ' => 'M', + 'Ⓝ' => 'N', + 'Ⓞ' => 'O', + 'Ⓟ' => 'P', + 'Ⓠ' => 'Q', + 'Ⓡ' => 'R', + 'Ⓢ' => 'S', + 'Ⓣ' => 'T', + 'Ⓤ' => 'U', + 'Ⓥ' => 'V', + 'Ⓦ' => 'W', + 'Ⓧ' => 'X', + 'Ⓨ' => 'Y', + 'Ⓩ' => 'Z', + 'ⓐ' => 'a', + 'ⓑ' => 'b', + 'ⓒ' => 'c', + 'ⓓ' => 'd', + 'ⓔ' => 'e', + 'ⓕ' => 'f', + 'ⓖ' => 'g', + 'ⓗ' => 'h', + 'ⓘ' => 'i', + 'ⓙ' => 'j', + 'ⓚ' => 'k', + 'ⓛ' => 'l', + 'ⓜ' => 'm', + 'ⓝ' => 'n', + 'ⓞ' => 'o', + 'ⓟ' => 'p', + 'ⓠ' => 'q', + 'ⓡ' => 'r', + 'ⓢ' => 's', + 'ⓣ' => 't', + 'ⓤ' => 'u', + 'ⓥ' => 'v', + 'ⓦ' => 'w', + 'ⓧ' => 'x', + 'ⓨ' => 'y', + 'ⓩ' => 'z', + '⓪' => '0', + '⨌' => '∫∫∫∫', + '⩴' => '::=', + '⩵' => '==', + '⩶' => '===', + 'ⱼ' => 'j', + 'ⱽ' => 'V', + 'ⵯ' => 'ⵡ', + '⺟' => '母', + '⻳' => '龟', + '⼀' => '一', + '⼁' => '丨', + '⼂' => '丶', + '⼃' => '丿', + '⼄' => '乙', + '⼅' => '亅', + '⼆' => '二', + '⼇' => '亠', + '⼈' => '人', + '⼉' => '儿', + '⼊' => '入', + '⼋' => '八', + '⼌' => '冂', + '⼍' => '冖', + '⼎' => '冫', + '⼏' => '几', + '⼐' => '凵', + '⼑' => '刀', + '⼒' => '力', + '⼓' => '勹', + '⼔' => '匕', + '⼕' => '匚', + '⼖' => '匸', + '⼗' => '十', + '⼘' => '卜', + '⼙' => '卩', + '⼚' => '厂', + '⼛' => '厶', + '⼜' => '又', + '⼝' => '口', + '⼞' => '囗', + '⼟' => '土', + '⼠' => '士', + '⼡' => '夂', + '⼢' => '夊', + '⼣' => '夕', + '⼤' => '大', + '⼥' => '女', + '⼦' => '子', + '⼧' => '宀', + '⼨' => '寸', + '⼩' => '小', + '⼪' => '尢', + '⼫' => '尸', + '⼬' => '屮', + '⼭' => '山', + '⼮' => '巛', + '⼯' => '工', + '⼰' => '己', + '⼱' => '巾', + '⼲' => '干', + '⼳' => '幺', + '⼴' => '广', + '⼵' => '廴', + '⼶' => '廾', + '⼷' => '弋', + '⼸' => '弓', + '⼹' => '彐', + '⼺' => '彡', + '⼻' => '彳', + '⼼' => '心', + '⼽' => '戈', + '⼾' => '戶', + '⼿' => '手', + '⽀' => '支', + '⽁' => '攴', + '⽂' => '文', + '⽃' => '斗', + '⽄' => '斤', + '⽅' => '方', + '⽆' => '无', + '⽇' => '日', + '⽈' => '曰', + '⽉' => '月', + '⽊' => '木', + '⽋' => '欠', + '⽌' => '止', + '⽍' => '歹', + '⽎' => '殳', + '⽏' => '毋', + '⽐' => '比', + '⽑' => '毛', + '⽒' => '氏', + '⽓' => '气', + '⽔' => '水', + '⽕' => '火', + '⽖' => '爪', + '⽗' => '父', + '⽘' => '爻', + '⽙' => '爿', + '⽚' => '片', + '⽛' => '牙', + '⽜' => '牛', + '⽝' => '犬', + '⽞' => '玄', + '⽟' => '玉', + '⽠' => '瓜', + '⽡' => '瓦', + '⽢' => '甘', + '⽣' => '生', + '⽤' => '用', + '⽥' => '田', + '⽦' => '疋', + '⽧' => '疒', + '⽨' => '癶', + '⽩' => '白', + '⽪' => '皮', + '⽫' => '皿', + '⽬' => '目', + '⽭' => '矛', + '⽮' => '矢', + '⽯' => '石', + '⽰' => '示', + '⽱' => '禸', + '⽲' => '禾', + '⽳' => '穴', + '⽴' => '立', + '⽵' => '竹', + '⽶' => '米', + '⽷' => '糸', + '⽸' => '缶', + '⽹' => '网', + '⽺' => '羊', + '⽻' => '羽', + '⽼' => '老', + '⽽' => '而', + '⽾' => '耒', + '⽿' => '耳', + '⾀' => '聿', + '⾁' => '肉', + '⾂' => '臣', + '⾃' => '自', + '⾄' => '至', + '⾅' => '臼', + '⾆' => '舌', + '⾇' => '舛', + '⾈' => '舟', + '⾉' => '艮', + '⾊' => '色', + '⾋' => '艸', + '⾌' => '虍', + '⾍' => '虫', + '⾎' => '血', + '⾏' => '行', + '⾐' => '衣', + '⾑' => '襾', + '⾒' => '見', + '⾓' => '角', + '⾔' => '言', + '⾕' => '谷', + '⾖' => '豆', + '⾗' => '豕', + '⾘' => '豸', + '⾙' => '貝', + '⾚' => '赤', + '⾛' => '走', + '⾜' => '足', + '⾝' => '身', + '⾞' => '車', + '⾟' => '辛', + '⾠' => '辰', + '⾡' => '辵', + '⾢' => '邑', + '⾣' => '酉', + '⾤' => '釆', + '⾥' => '里', + '⾦' => '金', + '⾧' => '長', + '⾨' => '門', + '⾩' => '阜', + '⾪' => '隶', + '⾫' => '隹', + '⾬' => '雨', + '⾭' => '靑', + '⾮' => '非', + '⾯' => '面', + '⾰' => '革', + '⾱' => '韋', + '⾲' => '韭', + '⾳' => '音', + '⾴' => '頁', + '⾵' => '風', + '⾶' => '飛', + '⾷' => '食', + '⾸' => '首', + '⾹' => '香', + '⾺' => '馬', + '⾻' => '骨', + '⾼' => '高', + '⾽' => '髟', + '⾾' => '鬥', + '⾿' => '鬯', + '⿀' => '鬲', + '⿁' => '鬼', + '⿂' => '魚', + '⿃' => '鳥', + '⿄' => '鹵', + '⿅' => '鹿', + '⿆' => '麥', + '⿇' => '麻', + '⿈' => '黃', + '⿉' => '黍', + '⿊' => '黑', + '⿋' => '黹', + '⿌' => '黽', + '⿍' => '鼎', + '⿎' => '鼓', + '⿏' => '鼠', + '⿐' => '鼻', + '⿑' => '齊', + '⿒' => '齒', + '⿓' => '龍', + '⿔' => '龜', + '⿕' => '龠', + ' ' => ' ', + '〶' => '〒', + '〸' => '十', + '〹' => '卄', + '〺' => '卅', + '゛' => ' ゙', + '゜' => ' ゚', + 'ゟ' => 'より', + 'ヿ' => 'コト', + 'ㄱ' => 'ᄀ', + 'ㄲ' => 'ᄁ', + 'ㄳ' => 'ᆪ', + 'ㄴ' => 'ᄂ', + 'ㄵ' => 'ᆬ', + 'ㄶ' => 'ᆭ', + 'ㄷ' => 'ᄃ', + 'ㄸ' => 'ᄄ', + 'ㄹ' => 'ᄅ', + 'ㄺ' => 'ᆰ', + 'ㄻ' => 'ᆱ', + 'ㄼ' => 'ᆲ', + 'ㄽ' => 'ᆳ', + 'ㄾ' => 'ᆴ', + 'ㄿ' => 'ᆵ', + 'ㅀ' => 'ᄚ', + 'ㅁ' => 'ᄆ', + 'ㅂ' => 'ᄇ', + 'ㅃ' => 'ᄈ', + 'ㅄ' => 'ᄡ', + 'ㅅ' => 'ᄉ', + 'ㅆ' => 'ᄊ', + 'ㅇ' => 'ᄋ', + 'ㅈ' => 'ᄌ', + 'ㅉ' => 'ᄍ', + 'ㅊ' => 'ᄎ', + 'ㅋ' => 'ᄏ', + 'ㅌ' => 'ᄐ', + 'ㅍ' => 'ᄑ', + 'ㅎ' => 'ᄒ', + 'ㅏ' => 'ᅡ', + 'ㅐ' => 'ᅢ', + 'ㅑ' => 'ᅣ', + 'ㅒ' => 'ᅤ', + 'ㅓ' => 'ᅥ', + 'ㅔ' => 'ᅦ', + 'ㅕ' => 'ᅧ', + 'ㅖ' => 'ᅨ', + 'ㅗ' => 'ᅩ', + 'ㅘ' => 'ᅪ', + 'ㅙ' => 'ᅫ', + 'ㅚ' => 'ᅬ', + 'ㅛ' => 'ᅭ', + 'ㅜ' => 'ᅮ', + 'ㅝ' => 'ᅯ', + 'ㅞ' => 'ᅰ', + 'ㅟ' => 'ᅱ', + 'ㅠ' => 'ᅲ', + 'ㅡ' => 'ᅳ', + 'ㅢ' => 'ᅴ', + 'ㅣ' => 'ᅵ', + 'ㅤ' => 'ᅠ', + 'ㅥ' => 'ᄔ', + 'ㅦ' => 'ᄕ', + 'ㅧ' => 'ᇇ', + 'ㅨ' => 'ᇈ', + 'ㅩ' => 'ᇌ', + 'ㅪ' => 'ᇎ', + 'ㅫ' => 'ᇓ', + 'ㅬ' => 'ᇗ', + 'ㅭ' => 'ᇙ', + 'ㅮ' => 'ᄜ', + 'ㅯ' => 'ᇝ', + 'ㅰ' => 'ᇟ', + 'ㅱ' => 'ᄝ', + 'ㅲ' => 'ᄞ', + 'ㅳ' => 'ᄠ', + 'ㅴ' => 'ᄢ', + 'ㅵ' => 'ᄣ', + 'ㅶ' => 'ᄧ', + 'ㅷ' => 'ᄩ', + 'ㅸ' => 'ᄫ', + 'ㅹ' => 'ᄬ', + 'ㅺ' => 'ᄭ', + 'ㅻ' => 'ᄮ', + 'ㅼ' => 'ᄯ', + 'ㅽ' => 'ᄲ', + 'ㅾ' => 'ᄶ', + 'ㅿ' => 'ᅀ', + 'ㆀ' => 'ᅇ', + 'ㆁ' => 'ᅌ', + 'ㆂ' => 'ᇱ', + 'ㆃ' => 'ᇲ', + 'ㆄ' => 'ᅗ', + 'ㆅ' => 'ᅘ', + 'ㆆ' => 'ᅙ', + 'ㆇ' => 'ᆄ', + 'ㆈ' => 'ᆅ', + 'ㆉ' => 'ᆈ', + 'ㆊ' => 'ᆑ', + 'ㆋ' => 'ᆒ', + 'ㆌ' => 'ᆔ', + 'ㆍ' => 'ᆞ', + 'ㆎ' => 'ᆡ', + '㆒' => '一', + '㆓' => '二', + '㆔' => '三', + '㆕' => '四', + '㆖' => '上', + '㆗' => '中', + '㆘' => '下', + '㆙' => '甲', + '㆚' => '乙', + '㆛' => '丙', + '㆜' => '丁', + '㆝' => '天', + '㆞' => '地', + '㆟' => '人', + '㈀' => '(ᄀ)', + '㈁' => '(ᄂ)', + '㈂' => '(ᄃ)', + '㈃' => '(ᄅ)', + '㈄' => '(ᄆ)', + '㈅' => '(ᄇ)', + '㈆' => '(ᄉ)', + '㈇' => '(ᄋ)', + '㈈' => '(ᄌ)', + '㈉' => '(ᄎ)', + '㈊' => '(ᄏ)', + '㈋' => '(ᄐ)', + '㈌' => '(ᄑ)', + '㈍' => '(ᄒ)', + '㈎' => '(가)', + '㈏' => '(나)', + '㈐' => '(다)', + '㈑' => '(라)', + '㈒' => '(마)', + '㈓' => '(바)', + '㈔' => '(사)', + '㈕' => '(아)', + '㈖' => '(자)', + '㈗' => '(차)', + '㈘' => '(카)', + '㈙' => '(타)', + '㈚' => '(파)', + '㈛' => '(하)', + '㈜' => '(주)', + '㈝' => '(오전)', + '㈞' => '(오후)', + '㈠' => '(一)', + '㈡' => '(二)', + '㈢' => '(三)', + '㈣' => '(四)', + '㈤' => '(五)', + '㈥' => '(六)', + '㈦' => '(七)', + '㈧' => '(八)', + '㈨' => '(九)', + '㈩' => '(十)', + '㈪' => '(月)', + '㈫' => '(火)', + '㈬' => '(水)', + '㈭' => '(木)', + '㈮' => '(金)', + '㈯' => '(土)', + '㈰' => '(日)', + '㈱' => '(株)', + '㈲' => '(有)', + '㈳' => '(社)', + '㈴' => '(名)', + '㈵' => '(特)', + '㈶' => '(財)', + '㈷' => '(祝)', + '㈸' => '(労)', + '㈹' => '(代)', + '㈺' => '(呼)', + '㈻' => '(学)', + '㈼' => '(監)', + '㈽' => '(企)', + '㈾' => '(資)', + '㈿' => '(協)', + '㉀' => '(祭)', + '㉁' => '(休)', + '㉂' => '(自)', + '㉃' => '(至)', + '㉄' => '問', + '㉅' => '幼', + '㉆' => '文', + '㉇' => '箏', + '㉐' => 'PTE', + '㉑' => '21', + '㉒' => '22', + '㉓' => '23', + '㉔' => '24', + '㉕' => '25', + '㉖' => '26', + '㉗' => '27', + '㉘' => '28', + '㉙' => '29', + '㉚' => '30', + '㉛' => '31', + '㉜' => '32', + '㉝' => '33', + '㉞' => '34', + '㉟' => '35', + '㉠' => 'ᄀ', + '㉡' => 'ᄂ', + '㉢' => 'ᄃ', + '㉣' => 'ᄅ', + '㉤' => 'ᄆ', + '㉥' => 'ᄇ', + '㉦' => 'ᄉ', + '㉧' => 'ᄋ', + '㉨' => 'ᄌ', + '㉩' => 'ᄎ', + '㉪' => 'ᄏ', + '㉫' => 'ᄐ', + '㉬' => 'ᄑ', + '㉭' => 'ᄒ', + '㉮' => '가', + '㉯' => '나', + '㉰' => '다', + '㉱' => '라', + '㉲' => '마', + '㉳' => '바', + '㉴' => '사', + '㉵' => '아', + '㉶' => '자', + '㉷' => '차', + '㉸' => '카', + '㉹' => '타', + '㉺' => '파', + '㉻' => '하', + '㉼' => '참고', + '㉽' => '주의', + '㉾' => '우', + '㊀' => '一', + '㊁' => '二', + '㊂' => '三', + '㊃' => '四', + '㊄' => '五', + '㊅' => '六', + '㊆' => '七', + '㊇' => '八', + '㊈' => '九', + '㊉' => '十', + '㊊' => '月', + '㊋' => '火', + '㊌' => '水', + '㊍' => '木', + '㊎' => '金', + '㊏' => '土', + '㊐' => '日', + '㊑' => '株', + '㊒' => '有', + '㊓' => '社', + '㊔' => '名', + '㊕' => '特', + '㊖' => '財', + '㊗' => '祝', + '㊘' => '労', + '㊙' => '秘', + '㊚' => '男', + '㊛' => '女', + '㊜' => '適', + '㊝' => '優', + '㊞' => '印', + '㊟' => '注', + '㊠' => '項', + '㊡' => '休', + '㊢' => '写', + '㊣' => '正', + '㊤' => '上', + '㊥' => '中', + '㊦' => '下', + '㊧' => '左', + '㊨' => '右', + '㊩' => '医', + '㊪' => '宗', + '㊫' => '学', + '㊬' => '監', + '㊭' => '企', + '㊮' => '資', + '㊯' => '協', + '㊰' => '夜', + '㊱' => '36', + '㊲' => '37', + '㊳' => '38', + '㊴' => '39', + '㊵' => '40', + '㊶' => '41', + '㊷' => '42', + '㊸' => '43', + '㊹' => '44', + '㊺' => '45', + '㊻' => '46', + '㊼' => '47', + '㊽' => '48', + '㊾' => '49', + '㊿' => '50', + '㋀' => '1月', + '㋁' => '2月', + '㋂' => '3月', + '㋃' => '4月', + '㋄' => '5月', + '㋅' => '6月', + '㋆' => '7月', + '㋇' => '8月', + '㋈' => '9月', + '㋉' => '10月', + '㋊' => '11月', + '㋋' => '12月', + '㋌' => 'Hg', + '㋍' => 'erg', + '㋎' => 'eV', + '㋏' => 'LTD', + '㋐' => 'ア', + '㋑' => 'イ', + '㋒' => 'ウ', + '㋓' => 'エ', + '㋔' => 'オ', + '㋕' => 'カ', + '㋖' => 'キ', + '㋗' => 'ク', + '㋘' => 'ケ', + '㋙' => 'コ', + '㋚' => 'サ', + '㋛' => 'シ', + '㋜' => 'ス', + '㋝' => 'セ', + '㋞' => 'ソ', + '㋟' => 'タ', + '㋠' => 'チ', + '㋡' => 'ツ', + '㋢' => 'テ', + '㋣' => 'ト', + '㋤' => 'ナ', + '㋥' => 'ニ', + '㋦' => 'ヌ', + '㋧' => 'ネ', + '㋨' => 'ノ', + '㋩' => 'ハ', + '㋪' => 'ヒ', + '㋫' => 'フ', + '㋬' => 'ヘ', + '㋭' => 'ホ', + '㋮' => 'マ', + '㋯' => 'ミ', + '㋰' => 'ム', + '㋱' => 'メ', + '㋲' => 'モ', + '㋳' => 'ヤ', + '㋴' => 'ユ', + '㋵' => 'ヨ', + '㋶' => 'ラ', + '㋷' => 'リ', + '㋸' => 'ル', + '㋹' => 'レ', + '㋺' => 'ロ', + '㋻' => 'ワ', + '㋼' => 'ヰ', + '㋽' => 'ヱ', + '㋾' => 'ヲ', + '㋿' => '令和', + '㌀' => 'アパート', + '㌁' => 'アルファ', + '㌂' => 'アンペア', + '㌃' => 'アール', + '㌄' => 'イニング', + '㌅' => 'インチ', + '㌆' => 'ウォン', + '㌇' => 'エスクード', + '㌈' => 'エーカー', + '㌉' => 'オンス', + '㌊' => 'オーム', + '㌋' => 'カイリ', + '㌌' => 'カラット', + '㌍' => 'カロリー', + '㌎' => 'ガロン', + '㌏' => 'ガンマ', + '㌐' => 'ギガ', + '㌑' => 'ギニー', + '㌒' => 'キュリー', + '㌓' => 'ギルダー', + '㌔' => 'キロ', + '㌕' => 'キログラム', + '㌖' => 'キロメートル', + '㌗' => 'キロワット', + '㌘' => 'グラム', + '㌙' => 'グラムトン', + '㌚' => 'クルゼイロ', + '㌛' => 'クローネ', + '㌜' => 'ケース', + '㌝' => 'コルナ', + '㌞' => 'コーポ', + '㌟' => 'サイクル', + '㌠' => 'サンチーム', + '㌡' => 'シリング', + '㌢' => 'センチ', + '㌣' => 'セント', + '㌤' => 'ダース', + '㌥' => 'デシ', + '㌦' => 'ドル', + '㌧' => 'トン', + '㌨' => 'ナノ', + '㌩' => 'ノット', + '㌪' => 'ハイツ', + '㌫' => 'パーセント', + '㌬' => 'パーツ', + '㌭' => 'バーレル', + '㌮' => 'ピアストル', + '㌯' => 'ピクル', + '㌰' => 'ピコ', + '㌱' => 'ビル', + '㌲' => 'ファラッド', + '㌳' => 'フィート', + '㌴' => 'ブッシェル', + '㌵' => 'フラン', + '㌶' => 'ヘクタール', + '㌷' => 'ペソ', + '㌸' => 'ペニヒ', + '㌹' => 'ヘルツ', + '㌺' => 'ペンス', + '㌻' => 'ページ', + '㌼' => 'ベータ', + '㌽' => 'ポイント', + '㌾' => 'ボルト', + '㌿' => 'ホン', + '㍀' => 'ポンド', + '㍁' => 'ホール', + '㍂' => 'ホーン', + '㍃' => 'マイクロ', + '㍄' => 'マイル', + '㍅' => 'マッハ', + '㍆' => 'マルク', + '㍇' => 'マンション', + '㍈' => 'ミクロン', + '㍉' => 'ミリ', + '㍊' => 'ミリバール', + '㍋' => 'メガ', + '㍌' => 'メガトン', + '㍍' => 'メートル', + '㍎' => 'ヤード', + '㍏' => 'ヤール', + '㍐' => 'ユアン', + '㍑' => 'リットル', + '㍒' => 'リラ', + '㍓' => 'ルピー', + '㍔' => 'ルーブル', + '㍕' => 'レム', + '㍖' => 'レントゲン', + '㍗' => 'ワット', + '㍘' => '0点', + '㍙' => '1点', + '㍚' => '2点', + '㍛' => '3点', + '㍜' => '4点', + '㍝' => '5点', + '㍞' => '6点', + '㍟' => '7点', + '㍠' => '8点', + '㍡' => '9点', + '㍢' => '10点', + '㍣' => '11点', + '㍤' => '12点', + '㍥' => '13点', + '㍦' => '14点', + '㍧' => '15点', + '㍨' => '16点', + '㍩' => '17点', + '㍪' => '18点', + '㍫' => '19点', + '㍬' => '20点', + '㍭' => '21点', + '㍮' => '22点', + '㍯' => '23点', + '㍰' => '24点', + '㍱' => 'hPa', + '㍲' => 'da', + '㍳' => 'AU', + '㍴' => 'bar', + '㍵' => 'oV', + '㍶' => 'pc', + '㍷' => 'dm', + '㍸' => 'dm2', + '㍹' => 'dm3', + '㍺' => 'IU', + '㍻' => '平成', + '㍼' => '昭和', + '㍽' => '大正', + '㍾' => '明治', + '㍿' => '株式会社', + '㎀' => 'pA', + '㎁' => 'nA', + '㎂' => 'μA', + '㎃' => 'mA', + '㎄' => 'kA', + '㎅' => 'KB', + '㎆' => 'MB', + '㎇' => 'GB', + '㎈' => 'cal', + '㎉' => 'kcal', + '㎊' => 'pF', + '㎋' => 'nF', + '㎌' => 'μF', + '㎍' => 'μg', + '㎎' => 'mg', + '㎏' => 'kg', + '㎐' => 'Hz', + '㎑' => 'kHz', + '㎒' => 'MHz', + '㎓' => 'GHz', + '㎔' => 'THz', + '㎕' => 'μl', + '㎖' => 'ml', + '㎗' => 'dl', + '㎘' => 'kl', + '㎙' => 'fm', + '㎚' => 'nm', + '㎛' => 'μm', + '㎜' => 'mm', + '㎝' => 'cm', + '㎞' => 'km', + '㎟' => 'mm2', + '㎠' => 'cm2', + '㎡' => 'm2', + '㎢' => 'km2', + '㎣' => 'mm3', + '㎤' => 'cm3', + '㎥' => 'm3', + '㎦' => 'km3', + '㎧' => 'm∕s', + '㎨' => 'm∕s2', + '㎩' => 'Pa', + '㎪' => 'kPa', + '㎫' => 'MPa', + '㎬' => 'GPa', + '㎭' => 'rad', + '㎮' => 'rad∕s', + '㎯' => 'rad∕s2', + '㎰' => 'ps', + '㎱' => 'ns', + '㎲' => 'μs', + '㎳' => 'ms', + '㎴' => 'pV', + '㎵' => 'nV', + '㎶' => 'μV', + '㎷' => 'mV', + '㎸' => 'kV', + '㎹' => 'MV', + '㎺' => 'pW', + '㎻' => 'nW', + '㎼' => 'μW', + '㎽' => 'mW', + '㎾' => 'kW', + '㎿' => 'MW', + '㏀' => 'kΩ', + '㏁' => 'MΩ', + '㏂' => 'a.m.', + '㏃' => 'Bq', + '㏄' => 'cc', + '㏅' => 'cd', + '㏆' => 'C∕kg', + '㏇' => 'Co.', + '㏈' => 'dB', + '㏉' => 'Gy', + '㏊' => 'ha', + '㏋' => 'HP', + '㏌' => 'in', + '㏍' => 'KK', + '㏎' => 'KM', + '㏏' => 'kt', + '㏐' => 'lm', + '㏑' => 'ln', + '㏒' => 'log', + '㏓' => 'lx', + '㏔' => 'mb', + '㏕' => 'mil', + '㏖' => 'mol', + '㏗' => 'PH', + '㏘' => 'p.m.', + '㏙' => 'PPM', + '㏚' => 'PR', + '㏛' => 'sr', + '㏜' => 'Sv', + '㏝' => 'Wb', + '㏞' => 'V∕m', + '㏟' => 'A∕m', + '㏠' => '1日', + '㏡' => '2日', + '㏢' => '3日', + '㏣' => '4日', + '㏤' => '5日', + '㏥' => '6日', + '㏦' => '7日', + '㏧' => '8日', + '㏨' => '9日', + '㏩' => '10日', + '㏪' => '11日', + '㏫' => '12日', + '㏬' => '13日', + '㏭' => '14日', + '㏮' => '15日', + '㏯' => '16日', + '㏰' => '17日', + '㏱' => '18日', + '㏲' => '19日', + '㏳' => '20日', + '㏴' => '21日', + '㏵' => '22日', + '㏶' => '23日', + '㏷' => '24日', + '㏸' => '25日', + '㏹' => '26日', + '㏺' => '27日', + '㏻' => '28日', + '㏼' => '29日', + '㏽' => '30日', + '㏾' => '31日', + '㏿' => 'gal', + 'ꚜ' => 'ъ', + 'ꚝ' => 'ь', + 'ꝰ' => 'ꝯ', + 'ꟸ' => 'Ħ', + 'ꟹ' => 'œ', + 'ꭜ' => 'ꜧ', + 'ꭝ' => 'ꬷ', + 'ꭞ' => 'ɫ', + 'ꭟ' => 'ꭒ', + 'ꭩ' => 'ʍ', + 'ff' => 'ff', + 'fi' => 'fi', + 'fl' => 'fl', + 'ffi' => 'ffi', + 'ffl' => 'ffl', + 'ſt' => 'st', + 'st' => 'st', + 'ﬓ' => 'մն', + 'ﬔ' => 'մե', + 'ﬕ' => 'մի', + 'ﬖ' => 'վն', + 'ﬗ' => 'մխ', + 'ﬠ' => 'ע', + 'ﬡ' => 'א', + 'ﬢ' => 'ד', + 'ﬣ' => 'ה', + 'ﬤ' => 'כ', + 'ﬥ' => 'ל', + 'ﬦ' => 'ם', + 'ﬧ' => 'ר', + 'ﬨ' => 'ת', + '﬩' => '+', + 'ﭏ' => 'אל', + 'ﭐ' => 'ٱ', + 'ﭑ' => 'ٱ', + 'ﭒ' => 'ٻ', + 'ﭓ' => 'ٻ', + 'ﭔ' => 'ٻ', + 'ﭕ' => 'ٻ', + 'ﭖ' => 'پ', + 'ﭗ' => 'پ', + 'ﭘ' => 'پ', + 'ﭙ' => 'پ', + 'ﭚ' => 'ڀ', + 'ﭛ' => 'ڀ', + 'ﭜ' => 'ڀ', + 'ﭝ' => 'ڀ', + 'ﭞ' => 'ٺ', + 'ﭟ' => 'ٺ', + 'ﭠ' => 'ٺ', + 'ﭡ' => 'ٺ', + 'ﭢ' => 'ٿ', + 'ﭣ' => 'ٿ', + 'ﭤ' => 'ٿ', + 'ﭥ' => 'ٿ', + 'ﭦ' => 'ٹ', + 'ﭧ' => 'ٹ', + 'ﭨ' => 'ٹ', + 'ﭩ' => 'ٹ', + 'ﭪ' => 'ڤ', + 'ﭫ' => 'ڤ', + 'ﭬ' => 'ڤ', + 'ﭭ' => 'ڤ', + 'ﭮ' => 'ڦ', + 'ﭯ' => 'ڦ', + 'ﭰ' => 'ڦ', + 'ﭱ' => 'ڦ', + 'ﭲ' => 'ڄ', + 'ﭳ' => 'ڄ', + 'ﭴ' => 'ڄ', + 'ﭵ' => 'ڄ', + 'ﭶ' => 'ڃ', + 'ﭷ' => 'ڃ', + 'ﭸ' => 'ڃ', + 'ﭹ' => 'ڃ', + 'ﭺ' => 'چ', + 'ﭻ' => 'چ', + 'ﭼ' => 'چ', + 'ﭽ' => 'چ', + 'ﭾ' => 'ڇ', + 'ﭿ' => 'ڇ', + 'ﮀ' => 'ڇ', + 'ﮁ' => 'ڇ', + 'ﮂ' => 'ڍ', + 'ﮃ' => 'ڍ', + 'ﮄ' => 'ڌ', + 'ﮅ' => 'ڌ', + 'ﮆ' => 'ڎ', + 'ﮇ' => 'ڎ', + 'ﮈ' => 'ڈ', + 'ﮉ' => 'ڈ', + 'ﮊ' => 'ژ', + 'ﮋ' => 'ژ', + 'ﮌ' => 'ڑ', + 'ﮍ' => 'ڑ', + 'ﮎ' => 'ک', + 'ﮏ' => 'ک', + 'ﮐ' => 'ک', + 'ﮑ' => 'ک', + 'ﮒ' => 'گ', + 'ﮓ' => 'گ', + 'ﮔ' => 'گ', + 'ﮕ' => 'گ', + 'ﮖ' => 'ڳ', + 'ﮗ' => 'ڳ', + 'ﮘ' => 'ڳ', + 'ﮙ' => 'ڳ', + 'ﮚ' => 'ڱ', + 'ﮛ' => 'ڱ', + 'ﮜ' => 'ڱ', + 'ﮝ' => 'ڱ', + 'ﮞ' => 'ں', + 'ﮟ' => 'ں', + 'ﮠ' => 'ڻ', + 'ﮡ' => 'ڻ', + 'ﮢ' => 'ڻ', + 'ﮣ' => 'ڻ', + 'ﮤ' => 'ۀ', + 'ﮥ' => 'ۀ', + 'ﮦ' => 'ہ', + 'ﮧ' => 'ہ', + 'ﮨ' => 'ہ', + 'ﮩ' => 'ہ', + 'ﮪ' => 'ھ', + 'ﮫ' => 'ھ', + 'ﮬ' => 'ھ', + 'ﮭ' => 'ھ', + 'ﮮ' => 'ے', + 'ﮯ' => 'ے', + 'ﮰ' => 'ۓ', + 'ﮱ' => 'ۓ', + 'ﯓ' => 'ڭ', + 'ﯔ' => 'ڭ', + 'ﯕ' => 'ڭ', + 'ﯖ' => 'ڭ', + 'ﯗ' => 'ۇ', + 'ﯘ' => 'ۇ', + 'ﯙ' => 'ۆ', + 'ﯚ' => 'ۆ', + 'ﯛ' => 'ۈ', + 'ﯜ' => 'ۈ', + 'ﯝ' => 'ۇٴ', + 'ﯞ' => 'ۋ', + 'ﯟ' => 'ۋ', + 'ﯠ' => 'ۅ', + 'ﯡ' => 'ۅ', + 'ﯢ' => 'ۉ', + 'ﯣ' => 'ۉ', + 'ﯤ' => 'ې', + 'ﯥ' => 'ې', + 'ﯦ' => 'ې', + 'ﯧ' => 'ې', + 'ﯨ' => 'ى', + 'ﯩ' => 'ى', + 'ﯪ' => 'ئا', + 'ﯫ' => 'ئا', + 'ﯬ' => 'ئە', + 'ﯭ' => 'ئە', + 'ﯮ' => 'ئو', + 'ﯯ' => 'ئو', + 'ﯰ' => 'ئۇ', + 'ﯱ' => 'ئۇ', + 'ﯲ' => 'ئۆ', + 'ﯳ' => 'ئۆ', + 'ﯴ' => 'ئۈ', + 'ﯵ' => 'ئۈ', + 'ﯶ' => 'ئې', + 'ﯷ' => 'ئې', + 'ﯸ' => 'ئې', + 'ﯹ' => 'ئى', + 'ﯺ' => 'ئى', + 'ﯻ' => 'ئى', + 'ﯼ' => 'ی', + 'ﯽ' => 'ی', + 'ﯾ' => 'ی', + 'ﯿ' => 'ی', + 'ﰀ' => 'ئج', + 'ﰁ' => 'ئح', + 'ﰂ' => 'ئم', + 'ﰃ' => 'ئى', + 'ﰄ' => 'ئي', + 'ﰅ' => 'بج', + 'ﰆ' => 'بح', + 'ﰇ' => 'بخ', + 'ﰈ' => 'بم', + 'ﰉ' => 'بى', + 'ﰊ' => 'بي', + 'ﰋ' => 'تج', + 'ﰌ' => 'تح', + 'ﰍ' => 'تخ', + 'ﰎ' => 'تم', + 'ﰏ' => 'تى', + 'ﰐ' => 'تي', + 'ﰑ' => 'ثج', + 'ﰒ' => 'ثم', + 'ﰓ' => 'ثى', + 'ﰔ' => 'ثي', + 'ﰕ' => 'جح', + 'ﰖ' => 'جم', + 'ﰗ' => 'حج', + 'ﰘ' => 'حم', + 'ﰙ' => 'خج', + 'ﰚ' => 'خح', + 'ﰛ' => 'خم', + 'ﰜ' => 'سج', + 'ﰝ' => 'سح', + 'ﰞ' => 'سخ', + 'ﰟ' => 'سم', + 'ﰠ' => 'صح', + 'ﰡ' => 'صم', + 'ﰢ' => 'ضج', + 'ﰣ' => 'ضح', + 'ﰤ' => 'ضخ', + 'ﰥ' => 'ضم', + 'ﰦ' => 'طح', + 'ﰧ' => 'طم', + 'ﰨ' => 'ظم', + 'ﰩ' => 'عج', + 'ﰪ' => 'عم', + 'ﰫ' => 'غج', + 'ﰬ' => 'غم', + 'ﰭ' => 'فج', + 'ﰮ' => 'فح', + 'ﰯ' => 'فخ', + 'ﰰ' => 'فم', + 'ﰱ' => 'فى', + 'ﰲ' => 'في', + 'ﰳ' => 'قح', + 'ﰴ' => 'قم', + 'ﰵ' => 'قى', + 'ﰶ' => 'قي', + 'ﰷ' => 'كا', + 'ﰸ' => 'كج', + 'ﰹ' => 'كح', + 'ﰺ' => 'كخ', + 'ﰻ' => 'كل', + 'ﰼ' => 'كم', + 'ﰽ' => 'كى', + 'ﰾ' => 'كي', + 'ﰿ' => 'لج', + 'ﱀ' => 'لح', + 'ﱁ' => 'لخ', + 'ﱂ' => 'لم', + 'ﱃ' => 'لى', + 'ﱄ' => 'لي', + 'ﱅ' => 'مج', + 'ﱆ' => 'مح', + 'ﱇ' => 'مخ', + 'ﱈ' => 'مم', + 'ﱉ' => 'مى', + 'ﱊ' => 'مي', + 'ﱋ' => 'نج', + 'ﱌ' => 'نح', + 'ﱍ' => 'نخ', + 'ﱎ' => 'نم', + 'ﱏ' => 'نى', + 'ﱐ' => 'ني', + 'ﱑ' => 'هج', + 'ﱒ' => 'هم', + 'ﱓ' => 'هى', + 'ﱔ' => 'هي', + 'ﱕ' => 'يج', + 'ﱖ' => 'يح', + 'ﱗ' => 'يخ', + 'ﱘ' => 'يم', + 'ﱙ' => 'يى', + 'ﱚ' => 'يي', + 'ﱛ' => 'ذٰ', + 'ﱜ' => 'رٰ', + 'ﱝ' => 'ىٰ', + 'ﱞ' => ' ٌّ', + 'ﱟ' => ' ٍّ', + 'ﱠ' => ' َّ', + 'ﱡ' => ' ُّ', + 'ﱢ' => ' ِّ', + 'ﱣ' => ' ّٰ', + 'ﱤ' => 'ئر', + 'ﱥ' => 'ئز', + 'ﱦ' => 'ئم', + 'ﱧ' => 'ئن', + 'ﱨ' => 'ئى', + 'ﱩ' => 'ئي', + 'ﱪ' => 'بر', + 'ﱫ' => 'بز', + 'ﱬ' => 'بم', + 'ﱭ' => 'بن', + 'ﱮ' => 'بى', + 'ﱯ' => 'بي', + 'ﱰ' => 'تر', + 'ﱱ' => 'تز', + 'ﱲ' => 'تم', + 'ﱳ' => 'تن', + 'ﱴ' => 'تى', + 'ﱵ' => 'تي', + 'ﱶ' => 'ثر', + 'ﱷ' => 'ثز', + 'ﱸ' => 'ثم', + 'ﱹ' => 'ثن', + 'ﱺ' => 'ثى', + 'ﱻ' => 'ثي', + 'ﱼ' => 'فى', + 'ﱽ' => 'في', + 'ﱾ' => 'قى', + 'ﱿ' => 'قي', + 'ﲀ' => 'كا', + 'ﲁ' => 'كل', + 'ﲂ' => 'كم', + 'ﲃ' => 'كى', + 'ﲄ' => 'كي', + 'ﲅ' => 'لم', + 'ﲆ' => 'لى', + 'ﲇ' => 'لي', + 'ﲈ' => 'ما', + 'ﲉ' => 'مم', + 'ﲊ' => 'نر', + 'ﲋ' => 'نز', + 'ﲌ' => 'نم', + 'ﲍ' => 'نن', + 'ﲎ' => 'نى', + 'ﲏ' => 'ني', + 'ﲐ' => 'ىٰ', + 'ﲑ' => 'ير', + 'ﲒ' => 'يز', + 'ﲓ' => 'يم', + 'ﲔ' => 'ين', + 'ﲕ' => 'يى', + 'ﲖ' => 'يي', + 'ﲗ' => 'ئج', + 'ﲘ' => 'ئح', + 'ﲙ' => 'ئخ', + 'ﲚ' => 'ئم', + 'ﲛ' => 'ئه', + 'ﲜ' => 'بج', + 'ﲝ' => 'بح', + 'ﲞ' => 'بخ', + 'ﲟ' => 'بم', + 'ﲠ' => 'به', + 'ﲡ' => 'تج', + 'ﲢ' => 'تح', + 'ﲣ' => 'تخ', + 'ﲤ' => 'تم', + 'ﲥ' => 'ته', + 'ﲦ' => 'ثم', + 'ﲧ' => 'جح', + 'ﲨ' => 'جم', + 'ﲩ' => 'حج', + 'ﲪ' => 'حم', + 'ﲫ' => 'خج', + 'ﲬ' => 'خم', + 'ﲭ' => 'سج', + 'ﲮ' => 'سح', + 'ﲯ' => 'سخ', + 'ﲰ' => 'سم', + 'ﲱ' => 'صح', + 'ﲲ' => 'صخ', + 'ﲳ' => 'صم', + 'ﲴ' => 'ضج', + 'ﲵ' => 'ضح', + 'ﲶ' => 'ضخ', + 'ﲷ' => 'ضم', + 'ﲸ' => 'طح', + 'ﲹ' => 'ظم', + 'ﲺ' => 'عج', + 'ﲻ' => 'عم', + 'ﲼ' => 'غج', + 'ﲽ' => 'غم', + 'ﲾ' => 'فج', + 'ﲿ' => 'فح', + 'ﳀ' => 'فخ', + 'ﳁ' => 'فم', + 'ﳂ' => 'قح', + 'ﳃ' => 'قم', + 'ﳄ' => 'كج', + 'ﳅ' => 'كح', + 'ﳆ' => 'كخ', + 'ﳇ' => 'كل', + 'ﳈ' => 'كم', + 'ﳉ' => 'لج', + 'ﳊ' => 'لح', + 'ﳋ' => 'لخ', + 'ﳌ' => 'لم', + 'ﳍ' => 'له', + 'ﳎ' => 'مج', + 'ﳏ' => 'مح', + 'ﳐ' => 'مخ', + 'ﳑ' => 'مم', + 'ﳒ' => 'نج', + 'ﳓ' => 'نح', + 'ﳔ' => 'نخ', + 'ﳕ' => 'نم', + 'ﳖ' => 'نه', + 'ﳗ' => 'هج', + 'ﳘ' => 'هم', + 'ﳙ' => 'هٰ', + 'ﳚ' => 'يج', + 'ﳛ' => 'يح', + 'ﳜ' => 'يخ', + 'ﳝ' => 'يم', + 'ﳞ' => 'يه', + 'ﳟ' => 'ئم', + 'ﳠ' => 'ئه', + 'ﳡ' => 'بم', + 'ﳢ' => 'به', + 'ﳣ' => 'تم', + 'ﳤ' => 'ته', + 'ﳥ' => 'ثم', + 'ﳦ' => 'ثه', + 'ﳧ' => 'سم', + 'ﳨ' => 'سه', + 'ﳩ' => 'شم', + 'ﳪ' => 'شه', + 'ﳫ' => 'كل', + 'ﳬ' => 'كم', + 'ﳭ' => 'لم', + 'ﳮ' => 'نم', + 'ﳯ' => 'نه', + 'ﳰ' => 'يم', + 'ﳱ' => 'يه', + 'ﳲ' => 'ـَّ', + 'ﳳ' => 'ـُّ', + 'ﳴ' => 'ـِّ', + 'ﳵ' => 'طى', + 'ﳶ' => 'طي', + 'ﳷ' => 'عى', + 'ﳸ' => 'عي', + 'ﳹ' => 'غى', + 'ﳺ' => 'غي', + 'ﳻ' => 'سى', + 'ﳼ' => 'سي', + 'ﳽ' => 'شى', + 'ﳾ' => 'شي', + 'ﳿ' => 'حى', + 'ﴀ' => 'حي', + 'ﴁ' => 'جى', + 'ﴂ' => 'جي', + 'ﴃ' => 'خى', + 'ﴄ' => 'خي', + 'ﴅ' => 'صى', + 'ﴆ' => 'صي', + 'ﴇ' => 'ضى', + 'ﴈ' => 'ضي', + 'ﴉ' => 'شج', + 'ﴊ' => 'شح', + 'ﴋ' => 'شخ', + 'ﴌ' => 'شم', + 'ﴍ' => 'شر', + 'ﴎ' => 'سر', + 'ﴏ' => 'صر', + 'ﴐ' => 'ضر', + 'ﴑ' => 'طى', + 'ﴒ' => 'طي', + 'ﴓ' => 'عى', + 'ﴔ' => 'عي', + 'ﴕ' => 'غى', + 'ﴖ' => 'غي', + 'ﴗ' => 'سى', + 'ﴘ' => 'سي', + 'ﴙ' => 'شى', + 'ﴚ' => 'شي', + 'ﴛ' => 'حى', + 'ﴜ' => 'حي', + 'ﴝ' => 'جى', + 'ﴞ' => 'جي', + 'ﴟ' => 'خى', + 'ﴠ' => 'خي', + 'ﴡ' => 'صى', + 'ﴢ' => 'صي', + 'ﴣ' => 'ضى', + 'ﴤ' => 'ضي', + 'ﴥ' => 'شج', + 'ﴦ' => 'شح', + 'ﴧ' => 'شخ', + 'ﴨ' => 'شم', + 'ﴩ' => 'شر', + 'ﴪ' => 'سر', + 'ﴫ' => 'صر', + 'ﴬ' => 'ضر', + 'ﴭ' => 'شج', + 'ﴮ' => 'شح', + 'ﴯ' => 'شخ', + 'ﴰ' => 'شم', + 'ﴱ' => 'سه', + 'ﴲ' => 'شه', + 'ﴳ' => 'طم', + 'ﴴ' => 'سج', + 'ﴵ' => 'سح', + 'ﴶ' => 'سخ', + 'ﴷ' => 'شج', + 'ﴸ' => 'شح', + 'ﴹ' => 'شخ', + 'ﴺ' => 'طم', + 'ﴻ' => 'ظم', + 'ﴼ' => 'اً', + 'ﴽ' => 'اً', + 'ﵐ' => 'تجم', + 'ﵑ' => 'تحج', + 'ﵒ' => 'تحج', + 'ﵓ' => 'تحم', + 'ﵔ' => 'تخم', + 'ﵕ' => 'تمج', + 'ﵖ' => 'تمح', + 'ﵗ' => 'تمخ', + 'ﵘ' => 'جمح', + 'ﵙ' => 'جمح', + 'ﵚ' => 'حمي', + 'ﵛ' => 'حمى', + 'ﵜ' => 'سحج', + 'ﵝ' => 'سجح', + 'ﵞ' => 'سجى', + 'ﵟ' => 'سمح', + 'ﵠ' => 'سمح', + 'ﵡ' => 'سمج', + 'ﵢ' => 'سمم', + 'ﵣ' => 'سمم', + 'ﵤ' => 'صحح', + 'ﵥ' => 'صحح', + 'ﵦ' => 'صمم', + 'ﵧ' => 'شحم', + 'ﵨ' => 'شحم', + 'ﵩ' => 'شجي', + 'ﵪ' => 'شمخ', + 'ﵫ' => 'شمخ', + 'ﵬ' => 'شمم', + 'ﵭ' => 'شمم', + 'ﵮ' => 'ضحى', + 'ﵯ' => 'ضخم', + 'ﵰ' => 'ضخم', + 'ﵱ' => 'طمح', + 'ﵲ' => 'طمح', + 'ﵳ' => 'طمم', + 'ﵴ' => 'طمي', + 'ﵵ' => 'عجم', + 'ﵶ' => 'عمم', + 'ﵷ' => 'عمم', + 'ﵸ' => 'عمى', + 'ﵹ' => 'غمم', + 'ﵺ' => 'غمي', + 'ﵻ' => 'غمى', + 'ﵼ' => 'فخم', + 'ﵽ' => 'فخم', + 'ﵾ' => 'قمح', + 'ﵿ' => 'قمم', + 'ﶀ' => 'لحم', + 'ﶁ' => 'لحي', + 'ﶂ' => 'لحى', + 'ﶃ' => 'لجج', + 'ﶄ' => 'لجج', + 'ﶅ' => 'لخم', + 'ﶆ' => 'لخم', + 'ﶇ' => 'لمح', + 'ﶈ' => 'لمح', + 'ﶉ' => 'محج', + 'ﶊ' => 'محم', + 'ﶋ' => 'محي', + 'ﶌ' => 'مجح', + 'ﶍ' => 'مجم', + 'ﶎ' => 'مخج', + 'ﶏ' => 'مخم', + 'ﶒ' => 'مجخ', + 'ﶓ' => 'همج', + 'ﶔ' => 'همم', + 'ﶕ' => 'نحم', + 'ﶖ' => 'نحى', + 'ﶗ' => 'نجم', + 'ﶘ' => 'نجم', + 'ﶙ' => 'نجى', + 'ﶚ' => 'نمي', + 'ﶛ' => 'نمى', + 'ﶜ' => 'يمم', + 'ﶝ' => 'يمم', + 'ﶞ' => 'بخي', + 'ﶟ' => 'تجي', + 'ﶠ' => 'تجى', + 'ﶡ' => 'تخي', + 'ﶢ' => 'تخى', + 'ﶣ' => 'تمي', + 'ﶤ' => 'تمى', + 'ﶥ' => 'جمي', + 'ﶦ' => 'جحى', + 'ﶧ' => 'جمى', + 'ﶨ' => 'سخى', + 'ﶩ' => 'صحي', + 'ﶪ' => 'شحي', + 'ﶫ' => 'ضحي', + 'ﶬ' => 'لجي', + 'ﶭ' => 'لمي', + 'ﶮ' => 'يحي', + 'ﶯ' => 'يجي', + 'ﶰ' => 'يمي', + 'ﶱ' => 'ممي', + 'ﶲ' => 'قمي', + 'ﶳ' => 'نحي', + 'ﶴ' => 'قمح', + 'ﶵ' => 'لحم', + 'ﶶ' => 'عمي', + 'ﶷ' => 'كمي', + 'ﶸ' => 'نجح', + 'ﶹ' => 'مخي', + 'ﶺ' => 'لجم', + 'ﶻ' => 'كمم', + 'ﶼ' => 'لجم', + 'ﶽ' => 'نجح', + 'ﶾ' => 'جحي', + 'ﶿ' => 'حجي', + 'ﷀ' => 'مجي', + 'ﷁ' => 'فمي', + 'ﷂ' => 'بحي', + 'ﷃ' => 'كمم', + 'ﷄ' => 'عجم', + 'ﷅ' => 'صمم', + 'ﷆ' => 'سخي', + 'ﷇ' => 'نجي', + 'ﷰ' => 'صلے', + 'ﷱ' => 'قلے', + 'ﷲ' => 'الله', + 'ﷳ' => 'اكبر', + 'ﷴ' => 'محمد', + 'ﷵ' => 'صلعم', + 'ﷶ' => 'رسول', + 'ﷷ' => 'عليه', + 'ﷸ' => 'وسلم', + 'ﷹ' => 'صلى', + 'ﷺ' => 'صلى الله عليه وسلم', + 'ﷻ' => 'جل جلاله', + '﷼' => 'ریال', + '︐' => ',', + '︑' => '、', + '︒' => '。', + '︓' => ':', + '︔' => ';', + '︕' => '!', + '︖' => '?', + '︗' => '〖', + '︘' => '〗', + '︙' => '...', + '︰' => '..', + '︱' => '—', + '︲' => '–', + '︳' => '_', + '︴' => '_', + '︵' => '(', + '︶' => ')', + '︷' => '{', + '︸' => '}', + '︹' => '〔', + '︺' => '〕', + '︻' => '【', + '︼' => '】', + '︽' => '《', + '︾' => '》', + '︿' => '〈', + '﹀' => '〉', + '﹁' => '「', + '﹂' => '」', + '﹃' => '『', + '﹄' => '』', + '﹇' => '[', + '﹈' => ']', + '﹉' => ' ̅', + '﹊' => ' ̅', + '﹋' => ' ̅', + '﹌' => ' ̅', + '﹍' => '_', + '﹎' => '_', + '﹏' => '_', + '﹐' => ',', + '﹑' => '、', + '﹒' => '.', + '﹔' => ';', + '﹕' => ':', + '﹖' => '?', + '﹗' => '!', + '﹘' => '—', + '﹙' => '(', + '﹚' => ')', + '﹛' => '{', + '﹜' => '}', + '﹝' => '〔', + '﹞' => '〕', + '﹟' => '#', + '﹠' => '&', + '﹡' => '*', + '﹢' => '+', + '﹣' => '-', + '﹤' => '<', + '﹥' => '>', + '﹦' => '=', + '﹨' => '\\', + '﹩' => '$', + '﹪' => '%', + '﹫' => '@', + 'ﹰ' => ' ً', + 'ﹱ' => 'ـً', + 'ﹲ' => ' ٌ', + 'ﹴ' => ' ٍ', + 'ﹶ' => ' َ', + 'ﹷ' => 'ـَ', + 'ﹸ' => ' ُ', + 'ﹹ' => 'ـُ', + 'ﹺ' => ' ِ', + 'ﹻ' => 'ـِ', + 'ﹼ' => ' ّ', + 'ﹽ' => 'ـّ', + 'ﹾ' => ' ْ', + 'ﹿ' => 'ـْ', + 'ﺀ' => 'ء', + 'ﺁ' => 'آ', + 'ﺂ' => 'آ', + 'ﺃ' => 'أ', + 'ﺄ' => 'أ', + 'ﺅ' => 'ؤ', + 'ﺆ' => 'ؤ', + 'ﺇ' => 'إ', + 'ﺈ' => 'إ', + 'ﺉ' => 'ئ', + 'ﺊ' => 'ئ', + 'ﺋ' => 'ئ', + 'ﺌ' => 'ئ', + 'ﺍ' => 'ا', + 'ﺎ' => 'ا', + 'ﺏ' => 'ب', + 'ﺐ' => 'ب', + 'ﺑ' => 'ب', + 'ﺒ' => 'ب', + 'ﺓ' => 'ة', + 'ﺔ' => 'ة', + 'ﺕ' => 'ت', + 'ﺖ' => 'ت', + 'ﺗ' => 'ت', + 'ﺘ' => 'ت', + 'ﺙ' => 'ث', + 'ﺚ' => 'ث', + 'ﺛ' => 'ث', + 'ﺜ' => 'ث', + 'ﺝ' => 'ج', + 'ﺞ' => 'ج', + 'ﺟ' => 'ج', + 'ﺠ' => 'ج', + 'ﺡ' => 'ح', + 'ﺢ' => 'ح', + 'ﺣ' => 'ح', + 'ﺤ' => 'ح', + 'ﺥ' => 'خ', + 'ﺦ' => 'خ', + 'ﺧ' => 'خ', + 'ﺨ' => 'خ', + 'ﺩ' => 'د', + 'ﺪ' => 'د', + 'ﺫ' => 'ذ', + 'ﺬ' => 'ذ', + 'ﺭ' => 'ر', + 'ﺮ' => 'ر', + 'ﺯ' => 'ز', + 'ﺰ' => 'ز', + 'ﺱ' => 'س', + 'ﺲ' => 'س', + 'ﺳ' => 'س', + 'ﺴ' => 'س', + 'ﺵ' => 'ش', + 'ﺶ' => 'ش', + 'ﺷ' => 'ش', + 'ﺸ' => 'ش', + 'ﺹ' => 'ص', + 'ﺺ' => 'ص', + 'ﺻ' => 'ص', + 'ﺼ' => 'ص', + 'ﺽ' => 'ض', + 'ﺾ' => 'ض', + 'ﺿ' => 'ض', + 'ﻀ' => 'ض', + 'ﻁ' => 'ط', + 'ﻂ' => 'ط', + 'ﻃ' => 'ط', + 'ﻄ' => 'ط', + 'ﻅ' => 'ظ', + 'ﻆ' => 'ظ', + 'ﻇ' => 'ظ', + 'ﻈ' => 'ظ', + 'ﻉ' => 'ع', + 'ﻊ' => 'ع', + 'ﻋ' => 'ع', + 'ﻌ' => 'ع', + 'ﻍ' => 'غ', + 'ﻎ' => 'غ', + 'ﻏ' => 'غ', + 'ﻐ' => 'غ', + 'ﻑ' => 'ف', + 'ﻒ' => 'ف', + 'ﻓ' => 'ف', + 'ﻔ' => 'ف', + 'ﻕ' => 'ق', + 'ﻖ' => 'ق', + 'ﻗ' => 'ق', + 'ﻘ' => 'ق', + 'ﻙ' => 'ك', + 'ﻚ' => 'ك', + 'ﻛ' => 'ك', + 'ﻜ' => 'ك', + 'ﻝ' => 'ل', + 'ﻞ' => 'ل', + 'ﻟ' => 'ل', + 'ﻠ' => 'ل', + 'ﻡ' => 'م', + 'ﻢ' => 'م', + 'ﻣ' => 'م', + 'ﻤ' => 'م', + 'ﻥ' => 'ن', + 'ﻦ' => 'ن', + 'ﻧ' => 'ن', + 'ﻨ' => 'ن', + 'ﻩ' => 'ه', + 'ﻪ' => 'ه', + 'ﻫ' => 'ه', + 'ﻬ' => 'ه', + 'ﻭ' => 'و', + 'ﻮ' => 'و', + 'ﻯ' => 'ى', + 'ﻰ' => 'ى', + 'ﻱ' => 'ي', + 'ﻲ' => 'ي', + 'ﻳ' => 'ي', + 'ﻴ' => 'ي', + 'ﻵ' => 'لآ', + 'ﻶ' => 'لآ', + 'ﻷ' => 'لأ', + 'ﻸ' => 'لأ', + 'ﻹ' => 'لإ', + 'ﻺ' => 'لإ', + 'ﻻ' => 'لا', + 'ﻼ' => 'لا', + '!' => '!', + '"' => '"', + '#' => '#', + '$' => '$', + '%' => '%', + '&' => '&', + ''' => '\'', + '(' => '(', + ')' => ')', + '*' => '*', + '+' => '+', + ',' => ',', + '-' => '-', + '.' => '.', + '/' => '/', + '0' => '0', + '1' => '1', + '2' => '2', + '3' => '3', + '4' => '4', + '5' => '5', + '6' => '6', + '7' => '7', + '8' => '8', + '9' => '9', + ':' => ':', + ';' => ';', + '<' => '<', + '=' => '=', + '>' => '>', + '?' => '?', + '@' => '@', + 'A' => 'A', + 'B' => 'B', + 'C' => 'C', + 'D' => 'D', + 'E' => 'E', + 'F' => 'F', + 'G' => 'G', + 'H' => 'H', + 'I' => 'I', + 'J' => 'J', + 'K' => 'K', + 'L' => 'L', + 'M' => 'M', + 'N' => 'N', + 'O' => 'O', + 'P' => 'P', + 'Q' => 'Q', + 'R' => 'R', + 'S' => 'S', + 'T' => 'T', + 'U' => 'U', + 'V' => 'V', + 'W' => 'W', + 'X' => 'X', + 'Y' => 'Y', + 'Z' => 'Z', + '[' => '[', + '\' => '\\', + ']' => ']', + '^' => '^', + '_' => '_', + '`' => '`', + 'a' => 'a', + 'b' => 'b', + 'c' => 'c', + 'd' => 'd', + 'e' => 'e', + 'f' => 'f', + 'g' => 'g', + 'h' => 'h', + 'i' => 'i', + 'j' => 'j', + 'k' => 'k', + 'l' => 'l', + 'm' => 'm', + 'n' => 'n', + 'o' => 'o', + 'p' => 'p', + 'q' => 'q', + 'r' => 'r', + 's' => 's', + 't' => 't', + 'u' => 'u', + 'v' => 'v', + 'w' => 'w', + 'x' => 'x', + 'y' => 'y', + 'z' => 'z', + '{' => '{', + '|' => '|', + '}' => '}', + '~' => '~', + '⦅' => '⦅', + '⦆' => '⦆', + '。' => '。', + '「' => '「', + '」' => '」', + '、' => '、', + '・' => '・', + 'ヲ' => 'ヲ', + 'ァ' => 'ァ', + 'ィ' => 'ィ', + 'ゥ' => 'ゥ', + 'ェ' => 'ェ', + 'ォ' => 'ォ', + 'ャ' => 'ャ', + 'ュ' => 'ュ', + 'ョ' => 'ョ', + 'ッ' => 'ッ', + 'ー' => 'ー', + 'ア' => 'ア', + 'イ' => 'イ', + 'ウ' => 'ウ', + 'エ' => 'エ', + 'オ' => 'オ', + 'カ' => 'カ', + 'キ' => 'キ', + 'ク' => 'ク', + 'ケ' => 'ケ', + 'コ' => 'コ', + 'サ' => 'サ', + 'シ' => 'シ', + 'ス' => 'ス', + 'セ' => 'セ', + 'ソ' => 'ソ', + 'タ' => 'タ', + 'チ' => 'チ', + 'ツ' => 'ツ', + 'テ' => 'テ', + 'ト' => 'ト', + 'ナ' => 'ナ', + 'ニ' => 'ニ', + 'ヌ' => 'ヌ', + 'ネ' => 'ネ', + 'ノ' => 'ノ', + 'ハ' => 'ハ', + 'ヒ' => 'ヒ', + 'フ' => 'フ', + 'ヘ' => 'ヘ', + 'ホ' => 'ホ', + 'マ' => 'マ', + 'ミ' => 'ミ', + 'ム' => 'ム', + 'メ' => 'メ', + 'モ' => 'モ', + 'ヤ' => 'ヤ', + 'ユ' => 'ユ', + 'ヨ' => 'ヨ', + 'ラ' => 'ラ', + 'リ' => 'リ', + 'ル' => 'ル', + 'レ' => 'レ', + 'ロ' => 'ロ', + 'ワ' => 'ワ', + 'ン' => 'ン', + '゙' => '゙', + '゚' => '゚', + 'ᅠ' => 'ᅠ', + 'ᄀ' => 'ᄀ', + 'ᄁ' => 'ᄁ', + 'ᆪ' => 'ᆪ', + 'ᄂ' => 'ᄂ', + 'ᆬ' => 'ᆬ', + 'ᆭ' => 'ᆭ', + 'ᄃ' => 'ᄃ', + 'ᄄ' => 'ᄄ', + 'ᄅ' => 'ᄅ', + 'ᆰ' => 'ᆰ', + 'ᆱ' => 'ᆱ', + 'ᆲ' => 'ᆲ', + 'ᆳ' => 'ᆳ', + 'ᆴ' => 'ᆴ', + 'ᆵ' => 'ᆵ', + 'ᄚ' => 'ᄚ', + 'ᄆ' => 'ᄆ', + 'ᄇ' => 'ᄇ', + 'ᄈ' => 'ᄈ', + 'ᄡ' => 'ᄡ', + 'ᄉ' => 'ᄉ', + 'ᄊ' => 'ᄊ', + 'ᄋ' => 'ᄋ', + 'ᄌ' => 'ᄌ', + 'ᄍ' => 'ᄍ', + 'ᄎ' => 'ᄎ', + 'ᄏ' => 'ᄏ', + 'ᄐ' => 'ᄐ', + 'ᄑ' => 'ᄑ', + 'ᄒ' => 'ᄒ', + 'ᅡ' => 'ᅡ', + 'ᅢ' => 'ᅢ', + 'ᅣ' => 'ᅣ', + 'ᅤ' => 'ᅤ', + 'ᅥ' => 'ᅥ', + 'ᅦ' => 'ᅦ', + 'ᅧ' => 'ᅧ', + 'ᅨ' => 'ᅨ', + 'ᅩ' => 'ᅩ', + 'ᅪ' => 'ᅪ', + 'ᅫ' => 'ᅫ', + 'ᅬ' => 'ᅬ', + 'ᅭ' => 'ᅭ', + 'ᅮ' => 'ᅮ', + 'ᅯ' => 'ᅯ', + 'ᅰ' => 'ᅰ', + 'ᅱ' => 'ᅱ', + 'ᅲ' => 'ᅲ', + 'ᅳ' => 'ᅳ', + 'ᅴ' => 'ᅴ', + 'ᅵ' => 'ᅵ', + '¢' => '¢', + '£' => '£', + '¬' => '¬', + ' ̄' => ' ̄', + '¦' => '¦', + '¥' => '¥', + '₩' => '₩', + '│' => '│', + '←' => '←', + '↑' => '↑', + '→' => '→', + '↓' => '↓', + '■' => '■', + '○' => '○', + '𝐀' => 'A', + '𝐁' => 'B', + '𝐂' => 'C', + '𝐃' => 'D', + '𝐄' => 'E', + '𝐅' => 'F', + '𝐆' => 'G', + '𝐇' => 'H', + '𝐈' => 'I', + '𝐉' => 'J', + '𝐊' => 'K', + '𝐋' => 'L', + '𝐌' => 'M', + '𝐍' => 'N', + '𝐎' => 'O', + '𝐏' => 'P', + '𝐐' => 'Q', + '𝐑' => 'R', + '𝐒' => 'S', + '𝐓' => 'T', + '𝐔' => 'U', + '𝐕' => 'V', + '𝐖' => 'W', + '𝐗' => 'X', + '𝐘' => 'Y', + '𝐙' => 'Z', + '𝐚' => 'a', + '𝐛' => 'b', + '𝐜' => 'c', + '𝐝' => 'd', + '𝐞' => 'e', + '𝐟' => 'f', + '𝐠' => 'g', + '𝐡' => 'h', + '𝐢' => 'i', + '𝐣' => 'j', + '𝐤' => 'k', + '𝐥' => 'l', + '𝐦' => 'm', + '𝐧' => 'n', + '𝐨' => 'o', + '𝐩' => 'p', + '𝐪' => 'q', + '𝐫' => 'r', + '𝐬' => 's', + '𝐭' => 't', + '𝐮' => 'u', + '𝐯' => 'v', + '𝐰' => 'w', + '𝐱' => 'x', + '𝐲' => 'y', + '𝐳' => 'z', + '𝐴' => 'A', + '𝐵' => 'B', + '𝐶' => 'C', + '𝐷' => 'D', + '𝐸' => 'E', + '𝐹' => 'F', + '𝐺' => 'G', + '𝐻' => 'H', + '𝐼' => 'I', + '𝐽' => 'J', + '𝐾' => 'K', + '𝐿' => 'L', + '𝑀' => 'M', + '𝑁' => 'N', + '𝑂' => 'O', + '𝑃' => 'P', + '𝑄' => 'Q', + '𝑅' => 'R', + '𝑆' => 'S', + '𝑇' => 'T', + '𝑈' => 'U', + '𝑉' => 'V', + '𝑊' => 'W', + '𝑋' => 'X', + '𝑌' => 'Y', + '𝑍' => 'Z', + '𝑎' => 'a', + '𝑏' => 'b', + '𝑐' => 'c', + '𝑑' => 'd', + '𝑒' => 'e', + '𝑓' => 'f', + '𝑔' => 'g', + '𝑖' => 'i', + '𝑗' => 'j', + '𝑘' => 'k', + '𝑙' => 'l', + '𝑚' => 'm', + '𝑛' => 'n', + '𝑜' => 'o', + '𝑝' => 'p', + '𝑞' => 'q', + '𝑟' => 'r', + '𝑠' => 's', + '𝑡' => 't', + '𝑢' => 'u', + '𝑣' => 'v', + '𝑤' => 'w', + '𝑥' => 'x', + '𝑦' => 'y', + '𝑧' => 'z', + '𝑨' => 'A', + '𝑩' => 'B', + '𝑪' => 'C', + '𝑫' => 'D', + '𝑬' => 'E', + '𝑭' => 'F', + '𝑮' => 'G', + '𝑯' => 'H', + '𝑰' => 'I', + '𝑱' => 'J', + '𝑲' => 'K', + '𝑳' => 'L', + '𝑴' => 'M', + '𝑵' => 'N', + '𝑶' => 'O', + '𝑷' => 'P', + '𝑸' => 'Q', + '𝑹' => 'R', + '𝑺' => 'S', + '𝑻' => 'T', + '𝑼' => 'U', + '𝑽' => 'V', + '𝑾' => 'W', + '𝑿' => 'X', + '𝒀' => 'Y', + '𝒁' => 'Z', + '𝒂' => 'a', + '𝒃' => 'b', + '𝒄' => 'c', + '𝒅' => 'd', + '𝒆' => 'e', + '𝒇' => 'f', + '𝒈' => 'g', + '𝒉' => 'h', + '𝒊' => 'i', + '𝒋' => 'j', + '𝒌' => 'k', + '𝒍' => 'l', + '𝒎' => 'm', + '𝒏' => 'n', + '𝒐' => 'o', + '𝒑' => 'p', + '𝒒' => 'q', + '𝒓' => 'r', + '𝒔' => 's', + '𝒕' => 't', + '𝒖' => 'u', + '𝒗' => 'v', + '𝒘' => 'w', + '𝒙' => 'x', + '𝒚' => 'y', + '𝒛' => 'z', + '𝒜' => 'A', + '𝒞' => 'C', + '𝒟' => 'D', + '𝒢' => 'G', + '𝒥' => 'J', + '𝒦' => 'K', + '𝒩' => 'N', + '𝒪' => 'O', + '𝒫' => 'P', + '𝒬' => 'Q', + '𝒮' => 'S', + '𝒯' => 'T', + '𝒰' => 'U', + '𝒱' => 'V', + '𝒲' => 'W', + '𝒳' => 'X', + '𝒴' => 'Y', + '𝒵' => 'Z', + '𝒶' => 'a', + '𝒷' => 'b', + '𝒸' => 'c', + '𝒹' => 'd', + '𝒻' => 'f', + '𝒽' => 'h', + '𝒾' => 'i', + '𝒿' => 'j', + '𝓀' => 'k', + '𝓁' => 'l', + '𝓂' => 'm', + '𝓃' => 'n', + '𝓅' => 'p', + '𝓆' => 'q', + '𝓇' => 'r', + '𝓈' => 's', + '𝓉' => 't', + '𝓊' => 'u', + '𝓋' => 'v', + '𝓌' => 'w', + '𝓍' => 'x', + '𝓎' => 'y', + '𝓏' => 'z', + '𝓐' => 'A', + '𝓑' => 'B', + '𝓒' => 'C', + '𝓓' => 'D', + '𝓔' => 'E', + '𝓕' => 'F', + '𝓖' => 'G', + '𝓗' => 'H', + '𝓘' => 'I', + '𝓙' => 'J', + '𝓚' => 'K', + '𝓛' => 'L', + '𝓜' => 'M', + '𝓝' => 'N', + '𝓞' => 'O', + '𝓟' => 'P', + '𝓠' => 'Q', + '𝓡' => 'R', + '𝓢' => 'S', + '𝓣' => 'T', + '𝓤' => 'U', + '𝓥' => 'V', + '𝓦' => 'W', + '𝓧' => 'X', + '𝓨' => 'Y', + '𝓩' => 'Z', + '𝓪' => 'a', + '𝓫' => 'b', + '𝓬' => 'c', + '𝓭' => 'd', + '𝓮' => 'e', + '𝓯' => 'f', + '𝓰' => 'g', + '𝓱' => 'h', + '𝓲' => 'i', + '𝓳' => 'j', + '𝓴' => 'k', + '𝓵' => 'l', + '𝓶' => 'm', + '𝓷' => 'n', + '𝓸' => 'o', + '𝓹' => 'p', + '𝓺' => 'q', + '𝓻' => 'r', + '𝓼' => 's', + '𝓽' => 't', + '𝓾' => 'u', + '𝓿' => 'v', + '𝔀' => 'w', + '𝔁' => 'x', + '𝔂' => 'y', + '𝔃' => 'z', + '𝔄' => 'A', + '𝔅' => 'B', + '𝔇' => 'D', + '𝔈' => 'E', + '𝔉' => 'F', + '𝔊' => 'G', + '𝔍' => 'J', + '𝔎' => 'K', + '𝔏' => 'L', + '𝔐' => 'M', + '𝔑' => 'N', + '𝔒' => 'O', + '𝔓' => 'P', + '𝔔' => 'Q', + '𝔖' => 'S', + '𝔗' => 'T', + '𝔘' => 'U', + '𝔙' => 'V', + '𝔚' => 'W', + '𝔛' => 'X', + '𝔜' => 'Y', + '𝔞' => 'a', + '𝔟' => 'b', + '𝔠' => 'c', + '𝔡' => 'd', + '𝔢' => 'e', + '𝔣' => 'f', + '𝔤' => 'g', + '𝔥' => 'h', + '𝔦' => 'i', + '𝔧' => 'j', + '𝔨' => 'k', + '𝔩' => 'l', + '𝔪' => 'm', + '𝔫' => 'n', + '𝔬' => 'o', + '𝔭' => 'p', + '𝔮' => 'q', + '𝔯' => 'r', + '𝔰' => 's', + '𝔱' => 't', + '𝔲' => 'u', + '𝔳' => 'v', + '𝔴' => 'w', + '𝔵' => 'x', + '𝔶' => 'y', + '𝔷' => 'z', + '𝔸' => 'A', + '𝔹' => 'B', + '𝔻' => 'D', + '𝔼' => 'E', + '𝔽' => 'F', + '𝔾' => 'G', + '𝕀' => 'I', + '𝕁' => 'J', + '𝕂' => 'K', + '𝕃' => 'L', + '𝕄' => 'M', + '𝕆' => 'O', + '𝕊' => 'S', + '𝕋' => 'T', + '𝕌' => 'U', + '𝕍' => 'V', + '𝕎' => 'W', + '𝕏' => 'X', + '𝕐' => 'Y', + '𝕒' => 'a', + '𝕓' => 'b', + '𝕔' => 'c', + '𝕕' => 'd', + '𝕖' => 'e', + '𝕗' => 'f', + '𝕘' => 'g', + '𝕙' => 'h', + '𝕚' => 'i', + '𝕛' => 'j', + '𝕜' => 'k', + '𝕝' => 'l', + '𝕞' => 'm', + '𝕟' => 'n', + '𝕠' => 'o', + '𝕡' => 'p', + '𝕢' => 'q', + '𝕣' => 'r', + '𝕤' => 's', + '𝕥' => 't', + '𝕦' => 'u', + '𝕧' => 'v', + '𝕨' => 'w', + '𝕩' => 'x', + '𝕪' => 'y', + '𝕫' => 'z', + '𝕬' => 'A', + '𝕭' => 'B', + '𝕮' => 'C', + '𝕯' => 'D', + '𝕰' => 'E', + '𝕱' => 'F', + '𝕲' => 'G', + '𝕳' => 'H', + '𝕴' => 'I', + '𝕵' => 'J', + '𝕶' => 'K', + '𝕷' => 'L', + '𝕸' => 'M', + '𝕹' => 'N', + '𝕺' => 'O', + '𝕻' => 'P', + '𝕼' => 'Q', + '𝕽' => 'R', + '𝕾' => 'S', + '𝕿' => 'T', + '𝖀' => 'U', + '𝖁' => 'V', + '𝖂' => 'W', + '𝖃' => 'X', + '𝖄' => 'Y', + '𝖅' => 'Z', + '𝖆' => 'a', + '𝖇' => 'b', + '𝖈' => 'c', + '𝖉' => 'd', + '𝖊' => 'e', + '𝖋' => 'f', + '𝖌' => 'g', + '𝖍' => 'h', + '𝖎' => 'i', + '𝖏' => 'j', + '𝖐' => 'k', + '𝖑' => 'l', + '𝖒' => 'm', + '𝖓' => 'n', + '𝖔' => 'o', + '𝖕' => 'p', + '𝖖' => 'q', + '𝖗' => 'r', + '𝖘' => 's', + '𝖙' => 't', + '𝖚' => 'u', + '𝖛' => 'v', + '𝖜' => 'w', + '𝖝' => 'x', + '𝖞' => 'y', + '𝖟' => 'z', + '𝖠' => 'A', + '𝖡' => 'B', + '𝖢' => 'C', + '𝖣' => 'D', + '𝖤' => 'E', + '𝖥' => 'F', + '𝖦' => 'G', + '𝖧' => 'H', + '𝖨' => 'I', + '𝖩' => 'J', + '𝖪' => 'K', + '𝖫' => 'L', + '𝖬' => 'M', + '𝖭' => 'N', + '𝖮' => 'O', + '𝖯' => 'P', + '𝖰' => 'Q', + '𝖱' => 'R', + '𝖲' => 'S', + '𝖳' => 'T', + '𝖴' => 'U', + '𝖵' => 'V', + '𝖶' => 'W', + '𝖷' => 'X', + '𝖸' => 'Y', + '𝖹' => 'Z', + '𝖺' => 'a', + '𝖻' => 'b', + '𝖼' => 'c', + '𝖽' => 'd', + '𝖾' => 'e', + '𝖿' => 'f', + '𝗀' => 'g', + '𝗁' => 'h', + '𝗂' => 'i', + '𝗃' => 'j', + '𝗄' => 'k', + '𝗅' => 'l', + '𝗆' => 'm', + '𝗇' => 'n', + '𝗈' => 'o', + '𝗉' => 'p', + '𝗊' => 'q', + '𝗋' => 'r', + '𝗌' => 's', + '𝗍' => 't', + '𝗎' => 'u', + '𝗏' => 'v', + '𝗐' => 'w', + '𝗑' => 'x', + '𝗒' => 'y', + '𝗓' => 'z', + '𝗔' => 'A', + '𝗕' => 'B', + '𝗖' => 'C', + '𝗗' => 'D', + '𝗘' => 'E', + '𝗙' => 'F', + '𝗚' => 'G', + '𝗛' => 'H', + '𝗜' => 'I', + '𝗝' => 'J', + '𝗞' => 'K', + '𝗟' => 'L', + '𝗠' => 'M', + '𝗡' => 'N', + '𝗢' => 'O', + '𝗣' => 'P', + '𝗤' => 'Q', + '𝗥' => 'R', + '𝗦' => 'S', + '𝗧' => 'T', + '𝗨' => 'U', + '𝗩' => 'V', + '𝗪' => 'W', + '𝗫' => 'X', + '𝗬' => 'Y', + '𝗭' => 'Z', + '𝗮' => 'a', + '𝗯' => 'b', + '𝗰' => 'c', + '𝗱' => 'd', + '𝗲' => 'e', + '𝗳' => 'f', + '𝗴' => 'g', + '𝗵' => 'h', + '𝗶' => 'i', + '𝗷' => 'j', + '𝗸' => 'k', + '𝗹' => 'l', + '𝗺' => 'm', + '𝗻' => 'n', + '𝗼' => 'o', + '𝗽' => 'p', + '𝗾' => 'q', + '𝗿' => 'r', + '𝘀' => 's', + '𝘁' => 't', + '𝘂' => 'u', + '𝘃' => 'v', + '𝘄' => 'w', + '𝘅' => 'x', + '𝘆' => 'y', + '𝘇' => 'z', + '𝘈' => 'A', + '𝘉' => 'B', + '𝘊' => 'C', + '𝘋' => 'D', + '𝘌' => 'E', + '𝘍' => 'F', + '𝘎' => 'G', + '𝘏' => 'H', + '𝘐' => 'I', + '𝘑' => 'J', + '𝘒' => 'K', + '𝘓' => 'L', + '𝘔' => 'M', + '𝘕' => 'N', + '𝘖' => 'O', + '𝘗' => 'P', + '𝘘' => 'Q', + '𝘙' => 'R', + '𝘚' => 'S', + '𝘛' => 'T', + '𝘜' => 'U', + '𝘝' => 'V', + '𝘞' => 'W', + '𝘟' => 'X', + '𝘠' => 'Y', + '𝘡' => 'Z', + '𝘢' => 'a', + '𝘣' => 'b', + '𝘤' => 'c', + '𝘥' => 'd', + '𝘦' => 'e', + '𝘧' => 'f', + '𝘨' => 'g', + '𝘩' => 'h', + '𝘪' => 'i', + '𝘫' => 'j', + '𝘬' => 'k', + '𝘭' => 'l', + '𝘮' => 'm', + '𝘯' => 'n', + '𝘰' => 'o', + '𝘱' => 'p', + '𝘲' => 'q', + '𝘳' => 'r', + '𝘴' => 's', + '𝘵' => 't', + '𝘶' => 'u', + '𝘷' => 'v', + '𝘸' => 'w', + '𝘹' => 'x', + '𝘺' => 'y', + '𝘻' => 'z', + '𝘼' => 'A', + '𝘽' => 'B', + '𝘾' => 'C', + '𝘿' => 'D', + '𝙀' => 'E', + '𝙁' => 'F', + '𝙂' => 'G', + '𝙃' => 'H', + '𝙄' => 'I', + '𝙅' => 'J', + '𝙆' => 'K', + '𝙇' => 'L', + '𝙈' => 'M', + '𝙉' => 'N', + '𝙊' => 'O', + '𝙋' => 'P', + '𝙌' => 'Q', + '𝙍' => 'R', + '𝙎' => 'S', + '𝙏' => 'T', + '𝙐' => 'U', + '𝙑' => 'V', + '𝙒' => 'W', + '𝙓' => 'X', + '𝙔' => 'Y', + '𝙕' => 'Z', + '𝙖' => 'a', + '𝙗' => 'b', + '𝙘' => 'c', + '𝙙' => 'd', + '𝙚' => 'e', + '𝙛' => 'f', + '𝙜' => 'g', + '𝙝' => 'h', + '𝙞' => 'i', + '𝙟' => 'j', + '𝙠' => 'k', + '𝙡' => 'l', + '𝙢' => 'm', + '𝙣' => 'n', + '𝙤' => 'o', + '𝙥' => 'p', + '𝙦' => 'q', + '𝙧' => 'r', + '𝙨' => 's', + '𝙩' => 't', + '𝙪' => 'u', + '𝙫' => 'v', + '𝙬' => 'w', + '𝙭' => 'x', + '𝙮' => 'y', + '𝙯' => 'z', + '𝙰' => 'A', + '𝙱' => 'B', + '𝙲' => 'C', + '𝙳' => 'D', + '𝙴' => 'E', + '𝙵' => 'F', + '𝙶' => 'G', + '𝙷' => 'H', + '𝙸' => 'I', + '𝙹' => 'J', + '𝙺' => 'K', + '𝙻' => 'L', + '𝙼' => 'M', + '𝙽' => 'N', + '𝙾' => 'O', + '𝙿' => 'P', + '𝚀' => 'Q', + '𝚁' => 'R', + '𝚂' => 'S', + '𝚃' => 'T', + '𝚄' => 'U', + '𝚅' => 'V', + '𝚆' => 'W', + '𝚇' => 'X', + '𝚈' => 'Y', + '𝚉' => 'Z', + '𝚊' => 'a', + '𝚋' => 'b', + '𝚌' => 'c', + '𝚍' => 'd', + '𝚎' => 'e', + '𝚏' => 'f', + '𝚐' => 'g', + '𝚑' => 'h', + '𝚒' => 'i', + '𝚓' => 'j', + '𝚔' => 'k', + '𝚕' => 'l', + '𝚖' => 'm', + '𝚗' => 'n', + '𝚘' => 'o', + '𝚙' => 'p', + '𝚚' => 'q', + '𝚛' => 'r', + '𝚜' => 's', + '𝚝' => 't', + '𝚞' => 'u', + '𝚟' => 'v', + '𝚠' => 'w', + '𝚡' => 'x', + '𝚢' => 'y', + '𝚣' => 'z', + '𝚤' => 'ı', + '𝚥' => 'ȷ', + '𝚨' => 'Α', + '𝚩' => 'Β', + '𝚪' => 'Γ', + '𝚫' => 'Δ', + '𝚬' => 'Ε', + '𝚭' => 'Ζ', + '𝚮' => 'Η', + '𝚯' => 'Θ', + '𝚰' => 'Ι', + '𝚱' => 'Κ', + '𝚲' => 'Λ', + '𝚳' => 'Μ', + '𝚴' => 'Ν', + '𝚵' => 'Ξ', + '𝚶' => 'Ο', + '𝚷' => 'Π', + '𝚸' => 'Ρ', + '𝚹' => 'Θ', + '𝚺' => 'Σ', + '𝚻' => 'Τ', + '𝚼' => 'Υ', + '𝚽' => 'Φ', + '𝚾' => 'Χ', + '𝚿' => 'Ψ', + '𝛀' => 'Ω', + '𝛁' => '∇', + '𝛂' => 'α', + '𝛃' => 'β', + '𝛄' => 'γ', + '𝛅' => 'δ', + '𝛆' => 'ε', + '𝛇' => 'ζ', + '𝛈' => 'η', + '𝛉' => 'θ', + '𝛊' => 'ι', + '𝛋' => 'κ', + '𝛌' => 'λ', + '𝛍' => 'μ', + '𝛎' => 'ν', + '𝛏' => 'ξ', + '𝛐' => 'ο', + '𝛑' => 'π', + '𝛒' => 'ρ', + '𝛓' => 'ς', + '𝛔' => 'σ', + '𝛕' => 'τ', + '𝛖' => 'υ', + '𝛗' => 'φ', + '𝛘' => 'χ', + '𝛙' => 'ψ', + '𝛚' => 'ω', + '𝛛' => '∂', + '𝛜' => 'ε', + '𝛝' => 'θ', + '𝛞' => 'κ', + '𝛟' => 'φ', + '𝛠' => 'ρ', + '𝛡' => 'π', + '𝛢' => 'Α', + '𝛣' => 'Β', + '𝛤' => 'Γ', + '𝛥' => 'Δ', + '𝛦' => 'Ε', + '𝛧' => 'Ζ', + '𝛨' => 'Η', + '𝛩' => 'Θ', + '𝛪' => 'Ι', + '𝛫' => 'Κ', + '𝛬' => 'Λ', + '𝛭' => 'Μ', + '𝛮' => 'Ν', + '𝛯' => 'Ξ', + '𝛰' => 'Ο', + '𝛱' => 'Π', + '𝛲' => 'Ρ', + '𝛳' => 'Θ', + '𝛴' => 'Σ', + '𝛵' => 'Τ', + '𝛶' => 'Υ', + '𝛷' => 'Φ', + '𝛸' => 'Χ', + '𝛹' => 'Ψ', + '𝛺' => 'Ω', + '𝛻' => '∇', + '𝛼' => 'α', + '𝛽' => 'β', + '𝛾' => 'γ', + '𝛿' => 'δ', + '𝜀' => 'ε', + '𝜁' => 'ζ', + '𝜂' => 'η', + '𝜃' => 'θ', + '𝜄' => 'ι', + '𝜅' => 'κ', + '𝜆' => 'λ', + '𝜇' => 'μ', + '𝜈' => 'ν', + '𝜉' => 'ξ', + '𝜊' => 'ο', + '𝜋' => 'π', + '𝜌' => 'ρ', + '𝜍' => 'ς', + '𝜎' => 'σ', + '𝜏' => 'τ', + '𝜐' => 'υ', + '𝜑' => 'φ', + '𝜒' => 'χ', + '𝜓' => 'ψ', + '𝜔' => 'ω', + '𝜕' => '∂', + '𝜖' => 'ε', + '𝜗' => 'θ', + '𝜘' => 'κ', + '𝜙' => 'φ', + '𝜚' => 'ρ', + '𝜛' => 'π', + '𝜜' => 'Α', + '𝜝' => 'Β', + '𝜞' => 'Γ', + '𝜟' => 'Δ', + '𝜠' => 'Ε', + '𝜡' => 'Ζ', + '𝜢' => 'Η', + '𝜣' => 'Θ', + '𝜤' => 'Ι', + '𝜥' => 'Κ', + '𝜦' => 'Λ', + '𝜧' => 'Μ', + '𝜨' => 'Ν', + '𝜩' => 'Ξ', + '𝜪' => 'Ο', + '𝜫' => 'Π', + '𝜬' => 'Ρ', + '𝜭' => 'Θ', + '𝜮' => 'Σ', + '𝜯' => 'Τ', + '𝜰' => 'Υ', + '𝜱' => 'Φ', + '𝜲' => 'Χ', + '𝜳' => 'Ψ', + '𝜴' => 'Ω', + '𝜵' => '∇', + '𝜶' => 'α', + '𝜷' => 'β', + '𝜸' => 'γ', + '𝜹' => 'δ', + '𝜺' => 'ε', + '𝜻' => 'ζ', + '𝜼' => 'η', + '𝜽' => 'θ', + '𝜾' => 'ι', + '𝜿' => 'κ', + '𝝀' => 'λ', + '𝝁' => 'μ', + '𝝂' => 'ν', + '𝝃' => 'ξ', + '𝝄' => 'ο', + '𝝅' => 'π', + '𝝆' => 'ρ', + '𝝇' => 'ς', + '𝝈' => 'σ', + '𝝉' => 'τ', + '𝝊' => 'υ', + '𝝋' => 'φ', + '𝝌' => 'χ', + '𝝍' => 'ψ', + '𝝎' => 'ω', + '𝝏' => '∂', + '𝝐' => 'ε', + '𝝑' => 'θ', + '𝝒' => 'κ', + '𝝓' => 'φ', + '𝝔' => 'ρ', + '𝝕' => 'π', + '𝝖' => 'Α', + '𝝗' => 'Β', + '𝝘' => 'Γ', + '𝝙' => 'Δ', + '𝝚' => 'Ε', + '𝝛' => 'Ζ', + '𝝜' => 'Η', + '𝝝' => 'Θ', + '𝝞' => 'Ι', + '𝝟' => 'Κ', + '𝝠' => 'Λ', + '𝝡' => 'Μ', + '𝝢' => 'Ν', + '𝝣' => 'Ξ', + '𝝤' => 'Ο', + '𝝥' => 'Π', + '𝝦' => 'Ρ', + '𝝧' => 'Θ', + '𝝨' => 'Σ', + '𝝩' => 'Τ', + '𝝪' => 'Υ', + '𝝫' => 'Φ', + '𝝬' => 'Χ', + '𝝭' => 'Ψ', + '𝝮' => 'Ω', + '𝝯' => '∇', + '𝝰' => 'α', + '𝝱' => 'β', + '𝝲' => 'γ', + '𝝳' => 'δ', + '𝝴' => 'ε', + '𝝵' => 'ζ', + '𝝶' => 'η', + '𝝷' => 'θ', + '𝝸' => 'ι', + '𝝹' => 'κ', + '𝝺' => 'λ', + '𝝻' => 'μ', + '𝝼' => 'ν', + '𝝽' => 'ξ', + '𝝾' => 'ο', + '𝝿' => 'π', + '𝞀' => 'ρ', + '𝞁' => 'ς', + '𝞂' => 'σ', + '𝞃' => 'τ', + '𝞄' => 'υ', + '𝞅' => 'φ', + '𝞆' => 'χ', + '𝞇' => 'ψ', + '𝞈' => 'ω', + '𝞉' => '∂', + '𝞊' => 'ε', + '𝞋' => 'θ', + '𝞌' => 'κ', + '𝞍' => 'φ', + '𝞎' => 'ρ', + '𝞏' => 'π', + '𝞐' => 'Α', + '𝞑' => 'Β', + '𝞒' => 'Γ', + '𝞓' => 'Δ', + '𝞔' => 'Ε', + '𝞕' => 'Ζ', + '𝞖' => 'Η', + '𝞗' => 'Θ', + '𝞘' => 'Ι', + '𝞙' => 'Κ', + '𝞚' => 'Λ', + '𝞛' => 'Μ', + '𝞜' => 'Ν', + '𝞝' => 'Ξ', + '𝞞' => 'Ο', + '𝞟' => 'Π', + '𝞠' => 'Ρ', + '𝞡' => 'Θ', + '𝞢' => 'Σ', + '𝞣' => 'Τ', + '𝞤' => 'Υ', + '𝞥' => 'Φ', + '𝞦' => 'Χ', + '𝞧' => 'Ψ', + '𝞨' => 'Ω', + '𝞩' => '∇', + '𝞪' => 'α', + '𝞫' => 'β', + '𝞬' => 'γ', + '𝞭' => 'δ', + '𝞮' => 'ε', + '𝞯' => 'ζ', + '𝞰' => 'η', + '𝞱' => 'θ', + '𝞲' => 'ι', + '𝞳' => 'κ', + '𝞴' => 'λ', + '𝞵' => 'μ', + '𝞶' => 'ν', + '𝞷' => 'ξ', + '𝞸' => 'ο', + '𝞹' => 'π', + '𝞺' => 'ρ', + '𝞻' => 'ς', + '𝞼' => 'σ', + '𝞽' => 'τ', + '𝞾' => 'υ', + '𝞿' => 'φ', + '𝟀' => 'χ', + '𝟁' => 'ψ', + '𝟂' => 'ω', + '𝟃' => '∂', + '𝟄' => 'ε', + '𝟅' => 'θ', + '𝟆' => 'κ', + '𝟇' => 'φ', + '𝟈' => 'ρ', + '𝟉' => 'π', + '𝟊' => 'Ϝ', + '𝟋' => 'ϝ', + '𝟎' => '0', + '𝟏' => '1', + '𝟐' => '2', + '𝟑' => '3', + '𝟒' => '4', + '𝟓' => '5', + '𝟔' => '6', + '𝟕' => '7', + '𝟖' => '8', + '𝟗' => '9', + '𝟘' => '0', + '𝟙' => '1', + '𝟚' => '2', + '𝟛' => '3', + '𝟜' => '4', + '𝟝' => '5', + '𝟞' => '6', + '𝟟' => '7', + '𝟠' => '8', + '𝟡' => '9', + '𝟢' => '0', + '𝟣' => '1', + '𝟤' => '2', + '𝟥' => '3', + '𝟦' => '4', + '𝟧' => '5', + '𝟨' => '6', + '𝟩' => '7', + '𝟪' => '8', + '𝟫' => '9', + '𝟬' => '0', + '𝟭' => '1', + '𝟮' => '2', + '𝟯' => '3', + '𝟰' => '4', + '𝟱' => '5', + '𝟲' => '6', + '𝟳' => '7', + '𝟴' => '8', + '𝟵' => '9', + '𝟶' => '0', + '𝟷' => '1', + '𝟸' => '2', + '𝟹' => '3', + '𝟺' => '4', + '𝟻' => '5', + '𝟼' => '6', + '𝟽' => '7', + '𝟾' => '8', + '𝟿' => '9', + '𞸀' => 'ا', + '𞸁' => 'ب', + '𞸂' => 'ج', + '𞸃' => 'د', + '𞸅' => 'و', + '𞸆' => 'ز', + '𞸇' => 'ح', + '𞸈' => 'ط', + '𞸉' => 'ي', + '𞸊' => 'ك', + '𞸋' => 'ل', + '𞸌' => 'م', + '𞸍' => 'ن', + '𞸎' => 'س', + '𞸏' => 'ع', + '𞸐' => 'ف', + '𞸑' => 'ص', + '𞸒' => 'ق', + '𞸓' => 'ر', + '𞸔' => 'ش', + '𞸕' => 'ت', + '𞸖' => 'ث', + '𞸗' => 'خ', + '𞸘' => 'ذ', + '𞸙' => 'ض', + '𞸚' => 'ظ', + '𞸛' => 'غ', + '𞸜' => 'ٮ', + '𞸝' => 'ں', + '𞸞' => 'ڡ', + '𞸟' => 'ٯ', + '𞸡' => 'ب', + '𞸢' => 'ج', + '𞸤' => 'ه', + '𞸧' => 'ح', + '𞸩' => 'ي', + '𞸪' => 'ك', + '𞸫' => 'ل', + '𞸬' => 'م', + '𞸭' => 'ن', + '𞸮' => 'س', + '𞸯' => 'ع', + '𞸰' => 'ف', + '𞸱' => 'ص', + '𞸲' => 'ق', + '𞸴' => 'ش', + '𞸵' => 'ت', + '𞸶' => 'ث', + '𞸷' => 'خ', + '𞸹' => 'ض', + '𞸻' => 'غ', + '𞹂' => 'ج', + '𞹇' => 'ح', + '𞹉' => 'ي', + '𞹋' => 'ل', + '𞹍' => 'ن', + '𞹎' => 'س', + '𞹏' => 'ع', + '𞹑' => 'ص', + '𞹒' => 'ق', + '𞹔' => 'ش', + '𞹗' => 'خ', + '𞹙' => 'ض', + '𞹛' => 'غ', + '𞹝' => 'ں', + '𞹟' => 'ٯ', + '𞹡' => 'ب', + '𞹢' => 'ج', + '𞹤' => 'ه', + '𞹧' => 'ح', + '𞹨' => 'ط', + '𞹩' => 'ي', + '𞹪' => 'ك', + '𞹬' => 'م', + '𞹭' => 'ن', + '𞹮' => 'س', + '𞹯' => 'ع', + '𞹰' => 'ف', + '𞹱' => 'ص', + '𞹲' => 'ق', + '𞹴' => 'ش', + '𞹵' => 'ت', + '𞹶' => 'ث', + '𞹷' => 'خ', + '𞹹' => 'ض', + '𞹺' => 'ظ', + '𞹻' => 'غ', + '𞹼' => 'ٮ', + '𞹾' => 'ڡ', + '𞺀' => 'ا', + '𞺁' => 'ب', + '𞺂' => 'ج', + '𞺃' => 'د', + '𞺄' => 'ه', + '𞺅' => 'و', + '𞺆' => 'ز', + '𞺇' => 'ح', + '𞺈' => 'ط', + '𞺉' => 'ي', + '𞺋' => 'ل', + '𞺌' => 'م', + '𞺍' => 'ن', + '𞺎' => 'س', + '𞺏' => 'ع', + '𞺐' => 'ف', + '𞺑' => 'ص', + '𞺒' => 'ق', + '𞺓' => 'ر', + '𞺔' => 'ش', + '𞺕' => 'ت', + '𞺖' => 'ث', + '𞺗' => 'خ', + '𞺘' => 'ذ', + '𞺙' => 'ض', + '𞺚' => 'ظ', + '𞺛' => 'غ', + '𞺡' => 'ب', + '𞺢' => 'ج', + '𞺣' => 'د', + '𞺥' => 'و', + '𞺦' => 'ز', + '𞺧' => 'ح', + '𞺨' => 'ط', + '𞺩' => 'ي', + '𞺫' => 'ل', + '𞺬' => 'م', + '𞺭' => 'ن', + '𞺮' => 'س', + '𞺯' => 'ع', + '𞺰' => 'ف', + '𞺱' => 'ص', + '𞺲' => 'ق', + '𞺳' => 'ر', + '𞺴' => 'ش', + '𞺵' => 'ت', + '𞺶' => 'ث', + '𞺷' => 'خ', + '𞺸' => 'ذ', + '𞺹' => 'ض', + '𞺺' => 'ظ', + '𞺻' => 'غ', + '🄀' => '0.', + '🄁' => '0,', + '🄂' => '1,', + '🄃' => '2,', + '🄄' => '3,', + '🄅' => '4,', + '🄆' => '5,', + '🄇' => '6,', + '🄈' => '7,', + '🄉' => '8,', + '🄊' => '9,', + '🄐' => '(A)', + '🄑' => '(B)', + '🄒' => '(C)', + '🄓' => '(D)', + '🄔' => '(E)', + '🄕' => '(F)', + '🄖' => '(G)', + '🄗' => '(H)', + '🄘' => '(I)', + '🄙' => '(J)', + '🄚' => '(K)', + '🄛' => '(L)', + '🄜' => '(M)', + '🄝' => '(N)', + '🄞' => '(O)', + '🄟' => '(P)', + '🄠' => '(Q)', + '🄡' => '(R)', + '🄢' => '(S)', + '🄣' => '(T)', + '🄤' => '(U)', + '🄥' => '(V)', + '🄦' => '(W)', + '🄧' => '(X)', + '🄨' => '(Y)', + '🄩' => '(Z)', + '🄪' => '〔S〕', + '🄫' => 'C', + '🄬' => 'R', + '🄭' => 'CD', + '🄮' => 'WZ', + '🄰' => 'A', + '🄱' => 'B', + '🄲' => 'C', + '🄳' => 'D', + '🄴' => 'E', + '🄵' => 'F', + '🄶' => 'G', + '🄷' => 'H', + '🄸' => 'I', + '🄹' => 'J', + '🄺' => 'K', + '🄻' => 'L', + '🄼' => 'M', + '🄽' => 'N', + '🄾' => 'O', + '🄿' => 'P', + '🅀' => 'Q', + '🅁' => 'R', + '🅂' => 'S', + '🅃' => 'T', + '🅄' => 'U', + '🅅' => 'V', + '🅆' => 'W', + '🅇' => 'X', + '🅈' => 'Y', + '🅉' => 'Z', + '🅊' => 'HV', + '🅋' => 'MV', + '🅌' => 'SD', + '🅍' => 'SS', + '🅎' => 'PPV', + '🅏' => 'WC', + '🅪' => 'MC', + '🅫' => 'MD', + '🅬' => 'MR', + '🆐' => 'DJ', + '🈀' => 'ほか', + '🈁' => 'ココ', + '🈂' => 'サ', + '🈐' => '手', + '🈑' => '字', + '🈒' => '双', + '🈓' => 'デ', + '🈔' => '二', + '🈕' => '多', + '🈖' => '解', + '🈗' => '天', + '🈘' => '交', + '🈙' => '映', + '🈚' => '無', + '🈛' => '料', + '🈜' => '前', + '🈝' => '後', + '🈞' => '再', + '🈟' => '新', + '🈠' => '初', + '🈡' => '終', + '🈢' => '生', + '🈣' => '販', + '🈤' => '声', + '🈥' => '吹', + '🈦' => '演', + '🈧' => '投', + '🈨' => '捕', + '🈩' => '一', + '🈪' => '三', + '🈫' => '遊', + '🈬' => '左', + '🈭' => '中', + '🈮' => '右', + '🈯' => '指', + '🈰' => '走', + '🈱' => '打', + '🈲' => '禁', + '🈳' => '空', + '🈴' => '合', + '🈵' => '満', + '🈶' => '有', + '🈷' => '月', + '🈸' => '申', + '🈹' => '割', + '🈺' => '営', + '🈻' => '配', + '🉀' => '〔本〕', + '🉁' => '〔三〕', + '🉂' => '〔二〕', + '🉃' => '〔安〕', + '🉄' => '〔点〕', + '🉅' => '〔打〕', + '🉆' => '〔盗〕', + '🉇' => '〔勝〕', + '🉈' => '〔敗〕', + '🉐' => '得', + '🉑' => '可', + '🯰' => '0', + '🯱' => '1', + '🯲' => '2', + '🯳' => '3', + '🯴' => '4', + '🯵' => '5', + '🯶' => '6', + '🯷' => '7', + '🯸' => '8', + '🯹' => '9', +); diff --git a/vendor/symfony/polyfill-intl-normalizer/bootstrap.php b/vendor/symfony/polyfill-intl-normalizer/bootstrap.php new file mode 100644 index 0000000..3608e5c --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/bootstrap.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Normalizer as p; + +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + +if (!function_exists('normalizer_is_normalized')) { + function normalizer_is_normalized($string, $form = p\Normalizer::FORM_C) { return p\Normalizer::isNormalized($string, $form); } +} +if (!function_exists('normalizer_normalize')) { + function normalizer_normalize($string, $form = p\Normalizer::FORM_C) { return p\Normalizer::normalize($string, $form); } +} diff --git a/vendor/symfony/polyfill-intl-normalizer/bootstrap80.php b/vendor/symfony/polyfill-intl-normalizer/bootstrap80.php new file mode 100644 index 0000000..e36d1a9 --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/bootstrap80.php @@ -0,0 +1,19 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Normalizer as p; + +if (!function_exists('normalizer_is_normalized')) { + function normalizer_is_normalized(?string $string, ?int $form = p\Normalizer::FORM_C): bool { return p\Normalizer::isNormalized((string) $string, (int) $form); } +} +if (!function_exists('normalizer_normalize')) { + function normalizer_normalize(?string $string, ?int $form = p\Normalizer::FORM_C): string|false { return p\Normalizer::normalize((string) $string, (int) $form); } +} diff --git a/vendor/symfony/polyfill-intl-normalizer/composer.json b/vendor/symfony/polyfill-intl-normalizer/composer.json new file mode 100644 index 0000000..65f72d6 --- /dev/null +++ b/vendor/symfony/polyfill-intl-normalizer/composer.json @@ -0,0 +1,39 @@ +{ + "name": "symfony/polyfill-intl-normalizer", + "type": "library", + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "normalizer"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "suggest": { + "ext-intl": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/vendor/symfony/polyfill-mbstring/LICENSE b/vendor/symfony/polyfill-mbstring/LICENSE index 24fa32c..4cd8bdd 100644 --- a/vendor/symfony/polyfill-mbstring/LICENSE +++ b/vendor/symfony/polyfill-mbstring/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2018 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/vendor/symfony/polyfill-mbstring/Mbstring.php b/vendor/symfony/polyfill-mbstring/Mbstring.php index 4bd326e..bce5c4a 100644 --- a/vendor/symfony/polyfill-mbstring/Mbstring.php +++ b/vendor/symfony/polyfill-mbstring/Mbstring.php @@ -35,6 +35,7 @@ * - mb_strlen - Get string length * - mb_strpos - Find position of first occurrence of string in a string * - mb_strrpos - Find position of last occurrence of a string in a string + * - mb_str_split - Convert a string to an array * - mb_strtolower - Make a string lowercase * - mb_strtoupper - Make a string uppercase * - mb_substitute_character - Set/Get substitution character @@ -44,7 +45,7 @@ * - mb_strrchr - Finds the last occurrence of a character in a string within another * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive - * - mb_strstr - Finds first occurrence of a string within anothers + * - 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 * @@ -66,19 +67,20 @@ */ final class Mbstring { - const MB_CASE_FOLD = PHP_INT_MAX; + public const MB_CASE_FOLD = \PHP_INT_MAX; - private static $encodingList = array('ASCII', 'UTF-8'); + 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", 'ι'], + ]; + + private static $encodingList = ['ASCII', 'UTF-8']; private static $language = 'neutral'; private static $internalEncoding = 'UTF-8'; - private static $caseFold = array( - array('µ','ſ',"\xCD\x85",'ς',"\xCF\x90","\xCF\x91","\xCF\x95","\xCF\x96","\xCF\xB0","\xCF\xB1","\xCF\xB5","\xE1\xBA\x9B","\xE1\xBE\xBE"), - array('μ','s','ι', 'σ','β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1",'ι'), - ); public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) { - if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) { + if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) { $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); } else { $fromEncoding = self::getEncoding($fromEncoding); @@ -103,24 +105,22 @@ public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s); } - return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s); + return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s); } if ('HTML-ENTITIES' === $fromEncoding) { - $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8'); + $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8'); $fromEncoding = 'UTF-8'; } return iconv($fromEncoding, $toEncoding.'//IGNORE', $s); } - public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) + public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars) { - $vars = array(&$a, &$b, &$c, &$d, &$e, &$f); - $ok = true; array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) { - if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { + if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { $ok = false; } }); @@ -135,22 +135,24 @@ public static function mb_decode_mimeheader($s) public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) { - trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING); + trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING); } public static function mb_decode_numericentity($s, $convmap, $encoding = null) { - 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); + 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; } - if (!\is_array($convmap) || !$convmap) { + if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { return false; } if (null !== $encoding && !\is_scalar($encoding)) { - trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.gettype($s).' given', E_USER_WARNING); + 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). } @@ -182,9 +184,10 @@ public static function mb_decode_numericentity($s, $convmap, $encoding = null) $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1]; for ($i = 0; $i < $cnt; $i += 4) { if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { - return Mbstring::mb_chr($c - $convmap[$i + 2]); + return self::mb_chr($c - $convmap[$i + 2]); } } + return $m[0]; }, $s); @@ -197,22 +200,25 @@ public static function mb_decode_numericentity($s, $convmap, $encoding = null) 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'))) { - trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.gettype($s).' given', E_USER_WARNING); + 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; } - if (!\is_array($convmap) || !$convmap) { + if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { return false; } if (null !== $encoding && !\is_scalar($encoding)) { - trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.gettype($s).' given', E_USER_WARNING); + 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)) { - trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.gettype($s).' given', E_USER_WARNING); + trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING); + return null; } @@ -232,7 +238,7 @@ public static function mb_encode_numericentity($s, $convmap, $encoding = null, $ $s = iconv($encoding, 'UTF-8//IGNORE', $s); } - static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); + static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; $cnt = floor(\count($convmap) / 4) * 4; $i = 0; @@ -280,11 +286,14 @@ public static function mb_convert_case($s, $mode, $encoding = null) $s = iconv($encoding, 'UTF-8//IGNORE', $s); } - if (MB_CASE_TITLE == $mode) { - $s = preg_replace_callback('/\b\p{Ll}/u', array(__CLASS__, 'title_case_upper'), $s); - $s = preg_replace_callback('/\B[\p{Lu}\p{Lt}]+/u', array(__CLASS__, 'title_case_lower'), $s); + if (\MB_CASE_TITLE == $mode) { + static $titleRegexp = null; + if (null === $titleRegexp) { + $titleRegexp = self::getData('titleCaseRegexp'); + } + $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s); } else { - if (MB_CASE_UPPER == $mode) { + if (\MB_CASE_UPPER == $mode) { static $upper = null; if (null === $upper) { $upper = self::getData('upperCase'); @@ -292,7 +301,7 @@ public static function mb_convert_case($s, $mode, $encoding = null) $map = $upper; } else { if (self::MB_CASE_FOLD === $mode) { - $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s); + $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s); } static $lower = null; @@ -302,7 +311,7 @@ public static function mb_convert_case($s, $mode, $encoding = null) $map = $lower; } - static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); + static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; $i = 0; $len = \strlen($s); @@ -324,7 +333,7 @@ public static function mb_convert_case($s, $mode, $encoding = null) } else { $s = substr_replace($s, $uchr, $i - $ulen, $ulen); $len += $nlen - $ulen; - $i += $nlen - $ulen; + $i += $nlen - $ulen; } } } @@ -343,15 +352,19 @@ public static function mb_internal_encoding($encoding = null) return self::$internalEncoding; } - $encoding = self::getEncoding($encoding); + $normalizedEncoding = self::getEncoding($encoding); - if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) { - self::$internalEncoding = $encoding; + if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) { + self::$internalEncoding = $normalizedEncoding; return true; } - return false; + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding)); } public static function mb_language($lang = null) @@ -360,20 +373,24 @@ public static function mb_language($lang = null) return self::$language; } - switch ($lang = strtolower($lang)) { + switch ($normalizedLang = strtolower($lang)) { case 'uni': case 'neutral': - self::$language = $lang; + self::$language = $normalizedLang; return true; } - return false; + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang)); } public static function mb_list_encodings() { - return array('UTF-8'); + return ['UTF-8']; } public static function mb_encoding_aliases($encoding) @@ -381,7 +398,7 @@ public static function mb_encoding_aliases($encoding) switch (strtoupper($encoding)) { case 'UTF8': case 'UTF-8': - return array('utf8'); + return ['utf8']; } return false; @@ -396,7 +413,7 @@ public static function mb_check_encoding($var = null, $encoding = null) $encoding = self::$internalEncoding; } - return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var); + return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var); } public static function mb_detect_encoding($str, $encodingList = null, $strict = false) @@ -452,6 +469,7 @@ public static function mb_detect_order($encodingList = null) if (strncmp($enc, 'ISO-8859-', 9)) { return false; } + // no break case 'ASCII': case 'UTF8': case 'UTF-8': @@ -482,9 +500,13 @@ public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = nu $needle = (string) $needle; if ('' === $needle) { - trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING); + if (80000 > \PHP_VERSION_ID) { + trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING); - return false; + return false; + } + + return 0; } return iconv_strpos($haystack, $needle, $offset, $encoding); @@ -501,42 +523,98 @@ public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = n $offset = 0; } elseif ($offset = (int) $offset) { if ($offset < 0) { - $haystack = self::mb_substr($haystack, 0, $offset, $encoding); + if (0 > $offset += self::mb_strlen($needle)) { + $haystack = self::mb_substr($haystack, 0, $offset, $encoding); + } $offset = 0; } else { $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding); } } - $pos = iconv_strrpos($haystack, $needle, $encoding); + $pos = '' !== $needle || 80000 > \PHP_VERSION_ID + ? iconv_strrpos($haystack, $needle, $encoding) + : self::mb_strlen($haystack, $encoding); return false !== $pos ? $offset + $pos : false; } + 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'))) { + trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING); + + return 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; + } + + throw new \ValueError('Argument #2 ($length) must be greater than 0'); + } + + if (null === $encoding) { + $encoding = mb_internal_encoding(); + } + + if ('UTF-8' === $encoding = self::getEncoding($encoding)) { + $rx = '/('; + while (65535 < $split_length) { + $rx .= '.{65535}'; + $split_length -= 65535; + } + $rx .= '.{'.$split_length.'})/us'; + + return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); + } + + $result = []; + $length = mb_strlen($string, $encoding); + + for ($i = 0; $i < $length; $i += $split_length) { + $result[] = mb_substr($string, $i, $split_length, $encoding); + } + + return $result; + } + public static function mb_strtolower($s, $encoding = null) { - return self::mb_convert_case($s, MB_CASE_LOWER, $encoding); + return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding); } public static function mb_strtoupper($s, $encoding = null) { - return self::mb_convert_case($s, MB_CASE_UPPER, $encoding); + return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding); } public static function mb_substitute_character($c = null) { + if (null === $c) { + return 'none'; + } if (0 === strcasecmp($c, 'none')) { return true; } + if (80000 > \PHP_VERSION_ID) { + return false; + } + if (\is_int($c) || 'long' === $c || 'entity' === $c) { + return false; + } - return null !== $c ? false : 'none'; + throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint'); } public static function mb_substr($s, $start, $length = null, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { - return substr($s, $start, null === $length ? 2147483647 : $length); + return (string) substr($s, $start, null === $length ? 2147483647 : $length); } if ($start < 0) { @@ -577,10 +655,11 @@ public static function mb_strrchr($haystack, $needle, $part = false, $encoding = { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { - return strrchr($haystack, $needle, $part); + $pos = strrpos($haystack, $needle); + } else { + $needle = self::mb_substr($needle, 0, 1, $encoding); + $pos = iconv_strrpos($haystack, $needle, $encoding); } - $needle = self::mb_substr($needle, 0, 1, $encoding); - $pos = iconv_strrpos($haystack, $needle, $encoding); return self::getSubpart($pos, $part, $haystack, $encoding); } @@ -616,7 +695,7 @@ public static function mb_strstr($haystack, $needle, $part = false, $encoding = public static function mb_get_info($type = 'all') { - $info = array( + $info = [ 'internal_encoding' => self::$internalEncoding, 'http_output' => 'pass', 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)', @@ -631,7 +710,7 @@ public static function mb_get_info($type = 'all') 'detect_order' => self::$encodingList, 'substitute_character' => 'none', 'strict_detection' => 'Off', - ); + ]; if ('all' === $type) { return $info; @@ -701,6 +780,10 @@ public static function mb_ord($s, $encoding = null) $s = mb_convert_encoding($s, 'UTF-8', $encoding); } + if (1 === \strlen($s)) { + return \ord($s); + } + $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; if (0xF0 <= $code) { return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; @@ -731,7 +814,7 @@ private static function html_encoding_callback(array $m) { $i = 1; $entities = ''; - $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8')); + $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8')); while (isset($m[$i])) { if (0x80 > $m[$i]) { @@ -752,14 +835,9 @@ private static function html_encoding_callback(array $m) return $entities; } - private static function title_case_lower(array $s) + private static function title_case(array $s) { - return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8'); - } - - private static function title_case_upper(array $s) - { - return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8'); + return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8'); } private static function getData($file) @@ -777,11 +855,16 @@ private static function getEncoding($encoding) return self::$internalEncoding; } + if ('UTF-8' === $encoding) { + return 'UTF-8'; + } + $encoding = strtoupper($encoding); if ('8BIT' === $encoding || 'BINARY' === $encoding) { return 'CP850'; } + if ('UTF8' === $encoding) { return 'UTF-8'; } diff --git a/vendor/symfony/polyfill-mbstring/README.md b/vendor/symfony/polyfill-mbstring/README.md index 342e828..478b40d 100644 --- a/vendor/symfony/polyfill-mbstring/README.md +++ b/vendor/symfony/polyfill-mbstring/README.md @@ -2,10 +2,10 @@ Symfony Polyfill / Mbstring =========================== This component provides a partial, native PHP implementation for the -[Mbstring](http://php.net/mbstring) extension. +[Mbstring](https://php.net/mbstring) extension. More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). License ======= diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php index 3ca1641..fac60b0 100644 --- a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php @@ -1,6 +1,6 @@ <?php -static $data = array ( +return array ( 'A' => 'a', 'B' => 'b', 'C' => 'c', @@ -81,7 +81,7 @@ 'Ī' => 'ī', 'Ĭ' => 'ĭ', 'Į' => 'į', - 'İ' => 'i', + 'İ' => 'i̇', 'IJ' => 'ij', 'Ĵ' => 'ĵ', 'Ķ' => 'ķ', @@ -510,6 +510,138 @@ 'Ⴥ' => 'ⴥ', 'Ⴧ' => 'ⴧ', 'Ⴭ' => 'ⴭ', + 'Ꭰ' => 'ꭰ', + 'Ꭱ' => 'ꭱ', + 'Ꭲ' => 'ꭲ', + 'Ꭳ' => 'ꭳ', + 'Ꭴ' => 'ꭴ', + 'Ꭵ' => 'ꭵ', + 'Ꭶ' => 'ꭶ', + 'Ꭷ' => 'ꭷ', + 'Ꭸ' => 'ꭸ', + 'Ꭹ' => 'ꭹ', + 'Ꭺ' => 'ꭺ', + 'Ꭻ' => 'ꭻ', + 'Ꭼ' => 'ꭼ', + 'Ꭽ' => 'ꭽ', + 'Ꭾ' => 'ꭾ', + 'Ꭿ' => 'ꭿ', + 'Ꮀ' => 'ꮀ', + 'Ꮁ' => 'ꮁ', + 'Ꮂ' => 'ꮂ', + 'Ꮃ' => 'ꮃ', + 'Ꮄ' => 'ꮄ', + 'Ꮅ' => 'ꮅ', + 'Ꮆ' => 'ꮆ', + 'Ꮇ' => 'ꮇ', + 'Ꮈ' => 'ꮈ', + 'Ꮉ' => 'ꮉ', + 'Ꮊ' => 'ꮊ', + 'Ꮋ' => 'ꮋ', + 'Ꮌ' => 'ꮌ', + 'Ꮍ' => 'ꮍ', + 'Ꮎ' => 'ꮎ', + 'Ꮏ' => 'ꮏ', + 'Ꮐ' => 'ꮐ', + 'Ꮑ' => 'ꮑ', + 'Ꮒ' => 'ꮒ', + 'Ꮓ' => 'ꮓ', + 'Ꮔ' => 'ꮔ', + 'Ꮕ' => 'ꮕ', + 'Ꮖ' => 'ꮖ', + 'Ꮗ' => 'ꮗ', + 'Ꮘ' => 'ꮘ', + 'Ꮙ' => 'ꮙ', + 'Ꮚ' => 'ꮚ', + 'Ꮛ' => 'ꮛ', + 'Ꮜ' => 'ꮜ', + 'Ꮝ' => 'ꮝ', + 'Ꮞ' => 'ꮞ', + 'Ꮟ' => 'ꮟ', + 'Ꮠ' => 'ꮠ', + 'Ꮡ' => 'ꮡ', + 'Ꮢ' => 'ꮢ', + 'Ꮣ' => 'ꮣ', + 'Ꮤ' => 'ꮤ', + 'Ꮥ' => 'ꮥ', + 'Ꮦ' => 'ꮦ', + 'Ꮧ' => 'ꮧ', + 'Ꮨ' => 'ꮨ', + 'Ꮩ' => 'ꮩ', + 'Ꮪ' => 'ꮪ', + 'Ꮫ' => 'ꮫ', + 'Ꮬ' => 'ꮬ', + 'Ꮭ' => 'ꮭ', + 'Ꮮ' => 'ꮮ', + 'Ꮯ' => 'ꮯ', + 'Ꮰ' => 'ꮰ', + 'Ꮱ' => 'ꮱ', + 'Ꮲ' => 'ꮲ', + 'Ꮳ' => 'ꮳ', + 'Ꮴ' => 'ꮴ', + 'Ꮵ' => 'ꮵ', + 'Ꮶ' => 'ꮶ', + 'Ꮷ' => 'ꮷ', + 'Ꮸ' => 'ꮸ', + 'Ꮹ' => 'ꮹ', + 'Ꮺ' => 'ꮺ', + 'Ꮻ' => 'ꮻ', + 'Ꮼ' => 'ꮼ', + 'Ꮽ' => 'ꮽ', + 'Ꮾ' => 'ꮾ', + 'Ꮿ' => 'ꮿ', + 'Ᏸ' => 'ᏸ', + 'Ᏹ' => 'ᏹ', + 'Ᏺ' => 'ᏺ', + 'Ᏻ' => 'ᏻ', + 'Ᏼ' => 'ᏼ', + 'Ᏽ' => 'ᏽ', + 'Ა' => 'ა', + 'Ბ' => 'ბ', + 'Გ' => 'გ', + 'Დ' => 'დ', + 'Ე' => 'ე', + 'Ვ' => 'ვ', + 'Ზ' => 'ზ', + 'Თ' => 'თ', + 'Ი' => 'ი', + 'Კ' => 'კ', + 'Ლ' => 'ლ', + 'Მ' => 'მ', + 'Ნ' => 'ნ', + 'Ო' => 'ო', + 'Პ' => 'პ', + 'Ჟ' => 'ჟ', + 'Რ' => 'რ', + 'Ს' => 'ს', + 'Ტ' => 'ტ', + 'Უ' => 'უ', + 'Ფ' => 'ფ', + 'Ქ' => 'ქ', + 'Ღ' => 'ღ', + 'Ყ' => 'ყ', + 'Შ' => 'შ', + 'Ჩ' => 'ჩ', + 'Ც' => 'ც', + 'Ძ' => 'ძ', + 'Წ' => 'წ', + 'Ჭ' => 'ჭ', + 'Ხ' => 'ხ', + 'Ჯ' => 'ჯ', + 'Ჰ' => 'ჰ', + 'Ჱ' => 'ჱ', + 'Ჲ' => 'ჲ', + 'Ჳ' => 'ჳ', + 'Ჴ' => 'ჴ', + 'Ჵ' => 'ჵ', + 'Ჶ' => 'ჶ', + 'Ჷ' => 'ჷ', + 'Ჸ' => 'ჸ', + 'Ჹ' => 'ჹ', + 'Ჺ' => 'ჺ', + 'Ჽ' => 'ჽ', + 'Ჾ' => 'ჾ', + 'Ჿ' => 'ჿ', 'Ḁ' => 'ḁ', 'Ḃ' => 'ḃ', 'Ḅ' => 'ḅ', @@ -993,8 +1125,24 @@ 'Ɜ' => 'ɜ', 'Ɡ' => 'ɡ', 'Ɬ' => 'ɬ', + 'Ɪ' => 'ɪ', 'Ʞ' => 'ʞ', 'Ʇ' => 'ʇ', + 'Ʝ' => 'ʝ', + 'Ꭓ' => 'ꭓ', + 'Ꞵ' => 'ꞵ', + 'Ꞷ' => 'ꞷ', + 'Ꞹ' => 'ꞹ', + 'Ꞻ' => 'ꞻ', + 'Ꞽ' => 'ꞽ', + 'Ꞿ' => 'ꞿ', + 'Ꟃ' => 'ꟃ', + 'Ꞔ' => 'ꞔ', + 'Ʂ' => 'ʂ', + 'Ᶎ' => 'ᶎ', + 'Ꟈ' => 'ꟈ', + 'Ꟊ' => 'ꟊ', + 'Ꟶ' => 'ꟶ', 'A' => 'a', 'B' => 'b', 'C' => 'c', @@ -1061,6 +1209,93 @@ '𐐥' => '𐑍', '𐐦' => '𐑎', '𐐧' => '𐑏', + '𐒰' => '𐓘', + '𐒱' => '𐓙', + '𐒲' => '𐓚', + '𐒳' => '𐓛', + '𐒴' => '𐓜', + '𐒵' => '𐓝', + '𐒶' => '𐓞', + '𐒷' => '𐓟', + '𐒸' => '𐓠', + '𐒹' => '𐓡', + '𐒺' => '𐓢', + '𐒻' => '𐓣', + '𐒼' => '𐓤', + '𐒽' => '𐓥', + '𐒾' => '𐓦', + '𐒿' => '𐓧', + '𐓀' => '𐓨', + '𐓁' => '𐓩', + '𐓂' => '𐓪', + '𐓃' => '𐓫', + '𐓄' => '𐓬', + '𐓅' => '𐓭', + '𐓆' => '𐓮', + '𐓇' => '𐓯', + '𐓈' => '𐓰', + '𐓉' => '𐓱', + '𐓊' => '𐓲', + '𐓋' => '𐓳', + '𐓌' => '𐓴', + '𐓍' => '𐓵', + '𐓎' => '𐓶', + '𐓏' => '𐓷', + '𐓐' => '𐓸', + '𐓑' => '𐓹', + '𐓒' => '𐓺', + '𐓓' => '𐓻', + '𐲀' => '𐳀', + '𐲁' => '𐳁', + '𐲂' => '𐳂', + '𐲃' => '𐳃', + '𐲄' => '𐳄', + '𐲅' => '𐳅', + '𐲆' => '𐳆', + '𐲇' => '𐳇', + '𐲈' => '𐳈', + '𐲉' => '𐳉', + '𐲊' => '𐳊', + '𐲋' => '𐳋', + '𐲌' => '𐳌', + '𐲍' => '𐳍', + '𐲎' => '𐳎', + '𐲏' => '𐳏', + '𐲐' => '𐳐', + '𐲑' => '𐳑', + '𐲒' => '𐳒', + '𐲓' => '𐳓', + '𐲔' => '𐳔', + '𐲕' => '𐳕', + '𐲖' => '𐳖', + '𐲗' => '𐳗', + '𐲘' => '𐳘', + '𐲙' => '𐳙', + '𐲚' => '𐳚', + '𐲛' => '𐳛', + '𐲜' => '𐳜', + '𐲝' => '𐳝', + '𐲞' => '𐳞', + '𐲟' => '𐳟', + '𐲠' => '𐳠', + '𐲡' => '𐳡', + '𐲢' => '𐳢', + '𐲣' => '𐳣', + '𐲤' => '𐳤', + '𐲥' => '𐳥', + '𐲦' => '𐳦', + '𐲧' => '𐳧', + '𐲨' => '𐳨', + '𐲩' => '𐳩', + '𐲪' => '𐳪', + '𐲫' => '𐳫', + '𐲬' => '𐳬', + '𐲭' => '𐳭', + '𐲮' => '𐳮', + '𐲯' => '𐳯', + '𐲰' => '𐳰', + '𐲱' => '𐳱', + '𐲲' => '𐳲', '𑢠' => '𑣀', '𑢡' => '𑣁', '𑢢' => '𑣂', @@ -1093,9 +1328,70 @@ '𑢽' => '𑣝', '𑢾' => '𑣞', '𑢿' => '𑣟', + '𖹀' => '𖹠', + '𖹁' => '𖹡', + '𖹂' => '𖹢', + '𖹃' => '𖹣', + '𖹄' => '𖹤', + '𖹅' => '𖹥', + '𖹆' => '𖹦', + '𖹇' => '𖹧', + '𖹈' => '𖹨', + '𖹉' => '𖹩', + '𖹊' => '𖹪', + '𖹋' => '𖹫', + '𖹌' => '𖹬', + '𖹍' => '𖹭', + '𖹎' => '𖹮', + '𖹏' => '𖹯', + '𖹐' => '𖹰', + '𖹑' => '𖹱', + '𖹒' => '𖹲', + '𖹓' => '𖹳', + '𖹔' => '𖹴', + '𖹕' => '𖹵', + '𖹖' => '𖹶', + '𖹗' => '𖹷', + '𖹘' => '𖹸', + '𖹙' => '𖹹', + '𖹚' => '𖹺', + '𖹛' => '𖹻', + '𖹜' => '𖹼', + '𖹝' => '𖹽', + '𖹞' => '𖹾', + '𖹟' => '𖹿', + '𞤀' => '𞤢', + '𞤁' => '𞤣', + '𞤂' => '𞤤', + '𞤃' => '𞤥', + '𞤄' => '𞤦', + '𞤅' => '𞤧', + '𞤆' => '𞤨', + '𞤇' => '𞤩', + '𞤈' => '𞤪', + '𞤉' => '𞤫', + '𞤊' => '𞤬', + '𞤋' => '𞤭', + '𞤌' => '𞤮', + '𞤍' => '𞤯', + '𞤎' => '𞤰', + '𞤏' => '𞤱', + '𞤐' => '𞤲', + '𞤑' => '𞤳', + '𞤒' => '𞤴', + '𞤓' => '𞤵', + '𞤔' => '𞤶', + '𞤕' => '𞤷', + '𞤖' => '𞤸', + '𞤗' => '𞤹', + '𞤘' => '𞤺', + '𞤙' => '𞤻', + '𞤚' => '𞤼', + '𞤛' => '𞤽', + '𞤜' => '𞤾', + '𞤝' => '𞤿', + '𞤞' => '𞥀', + '𞤟' => '𞥁', + '𞤠' => '𞥂', + '𞤡' => '𞥃', ); - -$result =& $data; -unset($data); - -return $result; diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php new file mode 100644 index 0000000..2a8f6e7 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php @@ -0,0 +1,5 @@ +<?php + +// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt + +return '/(?<![\x{0027}\x{002E}\x{003A}\x{005E}\x{0060}\x{00A8}\x{00AD}\x{00AF}\x{00B4}\x{00B7}\x{00B8}\x{02B0}-\x{02C1}\x{02C2}-\x{02C5}\x{02C6}-\x{02D1}\x{02D2}-\x{02DF}\x{02E0}-\x{02E4}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EE}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037A}\x{0384}-\x{0385}\x{0387}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0559}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{05F4}\x{0600}-\x{0605}\x{0610}-\x{061A}\x{061C}\x{0640}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DD}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07FA}\x{07FD}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0971}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E46}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}\x{0EBB}-\x{0EBC}\x{0EC6}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{10FC}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17D7}\x{17DD}\x{180B}-\x{180D}\x{180E}\x{1843}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AA7}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1C78}-\x{1C7D}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1D2C}-\x{1D6A}\x{1D78}\x{1D9B}-\x{1DBF}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200F}\x{2018}\x{2019}\x{2024}\x{2027}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{206F}\x{2071}\x{207F}\x{2090}-\x{209C}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2C7C}-\x{2C7D}\x{2CEF}-\x{2CF1}\x{2D6F}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E2F}\x{3005}\x{302A}-\x{302D}\x{3031}-\x{3035}\x{303B}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{309D}-\x{309E}\x{30FC}-\x{30FE}\x{A015}\x{A4F8}-\x{A4FD}\x{A60C}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A67F}\x{A69C}-\x{A69D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A770}\x{A788}\x{A789}-\x{A78A}\x{A7F8}-\x{A7F9}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}\x{A9CF}\x{A9E5}\x{A9E6}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA70}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AADD}\x{AAEC}-\x{AAED}\x{AAF3}-\x{AAF4}\x{AAF6}\x{AB5B}\x{AB5C}-\x{AB5F}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FBB2}-\x{FBC1}\x{FE00}-\x{FE0F}\x{FE13}\x{FE20}-\x{FE2F}\x{FE52}\x{FE55}\x{FEFF}\x{FF07}\x{FF0E}\x{FF1A}\x{FF3E}\x{FF40}\x{FF70}\x{FF9E}-\x{FF9F}\x{FFE3}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{110BD}\x{110CD}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16B40}-\x{16B43}\x{16F8F}-\x{16F92}\x{16F93}-\x{16F9F}\x{16FE0}-\x{16FE1}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1F3FB}-\x{1F3FF}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}])(\pL)(\pL*+)/u'; diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php index ec94221..56b9cb8 100644 --- a/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php @@ -1,6 +1,6 @@ <?php -static $data = array ( +return array ( 'a' => 'A', 'b' => 'B', 'c' => 'C', @@ -225,6 +225,7 @@ 'ɦ' => 'Ɦ', 'ɨ' => 'Ɨ', 'ɩ' => 'Ɩ', + 'ɪ' => 'Ɪ', 'ɫ' => 'Ɫ', 'ɬ' => 'Ɬ', 'ɯ' => 'Ɯ', @@ -233,6 +234,7 @@ 'ɵ' => 'Ɵ', 'ɽ' => 'Ɽ', 'ʀ' => 'Ʀ', + 'ʂ' => 'Ʂ', 'ʃ' => 'Ʃ', 'ʇ' => 'Ʇ', 'ʈ' => 'Ʈ', @@ -241,6 +243,7 @@ 'ʋ' => 'Ʋ', 'ʌ' => 'Ʌ', 'ʒ' => 'Ʒ', + 'ʝ' => 'Ʝ', 'ʞ' => 'Ʞ', 'ͅ' => 'Ι', 'ͱ' => 'Ͱ', @@ -493,8 +496,70 @@ 'ք' => 'Ք', 'օ' => 'Օ', 'ֆ' => 'Ֆ', + 'ა' => 'Ა', + 'ბ' => 'Ბ', + 'გ' => 'Გ', + 'დ' => 'Დ', + 'ე' => 'Ე', + 'ვ' => 'Ვ', + 'ზ' => 'Ზ', + 'თ' => 'Თ', + 'ი' => 'Ი', + 'კ' => 'Კ', + 'ლ' => 'Ლ', + 'მ' => 'Მ', + 'ნ' => 'Ნ', + 'ო' => 'Ო', + 'პ' => 'Პ', + 'ჟ' => 'Ჟ', + 'რ' => 'Რ', + 'ს' => 'Ს', + 'ტ' => 'Ტ', + 'უ' => 'Უ', + 'ფ' => 'Ფ', + 'ქ' => 'Ქ', + 'ღ' => 'Ღ', + 'ყ' => 'Ყ', + 'შ' => 'Შ', + 'ჩ' => 'Ჩ', + 'ც' => 'Ც', + 'ძ' => 'Ძ', + 'წ' => 'Წ', + 'ჭ' => 'Ჭ', + 'ხ' => 'Ხ', + 'ჯ' => 'Ჯ', + 'ჰ' => 'Ჰ', + 'ჱ' => 'Ჱ', + 'ჲ' => 'Ჲ', + 'ჳ' => 'Ჳ', + 'ჴ' => 'Ჴ', + 'ჵ' => 'Ჵ', + 'ჶ' => 'Ჶ', + 'ჷ' => 'Ჷ', + 'ჸ' => 'Ჸ', + 'ჹ' => 'Ჹ', + 'ჺ' => 'Ჺ', + 'ჽ' => 'Ჽ', + 'ჾ' => 'Ჾ', + 'ჿ' => 'Ჿ', + 'ᏸ' => 'Ᏸ', + 'ᏹ' => 'Ᏹ', + 'ᏺ' => 'Ᏺ', + 'ᏻ' => 'Ᏻ', + 'ᏼ' => 'Ᏼ', + 'ᏽ' => 'Ᏽ', + 'ᲀ' => 'В', + 'ᲁ' => 'Д', + 'ᲂ' => 'О', + 'ᲃ' => 'С', + 'ᲄ' => 'Т', + 'ᲅ' => 'Т', + 'ᲆ' => 'Ъ', + 'ᲇ' => 'Ѣ', + 'ᲈ' => 'Ꙋ', 'ᵹ' => 'Ᵹ', 'ᵽ' => 'Ᵽ', + 'ᶎ' => 'Ᶎ', 'ḁ' => 'Ḁ', 'ḃ' => 'Ḃ', 'ḅ' => 'Ḅ', @@ -681,41 +746,41 @@ 'ύ' => 'Ύ', 'ὼ' => 'Ὼ', 'ώ' => 'Ώ', - 'ᾀ' => 'ᾈ', - 'ᾁ' => 'ᾉ', - 'ᾂ' => 'ᾊ', - 'ᾃ' => 'ᾋ', - 'ᾄ' => 'ᾌ', - 'ᾅ' => 'ᾍ', - 'ᾆ' => 'ᾎ', - 'ᾇ' => 'ᾏ', - 'ᾐ' => 'ᾘ', - 'ᾑ' => 'ᾙ', - 'ᾒ' => 'ᾚ', - 'ᾓ' => 'ᾛ', - 'ᾔ' => 'ᾜ', - 'ᾕ' => 'ᾝ', - 'ᾖ' => 'ᾞ', - 'ᾗ' => 'ᾟ', - 'ᾠ' => 'ᾨ', - 'ᾡ' => 'ᾩ', - 'ᾢ' => 'ᾪ', - 'ᾣ' => 'ᾫ', - 'ᾤ' => 'ᾬ', - 'ᾥ' => 'ᾭ', - 'ᾦ' => 'ᾮ', - 'ᾧ' => 'ᾯ', + 'ᾀ' => 'ἈΙ', + 'ᾁ' => 'ἉΙ', + 'ᾂ' => 'ἊΙ', + 'ᾃ' => 'ἋΙ', + 'ᾄ' => 'ἌΙ', + 'ᾅ' => 'ἍΙ', + 'ᾆ' => 'ἎΙ', + 'ᾇ' => 'ἏΙ', + 'ᾐ' => 'ἨΙ', + 'ᾑ' => 'ἩΙ', + 'ᾒ' => 'ἪΙ', + 'ᾓ' => 'ἫΙ', + 'ᾔ' => 'ἬΙ', + 'ᾕ' => 'ἭΙ', + 'ᾖ' => 'ἮΙ', + 'ᾗ' => 'ἯΙ', + 'ᾠ' => 'ὨΙ', + 'ᾡ' => 'ὩΙ', + 'ᾢ' => 'ὪΙ', + 'ᾣ' => 'ὫΙ', + 'ᾤ' => 'ὬΙ', + 'ᾥ' => 'ὭΙ', + 'ᾦ' => 'ὮΙ', + 'ᾧ' => 'ὯΙ', 'ᾰ' => 'Ᾰ', 'ᾱ' => 'Ᾱ', - 'ᾳ' => 'ᾼ', + 'ᾳ' => 'ΑΙ', 'ι' => 'Ι', - 'ῃ' => 'ῌ', + 'ῃ' => 'ΗΙ', 'ῐ' => 'Ῐ', 'ῑ' => 'Ῑ', 'ῠ' => 'Ῠ', 'ῡ' => 'Ῡ', 'ῥ' => 'Ῥ', - 'ῳ' => 'ῼ', + 'ῳ' => 'ΩΙ', 'ⅎ' => 'Ⅎ', 'ⅰ' => 'Ⅰ', 'ⅱ' => 'Ⅱ', @@ -993,6 +1058,7 @@ 'ꞌ' => 'Ꞌ', 'ꞑ' => 'Ꞑ', 'ꞓ' => 'Ꞓ', + 'ꞔ' => 'Ꞔ', 'ꞗ' => 'Ꞗ', 'ꞙ' => 'Ꞙ', 'ꞛ' => 'Ꞛ', @@ -1003,6 +1069,97 @@ 'ꞥ' => 'Ꞥ', 'ꞧ' => 'Ꞧ', 'ꞩ' => 'Ꞩ', + 'ꞵ' => 'Ꞵ', + 'ꞷ' => 'Ꞷ', + 'ꞹ' => 'Ꞹ', + 'ꞻ' => 'Ꞻ', + 'ꞽ' => 'Ꞽ', + 'ꞿ' => 'Ꞿ', + 'ꟃ' => 'Ꟃ', + 'ꟈ' => 'Ꟈ', + 'ꟊ' => 'Ꟊ', + 'ꟶ' => 'Ꟶ', + 'ꭓ' => 'Ꭓ', + 'ꭰ' => 'Ꭰ', + 'ꭱ' => 'Ꭱ', + 'ꭲ' => 'Ꭲ', + 'ꭳ' => 'Ꭳ', + 'ꭴ' => 'Ꭴ', + 'ꭵ' => 'Ꭵ', + 'ꭶ' => 'Ꭶ', + 'ꭷ' => 'Ꭷ', + 'ꭸ' => 'Ꭸ', + 'ꭹ' => 'Ꭹ', + 'ꭺ' => 'Ꭺ', + 'ꭻ' => 'Ꭻ', + 'ꭼ' => 'Ꭼ', + 'ꭽ' => 'Ꭽ', + 'ꭾ' => 'Ꭾ', + 'ꭿ' => 'Ꭿ', + 'ꮀ' => 'Ꮀ', + 'ꮁ' => 'Ꮁ', + 'ꮂ' => 'Ꮂ', + 'ꮃ' => 'Ꮃ', + 'ꮄ' => 'Ꮄ', + 'ꮅ' => 'Ꮅ', + 'ꮆ' => 'Ꮆ', + 'ꮇ' => 'Ꮇ', + 'ꮈ' => 'Ꮈ', + 'ꮉ' => 'Ꮉ', + 'ꮊ' => 'Ꮊ', + 'ꮋ' => 'Ꮋ', + 'ꮌ' => 'Ꮌ', + 'ꮍ' => 'Ꮍ', + 'ꮎ' => 'Ꮎ', + 'ꮏ' => 'Ꮏ', + 'ꮐ' => 'Ꮐ', + 'ꮑ' => 'Ꮑ', + 'ꮒ' => 'Ꮒ', + 'ꮓ' => 'Ꮓ', + 'ꮔ' => 'Ꮔ', + 'ꮕ' => 'Ꮕ', + 'ꮖ' => 'Ꮖ', + 'ꮗ' => 'Ꮗ', + 'ꮘ' => 'Ꮘ', + 'ꮙ' => 'Ꮙ', + 'ꮚ' => 'Ꮚ', + 'ꮛ' => 'Ꮛ', + 'ꮜ' => 'Ꮜ', + 'ꮝ' => 'Ꮝ', + 'ꮞ' => 'Ꮞ', + 'ꮟ' => 'Ꮟ', + 'ꮠ' => 'Ꮠ', + 'ꮡ' => 'Ꮡ', + 'ꮢ' => 'Ꮢ', + 'ꮣ' => 'Ꮣ', + 'ꮤ' => 'Ꮤ', + 'ꮥ' => 'Ꮥ', + 'ꮦ' => 'Ꮦ', + 'ꮧ' => 'Ꮧ', + 'ꮨ' => 'Ꮨ', + 'ꮩ' => 'Ꮩ', + 'ꮪ' => 'Ꮪ', + 'ꮫ' => 'Ꮫ', + 'ꮬ' => 'Ꮬ', + 'ꮭ' => 'Ꮭ', + 'ꮮ' => 'Ꮮ', + 'ꮯ' => 'Ꮯ', + 'ꮰ' => 'Ꮰ', + 'ꮱ' => 'Ꮱ', + 'ꮲ' => 'Ꮲ', + 'ꮳ' => 'Ꮳ', + 'ꮴ' => 'Ꮴ', + 'ꮵ' => 'Ꮵ', + 'ꮶ' => 'Ꮶ', + 'ꮷ' => 'Ꮷ', + 'ꮸ' => 'Ꮸ', + 'ꮹ' => 'Ꮹ', + 'ꮺ' => 'Ꮺ', + 'ꮻ' => 'Ꮻ', + 'ꮼ' => 'Ꮼ', + 'ꮽ' => 'Ꮽ', + 'ꮾ' => 'Ꮾ', + 'ꮿ' => 'Ꮿ', 'a' => 'A', 'b' => 'B', 'c' => 'C', @@ -1069,6 +1226,93 @@ '𐑍' => '𐐥', '𐑎' => '𐐦', '𐑏' => '𐐧', + '𐓘' => '𐒰', + '𐓙' => '𐒱', + '𐓚' => '𐒲', + '𐓛' => '𐒳', + '𐓜' => '𐒴', + '𐓝' => '𐒵', + '𐓞' => '𐒶', + '𐓟' => '𐒷', + '𐓠' => '𐒸', + '𐓡' => '𐒹', + '𐓢' => '𐒺', + '𐓣' => '𐒻', + '𐓤' => '𐒼', + '𐓥' => '𐒽', + '𐓦' => '𐒾', + '𐓧' => '𐒿', + '𐓨' => '𐓀', + '𐓩' => '𐓁', + '𐓪' => '𐓂', + '𐓫' => '𐓃', + '𐓬' => '𐓄', + '𐓭' => '𐓅', + '𐓮' => '𐓆', + '𐓯' => '𐓇', + '𐓰' => '𐓈', + '𐓱' => '𐓉', + '𐓲' => '𐓊', + '𐓳' => '𐓋', + '𐓴' => '𐓌', + '𐓵' => '𐓍', + '𐓶' => '𐓎', + '𐓷' => '𐓏', + '𐓸' => '𐓐', + '𐓹' => '𐓑', + '𐓺' => '𐓒', + '𐓻' => '𐓓', + '𐳀' => '𐲀', + '𐳁' => '𐲁', + '𐳂' => '𐲂', + '𐳃' => '𐲃', + '𐳄' => '𐲄', + '𐳅' => '𐲅', + '𐳆' => '𐲆', + '𐳇' => '𐲇', + '𐳈' => '𐲈', + '𐳉' => '𐲉', + '𐳊' => '𐲊', + '𐳋' => '𐲋', + '𐳌' => '𐲌', + '𐳍' => '𐲍', + '𐳎' => '𐲎', + '𐳏' => '𐲏', + '𐳐' => '𐲐', + '𐳑' => '𐲑', + '𐳒' => '𐲒', + '𐳓' => '𐲓', + '𐳔' => '𐲔', + '𐳕' => '𐲕', + '𐳖' => '𐲖', + '𐳗' => '𐲗', + '𐳘' => '𐲘', + '𐳙' => '𐲙', + '𐳚' => '𐲚', + '𐳛' => '𐲛', + '𐳜' => '𐲜', + '𐳝' => '𐲝', + '𐳞' => '𐲞', + '𐳟' => '𐲟', + '𐳠' => '𐲠', + '𐳡' => '𐲡', + '𐳢' => '𐲢', + '𐳣' => '𐲣', + '𐳤' => '𐲤', + '𐳥' => '𐲥', + '𐳦' => '𐲦', + '𐳧' => '𐲧', + '𐳨' => '𐲨', + '𐳩' => '𐲩', + '𐳪' => '𐲪', + '𐳫' => '𐲫', + '𐳬' => '𐲬', + '𐳭' => '𐲭', + '𐳮' => '𐲮', + '𐳯' => '𐲯', + '𐳰' => '𐲰', + '𐳱' => '𐲱', + '𐳲' => '𐲲', '𑣀' => '𑢠', '𑣁' => '𑢡', '𑣂' => '𑢢', @@ -1101,9 +1345,145 @@ '𑣝' => '𑢽', '𑣞' => '𑢾', '𑣟' => '𑢿', + '𖹠' => '𖹀', + '𖹡' => '𖹁', + '𖹢' => '𖹂', + '𖹣' => '𖹃', + '𖹤' => '𖹄', + '𖹥' => '𖹅', + '𖹦' => '𖹆', + '𖹧' => '𖹇', + '𖹨' => '𖹈', + '𖹩' => '𖹉', + '𖹪' => '𖹊', + '𖹫' => '𖹋', + '𖹬' => '𖹌', + '𖹭' => '𖹍', + '𖹮' => '𖹎', + '𖹯' => '𖹏', + '𖹰' => '𖹐', + '𖹱' => '𖹑', + '𖹲' => '𖹒', + '𖹳' => '𖹓', + '𖹴' => '𖹔', + '𖹵' => '𖹕', + '𖹶' => '𖹖', + '𖹷' => '𖹗', + '𖹸' => '𖹘', + '𖹹' => '𖹙', + '𖹺' => '𖹚', + '𖹻' => '𖹛', + '𖹼' => '𖹜', + '𖹽' => '𖹝', + '𖹾' => '𖹞', + '𖹿' => '𖹟', + '𞤢' => '𞤀', + '𞤣' => '𞤁', + '𞤤' => '𞤂', + '𞤥' => '𞤃', + '𞤦' => '𞤄', + '𞤧' => '𞤅', + '𞤨' => '𞤆', + '𞤩' => '𞤇', + '𞤪' => '𞤈', + '𞤫' => '𞤉', + '𞤬' => '𞤊', + '𞤭' => '𞤋', + '𞤮' => '𞤌', + '𞤯' => '𞤍', + '𞤰' => '𞤎', + '𞤱' => '𞤏', + '𞤲' => '𞤐', + '𞤳' => '𞤑', + '𞤴' => '𞤒', + '𞤵' => '𞤓', + '𞤶' => '𞤔', + '𞤷' => '𞤕', + '𞤸' => '𞤖', + '𞤹' => '𞤗', + '𞤺' => '𞤘', + '𞤻' => '𞤙', + '𞤼' => '𞤚', + '𞤽' => '𞤛', + '𞤾' => '𞤜', + '𞤿' => '𞤝', + '𞥀' => '𞤞', + '𞥁' => '𞤟', + '𞥂' => '𞤠', + '𞥃' => '𞤡', + 'ß' => 'SS', + 'ff' => 'FF', + 'fi' => 'FI', + 'fl' => 'FL', + 'ffi' => 'FFI', + 'ffl' => 'FFL', + 'ſt' => 'ST', + 'st' => 'ST', + 'և' => 'ԵՒ', + 'ﬓ' => 'ՄՆ', + 'ﬔ' => 'ՄԵ', + 'ﬕ' => 'ՄԻ', + 'ﬖ' => 'ՎՆ', + 'ﬗ' => 'ՄԽ', + 'ʼn' => 'ʼN', + 'ΐ' => 'Ϊ́', + 'ΰ' => 'Ϋ́', + 'ǰ' => 'J̌', + 'ẖ' => 'H̱', + 'ẗ' => 'T̈', + 'ẘ' => 'W̊', + 'ẙ' => 'Y̊', + 'ẚ' => 'Aʾ', + 'ὐ' => 'Υ̓', + 'ὒ' => 'Υ̓̀', + 'ὔ' => 'Υ̓́', + 'ὖ' => 'Υ̓͂', + 'ᾶ' => 'Α͂', + 'ῆ' => 'Η͂', + 'ῒ' => 'Ϊ̀', + 'ΐ' => 'Ϊ́', + 'ῖ' => 'Ι͂', + 'ῗ' => 'Ϊ͂', + 'ῢ' => 'Ϋ̀', + 'ΰ' => 'Ϋ́', + 'ῤ' => 'Ρ̓', + 'ῦ' => 'Υ͂', + 'ῧ' => 'Ϋ͂', + 'ῶ' => 'Ω͂', + 'ᾈ' => 'ἈΙ', + 'ᾉ' => 'ἉΙ', + 'ᾊ' => 'ἊΙ', + 'ᾋ' => 'ἋΙ', + 'ᾌ' => 'ἌΙ', + 'ᾍ' => 'ἍΙ', + 'ᾎ' => 'ἎΙ', + 'ᾏ' => 'ἏΙ', + 'ᾘ' => 'ἨΙ', + 'ᾙ' => 'ἩΙ', + 'ᾚ' => 'ἪΙ', + 'ᾛ' => 'ἫΙ', + 'ᾜ' => 'ἬΙ', + 'ᾝ' => 'ἭΙ', + 'ᾞ' => 'ἮΙ', + 'ᾟ' => 'ἯΙ', + 'ᾨ' => 'ὨΙ', + 'ᾩ' => 'ὩΙ', + 'ᾪ' => 'ὪΙ', + 'ᾫ' => 'ὫΙ', + 'ᾬ' => 'ὬΙ', + 'ᾭ' => 'ὭΙ', + 'ᾮ' => 'ὮΙ', + 'ᾯ' => 'ὯΙ', + 'ᾼ' => 'ΑΙ', + 'ῌ' => 'ΗΙ', + 'ῼ' => 'ΩΙ', + 'ᾲ' => 'ᾺΙ', + 'ᾴ' => 'ΆΙ', + 'ῂ' => 'ῊΙ', + 'ῄ' => 'ΉΙ', + 'ῲ' => 'ῺΙ', + 'ῴ' => 'ΏΙ', + 'ᾷ' => 'Α͂Ι', + 'ῇ' => 'Η͂Ι', + 'ῷ' => 'Ω͂Ι', ); - -$result =& $data; -unset($data); - -return $result; diff --git a/vendor/symfony/polyfill-mbstring/bootstrap.php b/vendor/symfony/polyfill-mbstring/bootstrap.php index 2fdcc5a..1fedd1f 100644 --- a/vendor/symfony/polyfill-mbstring/bootstrap.php +++ b/vendor/symfony/polyfill-mbstring/bootstrap.php @@ -11,48 +11,137 @@ use Symfony\Polyfill\Mbstring as p; -if (!function_exists('mb_strlen')) { - define('MB_CASE_UPPER', 0); - define('MB_CASE_LOWER', 1); - define('MB_CASE_TITLE', 2); +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} - function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); } - function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); } - function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); } - function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); } - function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); } - function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); } - function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); } - function mb_language($lang = null) { return p\Mbstring::mb_language($lang); } +if (!function_exists('mb_convert_encoding')) { + function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); } +} +if (!function_exists('mb_decode_mimeheader')) { + function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); } +} +if (!function_exists('mb_encode_mimeheader')) { + function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); } +} +if (!function_exists('mb_decode_numericentity')) { + function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); } +} +if (!function_exists('mb_encode_numericentity')) { + function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); } +} +if (!function_exists('mb_convert_case')) { + function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); } +} +if (!function_exists('mb_internal_encoding')) { + function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); } +} +if (!function_exists('mb_language')) { + function mb_language($language = null) { return p\Mbstring::mb_language($language); } +} +if (!function_exists('mb_list_encodings')) { function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); } +} +if (!function_exists('mb_encoding_aliases')) { function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); } - function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); } - function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); } - function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); } - function mb_parse_str($s, &$result = array()) { parse_str($s, $result); } - function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); } - function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); } - function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); } - function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); } - function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); } - function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); } - function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); } - function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); } - function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); } - function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); } - function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); } - function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); } - function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); } +} +if (!function_exists('mb_check_encoding')) { + function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); } +} +if (!function_exists('mb_detect_encoding')) { + function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); } +} +if (!function_exists('mb_detect_order')) { + function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); } +} +if (!function_exists('mb_parse_str')) { + function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; } +} +if (!function_exists('mb_strlen')) { + function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); } +} +if (!function_exists('mb_strpos')) { + function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_strtolower')) { + function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); } +} +if (!function_exists('mb_strtoupper')) { + function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); } +} +if (!function_exists('mb_substitute_character')) { + function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); } +} +if (!function_exists('mb_substr')) { + function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); } +} +if (!function_exists('mb_stripos')) { + function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_stristr')) { + function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_strrchr')) { + function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_strrichr')) { + function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_strripos')) { + function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_strrpos')) { + function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); } +} +if (!function_exists('mb_strstr')) { + function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); } +} +if (!function_exists('mb_get_info')) { function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); } - function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); } - function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); } - function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); } - function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); } - function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); } - function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return p\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); } +} +if (!function_exists('mb_http_output')) { + function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); } +} +if (!function_exists('mb_strwidth')) { + function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); } +} +if (!function_exists('mb_substr_count')) { + function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); } +} +if (!function_exists('mb_output_handler')) { + function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); } +} +if (!function_exists('mb_http_input')) { + function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); } +} + +if (!function_exists('mb_convert_variables')) { + function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); } +} + +if (!function_exists('mb_ord')) { + function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); } } if (!function_exists('mb_chr')) { - function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); } - function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); } - function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); } + function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); } +} +if (!function_exists('mb_scrub')) { + function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); } +} +if (!function_exists('mb_str_split')) { + function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); } +} + +if (extension_loaded('mbstring')) { + return; +} + +if (!defined('MB_CASE_UPPER')) { + define('MB_CASE_UPPER', 0); +} +if (!defined('MB_CASE_LOWER')) { + define('MB_CASE_LOWER', 1); +} +if (!defined('MB_CASE_TITLE')) { + define('MB_CASE_TITLE', 2); } diff --git a/vendor/symfony/polyfill-mbstring/bootstrap80.php b/vendor/symfony/polyfill-mbstring/bootstrap80.php new file mode 100644 index 0000000..82f5ac4 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/bootstrap80.php @@ -0,0 +1,143 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Mbstring as p; + +if (!function_exists('mb_convert_encoding')) { + function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); } +} +if (!function_exists('mb_decode_mimeheader')) { + function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); } +} +if (!function_exists('mb_encode_mimeheader')) { + function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); } +} +if (!function_exists('mb_decode_numericentity')) { + function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); } +} +if (!function_exists('mb_encode_numericentity')) { + function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); } +} +if (!function_exists('mb_convert_case')) { + function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); } +} +if (!function_exists('mb_internal_encoding')) { + function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); } +} +if (!function_exists('mb_language')) { + function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); } +} +if (!function_exists('mb_list_encodings')) { + function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); } +} +if (!function_exists('mb_encoding_aliases')) { + function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); } +} +if (!function_exists('mb_check_encoding')) { + function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); } +} +if (!function_exists('mb_detect_encoding')) { + function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); } +} +if (!function_exists('mb_detect_order')) { + function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); } +} +if (!function_exists('mb_parse_str')) { + function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; } +} +if (!function_exists('mb_strlen')) { + function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); } +} +if (!function_exists('mb_strpos')) { + function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_strtolower')) { + function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); } +} +if (!function_exists('mb_strtoupper')) { + function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); } +} +if (!function_exists('mb_substitute_character')) { + function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); } +} +if (!function_exists('mb_substr')) { + function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); } +} +if (!function_exists('mb_stripos')) { + function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_stristr')) { + function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_strrchr')) { + function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_strrichr')) { + function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } +} +if (!function_exists('mb_strripos')) { + function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_strrpos')) { + function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } +} +if (!function_exists('mb_strstr')) { + 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 { 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); } +} +if (!function_exists('mb_strwidth')) { + function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); } +} +if (!function_exists('mb_substr_count')) { + function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); } +} +if (!function_exists('mb_output_handler')) { + function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); } +} +if (!function_exists('mb_http_input')) { + function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); } +} + +if (!function_exists('mb_convert_variables')) { + function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); } +} + +if (!function_exists('mb_ord')) { + function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); } +} +if (!function_exists('mb_chr')) { + function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); } +} +if (!function_exists('mb_scrub')) { + function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); } +} +if (!function_exists('mb_str_split')) { + 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 (extension_loaded('mbstring')) { + return; +} + +if (!defined('MB_CASE_UPPER')) { + define('MB_CASE_UPPER', 0); +} +if (!defined('MB_CASE_LOWER')) { + define('MB_CASE_LOWER', 1); +} +if (!defined('MB_CASE_TITLE')) { + define('MB_CASE_TITLE', 2); +} diff --git a/vendor/symfony/polyfill-mbstring/composer.json b/vendor/symfony/polyfill-mbstring/composer.json index 49b720d..4489553 100644 --- a/vendor/symfony/polyfill-mbstring/composer.json +++ b/vendor/symfony/polyfill-mbstring/composer.json @@ -16,7 +16,10 @@ } ], "require": { - "php": ">=5.3.3" + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, @@ -28,7 +31,11 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.8-dev" + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } } } diff --git a/vendor/symfony/polyfill-php72/LICENSE b/vendor/symfony/polyfill-php72/LICENSE new file mode 100644 index 0000000..4cd8bdd --- /dev/null +++ b/vendor/symfony/polyfill-php72/LICENSE @@ -0,0 +1,19 @@ +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 +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/vendor/symfony/polyfill-php72/Php72.php b/vendor/symfony/polyfill-php72/Php72.php new file mode 100644 index 0000000..7bf96c9 --- /dev/null +++ b/vendor/symfony/polyfill-php72/Php72.php @@ -0,0 +1,217 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php72; + +/** + * @author Nicolas Grekas <p@tchwork.com> + * @author Dariusz Rumiński <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class Php72 +{ + private static $hashMask; + + public static function utf8_encode($s) + { + $s .= $s; + $len = \strlen($s); + + for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) { + switch (true) { + case $s[$i] < "\x80": $s[$j] = $s[$i]; break; + case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break; + default: $s[$j] = "\xC3"; $s[++$j] = \chr(\ord($s[$i]) - 64); break; + } + } + + return substr($s, 0, $j); + } + + public static function utf8_decode($s) + { + $s = (string) $s; + $len = \strlen($s); + + for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) { + switch ($s[$i] & "\xF0") { + case "\xC0": + case "\xD0": + $c = (\ord($s[$i] & "\x1F") << 6) | \ord($s[++$i] & "\x3F"); + $s[$j] = $c < 256 ? \chr($c) : '?'; + break; + + case "\xF0": + ++$i; + // no break + + case "\xE0": + $s[$j] = '?'; + $i += 2; + break; + + default: + $s[$j] = $s[$i]; + } + } + + return substr($s, 0, $j); + } + + public static function php_os_family() + { + if ('\\' === \DIRECTORY_SEPARATOR) { + return 'Windows'; + } + + $map = [ + 'Darwin' => 'Darwin', + 'DragonFly' => 'BSD', + 'FreeBSD' => 'BSD', + 'NetBSD' => 'BSD', + 'OpenBSD' => 'BSD', + 'Linux' => 'Linux', + 'SunOS' => 'Solaris', + ]; + + return $map[\PHP_OS] ?? 'Unknown'; + } + + public static function spl_object_id($object) + { + if (null === self::$hashMask) { + self::initHashMask(); + } + if (null === $hash = spl_object_hash($object)) { + return; + } + + // On 32-bit systems, PHP_INT_SIZE is 4, + return self::$hashMask ^ hexdec(substr($hash, 16 - (\PHP_INT_SIZE * 2 - 1), \PHP_INT_SIZE * 2 - 1)); + } + + public static function sapi_windows_vt100_support($stream, $enable = null) + { + if (!\is_resource($stream)) { + trigger_error('sapi_windows_vt100_support() expects parameter 1 to be resource, '.\gettype($stream).' given', \E_USER_WARNING); + + return false; + } + + $meta = stream_get_meta_data($stream); + + if ('STDIO' !== $meta['stream_type']) { + trigger_error('sapi_windows_vt100_support() was not able to analyze the specified stream', \E_USER_WARNING); + + return false; + } + + // We cannot actually disable vt100 support if it is set + if (false === $enable || !self::stream_isatty($stream)) { + return false; + } + + // The native function does not apply to stdin + $meta = array_map('strtolower', $meta); + $stdin = 'php://stdin' === $meta['uri'] || 'php://fd/0' === $meta['uri']; + + return !$stdin + && (false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM') + || 'Hyper' === getenv('TERM_PROGRAM')); + } + + public static function stream_isatty($stream) + { + if (!\is_resource($stream)) { + trigger_error('stream_isatty() expects parameter 1 to be resource, '.\gettype($stream).' given', \E_USER_WARNING); + + return false; + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + $stat = @fstat($stream); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; + } + + return \function_exists('posix_isatty') && @posix_isatty($stream); + } + + private static function initHashMask() + { + $obj = (object) []; + self::$hashMask = -1; + + // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below + $obFuncs = ['ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush']; + foreach (debug_backtrace(\PHP_VERSION_ID >= 50400 ? \DEBUG_BACKTRACE_IGNORE_ARGS : false) as $frame) { + if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && \in_array($frame['function'], $obFuncs)) { + $frame['line'] = 0; + break; + } + } + if (!empty($frame['line'])) { + ob_start(); + debug_zval_dump($obj); + self::$hashMask = (int) substr(ob_get_clean(), 17); + } + + self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - (\PHP_INT_SIZE * 2 - 1), \PHP_INT_SIZE * 2 - 1)); + } + + public static function mb_chr($code, $encoding = null) + { + if (0x80 > $code %= 0x200000) { + $s = \chr($code); + } elseif (0x800 > $code) { + $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); + } elseif (0x10000 > $code) { + $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } else { + $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } + + if ('UTF-8' !== $encoding = $encoding ?? mb_internal_encoding()) { + $s = mb_convert_encoding($s, $encoding, 'UTF-8'); + } + + return $s; + } + + public static function mb_ord($s, $encoding = null) + { + if (null === $encoding) { + $s = mb_convert_encoding($s, 'UTF-8'); + } elseif ('UTF-8' !== $encoding) { + $s = mb_convert_encoding($s, 'UTF-8', $encoding); + } + + if (1 === \strlen($s)) { + return \ord($s); + } + + $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; + if (0xF0 <= $code) { + return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; + } + if (0xE0 <= $code) { + return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; + } + if (0xC0 <= $code) { + return (($code - 0xC0) << 6) + $s[2] - 0x80; + } + + return $code; + } +} diff --git a/vendor/symfony/polyfill-php72/README.md b/vendor/symfony/polyfill-php72/README.md new file mode 100644 index 0000000..ed19050 --- /dev/null +++ b/vendor/symfony/polyfill-php72/README.md @@ -0,0 +1,35 @@ +Symfony Polyfill / Php72 +======================== + +This component provides functions added to PHP 7.2 core: + +- [`spl_object_id`](https://php.net/spl_object_id) +- [`stream_isatty`](https://php.net/stream_isatty) + +And also functions added to PHP 7.2 mbstring: + +- [`mb_ord`](https://php.net/mb_ord) +- [`mb_chr`](https://php.net/mb_chr) +- [`mb_scrub`](https://php.net/mb_scrub) + +On Windows only: + +- [`sapi_windows_vt100_support`](https://php.net/sapi_windows_vt100_support) + +Moved to core since 7.2 (was in the optional XML extension earlier): + +- [`utf8_encode`](https://php.net/utf8_encode) +- [`utf8_decode`](https://php.net/utf8_decode) + +Also, it provides constants added to PHP 7.2: + +- [`PHP_FLOAT_*`](https://php.net/reserved.constants#constant.php-float-dig) +- [`PHP_OS_FAMILY`](https://php.net/reserved.constants#constant.php-os-family) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-php72/bootstrap.php b/vendor/symfony/polyfill-php72/bootstrap.php new file mode 100644 index 0000000..b5c92d4 --- /dev/null +++ b/vendor/symfony/polyfill-php72/bootstrap.php @@ -0,0 +1,57 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php72 as p; + +if (\PHP_VERSION_ID >= 70200) { + return; +} + +if (!defined('PHP_FLOAT_DIG')) { + define('PHP_FLOAT_DIG', 15); +} +if (!defined('PHP_FLOAT_EPSILON')) { + define('PHP_FLOAT_EPSILON', 2.2204460492503E-16); +} +if (!defined('PHP_FLOAT_MIN')) { + define('PHP_FLOAT_MIN', 2.2250738585072E-308); +} +if (!defined('PHP_FLOAT_MAX')) { + define('PHP_FLOAT_MAX', 1.7976931348623157E+308); +} +if (!defined('PHP_OS_FAMILY')) { + define('PHP_OS_FAMILY', p\Php72::php_os_family()); +} + +if ('\\' === \DIRECTORY_SEPARATOR && !function_exists('sapi_windows_vt100_support')) { + function sapi_windows_vt100_support($stream, $enable = null) { return p\Php72::sapi_windows_vt100_support($stream, $enable); } +} +if (!function_exists('stream_isatty')) { + function stream_isatty($stream) { return p\Php72::stream_isatty($stream); } +} +if (!function_exists('utf8_encode')) { + function utf8_encode($string) { return p\Php72::utf8_encode($string); } +} +if (!function_exists('utf8_decode')) { + function utf8_decode($string) { return p\Php72::utf8_decode($string); } +} +if (!function_exists('spl_object_id')) { + function spl_object_id($object) { return p\Php72::spl_object_id($object); } +} +if (!function_exists('mb_ord')) { + function mb_ord($string, $encoding = null) { return p\Php72::mb_ord($string, $encoding); } +} +if (!function_exists('mb_chr')) { + function mb_chr($codepoint, $encoding = null) { return p\Php72::mb_chr($codepoint, $encoding); } +} +if (!function_exists('mb_scrub')) { + function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); } +} diff --git a/vendor/symfony/polyfill-php72/composer.json b/vendor/symfony/polyfill-php72/composer.json new file mode 100644 index 0000000..5f17af3 --- /dev/null +++ b/vendor/symfony/polyfill-php72/composer.json @@ -0,0 +1,35 @@ +{ + "name": "symfony/polyfill-php72", + "type": "library", + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php72\\": "" }, + "files": [ "bootstrap.php" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/vendor/symfony/polyfill-php73/LICENSE b/vendor/symfony/polyfill-php73/LICENSE new file mode 100644 index 0000000..3f853aa --- /dev/null +++ b/vendor/symfony/polyfill-php73/LICENSE @@ -0,0 +1,19 @@ +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 +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/vendor/symfony/polyfill-php73/Php73.php b/vendor/symfony/polyfill-php73/Php73.php new file mode 100644 index 0000000..65c35a6 --- /dev/null +++ b/vendor/symfony/polyfill-php73/Php73.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php73; + +/** + * @author Gabriel Caruso <carusogabriel34@gmail.com> + * @author Ion Bazan <ion.bazan@gmail.com> + * + * @internal + */ +final class Php73 +{ + public static $startAt = 1533462603; + + /** + * @param bool $asNum + * + * @return array|float|int + */ + public static function hrtime($asNum = false) + { + $ns = microtime(false); + $s = substr($ns, 11) - self::$startAt; + $ns = 1E9 * (float) $ns; + + if ($asNum) { + $ns += $s * 1E9; + + return \PHP_INT_SIZE === 4 ? $ns : (int) $ns; + } + + return [$s, (int) $ns]; + } +} diff --git a/vendor/symfony/polyfill-php73/README.md b/vendor/symfony/polyfill-php73/README.md new file mode 100644 index 0000000..032fafb --- /dev/null +++ b/vendor/symfony/polyfill-php73/README.md @@ -0,0 +1,18 @@ +Symfony Polyfill / Php73 +======================== + +This component provides functions added to PHP 7.3 core: + +- [`array_key_first`](https://php.net/array_key_first) +- [`array_key_last`](https://php.net/array_key_last) +- [`hrtime`](https://php.net/function.hrtime) +- [`is_countable`](https://php.net/is_countable) +- [`JsonException`](https://php.net/JsonException) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/debug/Tests/MockExceptionHandler.php b/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php similarity index 52% rename from vendor/symfony/debug/Tests/MockExceptionHandler.php rename to vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php index 2d6ce56..f06d6c2 100644 --- a/vendor/symfony/debug/Tests/MockExceptionHandler.php +++ b/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php @@ -9,16 +9,8 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Debug\Tests; - -use Symfony\Component\Debug\ExceptionHandler; - -class MockExceptionHandler extends ExceptionHandler -{ - public $e; - - public function handle(\Exception $e) +if (\PHP_VERSION_ID < 70300) { + class JsonException extends Exception { - $this->e = $e; } } diff --git a/vendor/symfony/polyfill-php73/bootstrap.php b/vendor/symfony/polyfill-php73/bootstrap.php new file mode 100644 index 0000000..d6b2153 --- /dev/null +++ b/vendor/symfony/polyfill-php73/bootstrap.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php73 as p; + +if (\PHP_VERSION_ID >= 70300) { + return; +} + +if (!function_exists('is_countable')) { + function is_countable($value) { return is_array($value) || $value instanceof Countable || $value instanceof ResourceBundle || $value instanceof SimpleXmlElement; } +} +if (!function_exists('hrtime')) { + require_once __DIR__.'/Php73.php'; + p\Php73::$startAt = (int) microtime(true); + function hrtime($as_number = false) { return p\Php73::hrtime($as_number); } +} +if (!function_exists('array_key_first')) { + function array_key_first(array $array) { foreach ($array as $key => $value) { return $key; } } +} +if (!function_exists('array_key_last')) { + function array_key_last(array $array) { return key(array_slice($array, -1, 1, true)); } +} diff --git a/vendor/symfony/polyfill-php73/composer.json b/vendor/symfony/polyfill-php73/composer.json new file mode 100644 index 0000000..b5c58ec --- /dev/null +++ b/vendor/symfony/polyfill-php73/composer.json @@ -0,0 +1,36 @@ +{ + "name": "symfony/polyfill-php73", + "type": "library", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/vendor/symfony/polyfill-php80/LICENSE b/vendor/symfony/polyfill-php80/LICENSE new file mode 100644 index 0000000..5593b1d --- /dev/null +++ b/vendor/symfony/polyfill-php80/LICENSE @@ -0,0 +1,19 @@ +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 +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/vendor/symfony/polyfill-php80/Php80.php b/vendor/symfony/polyfill-php80/Php80.php new file mode 100644 index 0000000..362dd1a --- /dev/null +++ b/vendor/symfony/polyfill-php80/Php80.php @@ -0,0 +1,115 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php80; + +/** + * @author Ion Bazan <ion.bazan@gmail.com> + * @author Nico Oelgart <nicoswd@gmail.com> + * @author Nicolas Grekas <p@tchwork.com> + * + * @internal + */ +final class Php80 +{ + public static function fdiv(float $dividend, float $divisor): float + { + return @($dividend / $divisor); + } + + public static function get_debug_type($value): string + { + switch (true) { + case null === $value: return 'null'; + case \is_bool($value): return 'bool'; + case \is_string($value): return 'string'; + case \is_array($value): return 'array'; + case \is_int($value): return 'int'; + case \is_float($value): return 'float'; + case \is_object($value): break; + case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class'; + default: + if (null === $type = @get_resource_type($value)) { + return 'unknown'; + } + + if ('Unknown' === $type) { + $type = 'closed'; + } + + return "resource ($type)"; + } + + $class = \get_class($value); + + if (false === strpos($class, '@')) { + return $class; + } + + return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous'; + } + + public static function get_resource_id($res): int + { + if (!\is_resource($res) && null === @get_resource_type($res)) { + throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); + } + + return (int) $res; + } + + public static function preg_last_error_msg(): string + { + switch (preg_last_error()) { + case \PREG_INTERNAL_ERROR: + return 'Internal error'; + case \PREG_BAD_UTF8_ERROR: + return 'Malformed UTF-8 characters, possibly incorrectly encoded'; + case \PREG_BAD_UTF8_OFFSET_ERROR: + return 'The offset did not correspond to the beginning of a valid UTF-8 code point'; + case \PREG_BACKTRACK_LIMIT_ERROR: + return 'Backtrack limit exhausted'; + case \PREG_RECURSION_LIMIT_ERROR: + return 'Recursion limit exhausted'; + case \PREG_JIT_STACKLIMIT_ERROR: + return 'JIT stack limit exhausted'; + case \PREG_NO_ERROR: + return 'No error'; + default: + return 'Unknown error'; + } + } + + public static function str_contains(string $haystack, string $needle): bool + { + return '' === $needle || false !== strpos($haystack, $needle); + } + + public static function str_starts_with(string $haystack, string $needle): bool + { + return 0 === strncmp($haystack, $needle, \strlen($needle)); + } + + public static function str_ends_with(string $haystack, string $needle): bool + { + if ('' === $needle || $needle === $haystack) { + return true; + } + + if ('' === $haystack) { + return false; + } + + $needleLength = \strlen($needle); + + return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength); + } +} diff --git a/vendor/symfony/polyfill-php80/PhpToken.php b/vendor/symfony/polyfill-php80/PhpToken.php new file mode 100644 index 0000000..fe6e691 --- /dev/null +++ b/vendor/symfony/polyfill-php80/PhpToken.php @@ -0,0 +1,103 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php80; + +/** + * @author Fedonyuk Anton <info@ensostudio.ru> + * + * @internal + */ +class PhpToken implements \Stringable +{ + /** + * @var int + */ + public $id; + + /** + * @var string + */ + public $text; + + /** + * @var int + */ + public $line; + + /** + * @var int + */ + public $pos; + + public function __construct(int $id, string $text, int $line = -1, int $position = -1) + { + $this->id = $id; + $this->text = $text; + $this->line = $line; + $this->pos = $position; + } + + public function getTokenName(): ?string + { + if ('UNKNOWN' === $name = token_name($this->id)) { + $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text; + } + + return $name; + } + + /** + * @param int|string|array $kind + */ + public function is($kind): bool + { + foreach ((array) $kind as $value) { + if (\in_array($value, [$this->id, $this->text], true)) { + return true; + } + } + + return false; + } + + public function isIgnorable(): bool + { + return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true); + } + + public function __toString(): string + { + return (string) $this->text; + } + + /** + * @return static[] + */ + public static function tokenize(string $code, int $flags = 0): array + { + $line = 1; + $position = 0; + $tokens = token_get_all($code, $flags); + foreach ($tokens as $index => $token) { + if (\is_string($token)) { + $id = \ord($token); + $text = $token; + } else { + [$id, $text, $line] = $token; + } + $tokens[$index] = new static($id, $text, $line, $position); + $position += \strlen($text); + } + + return $tokens; + } +} diff --git a/vendor/symfony/polyfill-php80/README.md b/vendor/symfony/polyfill-php80/README.md new file mode 100644 index 0000000..3816c55 --- /dev/null +++ b/vendor/symfony/polyfill-php80/README.md @@ -0,0 +1,25 @@ +Symfony Polyfill / Php80 +======================== + +This component provides features added to PHP 8.0 core: + +- [`Stringable`](https://php.net/stringable) interface +- [`fdiv`](https://php.net/fdiv) +- [`ValueError`](https://php.net/valueerror) class +- [`UnhandledMatchError`](https://php.net/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) +- [`str_ends_with`](https://php.net/str_ends_with) +- [`get_resource_id`](https://php.net/get_resource_id) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php b/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php new file mode 100644 index 0000000..2b95542 --- /dev/null +++ b/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +#[Attribute(Attribute::TARGET_CLASS)] +final class Attribute +{ + public const TARGET_CLASS = 1; + public const TARGET_FUNCTION = 2; + public const TARGET_METHOD = 4; + public const TARGET_PROPERTY = 8; + public const TARGET_CLASS_CONSTANT = 16; + public const TARGET_PARAMETER = 32; + public const TARGET_ALL = 63; + public const IS_REPEATABLE = 64; + + /** @var int */ + public $flags; + + public function __construct(int $flags = self::TARGET_ALL) + { + $this->flags = $flags; + } +} diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php b/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php new file mode 100644 index 0000000..bd1212f --- /dev/null +++ b/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php @@ -0,0 +1,16 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) { + class PhpToken extends Symfony\Polyfill\Php80\PhpToken + { + } +} diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php b/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php new file mode 100644 index 0000000..7c62d75 --- /dev/null +++ b/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php @@ -0,0 +1,20 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + interface Stringable + { + /** + * @return string + */ + public function __toString(); + } +} diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php b/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php new file mode 100644 index 0000000..01c6c6c --- /dev/null +++ b/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php @@ -0,0 +1,16 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + class UnhandledMatchError extends Error + { + } +} diff --git a/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php b/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php new file mode 100644 index 0000000..783dbc2 --- /dev/null +++ b/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php @@ -0,0 +1,16 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (\PHP_VERSION_ID < 80000) { + class ValueError extends Error + { + } +} diff --git a/vendor/symfony/polyfill-php80/bootstrap.php b/vendor/symfony/polyfill-php80/bootstrap.php new file mode 100644 index 0000000..e5f7dbc --- /dev/null +++ b/vendor/symfony/polyfill-php80/bootstrap.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php80 as p; + +if (\PHP_VERSION_ID >= 80000) { + return; +} + +if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) { + define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN); +} + +if (!function_exists('fdiv')) { + function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); } +} +if (!function_exists('preg_last_error_msg')) { + function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); } +} +if (!function_exists('str_contains')) { + function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('str_starts_with')) { + function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('str_ends_with')) { + function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); } +} +if (!function_exists('get_debug_type')) { + function get_debug_type($value): string { return p\Php80::get_debug_type($value); } +} +if (!function_exists('get_resource_id')) { + function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); } +} diff --git a/vendor/symfony/polyfill-php80/composer.json b/vendor/symfony/polyfill-php80/composer.json new file mode 100644 index 0000000..bd9a326 --- /dev/null +++ b/vendor/symfony/polyfill-php80/composer.json @@ -0,0 +1,40 @@ +{ + "name": "symfony/polyfill-php80", + "type": "library", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + } +} diff --git a/vendor/symfony/process/.gitignore b/vendor/symfony/process/.gitignore deleted file mode 100644 index c49a5d8..0000000 --- a/vendor/symfony/process/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/vendor/symfony/process/CHANGELOG.md b/vendor/symfony/process/CHANGELOG.md index c5cdb99..31b9ee6 100644 --- a/vendor/symfony/process/CHANGELOG.md +++ b/vendor/symfony/process/CHANGELOG.md @@ -1,6 +1,65 @@ CHANGELOG ========= +5.2.0 +----- + + * added `Process::setOptions()` to set `Process` specific options + * added option `create_new_console` to allow a subprocess to continue + to run after the main script exited, both on Linux and on Windows + +5.1.0 +----- + + * added `Process::getStartTime()` to retrieve the start time of the process as float + +5.0.0 +----- + + * removed `Process::inheritEnvironmentVariables()` + * removed `PhpProcess::setPhpBinary()` + * `Process` must be instantiated with a command array, use `Process::fromShellCommandline()` when the command should be parsed by the shell + * removed `Process::setCommandLine()` + +4.4.0 +----- + + * deprecated `Process::inheritEnvironmentVariables()`: env variables are always inherited. + * added `Process::getLastOutputTime()` method + +4.2.0 +----- + + * added the `Process::fromShellCommandline()` to run commands in a shell wrapper + * deprecated passing a command as string when creating a `Process` instance + * deprecated the `Process::setCommandline()` and the `PhpProcess::setPhpBinary()` methods + * added the `Process::waitUntil()` method to wait for the process only for a + specific output, then continue the normal execution of your application + +4.1.0 +----- + + * added the `Process::isTtySupported()` method that allows to check for TTY support + * made `PhpExecutableFinder` look for the `PHP_BINARY` env var when searching the php binary + * added the `ProcessSignaledException` class to properly catch signaled process errors + +4.0.0 +----- + + * environment variables will always be inherited + * added a second `array $env = []` argument to the `start()`, `run()`, + `mustRun()`, and `restart()` methods of the `Process` class + * added a second `array $env = []` argument to the `start()` method of the + `PhpProcess` class + * the `ProcessUtils::escapeArgument()` method has been removed + * the `areEnvironmentVariablesInherited()`, `getOptions()`, and `setOptions()` + methods of the `Process` class have been removed + * support for passing `proc_open()` options has been removed + * removed the `ProcessBuilder` class, use the `Process` class instead + * removed the `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class + * passing a not existing working directory to the constructor of the `Symfony\Component\Process\Process` class is not + supported anymore + 3.4.0 ----- diff --git a/vendor/symfony/process/Exception/ExceptionInterface.php b/vendor/symfony/process/Exception/ExceptionInterface.php index 75c1c9e..bd4a604 100644 --- a/vendor/symfony/process/Exception/ExceptionInterface.php +++ b/vendor/symfony/process/Exception/ExceptionInterface.php @@ -16,6 +16,6 @@ * * @author Johannes M. Schmitt <schmittjoh@gmail.com> */ -interface ExceptionInterface +interface ExceptionInterface extends \Throwable { } diff --git a/vendor/symfony/process/Exception/ProcessSignaledException.php b/vendor/symfony/process/Exception/ProcessSignaledException.php new file mode 100644 index 0000000..d4d3227 --- /dev/null +++ b/vendor/symfony/process/Exception/ProcessSignaledException.php @@ -0,0 +1,41 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Exception; + +use Symfony\Component\Process\Process; + +/** + * Exception that is thrown when a process has been signaled. + * + * @author Sullivan Senechal <soullivaneuh@gmail.com> + */ +final class ProcessSignaledException extends RuntimeException +{ + private $process; + + public function __construct(Process $process) + { + $this->process = $process; + + parent::__construct(sprintf('The process has been signaled with signal "%s".', $process->getTermSignal())); + } + + public function getProcess(): Process + { + return $this->process; + } + + public function getSignal(): int + { + return $this->getProcess()->getTermSignal(); + } +} diff --git a/vendor/symfony/process/Exception/ProcessTimedOutException.php b/vendor/symfony/process/Exception/ProcessTimedOutException.php index fef4a8a..94391a4 100644 --- a/vendor/symfony/process/Exception/ProcessTimedOutException.php +++ b/vendor/symfony/process/Exception/ProcessTimedOutException.php @@ -20,13 +20,13 @@ */ class ProcessTimedOutException extends RuntimeException { - const TYPE_GENERAL = 1; - const TYPE_IDLE = 2; + public const TYPE_GENERAL = 1; + public const TYPE_IDLE = 2; private $process; private $timeoutType; - public function __construct(Process $process, $timeoutType) + public function __construct(Process $process, int $timeoutType) { $this->process = $process; $this->timeoutType = $timeoutType; diff --git a/vendor/symfony/process/ExecutableFinder.php b/vendor/symfony/process/ExecutableFinder.php index ccfa4c0..eb8f062 100644 --- a/vendor/symfony/process/ExecutableFinder.php +++ b/vendor/symfony/process/ExecutableFinder.php @@ -19,7 +19,7 @@ */ class ExecutableFinder { - private $suffixes = array('.exe', '.bat', '.cmd', '.com'); + private $suffixes = ['.exe', '.bat', '.cmd', '.com']; /** * Replaces default suffixes of executable. @@ -31,10 +31,8 @@ public function setSuffixes(array $suffixes) /** * Adds new possible suffix to check for executable. - * - * @param string $suffix */ - public function addSuffix($suffix) + public function addSuffix(string $suffix) { $this->suffixes[] = $suffix; } @@ -42,17 +40,17 @@ public function addSuffix($suffix) /** * Finds an executable by name. * - * @param string $name The executable name (without the extension) - * @param string $default The default to return if no executable is found - * @param array $extraDirs Additional dirs to check into + * @param string $name The executable name (without the extension) + * @param string|null $default The default to return if no executable is found + * @param array $extraDirs Additional dirs to check into * - * @return string The executable path or default value + * @return string|null */ - public function find($name, $default = null, array $extraDirs = array()) + public function find(string $name, string $default = null, array $extraDirs = []) { - if (ini_get('open_basedir')) { - $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir')); - $dirs = array(); + 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)) { @@ -65,15 +63,15 @@ public function find($name, $default = null, array $extraDirs = array()) } } else { $dirs = array_merge( - explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), + explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), $extraDirs ); } - $suffixes = array(''); + $suffixes = ['']; if ('\\' === \DIRECTORY_SEPARATOR) { $pathExt = getenv('PATHEXT'); - $suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes); + $suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes); } foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { diff --git a/vendor/symfony/process/InputStream.php b/vendor/symfony/process/InputStream.php index 9bd917a..240665f 100644 --- a/vendor/symfony/process/InputStream.php +++ b/vendor/symfony/process/InputStream.php @@ -17,12 +17,14 @@ * Provides a way to continuously write to the input of a Process until the InputStream is closed. * * @author Nicolas Grekas <p@tchwork.com> + * + * @implements \IteratorAggregate<int, string> */ class InputStream implements \IteratorAggregate { - /** @var null|callable */ + /** @var callable|null */ private $onEmpty = null; - private $input = array(); + private $input = []; private $open = true; /** @@ -36,8 +38,8 @@ public function onEmpty(callable $onEmpty = null) /** * Appends an input to the write buffer. * - * @param resource|string|int|float|bool|\Traversable|null The input to append as scalar, - * stream resource or \Traversable + * @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar, + * stream resource or \Traversable */ public function write($input) { @@ -45,7 +47,7 @@ public function write($input) return; } if ($this->isClosed()) { - throw new RuntimeException(sprintf('%s is closed', static::class)); + throw new RuntimeException(sprintf('"%s" is closed.', static::class)); } $this->input[] = ProcessUtils::validateInput(__METHOD__, $input); } @@ -66,6 +68,10 @@ public function isClosed() return !$this->open; } + /** + * @return \Traversable<int, string> + */ + #[\ReturnTypeWillChange] public function getIterator() { $this->open = true; @@ -78,9 +84,7 @@ public function getIterator() $current = array_shift($this->input); if ($current instanceof \Iterator) { - foreach ($current as $cur) { - yield $cur; - } + yield from $current; } else { yield $current; } diff --git a/vendor/symfony/process/LICENSE b/vendor/symfony/process/LICENSE index 21d7fb9..0138f8f 100644 --- a/vendor/symfony/process/LICENSE +++ b/vendor/symfony/process/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/process/PhpExecutableFinder.php b/vendor/symfony/process/PhpExecutableFinder.php index 334de13..bed6c3d 100644 --- a/vendor/symfony/process/PhpExecutableFinder.php +++ b/vendor/symfony/process/PhpExecutableFinder.php @@ -29,27 +29,39 @@ public function __construct() /** * Finds The PHP executable. * - * @param bool $includeArgs Whether or not include command arguments - * - * @return string|false The PHP executable path or false if it cannot be found + * @return string|false */ - public function find($includeArgs = true) + public function find(bool $includeArgs = true) { - $args = $this->findArguments(); - $args = $includeArgs && $args ? ' '.implode(' ', $args) : ''; + if ($php = getenv('PHP_BINARY')) { + if (!is_executable($php)) { + $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v'; + if ($php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) { + if (!is_executable($php)) { + return false; + } + } else { + return false; + } + } + + if (@is_dir($php)) { + return false; + } - // HHVM support - if (\defined('HHVM_VERSION')) { - return (getenv('PHP_BINARY') ?: PHP_BINARY).$args; + return $php; } + $args = $this->findArguments(); + $args = $includeArgs && $args ? ' '.implode(' ', $args) : ''; + // PHP_BINARY return the current sapi executable - if (PHP_BINARY && \in_array(\PHP_SAPI, array('cli', 'cli-server', 'phpdbg'), true)) { - return PHP_BINARY.$args; + if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cli', 'cli-server', 'phpdbg'], true)) { + return \PHP_BINARY.$args; } if ($php = getenv('PHP_PATH')) { - if (!@is_executable($php)) { + if (!@is_executable($php) || @is_dir($php)) { return false; } @@ -57,16 +69,16 @@ public function find($includeArgs = true) } if ($php = getenv('PHP_PEAR_PHP_BIN')) { - if (@is_executable($php)) { + if (@is_executable($php) && !@is_dir($php)) { return $php; } } - if (@is_executable($php = PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) { + if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php')) && !@is_dir($php)) { return $php; } - $dirs = array(PHP_BINDIR); + $dirs = [\PHP_BINDIR]; if ('\\' === \DIRECTORY_SEPARATOR) { $dirs[] = 'C:\xampp\php\\'; } @@ -77,15 +89,12 @@ public function find($includeArgs = true) /** * Finds the PHP executable arguments. * - * @return array The PHP executable arguments + * @return array */ public function findArguments() { - $arguments = array(); - - if (\defined('HHVM_VERSION')) { - $arguments[] = '--php'; - } elseif ('phpdbg' === \PHP_SAPI) { + $arguments = []; + if ('phpdbg' === \PHP_SAPI) { $arguments[] = '-qrr'; } diff --git a/vendor/symfony/process/PhpProcess.php b/vendor/symfony/process/PhpProcess.php index b476395..2bc338e 100644 --- a/vendor/symfony/process/PhpProcess.php +++ b/vendor/symfony/process/PhpProcess.php @@ -11,14 +11,15 @@ namespace Symfony\Component\Process; +use Symfony\Component\Process\Exception\LogicException; use Symfony\Component\Process\Exception\RuntimeException; /** * PhpProcess runs a PHP script in an independent process. * - * $p = new PhpProcess('<?php echo "foo"; ?>'); - * $p->run(); - * print $p->getOutput()."\n"; + * $p = new PhpProcess('<?php echo "foo"; ?>'); + * $p->run(); + * print $p->getOutput()."\n"; * * @author Fabien Potencier <fabien@symfony.com> */ @@ -29,15 +30,14 @@ class PhpProcess extends Process * @param string|null $cwd The working directory or null to use the working dir of the current PHP process * @param array|null $env The environment variables or null to use the same environment as the current PHP process * @param int $timeout The timeout in seconds - * @param array $options An array of options for proc_open + * @param array|null $php Path to the PHP binary to use with any additional arguments */ - public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = null) + public function __construct(string $script, string $cwd = null, array $env = null, int $timeout = 60, array $php = null) { - $executableFinder = new PhpExecutableFinder(); - if (false === $php = $executableFinder->find(false)) { - $php = null; - } else { - $php = array_merge(array($php), $executableFinder->findArguments()); + if (null === $php) { + $executableFinder = new PhpExecutableFinder(); + $php = $executableFinder->find(false); + $php = false === $php ? null : array_merge([$php], $executableFinder->findArguments()); } if ('phpdbg' === \PHP_SAPI) { $file = tempnam(sys_get_temp_dir(), 'dbg'); @@ -46,30 +46,26 @@ public function __construct($script, $cwd = null, array $env = null, $timeout = $php[] = $file; $script = null; } - if (null !== $options) { - @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since Symfony 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - } - parent::__construct($php, $cwd, $env, $script, $timeout, $options); + parent::__construct($php, $cwd, $env, $script, $timeout); } /** - * Sets the path to the PHP binary to use. + * {@inheritdoc} */ - public function setPhpBinary($php) + public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { - $this->setCommandLine($php); + throw new LogicException(sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class)); } /** * {@inheritdoc} */ - public function start(callable $callback = null/*, array $env = array()*/) + public function start(callable $callback = null, array $env = []) { if (null === $this->getCommandLine()) { throw new RuntimeException('Unable to find the PHP executable.'); } - $env = 1 < \func_num_args() ? func_get_arg(1) : null; parent::start($callback, $env); } diff --git a/vendor/symfony/process/Pipes/AbstractPipes.php b/vendor/symfony/process/Pipes/AbstractPipes.php index e5e2686..656dc03 100644 --- a/vendor/symfony/process/Pipes/AbstractPipes.php +++ b/vendor/symfony/process/Pipes/AbstractPipes.php @@ -20,7 +20,7 @@ */ abstract class AbstractPipes implements PipesInterface { - public $pipes = array(); + public $pipes = []; private $inputBuffer = ''; private $input; @@ -47,17 +47,17 @@ public function __construct($input) public function close() { foreach ($this->pipes as $pipe) { - fclose($pipe); + if (\is_resource($pipe)) { + fclose($pipe); + } } - $this->pipes = array(); + $this->pipes = []; } /** * Returns true if a system call has been interrupted. - * - * @return bool */ - protected function hasSystemCallBeenInterrupted() + protected function hasSystemCallBeenInterrupted(): bool { $lastError = $this->lastError; $this->lastError = null; @@ -90,10 +90,10 @@ protected function unblock() * * @throws InvalidArgumentException When an input iterator yields a non supported value */ - protected function write() + protected function write(): ?array { if (!isset($this->pipes[0])) { - return; + return null; } $input = $this->input; @@ -104,8 +104,8 @@ protected function write() stream_set_blocking($input, 0); } elseif (!isset($this->inputBuffer[0])) { if (!\is_string($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_class($this->input), \gettype($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; } @@ -117,12 +117,12 @@ protected function write() } } - $r = $e = array(); - $w = array($this->pipes[0]); + $r = $e = []; + $w = [$this->pipes[0]]; // let's have a look if something changed in streams if (false === @stream_select($r, $w, $e, 0, 0)) { - return; + return null; } foreach ($w as $stdin) { @@ -130,12 +130,12 @@ protected function write() $written = fwrite($stdin, $this->inputBuffer); $this->inputBuffer = substr($this->inputBuffer, $written); if (isset($this->inputBuffer[0])) { - return array($this->pipes[0]); + return [$this->pipes[0]]; } } if ($input) { - for (;;) { + while (true) { $data = fread($input, self::CHUNK_SIZE); if (!isset($data[0])) { break; @@ -145,7 +145,7 @@ protected function write() if (isset($data[0])) { $this->inputBuffer = $data; - return array($this->pipes[0]); + return [$this->pipes[0]]; } } if (feof($input)) { @@ -164,14 +164,16 @@ protected function write() fclose($this->pipes[0]); unset($this->pipes[0]); } elseif (!$w) { - return array($this->pipes[0]); + return [$this->pipes[0]]; } + + return null; } /** * @internal */ - public function handleError($type, $msg) + public function handleError(int $type, string $msg) { $this->lastError = $msg; } diff --git a/vendor/symfony/process/Pipes/PipesInterface.php b/vendor/symfony/process/Pipes/PipesInterface.php index 52bbe76..50eb5c4 100644 --- a/vendor/symfony/process/Pipes/PipesInterface.php +++ b/vendor/symfony/process/Pipes/PipesInterface.php @@ -20,21 +20,19 @@ */ interface PipesInterface { - const CHUNK_SIZE = 16384; + public const CHUNK_SIZE = 16384; /** * Returns an array of descriptors for the use of proc_open. - * - * @return array */ - public function getDescriptors(); + public function getDescriptors(): array; /** * Returns an array of filenames indexed by their related stream in case these pipes use temporary files. * * @return string[] */ - public function getFiles(); + public function getFiles(): array; /** * Reads data in file handles and pipes. @@ -44,21 +42,17 @@ public function getFiles(); * * @return string[] An array of read data indexed by their fd */ - public function readAndWrite($blocking, $close = false); + public function readAndWrite(bool $blocking, bool $close = false): array; /** * Returns if the current state has open file handles or pipes. - * - * @return bool */ - public function areOpen(); + public function areOpen(): bool; /** * Returns if pipes are able to read output. - * - * @return bool */ - public function haveReadSupport(); + public function haveReadSupport(): bool; /** * Closes file handles and pipes. diff --git a/vendor/symfony/process/Pipes/UnixPipes.php b/vendor/symfony/process/Pipes/UnixPipes.php index 254df51..5a0e9d4 100644 --- a/vendor/symfony/process/Pipes/UnixPipes.php +++ b/vendor/symfony/process/Pipes/UnixPipes.php @@ -26,15 +26,25 @@ class UnixPipes extends AbstractPipes private $ptyMode; private $haveReadSupport; - public function __construct($ttyMode, $ptyMode, $input, $haveReadSupport) + public function __construct(?bool $ttyMode, bool $ptyMode, $input, bool $haveReadSupport) { - $this->ttyMode = (bool) $ttyMode; - $this->ptyMode = (bool) $ptyMode; - $this->haveReadSupport = (bool) $haveReadSupport; + $this->ttyMode = $ttyMode; + $this->ptyMode = $ptyMode; + $this->haveReadSupport = $haveReadSupport; parent::__construct($input); } + public function __sleep(): array + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + public function __destruct() { $this->close(); @@ -43,69 +53,69 @@ public function __destruct() /** * {@inheritdoc} */ - public function getDescriptors() + public function getDescriptors(): array { if (!$this->haveReadSupport) { $nullstream = fopen('/dev/null', 'c'); - return array( - array('pipe', 'r'), + return [ + ['pipe', 'r'], $nullstream, $nullstream, - ); + ]; } if ($this->ttyMode) { - return array( - array('file', '/dev/tty', 'r'), - array('file', '/dev/tty', 'w'), - array('file', '/dev/tty', 'w'), - ); + return [ + ['file', '/dev/tty', 'r'], + ['file', '/dev/tty', 'w'], + ['file', '/dev/tty', 'w'], + ]; } if ($this->ptyMode && Process::isPtySupported()) { - return array( - array('pty'), - array('pty'), - array('pty'), - ); + return [ + ['pty'], + ['pty'], + ['pty'], + ]; } - return array( - array('pipe', 'r'), - array('pipe', 'w'), // stdout - array('pipe', 'w'), // stderr - ); + return [ + ['pipe', 'r'], + ['pipe', 'w'], // stdout + ['pipe', 'w'], // stderr + ]; } /** * {@inheritdoc} */ - public function getFiles() + public function getFiles(): array { - return array(); + return []; } /** * {@inheritdoc} */ - public function readAndWrite($blocking, $close = false) + public function readAndWrite(bool $blocking, bool $close = false): array { $this->unblock(); $w = $this->write(); - $read = $e = array(); + $read = $e = []; $r = $this->pipes; unset($r[0]); // let's have a look if something changed in streams - set_error_handler(array($this, 'handleError')); + set_error_handler([$this, 'handleError']); if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) { restore_error_handler(); // if a system call has been interrupted, forget about it, let's try again // otherwise, an error occurred, let's reset pipes if (!$this->hasSystemCallBeenInterrupted()) { - $this->pipes = array(); + $this->pipes = []; } return $read; @@ -118,7 +128,7 @@ public function readAndWrite($blocking, $close = false) $read[$type = array_search($pipe, $this->pipes, true)] = ''; do { - $data = fread($pipe, self::CHUNK_SIZE); + $data = @fread($pipe, self::CHUNK_SIZE); $read[$type] .= $data; } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1]))); @@ -138,7 +148,7 @@ public function readAndWrite($blocking, $close = false) /** * {@inheritdoc} */ - public function haveReadSupport() + public function haveReadSupport(): bool { return $this->haveReadSupport; } @@ -146,7 +156,7 @@ public function haveReadSupport() /** * {@inheritdoc} */ - public function areOpen() + public function areOpen(): bool { return (bool) $this->pipes; } diff --git a/vendor/symfony/process/Pipes/WindowsPipes.php b/vendor/symfony/process/Pipes/WindowsPipes.php index cfffd35..bca84f5 100644 --- a/vendor/symfony/process/Pipes/WindowsPipes.php +++ b/vendor/symfony/process/Pipes/WindowsPipes.php @@ -17,8 +17,8 @@ /** * WindowsPipes implementation uses temporary files as handles. * - * @see https://bugs.php.net/bug.php?id=51800 - * @see https://bugs.php.net/bug.php?id=65650 + * @see https://bugs.php.net/51800 + * @see https://bugs.php.net/65650 * * @author Romain Neutron <imprec@gmail.com> * @@ -26,52 +26,58 @@ */ class WindowsPipes extends AbstractPipes { - private $files = array(); - private $fileHandles = array(); - private $readBytes = array( + private $files = []; + private $fileHandles = []; + private $lockHandles = []; + private $readBytes = [ Process::STDOUT => 0, Process::STDERR => 0, - ); + ]; private $haveReadSupport; - public function __construct($input, $haveReadSupport) + public function __construct($input, bool $haveReadSupport) { - $this->haveReadSupport = (bool) $haveReadSupport; + $this->haveReadSupport = $haveReadSupport; if ($this->haveReadSupport) { // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big. // Workaround for this problem is to use temporary files instead of pipes on Windows platform. // - // @see https://bugs.php.net/bug.php?id=51800 - $pipes = array( + // @see https://bugs.php.net/51800 + $pipes = [ Process::STDOUT => Process::OUT, Process::STDERR => Process::ERR, - ); - $tmpCheck = false; + ]; $tmpDir = sys_get_temp_dir(); $lastError = 'unknown reason'; set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; }); for ($i = 0;; ++$i) { foreach ($pipes as $pipe => $name) { $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name); - if (file_exists($file) && !unlink($file)) { - continue 2; - } - $h = fopen($file, 'xb'); - if (!$h) { - $error = $lastError; - if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) { - continue; + + if (!$h = fopen($file.'.lock', 'w')) { + if (file_exists($file.'.lock')) { + continue 2; } restore_error_handler(); - throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error)); + throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError); } - if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) { + if (!flock($h, \LOCK_EX | \LOCK_NB)) { continue 2; } - if (isset($this->files[$pipe])) { - unlink($this->files[$pipe]); + if (isset($this->lockHandles[$pipe])) { + flock($this->lockHandles[$pipe], \LOCK_UN); + fclose($this->lockHandles[$pipe]); + } + $this->lockHandles[$pipe] = $h; + + if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) { + flock($this->lockHandles[$pipe], \LOCK_UN); + fclose($this->lockHandles[$pipe]); + unset($this->lockHandles[$pipe]); + continue 2; } + $this->fileHandles[$pipe] = $h; $this->files[$pipe] = $file; } break; @@ -82,41 +88,50 @@ public function __construct($input, $haveReadSupport) parent::__construct($input); } + public function __sleep(): array + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + public function __destruct() { $this->close(); - $this->removeFiles(); } /** * {@inheritdoc} */ - public function getDescriptors() + public function getDescriptors(): array { if (!$this->haveReadSupport) { $nullstream = fopen('NUL', 'c'); - return array( - array('pipe', 'r'), + return [ + ['pipe', 'r'], $nullstream, $nullstream, - ); + ]; } - // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800) - // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650 + // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800) + // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650 // So we redirect output within the commandline and pass the nul device to the process - return array( - array('pipe', 'r'), - array('file', 'NUL', 'w'), - array('file', 'NUL', 'w'), - ); + return [ + ['pipe', 'r'], + ['file', 'NUL', 'w'], + ['file', 'NUL', 'w'], + ]; } /** * {@inheritdoc} */ - public function getFiles() + public function getFiles(): array { return $this->files; } @@ -124,11 +139,11 @@ public function getFiles() /** * {@inheritdoc} */ - public function readAndWrite($blocking, $close = false) + public function readAndWrite(bool $blocking, bool $close = false): array { $this->unblock(); $w = $this->write(); - $read = $r = $e = array(); + $read = $r = $e = []; if ($blocking) { if ($w) { @@ -145,8 +160,11 @@ public function readAndWrite($blocking, $close = false) $read[$type] = $data; } if ($close) { + ftruncate($fileHandle, 0); fclose($fileHandle); - unset($this->fileHandles[$type]); + flock($this->lockHandles[$type], \LOCK_UN); + fclose($this->lockHandles[$type]); + unset($this->fileHandles[$type], $this->lockHandles[$type]); } } @@ -156,7 +174,7 @@ public function readAndWrite($blocking, $close = false) /** * {@inheritdoc} */ - public function haveReadSupport() + public function haveReadSupport(): bool { return $this->haveReadSupport; } @@ -164,7 +182,7 @@ public function haveReadSupport() /** * {@inheritdoc} */ - public function areOpen() + public function areOpen(): bool { return $this->pipes && $this->fileHandles; } @@ -175,22 +193,12 @@ public function areOpen() public function close() { parent::close(); - foreach ($this->fileHandles as $handle) { + foreach ($this->fileHandles as $type => $handle) { + ftruncate($handle, 0); fclose($handle); + flock($this->lockHandles[$type], \LOCK_UN); + fclose($this->lockHandles[$type]); } - $this->fileHandles = array(); - } - - /** - * Removes temporary files. - */ - private function removeFiles() - { - foreach ($this->files as $filename) { - if (file_exists($filename)) { - @unlink($filename); - } - } - $this->files = array(); + $this->fileHandles = $this->lockHandles = []; } } diff --git a/vendor/symfony/process/Process.php b/vendor/symfony/process/Process.php index a64f5f0..9b19475 100644 --- a/vendor/symfony/process/Process.php +++ b/vendor/symfony/process/Process.php @@ -14,6 +14,7 @@ use Symfony\Component\Process\Exception\InvalidArgumentException; use Symfony\Component\Process\Exception\LogicException; use Symfony\Component\Process\Exception\ProcessFailedException; +use Symfony\Component\Process\Exception\ProcessSignaledException; use Symfony\Component\Process\Exception\ProcessTimedOutException; use Symfony\Component\Process\Exception\RuntimeException; use Symfony\Component\Process\Pipes\PipesInterface; @@ -26,54 +27,53 @@ * * @author Fabien Potencier <fabien@symfony.com> * @author Romain Neutron <imprec@gmail.com> + * + * @implements \IteratorAggregate<string, string> */ class Process implements \IteratorAggregate { - const ERR = 'err'; - const OUT = 'out'; + public const ERR = 'err'; + public const OUT = 'out'; - const STATUS_READY = 'ready'; - const STATUS_STARTED = 'started'; - const STATUS_TERMINATED = 'terminated'; + public const STATUS_READY = 'ready'; + public const STATUS_STARTED = 'started'; + public const STATUS_TERMINATED = 'terminated'; - const STDIN = 0; - const STDOUT = 1; - const STDERR = 2; + public const STDIN = 0; + public const STDOUT = 1; + public const STDERR = 2; // Timeout Precision in seconds. - const TIMEOUT_PRECISION = 0.2; + public const TIMEOUT_PRECISION = 0.2; - const ITER_NON_BLOCKING = 1; // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking - const ITER_KEEP_OUTPUT = 2; // By default, outputs are cleared while iterating, use this flag to keep them in memory - const ITER_SKIP_OUT = 4; // Use this flag to skip STDOUT while iterating - const ITER_SKIP_ERR = 8; // Use this flag to skip STDERR while iterating + public const ITER_NON_BLOCKING = 1; // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking + public const ITER_KEEP_OUTPUT = 2; // By default, outputs are cleared while iterating, use this flag to keep them in memory + public const ITER_SKIP_OUT = 4; // Use this flag to skip STDOUT while iterating + public const ITER_SKIP_ERR = 8; // Use this flag to skip STDERR while iterating private $callback; private $hasCallback = false; private $commandline; private $cwd; - private $env; + private $env = []; private $input; private $starttime; private $lastOutputTime; private $timeout; private $idleTimeout; - private $options = array('suppress_errors' => true); private $exitcode; - private $fallbackStatus = array(); + private $fallbackStatus = []; private $processInformation; private $outputDisabled = false; private $stdout; private $stderr; - private $enhanceWindowsCompatibility = true; - private $enhanceSigchildCompatibility; private $process; private $status = self::STATUS_READY; private $incrementalOutputOffset = 0; private $incrementalErrorOutputOffset = 0; - private $tty; + private $tty = false; private $pty; - private $inheritEnv = false; + private $options = ['suppress_errors' => true, 'bypass_shell' => true]; private $useFileHandles = false; /** @var PipesInterface */ @@ -88,7 +88,7 @@ class Process implements \IteratorAggregate * * User-defined errors must use exit codes in the 64-113 range. */ - public static $exitCodes = array( + public static $exitCodes = [ 0 => 'OK', 1 => 'General error', 2 => 'Misuse of shell builtins', @@ -129,31 +129,30 @@ class Process implements \IteratorAggregate 157 => 'Pollable event', // 158 - not defined 159 => 'Bad syscall', - ); + ]; /** - * @param string|array $commandline The command line to run - * @param string|null $cwd The working directory or null to use the working dir of the current PHP process - * @param array|null $env The environment variables or null to use the same environment as the current PHP process - * @param mixed|null $input The input as stream resource, scalar or \Traversable, or null for no input - * @param int|float|null $timeout The timeout in seconds or null to disable - * @param array $options An array of options for proc_open + * @param array $command The command to run and its arguments listed as separate entries + * @param string|null $cwd The working directory or null to use the working dir of the current PHP process + * @param array|null $env The environment variables or null to use the same environment as the current PHP process + * @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input + * @param int|float|null $timeout The timeout in seconds or null to disable * - * @throws RuntimeException When proc_open is not installed + * @throws LogicException When proc_open is not installed */ - public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = null) + public function __construct(array $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { if (!\function_exists('proc_open')) { - throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.'); + throw new LogicException('The Process class relies on proc_open, which is not available on your PHP installation.'); } - $this->commandline = $commandline; + $this->commandline = $command; $this->cwd = $cwd; // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected - // @see : https://bugs.php.net/bug.php?id=51800 - // @see : https://bugs.php.net/bug.php?id=50524 + // @see : https://bugs.php.net/51800 + // @see : https://bugs.php.net/50524 if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) { $this->cwd = getcwd(); } @@ -165,16 +164,59 @@ public function __construct($commandline, $cwd = null, array $env = null, $input $this->setTimeout($timeout); $this->useFileHandles = '\\' === \DIRECTORY_SEPARATOR; $this->pty = false; - $this->enhanceSigchildCompatibility = '\\' !== \DIRECTORY_SEPARATOR && $this->isSigchildEnabled(); - if (null !== $options) { - @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since Symfony 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - $this->options = array_replace($this->options, $options); - } + } + + /** + * Creates a Process instance as a command-line to be run in a shell wrapper. + * + * Command-lines are parsed by the shell of your OS (/bin/sh on Unix-like, cmd.exe on Windows.) + * This allows using e.g. pipes or conditional execution. In this mode, signals are sent to the + * shell wrapper and not to your commands. + * + * In order to inject dynamic values into command-lines, we strongly recommend using placeholders. + * This will save escaping values, which is not portable nor secure anyway: + * + * $process = Process::fromShellCommandline('my_command "${:MY_VAR}"'); + * $process->run(null, ['MY_VAR' => $theValue]); + * + * @param string $command The command line to pass to the shell of the OS + * @param string|null $cwd The working directory or null to use the working dir of the current PHP process + * @param array|null $env The environment variables or null to use the same environment as the current PHP process + * @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input + * @param int|float|null $timeout The timeout in seconds or null to disable + * + * @return static + * + * @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) + { + $process = new static([], $cwd, $env, $input, $timeout); + $process->commandline = $command; + + return $process; + } + + /** + * @return array + */ + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } public function __destruct() { - $this->stop(0); + if ($this->options['create_new_console'] ?? false) { + $this->processPipes->close(); + } else { + $this->stop(0); + } } public function __clone() @@ -194,19 +236,19 @@ public function __clone() * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR - * @param array $env An array of additional env vars to set when running the process * * @return int The exit status code * - * @throws RuntimeException When process can't be launched - * @throws RuntimeException When process stopped after receiving signal - * @throws LogicException In case a callback is provided and output has been disabled + * @throws RuntimeException When process can't be launched + * @throws RuntimeException When process is already running + * @throws ProcessTimedOutException When process timed out + * @throws ProcessSignaledException When process stopped after receiving signal + * @throws LogicException In case a callback is provided and output has been disabled * - * @final since version 3.3 + * @final */ - public function run($callback = null/*, array $env = array()*/) + public function run(callable $callback = null, array $env = []): int { - $env = 1 < \func_num_args() ? func_get_arg(1) : null; $this->start($callback, $env); return $this->wait(); @@ -218,23 +260,14 @@ public function run($callback = null/*, array $env = array()*/) * This is identical to run() except that an exception is thrown if the process * exits with a non-zero exit code. * - * @param callable|null $callback - * @param array $env An array of additional env vars to set when running the process - * - * @return self + * @return $this * - * @throws RuntimeException if PHP was compiled with --enable-sigchild and the enhanced sigchild compatibility mode is not enabled * @throws ProcessFailedException if the process didn't terminate successfully * - * @final since version 3.3 + * @final */ - public function mustRun(callable $callback = null/*, array $env = array()*/) + public function mustRun(callable $callback = null, array $env = []): self { - if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); - } - $env = 1 < \func_num_args() ? func_get_arg(1) : null; - if (0 !== $this->run($callback, $env)) { throw new ProcessFailedException($this); } @@ -256,27 +289,15 @@ public function mustRun(callable $callback = null/*, array $env = array()*/) * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR - * @param array $env An array of additional env vars to set when running the process * * @throws RuntimeException When process can't be launched * @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 = array()*/) + public function start(callable $callback = null, array $env = []) { if ($this->isRunning()) { - throw new RuntimeException('Process is already running'); - } - if (2 <= \func_num_args()) { - $env = func_get_arg(1); - } else { - if (__CLASS__ !== static::class) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName() && (2 > $r->getNumberOfParameters() || 'env' !== $r->getParameters()[1]->name)) { - @trigger_error(sprintf('The %s::start() method expects a second "$env" argument since Symfony 3.3. It will be made mandatory in 4.0.', static::class), E_USER_DEPRECATED); - } - } - $env = null; + throw new RuntimeException('Process is already running.'); } $this->resetProcessData(); @@ -284,39 +305,29 @@ public function start(callable $callback = null/*, array $env = array()*/) $this->callback = $this->buildCallback($callback); $this->hasCallback = null !== $callback; $descriptors = $this->getDescriptors(); - $inheritEnv = $this->inheritEnv; + + if ($this->env) { + $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->env, $env, 'strcasecmp') : $this->env; + } + + $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->getDefaultEnv(), $env, 'strcasecmp') : $this->getDefaultEnv(); if (\is_array($commandline = $this->commandline)) { - $commandline = implode(' ', array_map(array($this, 'escapeArgument'), $commandline)); + $commandline = implode(' ', array_map([$this, 'escapeArgument'], $commandline)); if ('\\' !== \DIRECTORY_SEPARATOR) { // exec is mandatory to deal with sending a signal to the process $commandline = 'exec '.$commandline; } - } - - if (null === $env) { - $env = $this->env; } else { - if ($this->env) { - $env += $this->env; - } - $inheritEnv = true; + $commandline = $this->replacePlaceholders($commandline, $env); } - if (null !== $env && $inheritEnv) { - $env += $this->getDefaultEnv(); - } elseif (null !== $env) { - @trigger_error('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.', E_USER_DEPRECATED); - } else { - $env = $this->getDefaultEnv(); - } - if ('\\' === \DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) { - $this->options['bypass_shell'] = true; + if ('\\' === \DIRECTORY_SEPARATOR) { $commandline = $this->prepareWindowsCommandLine($commandline, $env); - } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { + } elseif (!$this->useFileHandles && $this->isSigchildEnabled()) { // last exit code is output on the fourth pipe and caught to work around --enable-sigchild - $descriptors[3] = array('pipe', 'w'); + $descriptors[3] = ['pipe', 'w']; // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;'; @@ -326,22 +337,19 @@ public function start(callable $callback = null/*, array $env = array()*/) // @see : https://bugs.php.net/69442 $ptsWorkaround = fopen(__FILE__, 'r'); } - if (\defined('HHVM_VERSION')) { - $envPairs = $env; - } else { - $envPairs = array(); - foreach ($env as $k => $v) { - if (false !== $v) { - $envPairs[] = $k.'='.$v; - } + + $envPairs = []; + foreach ($env as $k => $v) { + if (false !== $v && false === \in_array($k, ['argc', 'argv', 'ARGC', 'ARGV'], true)) { + $envPairs[] = $k.'='.$v; } } if (!is_dir($this->cwd)) { - @trigger_error('The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); + throw new RuntimeException(sprintf('The provided cwd "%s" does not exist.', $this->cwd)); } - $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options); + $this->process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options); if (!\is_resource($this->process)) { throw new RuntimeException('Unable to launch a new process.'); @@ -367,23 +375,21 @@ public function start(callable $callback = null/*, array $env = array()*/) * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR - * @param array $env An array of additional env vars to set when running the process * - * @return $this + * @return static * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running * * @see start() * - * @final since version 3.3 + * @final */ - public function restart(callable $callback = null/*, array $env = array()*/) + public function restart(callable $callback = null, array $env = []): self { if ($this->isRunning()) { - throw new RuntimeException('Process is already running'); + throw new RuntimeException('Process is already running.'); } - $env = 1 < \func_num_args() ? func_get_arg(1) : null; $process = clone $this; $process->start($callback, $env); @@ -402,9 +408,9 @@ public function restart(callable $callback = null/*, array $env = array()*/) * * @return int The exitcode of the process * - * @throws RuntimeException When process timed out - * @throws RuntimeException When process stopped after receiving signal - * @throws LogicException When process is not yet started + * @throws ProcessTimedOutException When process timed out + * @throws ProcessSignaledException When process stopped after receiving signal + * @throws LogicException When process is not yet started */ public function wait(callable $callback = null) { @@ -415,28 +421,75 @@ public function wait(callable $callback = null) if (null !== $callback) { if (!$this->processPipes->haveReadSupport()) { $this->stop(0); - throw new \LogicException('Pass the callback to the Process::start method or enableOutput to use a callback with Process::wait'); + throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::wait".'); } $this->callback = $this->buildCallback($callback); } do { $this->checkTimeout(); - $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); + $running = $this->isRunning() && ('\\' === \DIRECTORY_SEPARATOR || $this->processPipes->areOpen()); $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); } while ($running); while ($this->isRunning()) { + $this->checkTimeout(); usleep(1000); } if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) { - throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig'])); + throw new ProcessSignaledException($this); } return $this->exitcode; } + /** + * Waits until the callback returns true. + * + * The callback receives the type of output (out or err) and some bytes + * from the output in real-time while writing the standard input to the process. + * It allows to have feedback from the independent process during execution. + * + * @throws RuntimeException When process timed out + * @throws LogicException When process is not yet started + * @throws ProcessTimedOutException In case the timeout was reached + */ + public function waitUntil(callable $callback): bool + { + $this->requireProcessIsStarted(__FUNCTION__); + $this->updateStatus(false); + + if (!$this->processPipes->haveReadSupport()) { + $this->stop(0); + throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::waitUntil".'); + } + $callback = $this->buildCallback($callback); + + $ready = false; + while (true) { + $this->checkTimeout(); + $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); + $output = $this->processPipes->readAndWrite($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); + + foreach ($output as $type => $data) { + if (3 !== $type) { + $ready = $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data) || $ready; + } elseif (!isset($this->fallbackStatus['signaled'])) { + $this->fallbackStatus['exitcode'] = (int) $data; + } + } + if ($ready) { + return true; + } + if (!$running) { + return false; + } + + usleep(1000); + } + } + /** * Returns the Pid (process identifier), if applicable. * @@ -450,7 +503,7 @@ public function getPid() /** * Sends a POSIX signal to the process. * - * @param int $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php) + * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants) * * @return $this * @@ -458,7 +511,7 @@ public function getPid() * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed * @throws RuntimeException In case of failure */ - public function signal($signal) + public function signal(int $signal) { $this->doSignal($signal, true); @@ -479,7 +532,7 @@ public function disableOutput() throw new RuntimeException('Disabling output while the process is running is not possible.'); } if (null !== $this->idleTimeout) { - throw new LogicException('Output can not be disabled while an idle timeout is set.'); + throw new LogicException('Output cannot be disabled while an idle timeout is set.'); } $this->outputDisabled = true; @@ -518,7 +571,7 @@ public function isOutputDisabled() /** * Returns the current output of the process (STDOUT). * - * @return string The process output + * @return string * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started @@ -540,7 +593,7 @@ public function getOutput() * In comparison with the getOutput method which always return the whole * output, this one returns the new output since the last call. * - * @return string The process output since the last call + * @return string * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started @@ -564,12 +617,13 @@ public function getIncrementalOutput() * * @param int $flags A bit field of Process::ITER_* flags * + * @return \Generator<string, string> + * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started - * - * @return \Generator */ - public function getIterator($flags = 0) + #[\ReturnTypeWillChange] + public function getIterator(int $flags = 0) { $this->readPipesForOutput(__FUNCTION__, false); @@ -633,7 +687,7 @@ public function clearOutput() /** * Returns the current error output of the process (STDERR). * - * @return string The process error output + * @return string * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started @@ -656,7 +710,7 @@ public function getErrorOutput() * whole error output, this one returns the new error output since the last * call. * - * @return string The process error output since the last call + * @return string * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started @@ -692,16 +746,10 @@ public function clearErrorOutput() /** * Returns the exit code returned by the process. * - * @return null|int The exit status code, null if the Process is not terminated - * - * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled + * @return int|null The exit status code, null if the Process is not terminated */ public function getExitCode() { - if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); - } - $this->updateStatus(false); return $this->exitcode; @@ -713,7 +761,7 @@ public function getExitCode() * This method relies on the Unix exit code status standardization * and might not be relevant for other operating systems. * - * @return null|string A string representation for the exit status code, null if the Process is not terminated + * @return string|null A string representation for the exit status code, null if the Process is not terminated * * @see http://tldp.org/LDP/abs/html/exitcodes.html * @see http://en.wikipedia.org/wiki/Unix_signal @@ -721,16 +769,16 @@ public function getExitCode() public function getExitCodeText() { if (null === $exitcode = $this->getExitCode()) { - return; + return null; } - return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error'; + return self::$exitCodes[$exitcode] ?? 'Unknown error'; } /** * Checks if the process ended successfully. * - * @return bool true if the process ended successfully, false otherwise + * @return bool */ public function isSuccessful() { @@ -744,17 +792,12 @@ public function isSuccessful() * * @return bool * - * @throws RuntimeException In case --enable-sigchild is activated - * @throws LogicException In case the process is not terminated + * @throws LogicException In case the process is not terminated */ public function hasBeenSignaled() { $this->requireProcessIsTerminated(__FUNCTION__); - if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); - } - return $this->processInformation['signaled']; } @@ -772,8 +815,8 @@ public function getTermSignal() { $this->requireProcessIsTerminated(__FUNCTION__); - if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); + if ($this->isSigchildEnabled() && -1 === $this->processInformation['termsig']) { + throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal cannot be retrieved.'); } return $this->processInformation['termsig']; @@ -814,7 +857,7 @@ public function getStopSignal() /** * Checks if the process is currently running. * - * @return bool true if the process is currently running, false otherwise + * @return bool */ public function isRunning() { @@ -830,7 +873,7 @@ public function isRunning() /** * Checks if the process has been started with no regard to the current state. * - * @return bool true if status is ready, false otherwise + * @return bool */ public function isStarted() { @@ -840,7 +883,7 @@ public function isStarted() /** * Checks if the process is terminated. * - * @return bool true if process is terminated, false otherwise + * @return bool */ public function isTerminated() { @@ -854,7 +897,7 @@ public function isTerminated() * * The status is one of: ready, started, terminated. * - * @return string The current process status + * @return string */ public function getStatus() { @@ -867,15 +910,15 @@ public function getStatus() * Stops the process. * * @param int|float $timeout The timeout in seconds - * @param int $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9) + * @param int|null $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9) * - * @return int The exit-code of the process + * @return int|null The exit-code of the process or null if it's not running */ - public function stop($timeout = 10, $signal = null) + public function stop(float $timeout = 10, int $signal = null) { $timeoutMicro = microtime(true) + $timeout; if ($this->isRunning()) { - // given `SIGTERM` may not be defined and that `proc_terminate` uses the constant value and not the constant itself, we use the same here + // given SIGTERM may not be defined and that "proc_terminate" uses the constant value and not the constant itself, we use the same here $this->doSignal(15, false); do { usleep(1000); @@ -904,14 +947,12 @@ public function stop($timeout = 10, $signal = null) * Adds a line to the STDOUT stream. * * @internal - * - * @param string $line The line to append */ - public function addOutput($line) + public function addOutput(string $line) { $this->lastOutputTime = microtime(true); - fseek($this->stdout, 0, SEEK_END); + fseek($this->stdout, 0, \SEEK_END); fwrite($this->stdout, $line); fseek($this->stdout, $this->incrementalOutputOffset); } @@ -920,46 +961,38 @@ public function addOutput($line) * Adds a line to the STDERR stream. * * @internal - * - * @param string $line The line to append */ - public function addErrorOutput($line) + public function addErrorOutput(string $line) { $this->lastOutputTime = microtime(true); - fseek($this->stderr, 0, SEEK_END); + fseek($this->stderr, 0, \SEEK_END); fwrite($this->stderr, $line); fseek($this->stderr, $this->incrementalErrorOutputOffset); } /** - * Gets the command line to be executed. - * - * @return string The command to execute + * Gets the last output time in seconds. */ - public function getCommandLine() + public function getLastOutputTime(): ?float { - return \is_array($this->commandline) ? implode(' ', array_map(array($this, 'escapeArgument'), $this->commandline)) : $this->commandline; + return $this->lastOutputTime; } /** - * Sets the command line to be executed. - * - * @param string|array $commandline The command to execute + * Gets the command line to be executed. * - * @return self The current Process instance + * @return string */ - public function setCommandLine($commandline) + public function getCommandLine() { - $this->commandline = $commandline; - - return $this; + return \is_array($this->commandline) ? implode(' ', array_map([$this, 'escapeArgument'], $this->commandline)) : $this->commandline; } /** - * Gets the process timeout (max. runtime). + * Gets the process timeout in seconds (max. runtime). * - * @return float|null The timeout in seconds or null if it's disabled + * @return float|null */ public function getTimeout() { @@ -967,9 +1000,9 @@ public function getTimeout() } /** - * Gets the process idle timeout (max. time since last output). + * Gets the process idle timeout in seconds (max. time since last output). * - * @return float|null The timeout in seconds or null if it's disabled + * @return float|null */ public function getIdleTimeout() { @@ -977,17 +1010,15 @@ public function getIdleTimeout() } /** - * Sets the process timeout (max. runtime). + * Sets the process timeout (max. runtime) in seconds. * * To disable the timeout, set this value to null. * - * @param int|float|null $timeout The timeout in seconds - * - * @return self The current Process instance + * @return $this * * @throws InvalidArgumentException if the timeout is negative */ - public function setTimeout($timeout) + public function setTimeout(?float $timeout) { $this->timeout = $this->validateTimeout($timeout); @@ -995,21 +1026,19 @@ public function setTimeout($timeout) } /** - * Sets the process idle timeout (max. time since last output). + * Sets the process idle timeout (max. time since last output) in seconds. * * To disable the timeout, set this value to null. * - * @param int|float|null $timeout The timeout in seconds - * - * @return self The current Process instance + * @return $this * * @throws LogicException if the output is disabled * @throws InvalidArgumentException if the timeout is negative */ - public function setIdleTimeout($timeout) + public function setIdleTimeout(?float $timeout) { if (null !== $timeout && $this->outputDisabled) { - throw new LogicException('Idle timeout can not be set while the output is disabled.'); + throw new LogicException('Idle timeout cannot be set while the output is disabled.'); } $this->idleTimeout = $this->validateTimeout($timeout); @@ -1020,30 +1049,21 @@ public function setIdleTimeout($timeout) /** * Enables or disables the TTY mode. * - * @param bool $tty True to enabled and false to disable - * - * @return self The current Process instance + * @return $this * * @throws RuntimeException In case the TTY mode is not supported */ - public function setTty($tty) + public function setTty(bool $tty) { if ('\\' === \DIRECTORY_SEPARATOR && $tty) { throw new RuntimeException('TTY mode is not supported on Windows platform.'); } - if ($tty) { - static $isTtySupported; - - if (null === $isTtySupported) { - $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', array(array('file', '/dev/tty', 'r'), array('file', '/dev/tty', 'w'), array('file', '/dev/tty', 'w')), $pipes); - } - if (!$isTtySupported) { - throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.'); - } + if ($tty && !self::isTtySupported()) { + throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.'); } - $this->tty = (bool) $tty; + $this->tty = $tty; return $this; } @@ -1051,7 +1071,7 @@ public function setTty($tty) /** * Checks if the TTY mode is enabled. * - * @return bool true if the TTY mode is enabled, false otherwise + * @return bool */ public function isTty() { @@ -1061,13 +1081,11 @@ public function isTty() /** * Sets PTY mode. * - * @param bool $bool - * - * @return self + * @return $this */ - public function setPty($bool) + public function setPty(bool $bool) { - $this->pty = (bool) $bool; + $this->pty = $bool; return $this; } @@ -1085,7 +1103,7 @@ public function isPty() /** * Gets the working directory. * - * @return string|null The current working directory or null on failure + * @return string|null */ public function getWorkingDirectory() { @@ -1101,11 +1119,9 @@ public function getWorkingDirectory() /** * Sets the current working directory. * - * @param string $cwd The new working directory - * - * @return self The current Process instance + * @return $this */ - public function setWorkingDirectory($cwd) + public function setWorkingDirectory(string $cwd) { $this->cwd = $cwd; @@ -1115,7 +1131,7 @@ public function setWorkingDirectory($cwd) /** * Gets the environment variables. * - * @return array The current environment variables + * @return array */ public function getEnv() { @@ -1125,25 +1141,12 @@ public function getEnv() /** * Sets the environment variables. * - * Each environment variable value should be a string. - * If it is an array, the variable is ignored. - * If it is false or null, it will be removed when - * env vars are otherwise inherited. - * - * That happens in PHP when 'argv' is registered into - * the $_ENV array for instance. + * @param array<string|\Stringable> $env The new environment variables * - * @param array $env The new environment variables - * - * @return self The current Process instance + * @return $this */ public function setEnv(array $env) { - // Process can not handle env values that are arrays - $env = array_filter($env, function ($value) { - return !\is_array($value); - }); - $this->env = $env; return $this; @@ -1152,7 +1155,7 @@ public function setEnv(array $env) /** * Gets the Process input. * - * @return resource|string|\Iterator|null The Process input + * @return resource|string|\Iterator|null */ public function getInput() { @@ -1166,14 +1169,14 @@ public function getInput() * * @param string|int|float|bool|resource|\Traversable|null $input The content * - * @return self The current Process instance + * @return $this * * @throws LogicException In case the process is running */ public function setInput($input) { if ($this->isRunning()) { - throw new LogicException('Input can not be set while the process is running.'); + throw new LogicException('Input cannot be set while the process is running.'); } $this->input = ProcessUtils::validateInput(__METHOD__, $input); @@ -1182,164 +1185,82 @@ public function setInput($input) } /** - * Gets the options for proc_open. - * - * @return array The current options - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function getOptions() - { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - return $this->options; - } - - /** - * Sets the options for proc_open. - * - * @param array $options The new options - * - * @return self The current Process instance - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function setOptions(array $options) - { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - $this->options = $options; - - return $this; - } - - /** - * Gets whether or not Windows compatibility is enabled. - * - * This is true by default. + * Performs a check between the timeout definition and the time the process started. * - * @return bool + * In case you run a background process (with the start method), you should + * trigger this method regularly to ensure the process timeout * - * @deprecated since version 3.3, to be removed in 4.0. Enhanced Windows compatibility will always be enabled. + * @throws ProcessTimedOutException In case the timeout was reached */ - public function getEnhanceWindowsCompatibility() + public function checkTimeout() { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED); + if (self::STATUS_STARTED !== $this->status) { + return; + } - return $this->enhanceWindowsCompatibility; - } + if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) { + $this->stop(0); - /** - * Sets whether or not Windows compatibility is enabled. - * - * @param bool $enhance - * - * @return self The current Process instance - * - * @deprecated since version 3.3, to be removed in 4.0. Enhanced Windows compatibility will always be enabled. - */ - public function setEnhanceWindowsCompatibility($enhance) - { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED); + throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL); + } - $this->enhanceWindowsCompatibility = (bool) $enhance; + if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) { + $this->stop(0); - return $this; + throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE); + } } /** - * Returns whether sigchild compatibility mode is activated or not. - * - * @return bool - * - * @deprecated since version 3.3, to be removed in 4.0. Sigchild compatibility will always be enabled. + * @throws LogicException in case process is not started */ - public function getEnhanceSigchildCompatibility() + public function getStartTime(): float { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED); - - return $this->enhanceSigchildCompatibility; - } - - /** - * Activates sigchild compatibility mode. - * - * Sigchild compatibility mode is required to get the exit code and - * determine the success of a process when PHP has been compiled with - * the --enable-sigchild option - * - * @param bool $enhance - * - * @return self The current Process instance - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function setEnhanceSigchildCompatibility($enhance) - { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED); - - $this->enhanceSigchildCompatibility = (bool) $enhance; + if (!$this->isStarted()) { + throw new LogicException('Start time is only available after process start.'); + } - return $this; + return $this->starttime; } /** - * Sets whether environment variables will be inherited or not. + * Defines options to pass to the underlying proc_open(). * - * @param bool $inheritEnv + * @see https://php.net/proc_open for the options supported by PHP. * - * @return self The current Process instance + * Enabling the "create_new_console" option allows a subprocess to continue + * to run after the main process exited, on both Windows and *nix */ - public function inheritEnvironmentVariables($inheritEnv = true) + public function setOptions(array $options) { - if (!$inheritEnv) { - @trigger_error('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.', E_USER_DEPRECATED); + if ($this->isRunning()) { + throw new RuntimeException('Setting options while the process is running is not possible.'); } - $this->inheritEnv = (bool) $inheritEnv; + $defaultOptions = $this->options; + $existingOptions = ['blocking_pipes', 'create_process_group', 'create_new_console']; - return $this; + foreach ($options as $key => $value) { + if (!\in_array($key, $existingOptions)) { + $this->options = $defaultOptions; + throw new LogicException(sprintf('Invalid option "%s" passed to "%s()". Supported options are "%s".', $key, __METHOD__, implode('", "', $existingOptions))); + } + $this->options[$key] = $value; + } } /** - * Returns whether environment variables will be inherited or not. - * - * @return bool - * - * @deprecated since version 3.3, to be removed in 4.0. Environment variables will always be inherited. + * Returns whether TTY is supported on the current operating system. */ - public function areEnvironmentVariablesInherited() + public static function isTtySupported(): bool { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Environment variables will always be inherited.', __METHOD__), E_USER_DEPRECATED); - - return $this->inheritEnv; - } + static $isTtySupported; - /** - * Performs a check between the timeout definition and the time the process started. - * - * In case you run a background process (with the start method), you should - * trigger this method regularly to ensure the process timeout - * - * @throws ProcessTimedOutException In case the timeout was reached - */ - public function checkTimeout() - { - if (self::STATUS_STARTED !== $this->status) { - return; + if (null === $isTtySupported) { + $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes); } - if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) { - $this->stop(0); - - throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL); - } - - if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) { - $this->stop(0); - - throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE); - } + return $isTtySupported; } /** @@ -1359,15 +1280,13 @@ public static function isPtySupported() return $result = false; } - return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes); + return $result = (bool) @proc_open('echo 1 >/dev/null', [['pty'], ['pty'], ['pty']], $pipes); } /** * Creates the descriptors needed by the proc_open. - * - * @return array */ - private function getDescriptors() + private function getDescriptors(): array { if ($this->input instanceof \Iterator) { $this->input->rewind(); @@ -1389,30 +1308,26 @@ private function getDescriptors() * * @param callable|null $callback The user defined PHP callback * - * @return \Closure A PHP closure + * @return \Closure */ protected function buildCallback(callable $callback = null) { if ($this->outputDisabled) { - return function ($type, $data) use ($callback) { - if (null !== $callback) { - \call_user_func($callback, $type, $data); - } + return function ($type, $data) use ($callback): bool { + return null !== $callback && $callback($type, $data); }; } $out = self::OUT; - return function ($type, $data) use ($callback, $out) { + return function ($type, $data) use ($callback, $out): bool { if ($out == $type) { $this->addOutput($data); } else { $this->addErrorOutput($data); } - if (null !== $callback) { - \call_user_func($callback, $type, $data); - } + return null !== $callback && $callback($type, $data); }; } @@ -1421,7 +1336,7 @@ protected function buildCallback(callable $callback = null) * * @param bool $blocking Whether to use a blocking read call */ - protected function updateStatus($blocking) + protected function updateStatus(bool $blocking) { if (self::STATUS_STARTED !== $this->status) { return; @@ -1432,7 +1347,7 @@ protected function updateStatus($blocking) $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running); - if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { + if ($this->fallbackStatus && $this->isSigchildEnabled()) { $this->processInformation = $this->fallbackStatus + $this->processInformation; } @@ -1452,14 +1367,14 @@ protected function isSigchildEnabled() return self::$sigchild; } - if (!\function_exists('phpinfo') || \defined('HHVM_VERSION')) { + if (!\function_exists('phpinfo')) { return self::$sigchild = false; } ob_start(); - phpinfo(INFO_GENERAL); + phpinfo(\INFO_GENERAL); - return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild'); + return self::$sigchild = str_contains(ob_get_clean(), '--enable-sigchild'); } /** @@ -1470,7 +1385,7 @@ protected function isSigchildEnabled() * * @throws LogicException in case output has been disabled or process is not started */ - private function readPipesForOutput($caller, $blocking = false) + private function readPipesForOutput(string $caller, bool $blocking = false) { if ($this->outputDisabled) { throw new LogicException('Output has been disabled.'); @@ -1484,13 +1399,9 @@ private function readPipesForOutput($caller, $blocking = false) /** * Validates and returns the filtered timeout. * - * @param int|float|null $timeout - * - * @return float|null - * * @throws InvalidArgumentException if the given timeout is a negative number */ - private function validateTimeout($timeout) + private function validateTimeout(?float $timeout): ?float { $timeout = (float) $timeout; @@ -1509,7 +1420,7 @@ private function validateTimeout($timeout) * @param bool $blocking Whether to use blocking calls or not * @param bool $close Whether to close file handles or not */ - private function readPipes($blocking, $close) + private function readPipes(bool $blocking, bool $close) { $result = $this->processPipes->readAndWrite($blocking, $close); @@ -1528,7 +1439,7 @@ private function readPipes($blocking, $close) * * @return int The exitcode */ - private function close() + private function close(): int { $this->processPipes->close(); if (\is_resource($this->process)) { @@ -1541,7 +1452,7 @@ private function close() if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) { // if process has been signaled, no exitcode but a valid termsig, apply Unix convention $this->exitcode = 128 + $this->processInformation['termsig']; - } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { + } elseif ($this->isSigchildEnabled()) { $this->processInformation['signaled'] = true; $this->processInformation['termsig'] = -1; } @@ -1563,10 +1474,10 @@ private function resetProcessData() $this->starttime = null; $this->callback = null; $this->exitcode = null; - $this->fallbackStatus = array(); + $this->fallbackStatus = []; $this->processInformation = null; - $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+'); - $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+'); + $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+'); + $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+'); $this->process = null; $this->latestSignal = null; $this->status = self::STATUS_READY; @@ -1577,20 +1488,18 @@ private function resetProcessData() /** * Sends a POSIX signal to the process. * - * @param int $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php) + * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants) * @param bool $throwException Whether to throw exception in case signal failed * - * @return bool True if the signal was sent successfully, false otherwise - * * @throws LogicException In case the process is not running * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed * @throws RuntimeException In case of failure */ - private function doSignal($signal, $throwException) + private function doSignal(int $signal, bool $throwException): bool { if (null === $pid = $this->getPid()) { if ($throwException) { - throw new LogicException('Can not send signal on a non running process.'); + throw new LogicException('Cannot send signal on a non running process.'); } return false; @@ -1606,23 +1515,23 @@ private function doSignal($signal, $throwException) return false; } } else { - if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) { + if (!$this->isSigchildEnabled()) { $ok = @proc_terminate($this->process, $signal); } elseif (\function_exists('posix_kill')) { $ok = @posix_kill($pid, $signal); - } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) { + } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) { $ok = false === fgets($pipes[2]); } if (!$ok) { if ($throwException) { - throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal)); + throw new RuntimeException(sprintf('Error while sending signal "%s".', $signal)); } return false; } } - $this->latestSignal = (int) $signal; + $this->latestSignal = $signal; $this->fallbackStatus['signaled'] = true; $this->fallbackStatus['exitcode'] = -1; $this->fallbackStatus['termsig'] = $this->latestSignal; @@ -1630,11 +1539,11 @@ private function doSignal($signal, $throwException) return true; } - private function prepareWindowsCommandLine($cmd, array &$env) + private function prepareWindowsCommandLine(string $cmd, array &$env): string { $uid = uniqid('', true); $varCount = 0; - $varCache = array(); + $varCache = []; $cmd = preg_replace_callback( '/"(?:( [^"%!^]*+ @@ -1650,14 +1559,14 @@ function ($m) use (&$env, &$varCache, &$varCount, $uid) { if (isset($varCache[$m[0]])) { return $varCache[$m[0]]; } - if (false !== strpos($value = $m[1], "\0")) { + if (str_contains($value = $m[1], "\0")) { $value = str_replace("\0", '?', $value); } if (false === strpbrk($value, "\"%!\n")) { return '"'.$value.'"'; } - $value = str_replace(array('!LF!', '"^!"', '"^%"', '"^^"', '""'), array("\n", '!', '%', '^', '"'), $value); + $value = str_replace(['!LF!', '"^!"', '"^%"', '"^^"', '""'], ["\n", '!', '%', '^', '"'], $value); $value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"'; $var = $uid.++$varCount; @@ -1679,47 +1588,39 @@ function ($m) use (&$env, &$varCache, &$varCount, $uid) { /** * Ensures the process is running or terminated, throws a LogicException if the process has a not started. * - * @param string $functionName The function name that was called - * * @throws LogicException if the process has not run */ - private function requireProcessIsStarted($functionName) + private function requireProcessIsStarted(string $functionName) { if (!$this->isStarted()) { - throw new LogicException(sprintf('Process must be started before calling %s.', $functionName)); + throw new LogicException(sprintf('Process must be started before calling "%s()".', $functionName)); } } /** - * Ensures the process is terminated, throws a LogicException if the process has a status different than `terminated`. - * - * @param string $functionName The function name that was called + * Ensures the process is terminated, throws a LogicException if the process has a status different than "terminated". * * @throws LogicException if the process is not yet terminated */ - private function requireProcessIsTerminated($functionName) + private function requireProcessIsTerminated(string $functionName) { if (!$this->isTerminated()) { - throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName)); + throw new LogicException(sprintf('Process must be terminated before calling "%s()".', $functionName)); } } /** * Escapes a string to be used as a shell argument. - * - * @param string $argument The argument that will be escaped - * - * @return string The escaped argument */ - private function escapeArgument($argument) + private function escapeArgument(?string $argument): string { + if ('' === $argument || null === $argument) { + return '""'; + } if ('\\' !== \DIRECTORY_SEPARATOR) { return "'".str_replace("'", "'\\''", $argument)."'"; } - if ('' === $argument = (string) $argument) { - return '""'; - } - if (false !== strpos($argument, "\0")) { + if (str_contains($argument, "\0")) { $argument = str_replace("\0", '?', $argument); } if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) { @@ -1727,25 +1628,25 @@ private function escapeArgument($argument) } $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument); - return '"'.str_replace(array('"', '^', '%', '!', "\n"), array('""', '"^^"', '"^%"', '"^!"', '!LF!'), $argument).'"'; + return '"'.str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument).'"'; } - private function getDefaultEnv() + private function replacePlaceholders(string $commandline, array $env) { - $env = array(); - - foreach ($_SERVER as $k => $v) { - if (\is_string($v) && false !== $v = getenv($k)) { - $env[$k] = $v; + return preg_replace_callback('/"\$\{:([_a-zA-Z]++[_a-zA-Z0-9]*+)\}"/', function ($matches) use ($commandline, $env) { + if (!isset($env[$matches[1]]) || false === $env[$matches[1]]) { + throw new InvalidArgumentException(sprintf('Command line is missing a value for parameter "%s": ', $matches[1]).$commandline); } - } - foreach ($_ENV as $k => $v) { - if (\is_string($v)) { - $env[$k] = $v; - } - } + return $this->escapeArgument($env[$matches[1]]); + }, $commandline); + } + + private function getDefaultEnv(): array + { + $env = getenv(); + $env = ('\\' === \DIRECTORY_SEPARATOR ? array_intersect_ukey($env, $_SERVER, 'strcasecmp') : array_intersect_key($env, $_SERVER)) ?: $env; - return $env; + return $_ENV + ('\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($env, $_ENV, 'strcasecmp') : $env); } } diff --git a/vendor/symfony/process/ProcessBuilder.php b/vendor/symfony/process/ProcessBuilder.php deleted file mode 100644 index 916ff44..0000000 --- a/vendor/symfony/process/ProcessBuilder.php +++ /dev/null @@ -1,280 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process; - -@trigger_error(sprintf('The %s class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the Process class instead.', ProcessBuilder::class), E_USER_DEPRECATED); - -use Symfony\Component\Process\Exception\InvalidArgumentException; -use Symfony\Component\Process\Exception\LogicException; - -/** - * @author Kris Wallsmith <kris@symfony.com> - * - * @deprecated since version 3.4, to be removed in 4.0. Use the Process class instead. - */ -class ProcessBuilder -{ - private $arguments; - private $cwd; - private $env = array(); - private $input; - private $timeout = 60; - private $options; - private $inheritEnv = true; - private $prefix = array(); - private $outputDisabled = false; - - /** - * @param string[] $arguments An array of arguments - */ - public function __construct(array $arguments = array()) - { - $this->arguments = $arguments; - } - - /** - * Creates a process builder instance. - * - * @param string[] $arguments An array of arguments - * - * @return static - */ - public static function create(array $arguments = array()) - { - return new static($arguments); - } - - /** - * Adds an unescaped argument to the command string. - * - * @param string $argument A command argument - * - * @return $this - */ - public function add($argument) - { - $this->arguments[] = $argument; - - return $this; - } - - /** - * Adds a prefix to the command string. - * - * The prefix is preserved when resetting arguments. - * - * @param string|array $prefix A command prefix or an array of command prefixes - * - * @return $this - */ - public function setPrefix($prefix) - { - $this->prefix = \is_array($prefix) ? $prefix : array($prefix); - - return $this; - } - - /** - * Sets the arguments of the process. - * - * Arguments must not be escaped. - * Previous arguments are removed. - * - * @param string[] $arguments - * - * @return $this - */ - public function setArguments(array $arguments) - { - $this->arguments = $arguments; - - return $this; - } - - /** - * Sets the working directory. - * - * @param null|string $cwd The working directory - * - * @return $this - */ - public function setWorkingDirectory($cwd) - { - $this->cwd = $cwd; - - return $this; - } - - /** - * Sets whether environment variables will be inherited or not. - * - * @param bool $inheritEnv - * - * @return $this - */ - public function inheritEnvironmentVariables($inheritEnv = true) - { - $this->inheritEnv = $inheritEnv; - - return $this; - } - - /** - * Sets an environment variable. - * - * Setting a variable overrides its previous value. Use `null` to unset a - * defined environment variable. - * - * @param string $name The variable name - * @param null|string $value The variable value - * - * @return $this - */ - public function setEnv($name, $value) - { - $this->env[$name] = $value; - - return $this; - } - - /** - * Adds a set of environment variables. - * - * Already existing environment variables with the same name will be - * overridden by the new values passed to this method. Pass `null` to unset - * a variable. - * - * @param array $variables The variables - * - * @return $this - */ - public function addEnvironmentVariables(array $variables) - { - $this->env = array_replace($this->env, $variables); - - return $this; - } - - /** - * Sets the input of the process. - * - * @param resource|string|int|float|bool|\Traversable|null $input The input content - * - * @return $this - * - * @throws InvalidArgumentException In case the argument is invalid - */ - public function setInput($input) - { - $this->input = ProcessUtils::validateInput(__METHOD__, $input); - - return $this; - } - - /** - * Sets the process timeout. - * - * To disable the timeout, set this value to null. - * - * @param float|null $timeout - * - * @return $this - * - * @throws InvalidArgumentException - */ - public function setTimeout($timeout) - { - if (null === $timeout) { - $this->timeout = null; - - return $this; - } - - $timeout = (float) $timeout; - - if ($timeout < 0) { - throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.'); - } - - $this->timeout = $timeout; - - return $this; - } - - /** - * Adds a proc_open option. - * - * @param string $name The option name - * @param string $value The option value - * - * @return $this - */ - public function setOption($name, $value) - { - $this->options[$name] = $value; - - return $this; - } - - /** - * Disables fetching output and error output from the underlying process. - * - * @return $this - */ - public function disableOutput() - { - $this->outputDisabled = true; - - return $this; - } - - /** - * Enables fetching output and error output from the underlying process. - * - * @return $this - */ - public function enableOutput() - { - $this->outputDisabled = false; - - return $this; - } - - /** - * Creates a Process instance and returns it. - * - * @return Process - * - * @throws LogicException In case no arguments have been provided - */ - public function getProcess() - { - if (0 === \count($this->prefix) && 0 === \count($this->arguments)) { - throw new LogicException('You must add() command arguments before calling getProcess().'); - } - - $arguments = array_merge($this->prefix, $this->arguments); - $process = new Process($arguments, $this->cwd, $this->env, $this->input, $this->timeout, $this->options); - // to preserve the BC with symfony <3.3, we convert the array structure - // to a string structure to avoid the prefixing with the exec command - $process->setCommandLine($process->getCommandLine()); - - if ($this->inheritEnv) { - $process->inheritEnvironmentVariables(); - } - if ($this->outputDisabled) { - $process->disableOutput(); - } - - return $process; - } -} diff --git a/vendor/symfony/process/ProcessUtils.php b/vendor/symfony/process/ProcessUtils.php index c06aa24..2a7aff7 100644 --- a/vendor/symfony/process/ProcessUtils.php +++ b/vendor/symfony/process/ProcessUtils.php @@ -29,66 +29,17 @@ private function __construct() { } - /** - * Escapes a string to be used as a shell argument. - * - * @param string $argument The argument that will be escaped - * - * @return string The escaped argument - * - * @deprecated since version 3.3, to be removed in 4.0. Use a command line array or give env vars to the `Process::start/run()` method instead. - */ - public static function escapeArgument($argument) - { - @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use a command line array or give env vars to the Process::start/run() method instead.', E_USER_DEPRECATED); - - //Fix for PHP bug #43784 escapeshellarg removes % from given string - //Fix for PHP bug #49446 escapeshellarg doesn't work on Windows - //@see https://bugs.php.net/bug.php?id=43784 - //@see https://bugs.php.net/bug.php?id=49446 - if ('\\' === \DIRECTORY_SEPARATOR) { - if ('' === $argument) { - return escapeshellarg($argument); - } - - $escapedArgument = ''; - $quote = false; - foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) { - if ('"' === $part) { - $escapedArgument .= '\\"'; - } elseif (self::isSurroundedBy($part, '%')) { - // Avoid environment variable expansion - $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%'; - } else { - // escape trailing backslash - if ('\\' === substr($part, -1)) { - $part .= '\\'; - } - $quote = true; - $escapedArgument .= $part; - } - } - if ($quote) { - $escapedArgument = '"'.$escapedArgument.'"'; - } - - return $escapedArgument; - } - - return "'".str_replace("'", "'\\''", $argument)."'"; - } - /** * Validates and normalizes a Process input. * * @param string $caller The name of method call that validates the input * @param mixed $input The input to validate * - * @return mixed The validated input + * @return mixed * * @throws InvalidArgumentException In case the input is not valid */ - public static function validateInput($caller, $input) + public static function validateInput(string $caller, $input) { if (null !== $input) { if (\is_resource($input)) { @@ -97,7 +48,7 @@ public static function validateInput($caller, $input) if (\is_string($input)) { return $input; } - if (is_scalar($input)) { + if (\is_scalar($input)) { return (string) $input; } if ($input instanceof Process) { @@ -110,14 +61,9 @@ public static function validateInput($caller, $input) return new \IteratorIterator($input); } - throw new InvalidArgumentException(sprintf('%s only accepts strings, Traversable objects or stream resources.', $caller)); + throw new InvalidArgumentException(sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller)); } return $input; } - - private static function isSurroundedBy($arg, $char) - { - return 2 < \strlen($arg) && $char === $arg[0] && $char === $arg[\strlen($arg) - 1]; - } } diff --git a/vendor/symfony/process/README.md b/vendor/symfony/process/README.md index b7ca5b4..8777de4 100644 --- a/vendor/symfony/process/README.md +++ b/vendor/symfony/process/README.md @@ -3,11 +3,26 @@ Process Component The Process component executes commands in sub-processes. +Sponsor +------- + +The Process component for Symfony 5.4/6.0 is [backed][1] by [SensioLabs][2]. + +As the creator of Symfony, SensioLabs supports companies using Symfony, with an +offering encompassing consultancy, expertise, services, training, and technical +assistance to ensure the success of web application development projects. + +Help Symfony by [sponsoring][3] its development! + Resources --------- - * [Documentation](https://symfony.com/doc/current/components/process.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) + * [Documentation](https://symfony.com/doc/current/components/process.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) + +[1]: https://symfony.com/backers +[2]: https://sensiolabs.com +[3]: https://symfony.com/sponsor diff --git a/vendor/symfony/process/Tests/ExecutableFinderTest.php b/vendor/symfony/process/Tests/ExecutableFinderTest.php deleted file mode 100644 index ee25eda..0000000 --- a/vendor/symfony/process/Tests/ExecutableFinderTest.php +++ /dev/null @@ -1,163 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Process\ExecutableFinder; - -/** - * @author Chris Smith <chris@cs278.org> - */ -class ExecutableFinderTest extends TestCase -{ - private $path; - - protected function tearDown() - { - if ($this->path) { - // Restore path if it was changed. - putenv('PATH='.$this->path); - } - } - - private function setPath($path) - { - $this->path = getenv('PATH'); - putenv('PATH='.$path); - } - - public function testFind() - { - if (ini_get('open_basedir')) { - $this->markTestSkipped('Cannot test when open_basedir is set'); - } - - $this->setPath(\dirname(PHP_BINARY)); - - $finder = new ExecutableFinder(); - $result = $finder->find($this->getPhpBinaryName()); - - $this->assertSamePath(PHP_BINARY, $result); - } - - public function testFindWithDefault() - { - if (ini_get('open_basedir')) { - $this->markTestSkipped('Cannot test when open_basedir is set'); - } - - $expected = 'defaultValue'; - - $this->setPath(''); - - $finder = new ExecutableFinder(); - $result = $finder->find('foo', $expected); - - $this->assertEquals($expected, $result); - } - - public function testFindWithExtraDirs() - { - if (ini_get('open_basedir')) { - $this->markTestSkipped('Cannot test when open_basedir is set'); - } - - $this->setPath(''); - - $extraDirs = array(\dirname(PHP_BINARY)); - - $finder = new ExecutableFinder(); - $result = $finder->find($this->getPhpBinaryName(), null, $extraDirs); - - $this->assertSamePath(PHP_BINARY, $result); - } - - public function testFindWithOpenBaseDir() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Cannot run test on windows'); - } - - if (ini_get('open_basedir')) { - $this->markTestSkipped('Cannot test when open_basedir is set'); - } - - $this->iniSet('open_basedir', \dirname(PHP_BINARY).(!\defined('HHVM_VERSION') || HHVM_VERSION_ID >= 30800 ? PATH_SEPARATOR.'/' : '')); - - $finder = new ExecutableFinder(); - $result = $finder->find($this->getPhpBinaryName()); - - $this->assertSamePath(PHP_BINARY, $result); - } - - public function testFindProcessInOpenBasedir() - { - if (ini_get('open_basedir')) { - $this->markTestSkipped('Cannot test when open_basedir is set'); - } - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Cannot run test on windows'); - } - - $this->setPath(''); - $this->iniSet('open_basedir', PHP_BINARY.(!\defined('HHVM_VERSION') || HHVM_VERSION_ID >= 30800 ? PATH_SEPARATOR.'/' : '')); - - $finder = new ExecutableFinder(); - $result = $finder->find($this->getPhpBinaryName(), false); - - $this->assertSamePath(PHP_BINARY, $result); - } - - /** - * @requires PHP 5.4 - */ - public function testFindBatchExecutableOnWindows() - { - if (ini_get('open_basedir')) { - $this->markTestSkipped('Cannot test when open_basedir is set'); - } - if ('\\' !== \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Can be only tested on windows'); - } - - $target = tempnam(sys_get_temp_dir(), 'example-windows-executable'); - - touch($target); - touch($target.'.BAT'); - - $this->assertFalse(is_executable($target)); - - $this->setPath(sys_get_temp_dir()); - - $finder = new ExecutableFinder(); - $result = $finder->find(basename($target), false); - - unlink($target); - unlink($target.'.BAT'); - - $this->assertSamePath($target.'.BAT', $result); - } - - private function assertSamePath($expected, $tested) - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->assertEquals(strtolower($expected), strtolower($tested)); - } else { - $this->assertEquals($expected, $tested); - } - } - - private function getPhpBinaryName() - { - return basename(PHP_BINARY, '\\' === \DIRECTORY_SEPARATOR ? '.exe' : ''); - } -} diff --git a/vendor/symfony/process/Tests/NonStopableProcess.php b/vendor/symfony/process/Tests/NonStopableProcess.php deleted file mode 100644 index 5643259..0000000 --- a/vendor/symfony/process/Tests/NonStopableProcess.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Runs a PHP script that can be stopped only with a SIGKILL (9) signal for 3 seconds. - * - * @args duration Run this script with a custom duration - * - * @example `php NonStopableProcess.php 42` will run the script for 42 seconds - */ -function handleSignal($signal) -{ - switch ($signal) { - case SIGTERM: - $name = 'SIGTERM'; - break; - case SIGINT: - $name = 'SIGINT'; - break; - default: - $name = $signal.' (unknown)'; - break; - } - - echo "signal $name\n"; -} - -pcntl_signal(SIGTERM, 'handleSignal'); -pcntl_signal(SIGINT, 'handleSignal'); - -echo 'received '; - -$duration = isset($argv[1]) ? (int) $argv[1] : 3; -$start = microtime(true); - -while ($duration > (microtime(true) - $start)) { - usleep(10000); - pcntl_signal_dispatch(); -} diff --git a/vendor/symfony/process/Tests/PhpExecutableFinderTest.php b/vendor/symfony/process/Tests/PhpExecutableFinderTest.php deleted file mode 100644 index 0c9e32d..0000000 --- a/vendor/symfony/process/Tests/PhpExecutableFinderTest.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Process\PhpExecutableFinder; - -/** - * @author Robert Schönthal <seroscho@googlemail.com> - */ -class PhpExecutableFinderTest extends TestCase -{ - /** - * tests find() with the constant PHP_BINARY. - */ - public function testFind() - { - if (\defined('HHVM_VERSION')) { - $this->markTestSkipped('Should not be executed in HHVM context.'); - } - - $f = new PhpExecutableFinder(); - - $current = PHP_BINARY; - $args = 'phpdbg' === \PHP_SAPI ? ' -qrr' : ''; - - $this->assertEquals($current.$args, $f->find(), '::find() returns the executable PHP'); - $this->assertEquals($current, $f->find(false), '::find() returns the executable PHP'); - } - - /** - * tests find() with the env var / constant PHP_BINARY with HHVM. - */ - public function testFindWithHHVM() - { - if (!\defined('HHVM_VERSION')) { - $this->markTestSkipped('Should be executed in HHVM context.'); - } - - $f = new PhpExecutableFinder(); - - $current = getenv('PHP_BINARY') ?: PHP_BINARY; - - $this->assertEquals($current.' --php', $f->find(), '::find() returns the executable PHP'); - $this->assertEquals($current, $f->find(false), '::find() returns the executable PHP'); - } - - /** - * tests find() with the env var PHP_PATH. - */ - public function testFindArguments() - { - $f = new PhpExecutableFinder(); - - if (\defined('HHVM_VERSION')) { - $this->assertEquals($f->findArguments(), array('--php'), '::findArguments() returns HHVM arguments'); - } elseif ('phpdbg' === \PHP_SAPI) { - $this->assertEquals($f->findArguments(), array('-qrr'), '::findArguments() returns phpdbg arguments'); - } else { - $this->assertEquals($f->findArguments(), array(), '::findArguments() returns no arguments'); - } - } -} diff --git a/vendor/symfony/process/Tests/PhpProcessTest.php b/vendor/symfony/process/Tests/PhpProcessTest.php deleted file mode 100644 index b0f0a57..0000000 --- a/vendor/symfony/process/Tests/PhpProcessTest.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Process\PhpProcess; - -class PhpProcessTest extends TestCase -{ - public function testNonBlockingWorks() - { - $expected = 'hello world!'; - $process = new PhpProcess(<<<PHP -<?php echo '$expected'; -PHP - ); - $process->start(); - $process->wait(); - $this->assertEquals($expected, $process->getOutput()); - } - - public function testCommandLine() - { - $process = new PhpProcess(<<<'PHP' -<?php echo phpversion().PHP_SAPI; -PHP - ); - - $commandLine = $process->getCommandLine(); - - $process->start(); - $this->assertContains($commandLine, $process->getCommandLine(), '::getCommandLine() returns the command line of PHP after start'); - - $process->wait(); - $this->assertContains($commandLine, $process->getCommandLine(), '::getCommandLine() returns the command line of PHP after wait'); - - $this->assertSame(PHP_VERSION.\PHP_SAPI, $process->getOutput()); - } -} diff --git a/vendor/symfony/process/Tests/PipeStdinInStdoutStdErrStreamSelect.php b/vendor/symfony/process/Tests/PipeStdinInStdoutStdErrStreamSelect.php deleted file mode 100644 index 1ea0e12..0000000 --- a/vendor/symfony/process/Tests/PipeStdinInStdoutStdErrStreamSelect.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -define('ERR_SELECT_FAILED', 1); -define('ERR_TIMEOUT', 2); -define('ERR_READ_FAILED', 3); -define('ERR_WRITE_FAILED', 4); - -$read = array(STDIN); -$write = array(STDOUT, STDERR); - -stream_set_blocking(STDIN, 0); -stream_set_blocking(STDOUT, 0); -stream_set_blocking(STDERR, 0); - -$out = $err = ''; -while ($read || $write) { - $r = $read; - $w = $write; - $e = null; - $n = stream_select($r, $w, $e, 5); - - if (false === $n) { - die(ERR_SELECT_FAILED); - } elseif ($n < 1) { - die(ERR_TIMEOUT); - } - - if (in_array(STDOUT, $w) && strlen($out) > 0) { - $written = fwrite(STDOUT, (string) $out, 32768); - if (false === $written) { - die(ERR_WRITE_FAILED); - } - $out = (string) substr($out, $written); - } - if (null === $read && '' === $out) { - $write = array_diff($write, array(STDOUT)); - } - - if (in_array(STDERR, $w) && strlen($err) > 0) { - $written = fwrite(STDERR, (string) $err, 32768); - if (false === $written) { - die(ERR_WRITE_FAILED); - } - $err = (string) substr($err, $written); - } - if (null === $read && '' === $err) { - $write = array_diff($write, array(STDERR)); - } - - if ($r) { - $str = fread(STDIN, 32768); - if (false !== $str) { - $out .= $str; - $err .= $str; - } - if (false === $str || feof(STDIN)) { - $read = null; - if (!feof(STDIN)) { - die(ERR_READ_FAILED); - } - } - } -} diff --git a/vendor/symfony/process/Tests/ProcessBuilderTest.php b/vendor/symfony/process/Tests/ProcessBuilderTest.php deleted file mode 100644 index c98b873..0000000 --- a/vendor/symfony/process/Tests/ProcessBuilderTest.php +++ /dev/null @@ -1,226 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Process\ProcessBuilder; - -/** - * @group legacy - */ -class ProcessBuilderTest extends TestCase -{ - public function testInheritEnvironmentVars() - { - $proc = ProcessBuilder::create() - ->add('foo') - ->getProcess(); - - $this->assertTrue($proc->areEnvironmentVariablesInherited()); - - $proc = ProcessBuilder::create() - ->add('foo') - ->inheritEnvironmentVariables(false) - ->getProcess(); - - $this->assertFalse($proc->areEnvironmentVariablesInherited()); - } - - public function testAddEnvironmentVariables() - { - $pb = new ProcessBuilder(); - $env = array( - 'foo' => 'bar', - 'foo2' => 'bar2', - ); - $proc = $pb - ->add('command') - ->setEnv('foo', 'bar2') - ->addEnvironmentVariables($env) - ->getProcess() - ; - - $this->assertSame($env, $proc->getEnv()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException - */ - public function testNegativeTimeoutFromSetter() - { - $pb = new ProcessBuilder(); - $pb->setTimeout(-1); - } - - public function testNullTimeout() - { - $pb = new ProcessBuilder(); - $pb->setTimeout(10); - $pb->setTimeout(null); - - $r = new \ReflectionObject($pb); - $p = $r->getProperty('timeout'); - $p->setAccessible(true); - - $this->assertNull($p->getValue($pb)); - } - - public function testShouldSetArguments() - { - $pb = new ProcessBuilder(array('initial')); - $pb->setArguments(array('second')); - - $proc = $pb->getProcess(); - - $this->assertContains('second', $proc->getCommandLine()); - } - - public function testPrefixIsPrependedToAllGeneratedProcess() - { - $pb = new ProcessBuilder(); - $pb->setPrefix('/usr/bin/php'); - - $proc = $pb->setArguments(array('-v'))->getProcess(); - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php" -v', $proc->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php' '-v'", $proc->getCommandLine()); - } - - $proc = $pb->setArguments(array('-i'))->getProcess(); - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php" -i', $proc->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php' '-i'", $proc->getCommandLine()); - } - } - - public function testArrayPrefixesArePrependedToAllGeneratedProcess() - { - $pb = new ProcessBuilder(); - $pb->setPrefix(array('/usr/bin/php', 'composer.phar')); - - $proc = $pb->setArguments(array('-v'))->getProcess(); - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php" composer.phar -v', $proc->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php' 'composer.phar' '-v'", $proc->getCommandLine()); - } - - $proc = $pb->setArguments(array('-i'))->getProcess(); - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php" composer.phar -i', $proc->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php' 'composer.phar' '-i'", $proc->getCommandLine()); - } - } - - public function testShouldEscapeArguments() - { - $pb = new ProcessBuilder(array('%path%', 'foo " bar', '%baz%baz')); - $proc = $pb->getProcess(); - - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->assertSame('""^%"path"^%"" "foo "" bar" ""^%"baz"^%"baz"', $proc->getCommandLine()); - } else { - $this->assertSame("'%path%' 'foo \" bar' '%baz%baz'", $proc->getCommandLine()); - } - } - - public function testShouldEscapeArgumentsAndPrefix() - { - $pb = new ProcessBuilder(array('arg')); - $pb->setPrefix('%prefix%'); - $proc = $pb->getProcess(); - - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->assertSame('""^%"prefix"^%"" arg', $proc->getCommandLine()); - } else { - $this->assertSame("'%prefix%' 'arg'", $proc->getCommandLine()); - } - } - - /** - * @expectedException \Symfony\Component\Process\Exception\LogicException - */ - public function testShouldThrowALogicExceptionIfNoPrefixAndNoArgument() - { - ProcessBuilder::create()->getProcess(); - } - - public function testShouldNotThrowALogicExceptionIfNoArgument() - { - $process = ProcessBuilder::create() - ->setPrefix('/usr/bin/php') - ->getProcess(); - - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php"', $process->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php'", $process->getCommandLine()); - } - } - - public function testShouldNotThrowALogicExceptionIfNoPrefix() - { - $process = ProcessBuilder::create(array('/usr/bin/php')) - ->getProcess(); - - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php"', $process->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php'", $process->getCommandLine()); - } - } - - public function testShouldReturnProcessWithDisabledOutput() - { - $process = ProcessBuilder::create(array('/usr/bin/php')) - ->disableOutput() - ->getProcess(); - - $this->assertTrue($process->isOutputDisabled()); - } - - public function testShouldReturnProcessWithEnabledOutput() - { - $process = ProcessBuilder::create(array('/usr/bin/php')) - ->disableOutput() - ->enableOutput() - ->getProcess(); - - $this->assertFalse($process->isOutputDisabled()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException - * @expectedExceptionMessage Symfony\Component\Process\ProcessBuilder::setInput only accepts strings, Traversable objects or stream resources. - */ - public function testInvalidInput() - { - $builder = ProcessBuilder::create(); - $builder->setInput(array()); - } - - public function testDoesNotPrefixExec() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test cannot run on Windows.'); - } - - $builder = ProcessBuilder::create(array('command', '-v', 'ls')); - $process = $builder->getProcess(); - $process->run(); - - $this->assertTrue($process->isSuccessful()); - } -} diff --git a/vendor/symfony/process/Tests/ProcessFailedExceptionTest.php b/vendor/symfony/process/Tests/ProcessFailedExceptionTest.php deleted file mode 100644 index 25712af..0000000 --- a/vendor/symfony/process/Tests/ProcessFailedExceptionTest.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Process\Exception\ProcessFailedException; - -/** - * @author Sebastian Marek <proofek@gmail.com> - */ -class ProcessFailedExceptionTest extends TestCase -{ - /** - * tests ProcessFailedException throws exception if the process was successful. - */ - public function testProcessFailedExceptionThrowsException() - { - $process = $this->getMockBuilder('Symfony\Component\Process\Process')->setMethods(array('isSuccessful'))->setConstructorArgs(array('php'))->getMock(); - $process->expects($this->once()) - ->method('isSuccessful') - ->will($this->returnValue(true)); - - if (method_exists($this, 'expectException')) { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Expected a failed process, but the given process was successful.'); - } else { - $this->setExpectedException(\InvalidArgumentException::class, 'Expected a failed process, but the given process was successful.'); - } - - new ProcessFailedException($process); - } - - /** - * tests ProcessFailedException uses information from process output - * to generate exception message. - */ - public function testProcessFailedExceptionPopulatesInformationFromProcessOutput() - { - $cmd = 'php'; - $exitCode = 1; - $exitText = 'General error'; - $output = 'Command output'; - $errorOutput = 'FATAL: Unexpected error'; - $workingDirectory = getcwd(); - - $process = $this->getMockBuilder('Symfony\Component\Process\Process')->setMethods(array('isSuccessful', 'getOutput', 'getErrorOutput', 'getExitCode', 'getExitCodeText', 'isOutputDisabled', 'getWorkingDirectory'))->setConstructorArgs(array($cmd))->getMock(); - $process->expects($this->once()) - ->method('isSuccessful') - ->will($this->returnValue(false)); - - $process->expects($this->once()) - ->method('getOutput') - ->will($this->returnValue($output)); - - $process->expects($this->once()) - ->method('getErrorOutput') - ->will($this->returnValue($errorOutput)); - - $process->expects($this->once()) - ->method('getExitCode') - ->will($this->returnValue($exitCode)); - - $process->expects($this->once()) - ->method('getExitCodeText') - ->will($this->returnValue($exitText)); - - $process->expects($this->once()) - ->method('isOutputDisabled') - ->will($this->returnValue(false)); - - $process->expects($this->once()) - ->method('getWorkingDirectory') - ->will($this->returnValue($workingDirectory)); - - $exception = new ProcessFailedException($process); - - $this->assertEquals( - "The command \"$cmd\" failed.\n\nExit Code: $exitCode($exitText)\n\nWorking directory: {$workingDirectory}\n\nOutput:\n================\n{$output}\n\nError Output:\n================\n{$errorOutput}", - $exception->getMessage() - ); - } - - /** - * Tests that ProcessFailedException does not extract information from - * process output if it was previously disabled. - */ - public function testDisabledOutputInFailedExceptionDoesNotPopulateOutput() - { - $cmd = 'php'; - $exitCode = 1; - $exitText = 'General error'; - $workingDirectory = getcwd(); - - $process = $this->getMockBuilder('Symfony\Component\Process\Process')->setMethods(array('isSuccessful', 'isOutputDisabled', 'getExitCode', 'getExitCodeText', 'getOutput', 'getErrorOutput', 'getWorkingDirectory'))->setConstructorArgs(array($cmd))->getMock(); - $process->expects($this->once()) - ->method('isSuccessful') - ->will($this->returnValue(false)); - - $process->expects($this->never()) - ->method('getOutput'); - - $process->expects($this->never()) - ->method('getErrorOutput'); - - $process->expects($this->once()) - ->method('getExitCode') - ->will($this->returnValue($exitCode)); - - $process->expects($this->once()) - ->method('getExitCodeText') - ->will($this->returnValue($exitText)); - - $process->expects($this->once()) - ->method('isOutputDisabled') - ->will($this->returnValue(true)); - - $process->expects($this->once()) - ->method('getWorkingDirectory') - ->will($this->returnValue($workingDirectory)); - - $exception = new ProcessFailedException($process); - - $this->assertEquals( - "The command \"$cmd\" failed.\n\nExit Code: $exitCode($exitText)\n\nWorking directory: {$workingDirectory}", - $exception->getMessage() - ); - } -} diff --git a/vendor/symfony/process/Tests/ProcessTest.php b/vendor/symfony/process/Tests/ProcessTest.php deleted file mode 100644 index 9174cac..0000000 --- a/vendor/symfony/process/Tests/ProcessTest.php +++ /dev/null @@ -1,1621 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Process\Exception\LogicException; -use Symfony\Component\Process\Exception\ProcessTimedOutException; -use Symfony\Component\Process\Exception\RuntimeException; -use Symfony\Component\Process\InputStream; -use Symfony\Component\Process\PhpExecutableFinder; -use Symfony\Component\Process\Pipes\PipesInterface; -use Symfony\Component\Process\Process; - -/** - * @author Robert Schönthal <seroscho@googlemail.com> - */ -class ProcessTest extends TestCase -{ - private static $phpBin; - private static $process; - private static $sigchild; - private static $notEnhancedSigchild = false; - - public static function setUpBeforeClass() - { - $phpBin = new PhpExecutableFinder(); - self::$phpBin = getenv('SYMFONY_PROCESS_PHP_TEST_BINARY') ?: ('phpdbg' === \PHP_SAPI ? 'php' : $phpBin->find()); - - ob_start(); - phpinfo(INFO_GENERAL); - self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild'); - } - - protected function tearDown() - { - if (self::$process) { - self::$process->stop(0); - self::$process = null; - } - } - - /** - * @group legacy - * @expectedDeprecation The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since Symfony 3.4 and will be removed in 4.0. - */ - public function testInvalidCwd() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('False-positive on Windows/appveyor.'); - } - - // Check that it works fine if the CWD exists - $cmd = new Process('echo test', __DIR__); - $cmd->run(); - - $cmd = new Process('echo test', __DIR__.'/notfound/'); - $cmd->run(); - } - - public function testThatProcessDoesNotThrowWarningDuringRun() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test is transient on Windows'); - } - @trigger_error('Test Error', E_USER_NOTICE); - $process = $this->getProcessForCode('sleep(3)'); - $process->run(); - $actualError = error_get_last(); - $this->assertEquals('Test Error', $actualError['message']); - $this->assertEquals(E_USER_NOTICE, $actualError['type']); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException - */ - public function testNegativeTimeoutFromConstructor() - { - $this->getProcess('', null, null, null, -1); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException - */ - public function testNegativeTimeoutFromSetter() - { - $p = $this->getProcess(''); - $p->setTimeout(-1); - } - - public function testFloatAndNullTimeout() - { - $p = $this->getProcess(''); - - $p->setTimeout(10); - $this->assertSame(10.0, $p->getTimeout()); - - $p->setTimeout(null); - $this->assertNull($p->getTimeout()); - - $p->setTimeout(0.0); - $this->assertNull($p->getTimeout()); - } - - /** - * @requires extension pcntl - */ - public function testStopWithTimeoutIsActuallyWorking() - { - $p = $this->getProcess(array(self::$phpBin, __DIR__.'/NonStopableProcess.php', 30)); - $p->start(); - - while (false === strpos($p->getOutput(), 'received')) { - usleep(1000); - } - $start = microtime(true); - $p->stop(0.1); - - $p->wait(); - - $this->assertLessThan(15, microtime(true) - $start); - } - - public function testAllOutputIsActuallyReadOnTermination() - { - // this code will result in a maximum of 2 reads of 8192 bytes by calling - // start() and isRunning(). by the time getOutput() is called the process - // has terminated so the internal pipes array is already empty. normally - // the call to start() will not read any data as the process will not have - // generated output, but this is non-deterministic so we must count it as - // a possibility. therefore we need 2 * PipesInterface::CHUNK_SIZE plus - // another byte which will never be read. - $expectedOutputSize = PipesInterface::CHUNK_SIZE * 2 + 2; - - $code = sprintf('echo str_repeat(\'*\', %d);', $expectedOutputSize); - $p = $this->getProcessForCode($code); - - $p->start(); - - // Don't call Process::run nor Process::wait to avoid any read of pipes - $h = new \ReflectionProperty($p, 'process'); - $h->setAccessible(true); - $h = $h->getValue($p); - $s = @proc_get_status($h); - - while (!empty($s['running'])) { - usleep(1000); - $s = proc_get_status($h); - } - - $o = $p->getOutput(); - - $this->assertEquals($expectedOutputSize, \strlen($o)); - } - - public function testCallbacksAreExecutedWithStart() - { - $process = $this->getProcess('echo foo'); - $process->start(function ($type, $buffer) use (&$data) { - $data .= $buffer; - }); - - $process->wait(); - - $this->assertSame('foo'.PHP_EOL, $data); - } - - /** - * tests results from sub processes. - * - * @dataProvider responsesCodeProvider - */ - public function testProcessResponses($expected, $getter, $code) - { - $p = $this->getProcessForCode($code); - $p->run(); - - $this->assertSame($expected, $p->$getter()); - } - - /** - * tests results from sub processes. - * - * @dataProvider pipesCodeProvider - */ - public function testProcessPipes($code, $size) - { - $expected = str_repeat(str_repeat('*', 1024), $size).'!'; - $expectedLength = (1024 * $size) + 1; - - $p = $this->getProcessForCode($code); - $p->setInput($expected); - $p->run(); - - $this->assertEquals($expectedLength, \strlen($p->getOutput())); - $this->assertEquals($expectedLength, \strlen($p->getErrorOutput())); - } - - /** - * @dataProvider pipesCodeProvider - */ - public function testSetStreamAsInput($code, $size) - { - $expected = str_repeat(str_repeat('*', 1024), $size).'!'; - $expectedLength = (1024 * $size) + 1; - - $stream = fopen('php://temporary', 'w+'); - fwrite($stream, $expected); - rewind($stream); - - $p = $this->getProcessForCode($code); - $p->setInput($stream); - $p->run(); - - fclose($stream); - - $this->assertEquals($expectedLength, \strlen($p->getOutput())); - $this->assertEquals($expectedLength, \strlen($p->getErrorOutput())); - } - - public function testLiveStreamAsInput() - { - $stream = fopen('php://memory', 'r+'); - fwrite($stream, 'hello'); - rewind($stream); - - $p = $this->getProcessForCode('stream_copy_to_stream(STDIN, STDOUT);'); - $p->setInput($stream); - $p->start(function ($type, $data) use ($stream) { - if ('hello' === $data) { - fclose($stream); - } - }); - $p->wait(); - - $this->assertSame('hello', $p->getOutput()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\LogicException - * @expectedExceptionMessage Input can not be set while the process is running. - */ - public function testSetInputWhileRunningThrowsAnException() - { - $process = $this->getProcessForCode('sleep(30);'); - $process->start(); - try { - $process->setInput('foobar'); - $process->stop(); - $this->fail('A LogicException should have been raised.'); - } catch (LogicException $e) { - } - $process->stop(); - - throw $e; - } - - /** - * @dataProvider provideInvalidInputValues - * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException - * @expectedExceptionMessage Symfony\Component\Process\Process::setInput only accepts strings, Traversable objects or stream resources. - */ - public function testInvalidInput($value) - { - $process = $this->getProcess('foo'); - $process->setInput($value); - } - - public function provideInvalidInputValues() - { - return array( - array(array()), - array(new NonStringifiable()), - ); - } - - /** - * @dataProvider provideInputValues - */ - public function testValidInput($expected, $value) - { - $process = $this->getProcess('foo'); - $process->setInput($value); - $this->assertSame($expected, $process->getInput()); - } - - public function provideInputValues() - { - return array( - array(null, null), - array('24.5', 24.5), - array('input data', 'input data'), - ); - } - - public function chainedCommandsOutputProvider() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - return array( - array("2 \r\n2\r\n", '&&', '2'), - ); - } - - return array( - array("1\n1\n", ';', '1'), - array("2\n2\n", '&&', '2'), - ); - } - - /** - * @dataProvider chainedCommandsOutputProvider - */ - public function testChainedCommandsOutput($expected, $operator, $input) - { - $process = $this->getProcess(sprintf('echo %s %s echo %s', $input, $operator, $input)); - $process->run(); - $this->assertEquals($expected, $process->getOutput()); - } - - public function testCallbackIsExecutedForOutput() - { - $p = $this->getProcessForCode('echo \'foo\';'); - - $called = false; - $p->run(function ($type, $buffer) use (&$called) { - $called = 'foo' === $buffer; - }); - - $this->assertTrue($called, 'The callback should be executed with the output'); - } - - public function testCallbackIsExecutedForOutputWheneverOutputIsDisabled() - { - $p = $this->getProcessForCode('echo \'foo\';'); - $p->disableOutput(); - - $called = false; - $p->run(function ($type, $buffer) use (&$called) { - $called = 'foo' === $buffer; - }); - - $this->assertTrue($called, 'The callback should be executed with the output'); - } - - public function testGetErrorOutput() - { - $p = $this->getProcessForCode('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }'); - - $p->run(); - $this->assertEquals(3, preg_match_all('/ERROR/', $p->getErrorOutput(), $matches)); - } - - public function testFlushErrorOutput() - { - $p = $this->getProcessForCode('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }'); - - $p->run(); - $p->clearErrorOutput(); - $this->assertEmpty($p->getErrorOutput()); - } - - /** - * @dataProvider provideIncrementalOutput - */ - public function testIncrementalOutput($getOutput, $getIncrementalOutput, $uri) - { - $lock = tempnam(sys_get_temp_dir(), __FUNCTION__); - - $p = $this->getProcessForCode('file_put_contents($s = \''.$uri.'\', \'foo\'); flock(fopen('.var_export($lock, true).', \'r\'), LOCK_EX); file_put_contents($s, \'bar\');'); - - $h = fopen($lock, 'w'); - flock($h, LOCK_EX); - - $p->start(); - - foreach (array('foo', 'bar') as $s) { - while (false === strpos($p->$getOutput(), $s)) { - usleep(1000); - } - - $this->assertSame($s, $p->$getIncrementalOutput()); - $this->assertSame('', $p->$getIncrementalOutput()); - - flock($h, LOCK_UN); - } - - fclose($h); - } - - public function provideIncrementalOutput() - { - return array( - array('getOutput', 'getIncrementalOutput', 'php://stdout'), - array('getErrorOutput', 'getIncrementalErrorOutput', 'php://stderr'), - ); - } - - public function testGetOutput() - { - $p = $this->getProcessForCode('$n = 0; while ($n < 3) { echo \' foo \'; $n++; }'); - - $p->run(); - $this->assertEquals(3, preg_match_all('/foo/', $p->getOutput(), $matches)); - } - - public function testFlushOutput() - { - $p = $this->getProcessForCode('$n=0;while ($n<3) {echo \' foo \';$n++;}'); - - $p->run(); - $p->clearOutput(); - $this->assertEmpty($p->getOutput()); - } - - public function testZeroAsOutput() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - // see http://stackoverflow.com/questions/7105433/windows-batch-echo-without-new-line - $p = $this->getProcess('echo | set /p dummyName=0'); - } else { - $p = $this->getProcess('printf 0'); - } - - $p->run(); - $this->assertSame('0', $p->getOutput()); - } - - public function testExitCodeCommandFailed() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Windows does not support POSIX exit code'); - } - $this->skipIfNotEnhancedSigchild(); - - // such command run in bash return an exitcode 127 - $process = $this->getProcess('nonexistingcommandIhopeneversomeonewouldnameacommandlikethis'); - $process->run(); - - $this->assertGreaterThan(0, $process->getExitCode()); - } - - /** - * @group tty - */ - public function testTTYCommand() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Windows does not have /dev/tty support'); - } - - $process = $this->getProcess('echo "foo" >> /dev/null && '.$this->getProcessForCode('usleep(100000);')->getCommandLine()); - $process->setTty(true); - $process->start(); - $this->assertTrue($process->isRunning()); - $process->wait(); - - $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus()); - } - - /** - * @group tty - */ - public function testTTYCommandExitCode() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Windows does have /dev/tty support'); - } - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess('echo "foo" >> /dev/null'); - $process->setTty(true); - $process->run(); - - $this->assertTrue($process->isSuccessful()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\RuntimeException - * @expectedExceptionMessage TTY mode is not supported on Windows platform. - */ - public function testTTYInWindowsEnvironment() - { - if ('\\' !== \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test is for Windows platform only'); - } - - $process = $this->getProcess('echo "foo" >> /dev/null'); - $process->setTty(false); - $process->setTty(true); - } - - public function testExitCodeTextIsNullWhenExitCodeIsNull() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess(''); - $this->assertNull($process->getExitCodeText()); - } - - public function testPTYCommand() - { - if (!Process::isPtySupported()) { - $this->markTestSkipped('PTY is not supported on this operating system.'); - } - - $process = $this->getProcess('echo "foo"'); - $process->setPty(true); - $process->run(); - - $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus()); - $this->assertEquals("foo\r\n", $process->getOutput()); - } - - public function testMustRun() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess('echo foo'); - - $this->assertSame($process, $process->mustRun()); - $this->assertEquals('foo'.PHP_EOL, $process->getOutput()); - } - - public function testSuccessfulMustRunHasCorrectExitCode() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess('echo foo')->mustRun(); - $this->assertEquals(0, $process->getExitCode()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\ProcessFailedException - */ - public function testMustRunThrowsException() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess('exit 1'); - $process->mustRun(); - } - - public function testExitCodeText() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess(''); - $r = new \ReflectionObject($process); - $p = $r->getProperty('exitcode'); - $p->setAccessible(true); - - $p->setValue($process, 2); - $this->assertEquals('Misuse of shell builtins', $process->getExitCodeText()); - } - - public function testStartIsNonBlocking() - { - $process = $this->getProcessForCode('usleep(500000);'); - $start = microtime(true); - $process->start(); - $end = microtime(true); - $this->assertLessThan(0.4, $end - $start); - $process->stop(); - } - - public function testUpdateStatus() - { - $process = $this->getProcess('echo foo'); - $process->run(); - $this->assertGreaterThan(0, \strlen($process->getOutput())); - } - - public function testGetExitCodeIsNullOnStart() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcessForCode('usleep(100000);'); - $this->assertNull($process->getExitCode()); - $process->start(); - $this->assertNull($process->getExitCode()); - $process->wait(); - $this->assertEquals(0, $process->getExitCode()); - } - - public function testGetExitCodeIsNullOnWhenStartingAgain() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcessForCode('usleep(100000);'); - $process->run(); - $this->assertEquals(0, $process->getExitCode()); - $process->start(); - $this->assertNull($process->getExitCode()); - $process->wait(); - $this->assertEquals(0, $process->getExitCode()); - } - - public function testGetExitCode() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess('echo foo'); - $process->run(); - $this->assertSame(0, $process->getExitCode()); - } - - public function testStatus() - { - $process = $this->getProcessForCode('usleep(100000);'); - $this->assertFalse($process->isRunning()); - $this->assertFalse($process->isStarted()); - $this->assertFalse($process->isTerminated()); - $this->assertSame(Process::STATUS_READY, $process->getStatus()); - $process->start(); - $this->assertTrue($process->isRunning()); - $this->assertTrue($process->isStarted()); - $this->assertFalse($process->isTerminated()); - $this->assertSame(Process::STATUS_STARTED, $process->getStatus()); - $process->wait(); - $this->assertFalse($process->isRunning()); - $this->assertTrue($process->isStarted()); - $this->assertTrue($process->isTerminated()); - $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus()); - } - - public function testStop() - { - $process = $this->getProcessForCode('sleep(31);'); - $process->start(); - $this->assertTrue($process->isRunning()); - $process->stop(); - $this->assertFalse($process->isRunning()); - } - - public function testIsSuccessful() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess('echo foo'); - $process->run(); - $this->assertTrue($process->isSuccessful()); - } - - public function testIsSuccessfulOnlyAfterTerminated() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcessForCode('usleep(100000);'); - $process->start(); - - $this->assertFalse($process->isSuccessful()); - - $process->wait(); - - $this->assertTrue($process->isSuccessful()); - } - - public function testIsNotSuccessful() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcessForCode('throw new \Exception(\'BOUM\');'); - $process->run(); - $this->assertFalse($process->isSuccessful()); - } - - public function testProcessIsNotSignaled() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Windows does not support POSIX signals'); - } - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess('echo foo'); - $process->run(); - $this->assertFalse($process->hasBeenSignaled()); - } - - public function testProcessWithoutTermSignal() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Windows does not support POSIX signals'); - } - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess('echo foo'); - $process->run(); - $this->assertEquals(0, $process->getTermSignal()); - } - - public function testProcessIsSignaledIfStopped() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Windows does not support POSIX signals'); - } - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcessForCode('sleep(32);'); - $process->start(); - $process->stop(); - $this->assertTrue($process->hasBeenSignaled()); - $this->assertEquals(15, $process->getTermSignal()); // SIGTERM - } - - /** - * @expectedException \Symfony\Component\Process\Exception\RuntimeException - * @expectedExceptionMessage The process has been signaled - */ - public function testProcessThrowsExceptionWhenExternallySignaled() - { - if (!\function_exists('posix_kill')) { - $this->markTestSkipped('Function posix_kill is required.'); - } - $this->skipIfNotEnhancedSigchild(false); - - $process = $this->getProcessForCode('sleep(32.1);'); - $process->start(); - posix_kill($process->getPid(), 9); // SIGKILL - - $process->wait(); - } - - public function testRestart() - { - $process1 = $this->getProcessForCode('echo getmypid();'); - $process1->run(); - $process2 = $process1->restart(); - - $process2->wait(); // wait for output - - // Ensure that both processed finished and the output is numeric - $this->assertFalse($process1->isRunning()); - $this->assertFalse($process2->isRunning()); - $this->assertInternalType('numeric', $process1->getOutput()); - $this->assertInternalType('numeric', $process2->getOutput()); - - // Ensure that restart returned a new process by check that the output is different - $this->assertNotEquals($process1->getOutput(), $process2->getOutput()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\ProcessTimedOutException - * @expectedExceptionMessage exceeded the timeout of 0.1 seconds. - */ - public function testRunProcessWithTimeout() - { - $process = $this->getProcessForCode('sleep(30);'); - $process->setTimeout(0.1); - $start = microtime(true); - try { - $process->run(); - $this->fail('A RuntimeException should have been raised'); - } catch (RuntimeException $e) { - } - - $this->assertLessThan(15, microtime(true) - $start); - - throw $e; - } - - /** - * @expectedException \Symfony\Component\Process\Exception\ProcessTimedOutException - * @expectedExceptionMessage exceeded the timeout of 0.1 seconds. - */ - public function testIterateOverProcessWithTimeout() - { - $process = $this->getProcessForCode('sleep(30);'); - $process->setTimeout(0.1); - $start = microtime(true); - try { - $process->start(); - foreach ($process as $buffer); - $this->fail('A RuntimeException should have been raised'); - } catch (RuntimeException $e) { - } - - $this->assertLessThan(15, microtime(true) - $start); - - throw $e; - } - - public function testCheckTimeoutOnNonStartedProcess() - { - $process = $this->getProcess('echo foo'); - $this->assertNull($process->checkTimeout()); - } - - public function testCheckTimeoutOnTerminatedProcess() - { - $process = $this->getProcess('echo foo'); - $process->run(); - $this->assertNull($process->checkTimeout()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\ProcessTimedOutException - * @expectedExceptionMessage exceeded the timeout of 0.1 seconds. - */ - public function testCheckTimeoutOnStartedProcess() - { - $process = $this->getProcessForCode('sleep(33);'); - $process->setTimeout(0.1); - - $process->start(); - $start = microtime(true); - - try { - while ($process->isRunning()) { - $process->checkTimeout(); - usleep(100000); - } - $this->fail('A ProcessTimedOutException should have been raised'); - } catch (ProcessTimedOutException $e) { - } - - $this->assertLessThan(15, microtime(true) - $start); - - throw $e; - } - - public function testIdleTimeout() - { - $process = $this->getProcessForCode('sleep(34);'); - $process->setTimeout(60); - $process->setIdleTimeout(0.1); - - try { - $process->run(); - - $this->fail('A timeout exception was expected.'); - } catch (ProcessTimedOutException $e) { - $this->assertTrue($e->isIdleTimeout()); - $this->assertFalse($e->isGeneralTimeout()); - $this->assertEquals(0.1, $e->getExceededTimeout()); - } - } - - public function testIdleTimeoutNotExceededWhenOutputIsSent() - { - $process = $this->getProcessForCode('while (true) {echo \'foo \'; usleep(1000);}'); - $process->setTimeout(1); - $process->start(); - - while (false === strpos($process->getOutput(), 'foo')) { - usleep(1000); - } - - $process->setIdleTimeout(0.5); - - try { - $process->wait(); - $this->fail('A timeout exception was expected.'); - } catch (ProcessTimedOutException $e) { - $this->assertTrue($e->isGeneralTimeout(), 'A general timeout is expected.'); - $this->assertFalse($e->isIdleTimeout(), 'No idle timeout is expected.'); - $this->assertEquals(1, $e->getExceededTimeout()); - } - } - - /** - * @expectedException \Symfony\Component\Process\Exception\ProcessTimedOutException - * @expectedExceptionMessage exceeded the timeout of 0.1 seconds. - */ - public function testStartAfterATimeout() - { - $process = $this->getProcessForCode('sleep(35);'); - $process->setTimeout(0.1); - - try { - $process->run(); - $this->fail('A ProcessTimedOutException should have been raised.'); - } catch (ProcessTimedOutException $e) { - } - $this->assertFalse($process->isRunning()); - $process->start(); - $this->assertTrue($process->isRunning()); - $process->stop(0); - - throw $e; - } - - public function testGetPid() - { - $process = $this->getProcessForCode('sleep(36);'); - $process->start(); - $this->assertGreaterThan(0, $process->getPid()); - $process->stop(0); - } - - public function testGetPidIsNullBeforeStart() - { - $process = $this->getProcess('foo'); - $this->assertNull($process->getPid()); - } - - public function testGetPidIsNullAfterRun() - { - $process = $this->getProcess('echo foo'); - $process->run(); - $this->assertNull($process->getPid()); - } - - /** - * @requires extension pcntl - */ - public function testSignal() - { - $process = $this->getProcess(array(self::$phpBin, __DIR__.'/SignalListener.php')); - $process->start(); - - while (false === strpos($process->getOutput(), 'Caught')) { - usleep(1000); - } - $process->signal(SIGUSR1); - $process->wait(); - - $this->assertEquals('Caught SIGUSR1', $process->getOutput()); - } - - /** - * @requires extension pcntl - */ - public function testExitCodeIsAvailableAfterSignal() - { - $this->skipIfNotEnhancedSigchild(); - - $process = $this->getProcess('sleep 4'); - $process->start(); - $process->signal(SIGKILL); - - while ($process->isRunning()) { - usleep(10000); - } - - $this->assertFalse($process->isRunning()); - $this->assertTrue($process->hasBeenSignaled()); - $this->assertFalse($process->isSuccessful()); - $this->assertEquals(137, $process->getExitCode()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\LogicException - * @expectedExceptionMessage Can not send signal on a non running process. - */ - public function testSignalProcessNotRunning() - { - $process = $this->getProcess('foo'); - $process->signal(1); // SIGHUP - } - - /** - * @dataProvider provideMethodsThatNeedARunningProcess - */ - public function testMethodsThatNeedARunningProcess($method) - { - $process = $this->getProcess('foo'); - - if (method_exists($this, 'expectException')) { - $this->expectException('Symfony\Component\Process\Exception\LogicException'); - $this->expectExceptionMessage(sprintf('Process must be started before calling %s.', $method)); - } else { - $this->setExpectedException('Symfony\Component\Process\Exception\LogicException', sprintf('Process must be started before calling %s.', $method)); - } - - $process->{$method}(); - } - - public function provideMethodsThatNeedARunningProcess() - { - return array( - array('getOutput'), - array('getIncrementalOutput'), - array('getErrorOutput'), - array('getIncrementalErrorOutput'), - array('wait'), - ); - } - - /** - * @dataProvider provideMethodsThatNeedATerminatedProcess - * @expectedException \Symfony\Component\Process\Exception\LogicException - * @expectedExceptionMessage Process must be terminated before calling - */ - public function testMethodsThatNeedATerminatedProcess($method) - { - $process = $this->getProcessForCode('sleep(37);'); - $process->start(); - try { - $process->{$method}(); - $process->stop(0); - $this->fail('A LogicException must have been thrown'); - } catch (\Exception $e) { - } - $process->stop(0); - - throw $e; - } - - public function provideMethodsThatNeedATerminatedProcess() - { - return array( - array('hasBeenSignaled'), - array('getTermSignal'), - array('hasBeenStopped'), - array('getStopSignal'), - ); - } - - /** - * @dataProvider provideWrongSignal - * @expectedException \Symfony\Component\Process\Exception\RuntimeException - */ - public function testWrongSignal($signal) - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('POSIX signals do not work on Windows'); - } - - $process = $this->getProcessForCode('sleep(38);'); - $process->start(); - try { - $process->signal($signal); - $this->fail('A RuntimeException must have been thrown'); - } catch (RuntimeException $e) { - $process->stop(0); - } - - throw $e; - } - - public function provideWrongSignal() - { - return array( - array(-4), - array('Céphalopodes'), - ); - } - - public function testDisableOutputDisablesTheOutput() - { - $p = $this->getProcess('foo'); - $this->assertFalse($p->isOutputDisabled()); - $p->disableOutput(); - $this->assertTrue($p->isOutputDisabled()); - $p->enableOutput(); - $this->assertFalse($p->isOutputDisabled()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\RuntimeException - * @expectedExceptionMessage Disabling output while the process is running is not possible. - */ - public function testDisableOutputWhileRunningThrowsException() - { - $p = $this->getProcessForCode('sleep(39);'); - $p->start(); - $p->disableOutput(); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\RuntimeException - * @expectedExceptionMessage Enabling output while the process is running is not possible. - */ - public function testEnableOutputWhileRunningThrowsException() - { - $p = $this->getProcessForCode('sleep(40);'); - $p->disableOutput(); - $p->start(); - $p->enableOutput(); - } - - public function testEnableOrDisableOutputAfterRunDoesNotThrowException() - { - $p = $this->getProcess('echo foo'); - $p->disableOutput(); - $p->run(); - $p->enableOutput(); - $p->disableOutput(); - $this->assertTrue($p->isOutputDisabled()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\LogicException - * @expectedExceptionMessage Output can not be disabled while an idle timeout is set. - */ - public function testDisableOutputWhileIdleTimeoutIsSet() - { - $process = $this->getProcess('foo'); - $process->setIdleTimeout(1); - $process->disableOutput(); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\LogicException - * @expectedExceptionMessage timeout can not be set while the output is disabled. - */ - public function testSetIdleTimeoutWhileOutputIsDisabled() - { - $process = $this->getProcess('foo'); - $process->disableOutput(); - $process->setIdleTimeout(1); - } - - public function testSetNullIdleTimeoutWhileOutputIsDisabled() - { - $process = $this->getProcess('foo'); - $process->disableOutput(); - $this->assertSame($process, $process->setIdleTimeout(null)); - } - - /** - * @dataProvider provideOutputFetchingMethods - * @expectedException \Symfony\Component\Process\Exception\LogicException - * @expectedExceptionMessage Output has been disabled. - */ - public function testGetOutputWhileDisabled($fetchMethod) - { - $p = $this->getProcessForCode('sleep(41);'); - $p->disableOutput(); - $p->start(); - $p->{$fetchMethod}(); - } - - public function provideOutputFetchingMethods() - { - return array( - array('getOutput'), - array('getIncrementalOutput'), - array('getErrorOutput'), - array('getIncrementalErrorOutput'), - ); - } - - public function testStopTerminatesProcessCleanly() - { - $process = $this->getProcessForCode('echo 123; sleep(42);'); - $process->run(function () use ($process) { - $process->stop(); - }); - $this->assertTrue(true, 'A call to stop() is not expected to cause wait() to throw a RuntimeException'); - } - - public function testKillSignalTerminatesProcessCleanly() - { - $process = $this->getProcessForCode('echo 123; sleep(43);'); - $process->run(function () use ($process) { - $process->signal(9); // SIGKILL - }); - $this->assertTrue(true, 'A call to signal() is not expected to cause wait() to throw a RuntimeException'); - } - - public function testTermSignalTerminatesProcessCleanly() - { - $process = $this->getProcessForCode('echo 123; sleep(44);'); - $process->run(function () use ($process) { - $process->signal(15); // SIGTERM - }); - $this->assertTrue(true, 'A call to signal() is not expected to cause wait() to throw a RuntimeException'); - } - - public function responsesCodeProvider() - { - return array( - //expected output / getter / code to execute - //array(1,'getExitCode','exit(1);'), - //array(true,'isSuccessful','exit();'), - array('output', 'getOutput', 'echo \'output\';'), - ); - } - - public function pipesCodeProvider() - { - $variations = array( - 'fwrite(STDOUT, $in = file_get_contents(\'php://stdin\')); fwrite(STDERR, $in);', - 'include \''.__DIR__.'/PipeStdinInStdoutStdErrStreamSelect.php\';', - ); - - if ('\\' === \DIRECTORY_SEPARATOR) { - // Avoid XL buffers on Windows because of https://bugs.php.net/bug.php?id=65650 - $sizes = array(1, 2, 4, 8); - } else { - $sizes = array(1, 16, 64, 1024, 4096); - } - - $codes = array(); - foreach ($sizes as $size) { - foreach ($variations as $code) { - $codes[] = array($code, $size); - } - } - - return $codes; - } - - /** - * @dataProvider provideVariousIncrementals - */ - public function testIncrementalOutputDoesNotRequireAnotherCall($stream, $method) - { - $process = $this->getProcessForCode('$n = 0; while ($n < 3) { file_put_contents(\''.$stream.'\', $n, 1); $n++; usleep(1000); }', null, null, null, null); - $process->start(); - $result = ''; - $limit = microtime(true) + 3; - $expected = '012'; - - while ($result !== $expected && microtime(true) < $limit) { - $result .= $process->$method(); - } - - $this->assertSame($expected, $result); - $process->stop(); - } - - public function provideVariousIncrementals() - { - return array( - array('php://stdout', 'getIncrementalOutput'), - array('php://stderr', 'getIncrementalErrorOutput'), - ); - } - - public function testIteratorInput() - { - $input = function () { - yield 'ping'; - yield 'pong'; - }; - - $process = $this->getProcessForCode('stream_copy_to_stream(STDIN, STDOUT);', null, null, $input()); - $process->run(); - $this->assertSame('pingpong', $process->getOutput()); - } - - public function testSimpleInputStream() - { - $input = new InputStream(); - - $process = $this->getProcessForCode('echo \'ping\'; echo fread(STDIN, 4); echo fread(STDIN, 4);'); - $process->setInput($input); - - $process->start(function ($type, $data) use ($input) { - if ('ping' === $data) { - $input->write('pang'); - } elseif (!$input->isClosed()) { - $input->write('pong'); - $input->close(); - } - }); - - $process->wait(); - $this->assertSame('pingpangpong', $process->getOutput()); - } - - public function testInputStreamWithCallable() - { - $i = 0; - $stream = fopen('php://memory', 'w+'); - $stream = function () use ($stream, &$i) { - if ($i < 3) { - rewind($stream); - fwrite($stream, ++$i); - rewind($stream); - - return $stream; - } - }; - - $input = new InputStream(); - $input->onEmpty($stream); - $input->write($stream()); - - $process = $this->getProcessForCode('echo fread(STDIN, 3);'); - $process->setInput($input); - $process->start(function ($type, $data) use ($input) { - $input->close(); - }); - - $process->wait(); - $this->assertSame('123', $process->getOutput()); - } - - public function testInputStreamWithGenerator() - { - $input = new InputStream(); - $input->onEmpty(function ($input) { - yield 'pong'; - $input->close(); - }); - - $process = $this->getProcessForCode('stream_copy_to_stream(STDIN, STDOUT);'); - $process->setInput($input); - $process->start(); - $input->write('ping'); - $process->wait(); - $this->assertSame('pingpong', $process->getOutput()); - } - - public function testInputStreamOnEmpty() - { - $i = 0; - $input = new InputStream(); - $input->onEmpty(function () use (&$i) { ++$i; }); - - $process = $this->getProcessForCode('echo 123; echo fread(STDIN, 1); echo 456;'); - $process->setInput($input); - $process->start(function ($type, $data) use ($input) { - if ('123' === $data) { - $input->close(); - } - }); - $process->wait(); - - $this->assertSame(0, $i, 'InputStream->onEmpty callback should be called only when the input *becomes* empty'); - $this->assertSame('123456', $process->getOutput()); - } - - public function testIteratorOutput() - { - $input = new InputStream(); - - $process = $this->getProcessForCode('fwrite(STDOUT, 123); fwrite(STDERR, 234); flush(); usleep(10000); fwrite(STDOUT, fread(STDIN, 3)); fwrite(STDERR, 456);'); - $process->setInput($input); - $process->start(); - $output = array(); - - foreach ($process as $type => $data) { - $output[] = array($type, $data); - break; - } - $expectedOutput = array( - array($process::OUT, '123'), - ); - $this->assertSame($expectedOutput, $output); - - $input->write(345); - - foreach ($process as $type => $data) { - $output[] = array($type, $data); - } - - $this->assertSame('', $process->getOutput()); - $this->assertFalse($process->isRunning()); - - $expectedOutput = array( - array($process::OUT, '123'), - array($process::ERR, '234'), - array($process::OUT, '345'), - array($process::ERR, '456'), - ); - $this->assertSame($expectedOutput, $output); - } - - public function testNonBlockingNorClearingIteratorOutput() - { - $input = new InputStream(); - - $process = $this->getProcessForCode('fwrite(STDOUT, fread(STDIN, 3));'); - $process->setInput($input); - $process->start(); - $output = array(); - - foreach ($process->getIterator($process::ITER_NON_BLOCKING | $process::ITER_KEEP_OUTPUT) as $type => $data) { - $output[] = array($type, $data); - break; - } - $expectedOutput = array( - array($process::OUT, ''), - ); - $this->assertSame($expectedOutput, $output); - - $input->write(123); - - foreach ($process->getIterator($process::ITER_NON_BLOCKING | $process::ITER_KEEP_OUTPUT) as $type => $data) { - if ('' !== $data) { - $output[] = array($type, $data); - } - } - - $this->assertSame('123', $process->getOutput()); - $this->assertFalse($process->isRunning()); - - $expectedOutput = array( - array($process::OUT, ''), - array($process::OUT, '123'), - ); - $this->assertSame($expectedOutput, $output); - } - - public function testChainedProcesses() - { - $p1 = $this->getProcessForCode('fwrite(STDERR, 123); fwrite(STDOUT, 456);'); - $p2 = $this->getProcessForCode('stream_copy_to_stream(STDIN, STDOUT);'); - $p2->setInput($p1); - - $p1->start(); - $p2->run(); - - $this->assertSame('123', $p1->getErrorOutput()); - $this->assertSame('', $p1->getOutput()); - $this->assertSame('', $p2->getErrorOutput()); - $this->assertSame('456', $p2->getOutput()); - } - - public function testSetBadEnv() - { - $process = $this->getProcess('echo hello'); - $process->setEnv(array('bad%%' => '123')); - $process->inheritEnvironmentVariables(true); - - $process->run(); - - $this->assertSame('hello'.PHP_EOL, $process->getOutput()); - $this->assertSame('', $process->getErrorOutput()); - } - - public function testEnvBackupDoesNotDeleteExistingVars() - { - putenv('existing_var=foo'); - $_ENV['existing_var'] = 'foo'; - $process = $this->getProcess('php -r "echo getenv(\'new_test_var\');"'); - $process->setEnv(array('existing_var' => 'bar', 'new_test_var' => 'foo')); - $process->inheritEnvironmentVariables(); - - $process->run(); - - $this->assertSame('foo', $process->getOutput()); - $this->assertSame('foo', getenv('existing_var')); - $this->assertFalse(getenv('new_test_var')); - - putenv('existing_var'); - unset($_ENV['existing_var']); - } - - public function testEnvIsInherited() - { - $process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ', 'EMPTY' => '')); - - putenv('FOO=BAR'); - $_ENV['FOO'] = 'BAR'; - - $process->run(); - - $expected = array('BAR' => 'BAZ', 'EMPTY' => '', 'FOO' => 'BAR'); - $env = array_intersect_key(unserialize($process->getOutput()), $expected); - - $this->assertEquals($expected, $env); - - putenv('FOO'); - unset($_ENV['FOO']); - } - - /** - * @group legacy - */ - public function testInheritEnvDisabled() - { - $process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ')); - - putenv('FOO=BAR'); - $_ENV['FOO'] = 'BAR'; - - $this->assertSame($process, $process->inheritEnvironmentVariables(false)); - $this->assertFalse($process->areEnvironmentVariablesInherited()); - - $process->run(); - - $expected = array('BAR' => 'BAZ', 'FOO' => 'BAR'); - $env = array_intersect_key(unserialize($process->getOutput()), $expected); - unset($expected['FOO']); - - $this->assertSame($expected, $env); - - putenv('FOO'); - unset($_ENV['FOO']); - } - - public function testGetCommandLine() - { - $p = new Process(array('/usr/bin/php')); - - $expected = '\\' === \DIRECTORY_SEPARATOR ? '"/usr/bin/php"' : "'/usr/bin/php'"; - $this->assertSame($expected, $p->getCommandLine()); - } - - /** - * @dataProvider provideEscapeArgument - */ - public function testEscapeArgument($arg) - { - $p = new Process(array(self::$phpBin, '-r', 'echo $argv[1];', $arg)); - $p->run(); - - $this->assertSame($arg, $p->getOutput()); - } - - /** - * @dataProvider provideEscapeArgument - * @group legacy - */ - public function testEscapeArgumentWhenInheritEnvDisabled($arg) - { - $p = new Process(array(self::$phpBin, '-r', 'echo $argv[1];', $arg), null, array('BAR' => 'BAZ')); - $p->inheritEnvironmentVariables(false); - $p->run(); - - $this->assertSame($arg, $p->getOutput()); - } - - public function testRawCommandLine() - { - $p = new Process(sprintf('"%s" -r %s "a" "" "b"', self::$phpBin, escapeshellarg('print_r($argv);'))); - $p->run(); - - $expected = <<<EOTXT -Array -( - [0] => - - [1] => a - [2] => - [3] => b -) - -EOTXT; - $this->assertSame($expected, str_replace('Standard input code', '-', $p->getOutput())); - } - - public function provideEscapeArgument() - { - yield array('a"b%c%'); - yield array('a"b^c^'); - yield array("a\nb'c"); - yield array('a^b c!'); - yield array("a!b\tc"); - yield array('a\\\\"\\"'); - yield array('éÉèÈàÀöä'); - } - - public function testEnvArgument() - { - $env = array('FOO' => 'Foo', 'BAR' => 'Bar'); - $cmd = '\\' === \DIRECTORY_SEPARATOR ? 'echo !FOO! !BAR! !BAZ!' : 'echo $FOO $BAR $BAZ'; - $p = new Process($cmd, null, $env); - $p->run(null, array('BAR' => 'baR', 'BAZ' => 'baZ')); - - $this->assertSame('Foo baR baZ', rtrim($p->getOutput())); - $this->assertSame($env, $p->getEnv()); - } - - /** - * @param string $commandline - * @param null|string $cwd - * @param null|array $env - * @param null|string $input - * @param int $timeout - * @param array $options - * - * @return Process - */ - private function getProcess($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60) - { - $process = new Process($commandline, $cwd, $env, $input, $timeout); - $process->inheritEnvironmentVariables(); - - if (false !== $enhance = getenv('ENHANCE_SIGCHLD')) { - try { - $process->setEnhanceSigchildCompatibility(false); - $process->getExitCode(); - $this->fail('ENHANCE_SIGCHLD must be used together with a sigchild-enabled PHP.'); - } catch (RuntimeException $e) { - $this->assertSame('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.', $e->getMessage()); - if ($enhance) { - $process->setEnhanceSigchildCompatibility(true); - } else { - self::$notEnhancedSigchild = true; - } - } - } - - if (self::$process) { - self::$process->stop(0); - } - - return self::$process = $process; - } - - /** - * @return Process - */ - private function getProcessForCode($code, $cwd = null, array $env = null, $input = null, $timeout = 60) - { - return $this->getProcess(array(self::$phpBin, '-r', $code), $cwd, $env, $input, $timeout); - } - - private function skipIfNotEnhancedSigchild($expectException = true) - { - if (self::$sigchild) { - if (!$expectException) { - $this->markTestSkipped('PHP is compiled with --enable-sigchild.'); - } elseif (self::$notEnhancedSigchild) { - if (method_exists($this, 'expectException')) { - $this->expectException('Symfony\Component\Process\Exception\RuntimeException'); - $this->expectExceptionMessage('This PHP has been compiled with --enable-sigchild.'); - } else { - $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild.'); - } - } - } - } -} - -class NonStringifiable -{ -} diff --git a/vendor/symfony/process/Tests/ProcessUtilsTest.php b/vendor/symfony/process/Tests/ProcessUtilsTest.php deleted file mode 100644 index 0a3ccb5..0000000 --- a/vendor/symfony/process/Tests/ProcessUtilsTest.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Process\ProcessUtils; - -/** - * @group legacy - */ -class ProcessUtilsTest extends TestCase -{ - /** - * @dataProvider dataArguments - */ - public function testEscapeArgument($result, $argument) - { - $this->assertSame($result, ProcessUtils::escapeArgument($argument)); - } - - public function dataArguments() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - return array( - array('"\"php\" \"-v\""', '"php" "-v"'), - array('"foo bar"', 'foo bar'), - array('^%"path"^%', '%path%'), - array('"<|>\\" \\"\'f"', '<|>" "\'f'), - array('""', ''), - array('"with\trailingbs\\\\"', 'with\trailingbs\\'), - ); - } - - return array( - array("'\"php\" \"-v\"'", '"php" "-v"'), - array("'foo bar'", 'foo bar'), - array("'%path%'", '%path%'), - array("'<|>\" \"'\\''f'", '<|>" "\'f'), - array("''", ''), - array("'with\\trailingbs\\'", 'with\trailingbs\\'), - array("'withNonAsciiAccentLikeéÉèÈàÀöä'", 'withNonAsciiAccentLikeéÉèÈàÀöä'), - ); - } -} diff --git a/vendor/symfony/process/composer.json b/vendor/symfony/process/composer.json index b8867db..1669eba 100644 --- a/vendor/symfony/process/composer.json +++ b/vendor/symfony/process/composer.json @@ -1,7 +1,7 @@ { "name": "symfony/process", "type": "library", - "description": "Symfony Process Component", + "description": "Executes commands in sub-processes", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", @@ -16,7 +16,8 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" }, "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" }, @@ -24,10 +25,5 @@ "/Tests/" ] }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - } + "minimum-stability": "dev" } diff --git a/vendor/symfony/process/phpunit.xml.dist b/vendor/symfony/process/phpunit.xml.dist deleted file mode 100644 index d388467..0000000 --- a/vendor/symfony/process/phpunit.xml.dist +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" - backupGlobals="false" - colors="true" - bootstrap="vendor/autoload.php" - failOnRisky="true" - failOnWarning="true" -> - <php> - <ini name="error_reporting" value="-1" /> - </php> - - <testsuites> - <testsuite name="Symfony Process Component Test Suite"> - <directory>./Tests/</directory> - </testsuite> - </testsuites> - - <filter> - <whitelist> - <directory>./</directory> - <exclude> - <directory>./Tests</directory> - <directory>./vendor</directory> - </exclude> - </whitelist> - </filter> -</phpunit> diff --git a/vendor/symfony/event-dispatcher/.gitignore b/vendor/symfony/service-contracts/.gitignore similarity index 100% rename from vendor/symfony/event-dispatcher/.gitignore rename to vendor/symfony/service-contracts/.gitignore diff --git a/vendor/symfony/service-contracts/Attribute/Required.php b/vendor/symfony/service-contracts/Attribute/Required.php new file mode 100644 index 0000000..9df8511 --- /dev/null +++ b/vendor/symfony/service-contracts/Attribute/Required.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service\Attribute; + +/** + * A required dependency. + * + * This attribute indicates that a property holds a required dependency. The annotated property or method should be + * considered during the instantiation process of the containing class. + * + * @author Alexander M. Turek <me@derrabus.de> + */ +#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] +final class Required +{ +} diff --git a/vendor/symfony/service-contracts/Attribute/SubscribedService.php b/vendor/symfony/service-contracts/Attribute/SubscribedService.php new file mode 100644 index 0000000..10d1bc3 --- /dev/null +++ b/vendor/symfony/service-contracts/Attribute/SubscribedService.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service\Attribute; + +use Symfony\Contracts\Service\ServiceSubscriberTrait; + +/** + * Use with {@see ServiceSubscriberTrait} to mark a method's return type + * as a subscribed service. + * + * @author Kevin Bond <kevinbond@gmail.com> + */ +#[\Attribute(\Attribute::TARGET_METHOD)] +final class SubscribedService +{ + /** + * @param string|null $key The key to use for the service + * If null, use "ClassName::methodName" + */ + public function __construct( + public ?string $key = null + ) { + } +} diff --git a/vendor/symfony/service-contracts/CHANGELOG.md b/vendor/symfony/service-contracts/CHANGELOG.md new file mode 100644 index 0000000..7932e26 --- /dev/null +++ b/vendor/symfony/service-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/main/CHANGELOG.md diff --git a/vendor/symfony/service-contracts/LICENSE b/vendor/symfony/service-contracts/LICENSE new file mode 100644 index 0000000..74cdc2d --- /dev/null +++ b/vendor/symfony/service-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-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 +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/vendor/symfony/service-contracts/README.md b/vendor/symfony/service-contracts/README.md new file mode 100644 index 0000000..41e054a --- /dev/null +++ b/vendor/symfony/service-contracts/README.md @@ -0,0 +1,9 @@ +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 +that already have battle tested implementations. + +See https://github.com/symfony/contracts/blob/main/README.md for more information. diff --git a/vendor/symfony/service-contracts/ResetInterface.php b/vendor/symfony/service-contracts/ResetInterface.php new file mode 100644 index 0000000..1af1075 --- /dev/null +++ b/vendor/symfony/service-contracts/ResetInterface.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +/** + * Provides a way to reset an object to its initial state. + * + * When calling the "reset()" method on an object, it should be put back to its + * initial state. This usually means clearing any internal buffers and forwarding + * the call to internal dependencies. All properties of the object should be put + * back to the same state it had when it was first ready to use. + * + * This method could be called, for example, to recycle objects that are used as + * services, so that they can be used to handle several requests in the same + * process loop (note that we advise making your services stateless instead of + * implementing this interface when possible.) + */ +interface ResetInterface +{ + public function reset(); +} diff --git a/vendor/symfony/service-contracts/ServiceLocatorTrait.php b/vendor/symfony/service-contracts/ServiceLocatorTrait.php new file mode 100644 index 0000000..74dfa43 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceLocatorTrait.php @@ -0,0 +1,128 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(ContainerExceptionInterface::class); +class_exists(NotFoundExceptionInterface::class); + +/** + * A trait to help implement ServiceProviderInterface. + * + * @author Robin Chalas <robin.chalas@gmail.com> + * @author Nicolas Grekas <p@tchwork.com> + */ +trait ServiceLocatorTrait +{ + private $factories; + private $loading = []; + private $providedTypes; + + /** + * @param callable[] $factories + */ + public function __construct(array $factories) + { + $this->factories = $factories; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function has(string $id) + { + return isset($this->factories[$id]); + } + + /** + * {@inheritdoc} + * + * @return mixed + */ + public function get(string $id) + { + if (!isset($this->factories[$id])) { + throw $this->createNotFoundException($id); + } + + if (isset($this->loading[$id])) { + $ids = array_values($this->loading); + $ids = \array_slice($this->loading, array_search($id, $ids)); + $ids[] = $id; + + throw $this->createCircularReferenceException($id, $ids); + } + + $this->loading[$id] = $id; + try { + return $this->factories[$id]($this); + } finally { + unset($this->loading[$id]); + } + } + + /** + * {@inheritdoc} + */ + public function getProvidedServices(): array + { + if (null === $this->providedTypes) { + $this->providedTypes = []; + + foreach ($this->factories as $name => $factory) { + if (!\is_callable($factory)) { + $this->providedTypes[$name] = '?'; + } else { + $type = (new \ReflectionFunction($factory))->getReturnType(); + + $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '').($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?'; + } + } + } + + return $this->providedTypes; + } + + private function createNotFoundException(string $id): NotFoundExceptionInterface + { + if (!$alternatives = array_keys($this->factories)) { + $message = 'is empty...'; + } else { + $last = array_pop($alternatives); + if ($alternatives) { + $message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last); + } else { + $message = sprintf('only knows about the "%s" service.', $last); + } + } + + if ($this->loading) { + $message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message); + } else { + $message = sprintf('Service "%s" not found: the current service locator %s', $id, $message); + } + + return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface { + }; + } + + private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface + { + return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface { + }; + } +} diff --git a/vendor/symfony/service-contracts/ServiceProviderInterface.php b/vendor/symfony/service-contracts/ServiceProviderInterface.php new file mode 100644 index 0000000..c60ad0b --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceProviderInterface.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Psr\Container\ContainerInterface; + +/** + * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container. + * + * @author Nicolas Grekas <p@tchwork.com> + * @author Mateusz Sip <mateusz.sip@gmail.com> + */ +interface ServiceProviderInterface extends ContainerInterface +{ + /** + * Returns an associative array of service types keyed by the identifiers provided by the current container. + * + * Examples: + * + * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface + * * ['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 string[] The provided service types, keyed by service names + */ + public function getProvidedServices(): array; +} diff --git a/vendor/symfony/service-contracts/ServiceSubscriberInterface.php b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php new file mode 100644 index 0000000..098ab90 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php @@ -0,0 +1,53 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +/** + * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. + * + * The getSubscribedServices method returns an array of service types required by such instances, + * optionally keyed by the service names used internally. Service types that start with an interrogation + * mark "?" are optional, while the other ones are mandatory service dependencies. + * + * The injected service locators SHOULD NOT allow access to any other services not specified by the method. + * + * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally. + * This interface does not dictate any injection method for these service locators, although constructor + * injection is recommended. + * + * @author Nicolas Grekas <p@tchwork.com> + */ +interface ServiceSubscriberInterface +{ + /** + * Returns an array of service types required by such instances, optionally keyed by the service names used internally. + * + * For mandatory dependencies: + * + * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name + * internally to fetch a service which must implement Psr\Log\LoggerInterface. + * * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name + * internally to fetch an iterable of Psr\Log\LoggerInterface instances. + * * ['Psr\Log\LoggerInterface'] is a shortcut for + * * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface'] + * + * otherwise: + * + * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency + * * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency + * * ['?Psr\Log\LoggerInterface'] is a shortcut for + * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] + * + * @return string[] The required service types, optionally keyed by service names + */ + public static function getSubscribedServices(); +} diff --git a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php new file mode 100644 index 0000000..16e3eb2 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php @@ -0,0 +1,109 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\Attribute\SubscribedService; + +/** + * Implementation of ServiceSubscriberInterface that determines subscribed services from + * method return types. Service ids are available as "ClassName::methodName". + * + * @author Kevin Bond <kevinbond@gmail.com> + */ +trait ServiceSubscriberTrait +{ + /** @var ContainerInterface */ + protected $container; + + /** + * {@inheritdoc} + */ + public static function getSubscribedServices(): array + { + $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : []; + $attributeOptIn = false; + + 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)); + } + + $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; + } + + if ($returnType->isBuiltin()) { + continue; + } + + 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 + * + * @return ContainerInterface|null + */ + public function setContainer(ContainerInterface $container) + { + $this->container = $container; + + if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) { + return parent::setContainer($container); + } + + return null; + } +} diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php new file mode 100644 index 0000000..2a1b565 --- /dev/null +++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php @@ -0,0 +1,95 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service\Test; + +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\ServiceLocatorTrait; + +abstract class ServiceLocatorTest extends TestCase +{ + /** + * @return ContainerInterface + */ + 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/vendor/symfony/service-contracts/composer.json b/vendor/symfony/service-contracts/composer.json new file mode 100644 index 0000000..f058637 --- /dev/null +++ b/vendor/symfony/service-contracts/composer.json @@ -0,0 +1,42 @@ +{ + "name": "symfony/service-contracts", + "type": "library", + "description": "Generic abstractions related to writing services", + "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\Service\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/vendor/symfony/stopwatch/.gitignore b/vendor/symfony/stopwatch/.gitignore deleted file mode 100644 index c49a5d8..0000000 --- a/vendor/symfony/stopwatch/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/vendor/symfony/stopwatch/CHANGELOG.md b/vendor/symfony/stopwatch/CHANGELOG.md index 36d0c25..f2fd7d0 100644 --- a/vendor/symfony/stopwatch/CHANGELOG.md +++ b/vendor/symfony/stopwatch/CHANGELOG.md @@ -1,6 +1,21 @@ CHANGELOG ========= +5.2 +--- + + * Add `name` argument to the `StopWatchEvent` constructor, accessible via a new `StopwatchEvent::getName()` + +5.0.0 +----- + + * Removed support for passing `null` as 1st (`$id`) argument of `Section::get()` method, pass a valid child section identifier instead. + +4.4.0 +----- + + * Deprecated passing `null` as 1st (`$id`) argument of `Section::get()` method, pass a valid child section identifier instead. + 3.4.0 ----- diff --git a/vendor/symfony/stopwatch/LICENSE b/vendor/symfony/stopwatch/LICENSE index 21d7fb9..0138f8f 100644 --- a/vendor/symfony/stopwatch/LICENSE +++ b/vendor/symfony/stopwatch/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/stopwatch/README.md b/vendor/symfony/stopwatch/README.md index eb0ebb3..13a9dfa 100644 --- a/vendor/symfony/stopwatch/README.md +++ b/vendor/symfony/stopwatch/README.md @@ -3,11 +3,40 @@ Stopwatch Component The Stopwatch component provides a way to profile code. +Getting Started +--------------- + +``` +$ composer require symfony/stopwatch +``` + +```php +use Symfony\Component\Stopwatch\Stopwatch; + +$stopwatch = new Stopwatch(); + +// optionally group events into sections (e.g. phases of the execution) +$stopwatch->openSection(); + +// starts event named 'eventName' +$stopwatch->start('eventName'); + +// ... run your code here + +// optionally, start a new "lap" time +$stopwatch->lap('foo'); + +// ... run your code here + +$event = $stopwatch->stop('eventName'); + +$stopwatch->stopSection('phase_1'); +``` + Resources --------- - * [Documentation](https://symfony.com/doc/current/components/stopwatch.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/stopwatch/Section.php b/vendor/symfony/stopwatch/Section.php index 0860dbe..56cdc6f 100644 --- a/vendor/symfony/stopwatch/Section.php +++ b/vendor/symfony/stopwatch/Section.php @@ -21,10 +21,10 @@ class Section /** * @var StopwatchEvent[] */ - private $events = array(); + private $events = []; /** - * @var null|float + * @var float|null */ private $origin; @@ -41,32 +41,32 @@ class Section /** * @var Section[] */ - private $children = array(); + private $children = []; /** * @param float|null $origin Set the origin of the events in this section, use null to set their origin to their start time * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision */ - public function __construct($origin = null, $morePrecision = false) + public function __construct(float $origin = null, bool $morePrecision = false) { - $this->origin = is_numeric($origin) ? $origin : null; + $this->origin = $origin; $this->morePrecision = $morePrecision; } /** * Returns the child section. * - * @param string $id The child section identifier - * - * @return self|null The child section or null when none found + * @return self|null */ - public function get($id) + public function get(string $id) { foreach ($this->children as $child) { if ($id === $child->getId()) { return $child; } } + + return null; } /** @@ -76,9 +76,9 @@ public function get($id) * * @return self */ - public function open($id) + public function open(?string $id) { - if (null === $session = $this->get($id)) { + if (null === $id || null === $session = $this->get($id)) { $session = $this->children[] = new self(microtime(true) * 1000, $this->morePrecision); } @@ -86,7 +86,7 @@ public function open($id) } /** - * @return string The identifier of the section + * @return string */ public function getId() { @@ -96,11 +96,9 @@ public function getId() /** * Sets the session identifier. * - * @param string $id The session identifier - * * @return $this */ - public function setId($id) + public function setId(string $id) { $this->id = $id; @@ -110,15 +108,12 @@ public function setId($id) /** * Starts an event. * - * @param string $name The event name - * @param string $category The event category - * - * @return StopwatchEvent The event + * @return StopwatchEvent */ - public function startEvent($name, $category) + public function startEvent(string $name, ?string $category) { if (!isset($this->events[$name])) { - $this->events[$name] = new StopwatchEvent($this->origin ?: microtime(true) * 1000, $category, $this->morePrecision); + $this->events[$name] = new StopwatchEvent($this->origin ?: microtime(true) * 1000, $category, $this->morePrecision, $name); } return $this->events[$name]->start(); @@ -127,11 +122,9 @@ public function startEvent($name, $category) /** * Checks if the event was started. * - * @param string $name The event name - * * @return bool */ - public function isEventStarted($name) + public function isEventStarted(string $name) { return isset($this->events[$name]) && $this->events[$name]->isStarted(); } @@ -139,13 +132,11 @@ public function isEventStarted($name) /** * Stops an event. * - * @param string $name The event name - * - * @return StopwatchEvent The event + * @return StopwatchEvent * * @throws \LogicException When the event has not been started */ - public function stopEvent($name) + public function stopEvent(string $name) { if (!isset($this->events[$name])) { throw new \LogicException(sprintf('Event "%s" is not started.', $name)); @@ -157,13 +148,11 @@ public function stopEvent($name) /** * Stops then restarts an event. * - * @param string $name The event name - * - * @return StopwatchEvent The event + * @return StopwatchEvent * * @throws \LogicException When the event has not been started */ - public function lap($name) + public function lap(string $name) { return $this->stopEvent($name)->start(); } @@ -171,13 +160,11 @@ public function lap($name) /** * Returns a specific event by name. * - * @param string $name The event name - * - * @return StopwatchEvent The event + * @return StopwatchEvent * * @throws \LogicException When the event is not known */ - public function getEvent($name) + public function getEvent(string $name) { if (!isset($this->events[$name])) { throw new \LogicException(sprintf('Event "%s" is not known.', $name)); @@ -189,7 +176,7 @@ public function getEvent($name) /** * Returns the events from this section. * - * @return StopwatchEvent[] An array of StopwatchEvent instances + * @return StopwatchEvent[] */ public function getEvents() { diff --git a/vendor/symfony/stopwatch/Stopwatch.php b/vendor/symfony/stopwatch/Stopwatch.php index 9da84f6..2f46c59 100644 --- a/vendor/symfony/stopwatch/Stopwatch.php +++ b/vendor/symfony/stopwatch/Stopwatch.php @@ -11,12 +11,17 @@ namespace Symfony\Component\Stopwatch; +use Symfony\Contracts\Service\ResetInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(Section::class); + /** * Stopwatch provides a way to profile code. * * @author Fabien Potencier <fabien@symfony.com> */ -class Stopwatch +class Stopwatch implements ResetInterface { /** * @var bool @@ -36,7 +41,7 @@ class Stopwatch /** * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision */ - public function __construct($morePrecision = false) + public function __construct(bool $morePrecision = false) { $this->morePrecision = $morePrecision; $this->reset(); @@ -57,12 +62,12 @@ public function getSections() * * @throws \LogicException When the section to re-open is not reachable */ - public function openSection($id = null) + public function openSection(string $id = null) { $current = end($this->activeSections); if (null !== $id && null === $current->get($id)) { - throw new \LogicException(sprintf('The section "%s" has been started at an other level and can not be opened.', $id)); + throw new \LogicException(sprintf('The section "%s" has been started at an other level and cannot be opened.', $id)); } $this->start('__section__.child', 'section'); @@ -77,11 +82,9 @@ public function openSection($id = null) * * @see getSectionEvents() * - * @param string $id The identifier of the section - * * @throws \LogicException When there's no started section to be stopped */ - public function stopSection($id) + public function stopSection(string $id) { $this->stop('__section__'); @@ -96,12 +99,9 @@ public function stopSection($id) /** * Starts an event. * - * @param string $name The event name - * @param string $category The event category - * * @return StopwatchEvent */ - public function start($name, $category = null) + public function start(string $name, string $category = null) { return end($this->activeSections)->startEvent($name, $category); } @@ -109,11 +109,9 @@ public function start($name, $category = null) /** * Checks if the event was started. * - * @param string $name The event name - * * @return bool */ - public function isStarted($name) + public function isStarted(string $name) { return end($this->activeSections)->isEventStarted($name); } @@ -121,11 +119,9 @@ public function isStarted($name) /** * Stops an event. * - * @param string $name The event name - * * @return StopwatchEvent */ - public function stop($name) + public function stop(string $name) { return end($this->activeSections)->stopEvent($name); } @@ -133,11 +129,9 @@ public function stop($name) /** * Stops then restarts an event. * - * @param string $name The event name - * * @return StopwatchEvent */ - public function lap($name) + public function lap(string $name) { return end($this->activeSections)->stopEvent($name)->start(); } @@ -145,11 +139,9 @@ public function lap($name) /** * Returns a specific event by name. * - * @param string $name The event name - * * @return StopwatchEvent */ - public function getEvent($name) + public function getEvent(string $name) { return end($this->activeSections)->getEvent($name); } @@ -157,13 +149,11 @@ public function getEvent($name) /** * Gets all events for a given section. * - * @param string $id A section identifier - * * @return StopwatchEvent[] */ - public function getSectionEvents($id) + public function getSectionEvents(string $id) { - return isset($this->sections[$id]) ? $this->sections[$id]->getEvents() : array(); + return isset($this->sections[$id]) ? $this->sections[$id]->getEvents() : []; } /** @@ -171,6 +161,6 @@ public function getSectionEvents($id) */ public function reset() { - $this->sections = $this->activeSections = array('__root__' => new Section(null, $this->morePrecision)); + $this->sections = $this->activeSections = ['__root__' => new Section(null, $this->morePrecision)]; } } diff --git a/vendor/symfony/stopwatch/StopwatchEvent.php b/vendor/symfony/stopwatch/StopwatchEvent.php index f04f0ac..945bc70 100644 --- a/vendor/symfony/stopwatch/StopwatchEvent.php +++ b/vendor/symfony/stopwatch/StopwatchEvent.php @@ -21,7 +21,7 @@ class StopwatchEvent /** * @var StopwatchPeriod[] */ - private $periods = array(); + private $periods = []; /** * @var float @@ -41,26 +41,33 @@ class StopwatchEvent /** * @var float[] */ - private $started = array(); + private $started = []; + + /** + * @var string + */ + private $name; /** * @param float $origin The origin time in milliseconds * @param string|null $category The event category or null to use the default * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision + * @param string|null $name The event name or null to define the name as default * * @throws \InvalidArgumentException When the raw time is not valid */ - public function __construct($origin, $category = null, $morePrecision = false) + public function __construct(float $origin, string $category = null, bool $morePrecision = false, string $name = null) { $this->origin = $this->formatTime($origin); $this->category = \is_string($category) ? $category : 'default'; $this->morePrecision = $morePrecision; + $this->name = $name ?? 'default'; } /** * Gets the category. * - * @return string The category + * @return string */ public function getCategory() { @@ -68,9 +75,9 @@ public function getCategory() } /** - * Gets the origin. + * Gets the origin in milliseconds. * - * @return float The origin in milliseconds + * @return float */ public function getOrigin() { @@ -140,7 +147,7 @@ public function ensureStopped() /** * Gets all event periods. * - * @return StopwatchPeriod[] An array of StopwatchPeriod instances + * @return StopwatchPeriod[] */ public function getPeriods() { @@ -148,19 +155,27 @@ public function getPeriods() } /** - * Gets the relative time of the start of the first period. + * Gets the relative time of the start of the first period in milliseconds. * - * @return int|float The time (in milliseconds) + * @return int|float */ public function getStartTime() { - return isset($this->periods[0]) ? $this->periods[0]->getStartTime() : 0; + if (isset($this->periods[0])) { + return $this->periods[0]->getStartTime(); + } + + if ($this->started) { + return $this->started[0]; + } + + return 0; } /** - * Gets the relative time of the end of the last period. + * Gets the relative time of the end of the last period in milliseconds. * - * @return int|float The time (in milliseconds) + * @return int|float */ public function getEndTime() { @@ -170,19 +185,17 @@ public function getEndTime() } /** - * Gets the duration of the events (including all periods). + * Gets the duration of the events in milliseconds (including all periods). * - * @return int|float The duration (in milliseconds) + * @return int|float */ public function getDuration() { $periods = $this->periods; - $stopped = \count($periods); - $left = \count($this->started) - $stopped; + $left = \count($this->started); - for ($i = 0; $i < $left; ++$i) { - $index = $stopped + $i; - $periods[] = new StopwatchPeriod($this->started[$index], $this->getNow(), $this->morePrecision); + for ($i = $left - 1; $i >= 0; --$i) { + $periods[] = new StopwatchPeriod($this->started[$i], $this->getNow(), $this->morePrecision); } $total = 0; @@ -194,9 +207,9 @@ public function getDuration() } /** - * Gets the max memory usage of all periods. + * Gets the max memory usage of all periods in bytes. * - * @return int The memory usage (in bytes) + * @return int */ public function getMemory() { @@ -211,9 +224,9 @@ public function getMemory() } /** - * Return the current time relative to origin. + * Return the current time relative to origin in milliseconds. * - * @return float Time in ms + * @return float */ protected function getNow() { @@ -223,26 +236,23 @@ protected function getNow() /** * Formats a time. * - * @param int|float $time A raw time - * - * @return float The formatted time - * * @throws \InvalidArgumentException When the raw time is not valid */ - private function formatTime($time) + private function formatTime(float $time): float { - if (!is_numeric($time)) { - throw new \InvalidArgumentException('The time must be a numerical value'); - } - return round($time, 1); } /** - * @return string + * Gets the event name. */ - public function __toString() + public function getName(): string + { + return $this->name; + } + + public function __toString(): string { - return sprintf('%s: %.2F MiB - %d ms', $this->getCategory(), $this->getMemory() / 1024 / 1024, $this->getDuration()); + return sprintf('%s/%s: %.2F MiB - %d ms', $this->getCategory(), $this->getName(), $this->getMemory() / 1024 / 1024, $this->getDuration()); } } diff --git a/vendor/symfony/stopwatch/StopwatchPeriod.php b/vendor/symfony/stopwatch/StopwatchPeriod.php index 5626aa5..7a7ae1a 100644 --- a/vendor/symfony/stopwatch/StopwatchPeriod.php +++ b/vendor/symfony/stopwatch/StopwatchPeriod.php @@ -27,7 +27,7 @@ class StopwatchPeriod * @param int|float $end The relative time of the end of the period (in milliseconds) * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision */ - public function __construct($start, $end, $morePrecision = false) + public function __construct($start, $end, bool $morePrecision = false) { $this->start = $morePrecision ? (float) $start : (int) $start; $this->end = $morePrecision ? (float) $end : (int) $end; @@ -35,9 +35,9 @@ public function __construct($start, $end, $morePrecision = false) } /** - * Gets the relative time of the start of the period. + * Gets the relative time of the start of the period in milliseconds. * - * @return int|float The time (in milliseconds) + * @return int|float */ public function getStartTime() { @@ -45,9 +45,9 @@ public function getStartTime() } /** - * Gets the relative time of the end of the period. + * Gets the relative time of the end of the period in milliseconds. * - * @return int|float The time (in milliseconds) + * @return int|float */ public function getEndTime() { @@ -55,9 +55,9 @@ public function getEndTime() } /** - * Gets the time spent in this period. + * Gets the time spent in this period in milliseconds. * - * @return int|float The period duration (in milliseconds) + * @return int|float */ public function getDuration() { @@ -65,12 +65,17 @@ public function getDuration() } /** - * Gets the memory usage. + * Gets the memory usage in bytes. * - * @return int The memory usage (in bytes) + * @return int */ public function getMemory() { return $this->memory; } + + public function __toString(): string + { + return sprintf('%.2F MiB - %d ms', $this->getMemory() / 1024 / 1024, $this->getDuration()); + } } diff --git a/vendor/symfony/stopwatch/Tests/StopwatchEventTest.php b/vendor/symfony/stopwatch/Tests/StopwatchEventTest.php deleted file mode 100644 index 2742ca5..0000000 --- a/vendor/symfony/stopwatch/Tests/StopwatchEventTest.php +++ /dev/null @@ -1,176 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Stopwatch\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Stopwatch\StopwatchEvent; - -/** - * StopwatchEventTest. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @group time-sensitive - */ -class StopwatchEventTest extends TestCase -{ - const DELTA = 37; - - public function testGetOrigin() - { - $event = new StopwatchEvent(12); - $this->assertEquals(12, $event->getOrigin()); - } - - public function testGetCategory() - { - $event = new StopwatchEvent(microtime(true) * 1000); - $this->assertEquals('default', $event->getCategory()); - - $event = new StopwatchEvent(microtime(true) * 1000, 'cat'); - $this->assertEquals('cat', $event->getCategory()); - } - - public function testGetPeriods() - { - $event = new StopwatchEvent(microtime(true) * 1000); - $this->assertEquals(array(), $event->getPeriods()); - - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - $event->stop(); - $this->assertCount(1, $event->getPeriods()); - - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - $event->stop(); - $event->start(); - $event->stop(); - $this->assertCount(2, $event->getPeriods()); - } - - public function testLap() - { - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - $event->lap(); - $event->stop(); - $this->assertCount(2, $event->getPeriods()); - } - - public function testDuration() - { - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - usleep(200000); - $event->stop(); - $this->assertEquals(200, $event->getDuration(), '', self::DELTA); - - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - usleep(100000); - $event->stop(); - usleep(50000); - $event->start(); - usleep(100000); - $event->stop(); - $this->assertEquals(200, $event->getDuration(), '', self::DELTA); - } - - public function testDurationBeforeStop() - { - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - usleep(200000); - $this->assertEquals(200, $event->getDuration(), '', self::DELTA); - - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - usleep(100000); - $event->stop(); - usleep(50000); - $event->start(); - usleep(100000); - $this->assertEquals(100, $event->getDuration(), '', self::DELTA); - } - - /** - * @expectedException \LogicException - */ - public function testStopWithoutStart() - { - $event = new StopwatchEvent(microtime(true) * 1000); - $event->stop(); - } - - public function testIsStarted() - { - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - $this->assertTrue($event->isStarted()); - } - - public function testIsNotStarted() - { - $event = new StopwatchEvent(microtime(true) * 1000); - $this->assertFalse($event->isStarted()); - } - - public function testEnsureStopped() - { - // this also test overlap between two periods - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - usleep(100000); - $event->start(); - usleep(100000); - $event->ensureStopped(); - $this->assertEquals(300, $event->getDuration(), '', self::DELTA); - } - - public function testStartTime() - { - $event = new StopwatchEvent(microtime(true) * 1000); - $this->assertLessThanOrEqual(0.5, $event->getStartTime()); - - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - $event->stop(); - $this->assertLessThanOrEqual(1, $event->getStartTime()); - - $event = new StopwatchEvent(microtime(true) * 1000); - $event->start(); - usleep(100000); - $event->stop(); - $this->assertEquals(0, $event->getStartTime(), '', self::DELTA); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testInvalidOriginThrowsAnException() - { - new StopwatchEvent('abc'); - } - - public function testHumanRepresentation() - { - $event = new StopwatchEvent(microtime(true) * 1000); - $this->assertEquals('default: 0.00 MiB - 0 ms', (string) $event); - $event->start(); - $event->stop(); - $this->assertEquals(1, preg_match('/default: [0-9\.]+ MiB - [0-9]+ ms/', (string) $event)); - - $event = new StopwatchEvent(microtime(true) * 1000, 'foo'); - $this->assertEquals('foo: 0.00 MiB - 0 ms', (string) $event); - } -} diff --git a/vendor/symfony/stopwatch/Tests/StopwatchPeriodTest.php b/vendor/symfony/stopwatch/Tests/StopwatchPeriodTest.php deleted file mode 100644 index f2387b8..0000000 --- a/vendor/symfony/stopwatch/Tests/StopwatchPeriodTest.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Stopwatch\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Stopwatch\StopwatchPeriod; - -class StopwatchPeriodTest extends TestCase -{ - /** - * @dataProvider provideTimeValues - */ - public function testGetStartTime($start, $useMorePrecision, $expected) - { - $period = new StopwatchPeriod($start, $start, $useMorePrecision); - $this->assertSame($expected, $period->getStartTime()); - } - - /** - * @dataProvider provideTimeValues - */ - public function testGetEndTime($end, $useMorePrecision, $expected) - { - $period = new StopwatchPeriod($end, $end, $useMorePrecision); - $this->assertSame($expected, $period->getEndTime()); - } - - /** - * @dataProvider provideDurationValues - */ - public function testGetDuration($start, $end, $useMorePrecision, $duration) - { - $period = new StopwatchPeriod($start, $end, $useMorePrecision); - $this->assertSame($duration, $period->getDuration()); - } - - public function provideTimeValues() - { - yield array(0, false, 0); - yield array(0, true, 0.0); - yield array(0.0, false, 0); - yield array(0.0, true, 0.0); - yield array(2.71, false, 2); - yield array(2.71, true, 2.71); - } - - public function provideDurationValues() - { - yield array(0, 0, false, 0); - yield array(0, 0, true, 0.0); - yield array(0.0, 0.0, false, 0); - yield array(0.0, 0.0, true, 0.0); - yield array(2, 3.14, false, 1); - yield array(2, 3.14, true, 1.14); - yield array(2.71, 3.14, false, 1); - yield array(2.71, 3.14, true, 0.43); - } -} diff --git a/vendor/symfony/stopwatch/Tests/StopwatchTest.php b/vendor/symfony/stopwatch/Tests/StopwatchTest.php deleted file mode 100644 index 10e6a14..0000000 --- a/vendor/symfony/stopwatch/Tests/StopwatchTest.php +++ /dev/null @@ -1,180 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Stopwatch\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Stopwatch\Stopwatch; - -/** - * StopwatchTest. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @group time-sensitive - */ -class StopwatchTest extends TestCase -{ - const DELTA = 20; - - public function testStart() - { - $stopwatch = new Stopwatch(); - $event = $stopwatch->start('foo', 'cat'); - - $this->assertInstanceOf('Symfony\Component\Stopwatch\StopwatchEvent', $event); - $this->assertEquals('cat', $event->getCategory()); - $this->assertSame($event, $stopwatch->getEvent('foo')); - } - - public function testIsStarted() - { - $stopwatch = new Stopwatch(); - $stopwatch->start('foo', 'cat'); - - $this->assertTrue($stopwatch->isStarted('foo')); - } - - public function testIsNotStarted() - { - $stopwatch = new Stopwatch(); - - $this->assertFalse($stopwatch->isStarted('foo')); - } - - public function testIsNotStartedEvent() - { - $stopwatch = new Stopwatch(); - - $sections = new \ReflectionProperty('Symfony\Component\Stopwatch\Stopwatch', 'sections'); - $sections->setAccessible(true); - $section = $sections->getValue($stopwatch); - - $events = new \ReflectionProperty('Symfony\Component\Stopwatch\Section', 'events'); - $events->setAccessible(true); - - $stopwatchMockEvent = $this->getMockBuilder('Symfony\Component\Stopwatch\StopwatchEvent') - ->setConstructorArgs(array(microtime(true) * 1000)) - ->getMock() - ; - - $events->setValue(end($section), array('foo' => $stopwatchMockEvent)); - - $this->assertFalse($stopwatch->isStarted('foo')); - } - - public function testStop() - { - $stopwatch = new Stopwatch(); - $stopwatch->start('foo', 'cat'); - usleep(200000); - $event = $stopwatch->stop('foo'); - - $this->assertInstanceOf('Symfony\Component\Stopwatch\StopwatchEvent', $event); - $this->assertEquals(200, $event->getDuration(), '', self::DELTA); - } - - /** - * @expectedException \LogicException - */ - public function testUnknownEvent() - { - $stopwatch = new Stopwatch(); - $stopwatch->getEvent('foo'); - } - - /** - * @expectedException \LogicException - */ - public function testStopWithoutStart() - { - $stopwatch = new Stopwatch(); - $stopwatch->stop('foo'); - } - - public function testMorePrecision() - { - $stopwatch = new Stopwatch(true); - - $stopwatch->start('foo'); - $event = $stopwatch->stop('foo'); - - $this->assertInternalType('float', $event->getStartTime()); - $this->assertInternalType('float', $event->getEndTime()); - $this->assertInternalType('float', $event->getDuration()); - } - - public function testSection() - { - $stopwatch = new Stopwatch(); - - $stopwatch->openSection(); - $stopwatch->start('foo', 'cat'); - $stopwatch->stop('foo'); - $stopwatch->start('bar', 'cat'); - $stopwatch->stop('bar'); - $stopwatch->stopSection('1'); - - $stopwatch->openSection(); - $stopwatch->start('foobar', 'cat'); - $stopwatch->stop('foobar'); - $stopwatch->stopSection('2'); - - $stopwatch->openSection(); - $stopwatch->start('foobar', 'cat'); - $stopwatch->stop('foobar'); - $stopwatch->stopSection('0'); - - // the section is an event by itself - $this->assertCount(3, $stopwatch->getSectionEvents('1')); - $this->assertCount(2, $stopwatch->getSectionEvents('2')); - $this->assertCount(2, $stopwatch->getSectionEvents('0')); - } - - public function testReopenASection() - { - $stopwatch = new Stopwatch(); - - $stopwatch->openSection(); - $stopwatch->start('foo', 'cat'); - $stopwatch->stopSection('section'); - - $stopwatch->openSection('section'); - $stopwatch->start('bar', 'cat'); - $stopwatch->stopSection('section'); - - $events = $stopwatch->getSectionEvents('section'); - - $this->assertCount(3, $events); - $this->assertCount(2, $events['__section__']->getPeriods()); - } - - /** - * @expectedException \LogicException - */ - public function testReopenANewSectionShouldThrowAnException() - { - $stopwatch = new Stopwatch(); - $stopwatch->openSection('section'); - } - - public function testReset() - { - $stopwatch = new Stopwatch(); - - $stopwatch->openSection(); - $stopwatch->start('foo', 'cat'); - - $stopwatch->reset(); - - $this->assertEquals(new Stopwatch(), $stopwatch); - } -} diff --git a/vendor/symfony/stopwatch/composer.json b/vendor/symfony/stopwatch/composer.json index 8c33978..ed918d3 100644 --- a/vendor/symfony/stopwatch/composer.json +++ b/vendor/symfony/stopwatch/composer.json @@ -1,7 +1,7 @@ { "name": "symfony/stopwatch", "type": "library", - "description": "Symfony Stopwatch Component", + "description": "Provides a way to profile code", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", @@ -16,7 +16,8 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=7.2.5", + "symfony/service-contracts": "^1|^2|^3" }, "autoload": { "psr-4": { "Symfony\\Component\\Stopwatch\\": "" }, @@ -24,10 +25,5 @@ "/Tests/" ] }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - } + "minimum-stability": "dev" } diff --git a/vendor/symfony/stopwatch/phpunit.xml.dist b/vendor/symfony/stopwatch/phpunit.xml.dist deleted file mode 100644 index f28559a..0000000 --- a/vendor/symfony/stopwatch/phpunit.xml.dist +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" - backupGlobals="false" - colors="true" - bootstrap="vendor/autoload.php" - failOnRisky="true" - failOnWarning="true" -> - <php> - <ini name="error_reporting" value="-1" /> - </php> - - <testsuites> - <testsuite name="Symfony Stopwatch Component Test Suite"> - <directory>./Tests/</directory> - </testsuite> - </testsuites> - - <filter> - <whitelist> - <directory>./</directory> - <exclude> - <directory>./Tests</directory> - <directory>./vendor</directory> - </exclude> - </whitelist> - </filter> -</phpunit> diff --git a/vendor/symfony/string/AbstractString.php b/vendor/symfony/string/AbstractString.php new file mode 100644 index 0000000..13567c7 --- /dev/null +++ b/vendor/symfony/string/AbstractString.php @@ -0,0 +1,795 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +use Symfony\Component\String\Exception\ExceptionInterface; +use Symfony\Component\String\Exception\InvalidArgumentException; +use Symfony\Component\String\Exception\RuntimeException; + +/** + * Represents a string of abstract characters. + * + * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). + * This class is the abstract type to use as a type-hint when the logic you want to + * implement doesn't care about the exact variant it deals with. + * + * @author Nicolas Grekas <p@tchwork.com> + * @author Hugo Hamon <hugohamon@neuf.fr> + * + * @throws ExceptionInterface + */ +abstract class AbstractString implements \Stringable, \JsonSerializable +{ + public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER; + public const PREG_SET_ORDER = \PREG_SET_ORDER; + public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE; + public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL; + + public const PREG_SPLIT = 0; + public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY; + public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE; + public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE; + + protected $string = ''; + protected $ignoreCase = false; + + abstract public function __construct(string $string = ''); + + /** + * Unwraps instances of AbstractString back to strings. + * + * @return string[]|array + */ + public static function unwrap(array $values): array + { + foreach ($values as $k => $v) { + if ($v instanceof self) { + $values[$k] = $v->__toString(); + } elseif (\is_array($v) && $values[$k] !== $v = static::unwrap($v)) { + $values[$k] = $v; + } + } + + return $values; + } + + /** + * Wraps (and normalizes) strings in instances of AbstractString. + * + * @return static[]|array + */ + public static function wrap(array $values): array + { + $i = 0; + $keys = null; + + foreach ($values as $k => $v) { + if (\is_string($k) && '' !== $k && $k !== $j = (string) new static($k)) { + $keys = $keys ?? array_keys($values); + $keys[$i] = $j; + } + + if (\is_string($v)) { + $values[$k] = new static($v); + } elseif (\is_array($v) && $values[$k] !== $v = static::wrap($v)) { + $values[$k] = $v; + } + + ++$i; + } + + return null !== $keys ? array_combine($keys, $values) : $values; + } + + /** + * @param string|string[] $needle + * + * @return static + */ + public function after($needle, bool $includeNeedle = false, int $offset = 0): self + { + $str = clone $this; + $i = \PHP_INT_MAX; + + foreach ((array) $needle as $n) { + $n = (string) $n; + $j = $this->indexOf($n, $offset); + + if (null !== $j && $j < $i) { + $i = $j; + $str->string = $n; + } + } + + if (\PHP_INT_MAX === $i) { + return $str; + } + + if (!$includeNeedle) { + $i += $str->length(); + } + + return $this->slice($i); + } + + /** + * @param string|string[] $needle + * + * @return static + */ + public function afterLast($needle, bool $includeNeedle = false, int $offset = 0): self + { + $str = clone $this; + $i = null; + + foreach ((array) $needle as $n) { + $n = (string) $n; + $j = $this->indexOfLast($n, $offset); + + if (null !== $j && $j >= $i) { + $i = $offset = $j; + $str->string = $n; + } + } + + if (null === $i) { + return $str; + } + + if (!$includeNeedle) { + $i += $str->length(); + } + + return $this->slice($i); + } + + /** + * @return static + */ + abstract public function append(string ...$suffix): self; + + /** + * @param string|string[] $needle + * + * @return static + */ + public function before($needle, bool $includeNeedle = false, int $offset = 0): self + { + $str = clone $this; + $i = \PHP_INT_MAX; + + foreach ((array) $needle as $n) { + $n = (string) $n; + $j = $this->indexOf($n, $offset); + + if (null !== $j && $j < $i) { + $i = $j; + $str->string = $n; + } + } + + if (\PHP_INT_MAX === $i) { + return $str; + } + + if ($includeNeedle) { + $i += $str->length(); + } + + return $this->slice(0, $i); + } + + /** + * @param string|string[] $needle + * + * @return static + */ + public function beforeLast($needle, bool $includeNeedle = false, int $offset = 0): self + { + $str = clone $this; + $i = null; + + foreach ((array) $needle as $n) { + $n = (string) $n; + $j = $this->indexOfLast($n, $offset); + + if (null !== $j && $j >= $i) { + $i = $offset = $j; + $str->string = $n; + } + } + + if (null === $i) { + return $str; + } + + if ($includeNeedle) { + $i += $str->length(); + } + + return $this->slice(0, $i); + } + + /** + * @return int[] + */ + public function bytesAt(int $offset): array + { + $str = $this->slice($offset, 1); + + return '' === $str->string ? [] : array_values(unpack('C*', $str->string)); + } + + /** + * @return static + */ + abstract public function camel(): self; + + /** + * @return static[] + */ + abstract public function chunk(int $length = 1): array; + + /** + * @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"); + + return $str; + } + + /** + * @param string|string[] $needle + */ + public function containsAny($needle): bool + { + return null !== $this->indexOf($needle); + } + + /** + * @param string|string[] $suffix + */ + public function endsWith($suffix): bool + { + 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)); + } + + foreach ($suffix as $s) { + if ($this->endsWith((string) $s)) { + return true; + } + } + + return false; + } + + /** + * @return static + */ + public function ensureEnd(string $suffix): self + { + if (!$this->endsWith($suffix)) { + return $this->append($suffix); + } + + $suffix = preg_quote($suffix); + $regex = '{('.$suffix.')(?:'.$suffix.')++$}D'; + + return $this->replaceMatches($regex.($this->ignoreCase ? 'i' : ''), '$1'); + } + + /** + * @return static + */ + public function ensureStart(string $prefix): self + { + $prefix = new static($prefix); + + if (!$this->startsWith($prefix)) { + return $this->prepend($prefix); + } + + $str = clone $this; + $i = $prefixLen = $prefix->length(); + + while ($this->indexOf($prefix, $i) === $i) { + $str = $str->slice($prefixLen); + $i += $prefixLen; + } + + return $str; + } + + /** + * @param string|string[] $string + */ + public function equalsTo($string): bool + { + 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)); + } + + foreach ($string as $s) { + if ($this->equalsTo((string) $s)) { + return true; + } + } + + return false; + } + + /** + * @return static + */ + abstract public function folded(): self; + + /** + * @return static + */ + public function ignoreCase(): self + { + $str = clone $this; + $str->ignoreCase = true; + + return $str; + } + + /** + * @param string|string[] $needle + */ + public function indexOf($needle, int $offset = 0): ?int + { + 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)); + } + + $i = \PHP_INT_MAX; + + foreach ($needle as $n) { + $j = $this->indexOf((string) $n, $offset); + + if (null !== $j && $j < $i) { + $i = $j; + } + } + + return \PHP_INT_MAX === $i ? null : $i; + } + + /** + * @param string|string[] $needle + */ + public function indexOfLast($needle, int $offset = 0): ?int + { + 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)); + } + + $i = null; + + foreach ($needle as $n) { + $j = $this->indexOfLast((string) $n, $offset); + + if (null !== $j && $j >= $i) { + $i = $offset = $j; + } + } + + return $i; + } + + public function isEmpty(): bool + { + return '' === $this->string; + } + + /** + * @return static + */ + abstract public function join(array $strings, string $lastGlue = null): self; + + public function jsonSerialize(): string + { + return $this->string; + } + + abstract public function length(): int; + + /** + * @return static + */ + abstract public function lower(): self; + + /** + * Matches the string using a regular expression. + * + * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression. + * + * @return array All matches in a multi-dimensional array ordered according to flags + */ + abstract public function match(string $regexp, int $flags = 0, int $offset = 0): array; + + /** + * @return static + */ + abstract public function padBoth(int $length, string $padStr = ' '): self; + + /** + * @return static + */ + abstract public function padEnd(int $length, string $padStr = ' '): self; + + /** + * @return static + */ + abstract public function padStart(int $length, string $padStr = ' '): self; + + /** + * @return static + */ + abstract public function prepend(string ...$prefix): self; + + /** + * @return static + */ + public function repeat(int $multiplier): self + { + if (0 > $multiplier) { + throw new InvalidArgumentException(sprintf('Multiplier must be positive, %d given.', $multiplier)); + } + + $str = clone $this; + $str->string = str_repeat($str->string, $multiplier); + + return $str; + } + + /** + * @return static + */ + abstract public function replace(string $from, string $to): self; + + /** + * @param string|callable $to + * + * @return static + */ + abstract public function replaceMatches(string $fromRegexp, $to): self; + + /** + * @return static + */ + abstract public function reverse(): self; + + /** + * @return static + */ + abstract public function slice(int $start = 0, int $length = null): self; + + /** + * @return static + */ + abstract public function snake(): self; + + /** + * @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 + { + if (null === $flags) { + throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.'); + } + + if ($this->ignoreCase) { + $delimiter .= 'i'; + } + + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + + try { + if (false === $chunks = preg_split($delimiter, $this->string, $limit, $flags)) { + $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(); + } + + $str = clone $this; + + if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) { + foreach ($chunks as &$chunk) { + $str->string = $chunk[0]; + $chunk[0] = clone $str; + } + } else { + foreach ($chunks as &$chunk) { + $str->string = $chunk; + $chunk = clone $str; + } + } + + return $chunks; + } + + /** + * @param string|string[] $prefix + */ + public function startsWith($prefix): bool + { + 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)); + } + + foreach ($prefix as $prefix) { + if ($this->startsWith((string) $prefix)) { + return true; + } + } + + return false; + } + + /** + * @return static + */ + abstract public function title(bool $allWords = false): self; + + public function toByteString(string $toEncoding = null): ByteString + { + $b = new ByteString(); + + $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], true) ? 'UTF-8' : $toEncoding; + + if (null === $toEncoding || $toEncoding === $fromEncoding = $this instanceof AbstractUnicodeString || preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252') { + $b->string = $this->string; + + return $b; + } + + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + + try { + 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); + } + } finally { + restore_error_handler(); + } + + return $b; + } + + public function toCodePointString(): CodePointString + { + return new CodePointString($this->string); + } + + public function toString(): string + { + return $this->string; + } + + public function toUnicodeString(): UnicodeString + { + return new UnicodeString($this->string); + } + + /** + * @return static + */ + abstract public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): self; + + /** + * @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): self + { + if (\is_array($prefix) || $prefix instanceof \Traversable) { + foreach ($prefix as $s) { + $t = $this->trimPrefix($s); + + if ($t->string !== $this->string) { + return $t; + } + } + + return clone $this; + } + + $str = clone $this; + + if ($prefix instanceof self) { + $prefix = $prefix->string; + } else { + $prefix = (string) $prefix; + } + + if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) { + $str->string = substr($this->string, \strlen($prefix)); + } + + return $str; + } + + /** + * @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): self + { + if (\is_array($suffix) || $suffix instanceof \Traversable) { + foreach ($suffix as $s) { + $t = $this->trimSuffix($s); + + if ($t->string !== $this->string) { + return $t; + } + } + + return clone $this; + } + + $str = clone $this; + + if ($suffix instanceof self) { + $suffix = $suffix->string; + } else { + $suffix = (string) $suffix; + } + + if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) { + $str->string = substr($this->string, 0, -\strlen($suffix)); + } + + return $str; + } + + /** + * @return static + */ + public function truncate(int $length, string $ellipsis = '', bool $cut = true): self + { + $stringLength = $this->length(); + + if ($stringLength <= $length) { + return clone $this; + } + + $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0; + + if ($length < $ellipsisLength) { + $ellipsisLength = 0; + } + + if (!$cut) { + if (null === $length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1)) { + return clone $this; + } + + $length += $ellipsisLength; + } + + $str = $this->slice(0, $length - $ellipsisLength); + + return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str; + } + + /** + * @return static + */ + abstract public function upper(): self; + + /** + * Returns the printable length on a terminal. + */ + abstract public function width(bool $ignoreAnsiDecoration = true): int; + + /** + * @return static + */ + public function wordwrap(int $width = 75, string $break = "\n", bool $cut = false): self + { + $lines = '' !== $break ? $this->split($break) : [clone $this]; + $chars = []; + $mask = ''; + + if (1 === \count($lines) && '' === $lines[0]->string) { + return $lines[0]; + } + + foreach ($lines as $i => $line) { + if ($i) { + $chars[] = $break; + $mask .= '#'; + } + + foreach ($line->chunk() as $char) { + $chars[] = $char->string; + $mask .= ' ' === $char->string ? ' ' : '?'; + } + } + + $string = ''; + $j = 0; + $b = $i = -1; + $mask = wordwrap($mask, $width, '#', $cut); + + while (false !== $b = strpos($mask, '#', $b + 1)) { + for (++$i; $i < $b; ++$i) { + $string .= $chars[$j]; + unset($chars[$j++]); + } + + if ($break === $chars[$j] || ' ' === $chars[$j]) { + unset($chars[$j++]); + } + + $string .= $break; + } + + $str = clone $this; + $str->string = $string.implode('', $chars); + + return $str; + } + + public function __sleep(): array + { + return ['string']; + } + + public function __clone() + { + $this->ignoreCase = false; + } + + public function __toString(): string + { + return $this->string; + } +} diff --git a/vendor/symfony/string/AbstractUnicodeString.php b/vendor/symfony/string/AbstractUnicodeString.php new file mode 100644 index 0000000..80b8326 --- /dev/null +++ b/vendor/symfony/string/AbstractUnicodeString.php @@ -0,0 +1,623 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +use Symfony\Component\String\Exception\ExceptionInterface; +use Symfony\Component\String\Exception\InvalidArgumentException; +use Symfony\Component\String\Exception\RuntimeException; + +/** + * Represents a string of abstract Unicode characters. + * + * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). + * This class is the abstract type to use as a type-hint when the logic you want to + * implement is Unicode-aware but doesn't care about code points vs grapheme clusters. + * + * @author Nicolas Grekas <p@tchwork.com> + * + * @throws ExceptionInterface + */ +abstract class AbstractUnicodeString extends AbstractString +{ + public const NFC = \Normalizer::NFC; + public const NFD = \Normalizer::NFD; + public const NFKC = \Normalizer::NFKC; + public const NFKD = \Normalizer::NFKD; + + // all ASCII letters sorted by typical frequency of occurrence + 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', 'մն', 'մե', 'մի', 'վն', 'մխ']; + + // 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 $transliterators = []; + private static $tableZero; + private static $tableWide; + + /** + * @return static + */ + public static function fromCodePoints(int ...$codes): self + { + $string = ''; + + foreach ($codes as $code) { + if (0x80 > $code %= 0x200000) { + $string .= \chr($code); + } elseif (0x800 > $code) { + $string .= \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); + } elseif (0x10000 > $code) { + $string .= \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } else { + $string .= \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } + } + + return new static($string); + } + + /** + * Generic UTF-8 to ASCII transliteration. + * + * Install the intl extension for best results. + * + * @param string[]|\Transliterator[]|\Closure[] $rules See "*-Latin" rules from Transliterator::listIDs() + */ + public function ascii(array $rules = []): self + { + $str = clone $this; + $s = $str->string; + $str->string = ''; + + array_unshift($rules, 'nfd'); + $rules[] = 'latin-ascii'; + + if (\function_exists('transliterator_transliterate')) { + $rules[] = 'any-latin/bgn'; + } + + $rules[] = 'nfkd'; + $rules[] = '[:nonspacing mark:] remove'; + + while (\strlen($s) - 1 > $i = strspn($s, self::ASCII)) { + if (0 < --$i) { + $str->string .= substr($s, 0, $i); + $s = substr($s, $i); + } + + if (!$rule = array_shift($rules)) { + $rules = []; // An empty rule interrupts the next ones + } + + if ($rule instanceof \Transliterator) { + $s = $rule->transliterate($s); + } elseif ($rule instanceof \Closure) { + $s = $rule($s); + } elseif ($rule) { + if ('nfd' === $rule = strtolower($rule)) { + normalizer_is_normalized($s, self::NFD) ?: $s = normalizer_normalize($s, self::NFD); + } elseif ('nfkd' === $rule) { + normalizer_is_normalized($s, self::NFKD) ?: $s = normalizer_normalize($s, self::NFKD); + } elseif ('[:nonspacing mark:] remove' === $rule) { + $s = preg_replace('/\p{Mn}++/u', '', $s); + } elseif ('latin-ascii' === $rule) { + $s = str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s); + } elseif ('de-ascii' === $rule) { + $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] ?? self::$transliterators[$rule] = \Transliterator::create($rule)) { + if ('any-latin/bgn' === $rule) { + $rule = 'any-latin'; + $transliterator = self::$transliterators[$rule] ?? self::$transliterators[$rule] = \Transliterator::create($rule); + } + + if (null === $transliterator) { + throw new InvalidArgumentException(sprintf('Unknown transliteration rule "%s".', $rule)); + } + + self::$transliterators['any-latin/bgn'] = $transliterator; + } + + $s = $transliterator->transliterate($s); + } + } elseif (!\function_exists('iconv')) { + $s = preg_replace('/[^\x00-\x7F]/u', '?', $s); + } else { + $s = @preg_replace_callback('/[^\x00-\x7F]/u', static function ($c) { + $c = (string) iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]); + + if ('' === $c && '' === iconv('UTF-8', 'ASCII//TRANSLIT', '²')) { + throw new \LogicException(sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class)); + } + + return 1 < \strlen($c) ? ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?'); + }, $s); + } + } + + $str->string .= $s; + + return $str; + } + + public function camel(): parent + { + $str = clone $this; + $str->string = str_replace(' ', '', preg_replace_callback('/\b.(?![A-Z]{2,})/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))); + + return $str; + } + + /** + * @return int[] + */ + public function codePointsAt(int $offset): array + { + $str = $this->slice($offset, 1); + + if ('' === $str->string) { + return []; + } + + $codePoints = []; + + foreach (preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { + $codePoints[] = mb_ord($c, 'UTF-8'); + } + + return $codePoints; + } + + public function folded(bool $compat = true): parent + { + $str = clone $this; + + 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, $this->string), 'UTF-8'); + } else { + $str->string = normalizer_normalize($str->string, \Normalizer::NFKC_CF); + } + + return $str; + } + + public function join(array $strings, string $lastGlue = null): parent + { + $str = clone $this; + + $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : ''; + $str->string = implode($this->string, $strings).$tail; + + if (!preg_match('//u', $str->string)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function lower(): parent + { + $str = clone $this; + $str->string = mb_strtolower(str_replace('İ', 'i̇', $str->string), 'UTF-8'); + + return $str; + } + + public function match(string $regexp, int $flags = 0, int $offset = 0): array + { + $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match'; + + if ($this->ignoreCase) { + $regexp .= 'i'; + } + + 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)) { + $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(); + } + + return $matches; + } + + /** + * @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.'); + } + + $str = clone $this; + normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form); + + return $str; + } + + public function padBoth(int $length, string $padStr = ' '): parent + { + if ('' === $padStr || !preg_match('//u', $padStr)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + $pad = clone $this; + $pad->string = $padStr; + + return $this->pad($length, $pad, \STR_PAD_BOTH); + } + + public function padEnd(int $length, string $padStr = ' '): parent + { + if ('' === $padStr || !preg_match('//u', $padStr)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + $pad = clone $this; + $pad->string = $padStr; + + return $this->pad($length, $pad, \STR_PAD_RIGHT); + } + + public function padStart(int $length, string $padStr = ' '): parent + { + if ('' === $padStr || !preg_match('//u', $padStr)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + $pad = clone $this; + $pad->string = $padStr; + + return $this->pad($length, $pad, \STR_PAD_LEFT); + } + + 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); + + if ('' !== $to && (!\is_string($to) || !preg_match('//u', $to))) { + throw new InvalidArgumentException('Replace callback must return a valid UTF-8 string.'); + } + + return $to; + }; + } elseif ('' !== $to && !preg_match('//u', $to)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } else { + $replace = 'preg_replace'; + } + + 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 && '_ERROR' === substr($k, -6)) { + throw new RuntimeException('Matching failed with '.$k.'.'); + } + } + + throw new RuntimeException('Matching failed with unknown error code.'); + } + } finally { + restore_error_handler(); + } + + $str = clone $this; + $str->string = $string; + + return $str; + } + + 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))); + + return $str; + } + + public function snake(): parent + { + $str = $this->camel(); + $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): parent + { + $str = clone $this; + + $limit = $allWords ? -1 : 1; + + $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}"): parent + { + if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { + throw new InvalidArgumentException('Invalid UTF-8 chars.'); + } + $chars = preg_quote($chars); + + $str = clone $this; + $str->string = preg_replace("{^[$chars]++|[$chars]++$}uD", '', $str->string); + + return $str; + } + + 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.'); + } + $chars = preg_quote($chars); + + $str = clone $this; + $str->string = preg_replace("{[$chars]++$}uD", '', $str->string); + + return $str; + } + + public function trimPrefix($prefix): parent + { + if (!$this->ignoreCase) { + return parent::trimPrefix($prefix); + } + + $str = clone $this; + + if ($prefix instanceof \Traversable) { + $prefix = iterator_to_array($prefix, false); + } elseif ($prefix instanceof parent) { + $prefix = $prefix->string; + } + + $prefix = implode('|', array_map('preg_quote', (array) $prefix)); + $str->string = preg_replace("{^(?:$prefix)}iuD", '', $this->string); + + return $str; + } + + 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.'); + } + $chars = preg_quote($chars); + + $str = clone $this; + $str->string = preg_replace("{^[$chars]++}uD", '', $str->string); + + return $str; + } + + public function trimSuffix($suffix): parent + { + if (!$this->ignoreCase) { + return parent::trimSuffix($suffix); + } + + $str = clone $this; + + if ($suffix instanceof \Traversable) { + $suffix = iterator_to_array($suffix, false); + } elseif ($suffix instanceof parent) { + $suffix = $suffix->string; + } + + $suffix = implode('|', array_map('preg_quote', (array) $suffix)); + $str->string = preg_replace("{(?:$suffix)$}iuD", '', $this->string); + + return $str; + } + + 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; + } + + public function width(bool $ignoreAnsiDecoration = true): int + { + $width = 0; + $s = str_replace(["\x00", "\x05", "\x07"], '', $this->string); + + if (false !== strpos($s, "\r")) { + $s = str_replace(["\r\n", "\r"], "\n", $s); + } + + if (!$ignoreAnsiDecoration) { + $s = preg_replace('/[\p{Cc}\x7F]++/u', '', $s); + } + + foreach (explode("\n", $s) as $s) { + if ($ignoreAnsiDecoration) { + $s = preg_replace('/(?:\x1B(?: + \[ [\x30-\x3F]*+ [\x20-\x2F]*+ [\x40-\x7E] + | [P\]X^_] .*? \x1B\\\\ + | [\x41-\x7E] + )|[\p{Cc}\x7F]++)/xu', '', $s); + } + + $lineWidth = $this->wcswidth($s); + + if ($lineWidth > $width) { + $width = $lineWidth; + } + } + + return $width; + } + + /** + * @return static + */ + private function pad(int $len, self $pad, int $type): parent + { + $sLen = $this->length(); + + if ($len <= $sLen) { + return clone $this; + } + + $padLen = $pad->length(); + $freeLen = $len - $sLen; + $len = $freeLen % $padLen; + + switch ($type) { + case \STR_PAD_RIGHT: + return $this->append(str_repeat($pad->string, intdiv($freeLen, $padLen)).($len ? $pad->slice(0, $len) : '')); + + case \STR_PAD_LEFT: + return $this->prepend(str_repeat($pad->string, intdiv($freeLen, $padLen)).($len ? $pad->slice(0, $len) : '')); + + case \STR_PAD_BOTH: + $freeLen /= 2; + + $rightLen = ceil($freeLen); + $len = $rightLen % $padLen; + $str = $this->append(str_repeat($pad->string, intdiv($rightLen, $padLen)).($len ? $pad->slice(0, $len) : '')); + + $leftLen = floor($freeLen); + $len = $leftLen % $padLen; + + return $str->prepend(str_repeat($pad->string, intdiv($leftLen, $padLen)).($len ? $pad->slice(0, $len) : '')); + + default: + throw new InvalidArgumentException('Invalid padding type.'); + } + } + + /** + * Based on https://github.com/jquast/wcwidth, a Python implementation of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c. + */ + private function wcswidth(string $string): int + { + $width = 0; + + foreach (preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { + $codePoint = mb_ord($c, 'UTF-8'); + + if (0 === $codePoint // NULL + || 0x034F === $codePoint // COMBINING GRAPHEME JOINER + || (0x200B <= $codePoint && 0x200F >= $codePoint) // ZERO WIDTH SPACE to RIGHT-TO-LEFT MARK + || 0x2028 === $codePoint // LINE SEPARATOR + || 0x2029 === $codePoint // PARAGRAPH SEPARATOR + || (0x202A <= $codePoint && 0x202E >= $codePoint) // LEFT-TO-RIGHT EMBEDDING to RIGHT-TO-LEFT OVERRIDE + || (0x2060 <= $codePoint && 0x2063 >= $codePoint) // WORD JOINER to INVISIBLE SEPARATOR + ) { + continue; + } + + // Non printable characters + if (32 > $codePoint // C0 control characters + || (0x07F <= $codePoint && 0x0A0 > $codePoint) // C1 control characters and DEL + ) { + return -1; + } + + 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; + while ($ubound >= $lbound) { + $mid = floor(($lbound + $ubound) / 2); + + if ($codePoint > self::$tableZero[$mid][1]) { + $lbound = $mid + 1; + } elseif ($codePoint < self::$tableZero[$mid][0]) { + $ubound = $mid - 1; + } else { + continue 2; + } + } + } + + 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; + while ($ubound >= $lbound) { + $mid = floor(($lbound + $ubound) / 2); + + if ($codePoint > self::$tableWide[$mid][1]) { + $lbound = $mid + 1; + } elseif ($codePoint < self::$tableWide[$mid][0]) { + $ubound = $mid - 1; + } else { + $width += 2; + + continue 2; + } + } + } + + ++$width; + } + + return $width; + } +} diff --git a/vendor/symfony/string/ByteString.php b/vendor/symfony/string/ByteString.php new file mode 100644 index 0000000..626d8c1 --- /dev/null +++ b/vendor/symfony/string/ByteString.php @@ -0,0 +1,509 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +use Symfony\Component\String\Exception\ExceptionInterface; +use Symfony\Component\String\Exception\InvalidArgumentException; +use Symfony\Component\String\Exception\RuntimeException; + +/** + * Represents a binary-safe string of bytes. + * + * @author Nicolas Grekas <p@tchwork.com> + * @author Hugo Hamon <hugohamon@neuf.fr> + * + * @throws ExceptionInterface + */ +class ByteString extends AbstractString +{ + private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; + + public function __construct(string $string = '') + { + $this->string = $string; + } + + /* + * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03) + * + * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16 + * + * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE). + * + * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/) + */ + + 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 = $alphabet ?? self::ALPHABET_ALPHANUMERIC; + $alphabetSize = \strlen($alphabet); + $bits = (int) ceil(log($alphabetSize, 2.0)); + if ($bits <= 0 || $bits > 56) { + throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.'); + } + + $ret = ''; + while ($length > 0) { + $urandomLength = (int) ceil(2 * $length * $bits / 8.0); + $data = random_bytes($urandomLength); + $unpackedData = 0; + $unpackedBits = 0; + for ($i = 0; $i < $urandomLength && $length > 0; ++$i) { + // Unpack 8 bits + $unpackedData = ($unpackedData << 8) | \ord($data[$i]); + $unpackedBits += 8; + + // While we have enough bits to select a character from the alphabet, keep + // consuming the random data + for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) { + $index = ($unpackedData & ((1 << $bits) - 1)); + $unpackedData >>= $bits; + // Unfortunately, the alphabet size is not necessarily a power of two. + // Worst case, it is 2^k + 1, which means we need (k+1) bits and we + // have around a 50% chance of missing as k gets larger + if ($index < $alphabetSize) { + $ret .= $alphabet[$index]; + --$length; + } + } + } + } + + return new static($ret); + } + + public function bytesAt(int $offset): array + { + $str = $this->string[$offset] ?? ''; + + return '' === $str ? [] : [\ord($str)]; + } + + public function append(string ...$suffix): parent + { + $str = clone $this; + $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); + + return $str; + } + + 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); + + return $str; + } + + public function chunk(int $length = 1): array + { + if (1 > $length) { + throw new InvalidArgumentException('The chunk length must be greater than zero.'); + } + + if ('' === $this->string) { + return []; + } + + $str = clone $this; + $chunks = []; + + foreach (str_split($this->string, $length) as $chunk) { + $str->string = $chunk; + $chunks[] = clone $str; + } + + return $chunks; + } + + public function endsWith($suffix): bool + { + if ($suffix instanceof parent) { + $suffix = $suffix->string; + } 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): bool + { + if ($string instanceof parent) { + $string = $string->string; + } elseif (\is_array($string) || $string instanceof \Traversable) { + return parent::equalsTo($string); + } else { + $string = (string) $string; + } + + if ('' !== $string && $this->ignoreCase) { + return 0 === strcasecmp($string, $this->string); + } + + return $string === $this->string; + } + + public function folded(): parent + { + $str = clone $this; + $str->string = strtolower($str->string); + + return $str; + } + + public function indexOf($needle, int $offset = 0): ?int + { + if ($needle instanceof parent) { + $needle = $needle->string; + } elseif (\is_array($needle) || $needle instanceof \Traversable) { + return parent::indexOf($needle, $offset); + } else { + $needle = (string) $needle; + } + + if ('' === $needle) { + return null; + } + + $i = $this->ignoreCase ? stripos($this->string, $needle, $offset) : strpos($this->string, $needle, $offset); + + return false === $i ? null : $i; + } + + public function indexOfLast($needle, int $offset = 0): ?int + { + if ($needle instanceof parent) { + $needle = $needle->string; + } elseif (\is_array($needle) || $needle instanceof \Traversable) { + return parent::indexOfLast($needle, $offset); + } else { + $needle = (string) $needle; + } + + if ('' === $needle) { + return null; + } + + $i = $this->ignoreCase ? strripos($this->string, $needle, $offset) : strrpos($this->string, $needle, $offset); + + return false === $i ? null : $i; + } + + public function isUtf8(): bool + { + return '' === $this->string || preg_match('//u', $this->string); + } + + public function join(array $strings, string $lastGlue = null): parent + { + $str = clone $this; + + $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : ''; + $str->string = implode($this->string, $strings).$tail; + + return $str; + } + + public function length(): int + { + return \strlen($this->string); + } + + public function lower(): parent + { + $str = clone $this; + $str->string = strtolower($str->string); + + return $str; + } + + public function match(string $regexp, int $flags = 0, int $offset = 0): array + { + $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match'; + + if ($this->ignoreCase) { + $regexp .= 'i'; + } + + 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)) { + $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(); + } + + return $matches; + } + + public function padBoth(int $length, string $padStr = ' '): parent + { + $str = clone $this; + $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_BOTH); + + return $str; + } + + public function padEnd(int $length, string $padStr = ' '): parent + { + $str = clone $this; + $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT); + + return $str; + } + + public function padStart(int $length, string $padStr = ' '): parent + { + $str = clone $this; + $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_LEFT); + + return $str; + } + + public function prepend(string ...$prefix): parent + { + $str = clone $this; + $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$str->string; + + return $str; + } + + public function replace(string $from, string $to): parent + { + $str = clone $this; + + if ('' !== $from) { + $str->string = $this->ignoreCase ? str_ireplace($from, $to, $this->string) : str_replace($from, $to, $this->string); + } + + return $str; + } + + public function replaceMatches(string $fromRegexp, $to): parent + { + if ($this->ignoreCase) { + $fromRegexp .= 'i'; + } + + 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 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 && '_ERROR' === substr($k, -6)) { + throw new RuntimeException('Matching failed with '.$k.'.'); + } + } + + throw new RuntimeException('Matching failed with unknown error code.'); + } + } finally { + restore_error_handler(); + } + + $str = clone $this; + $str->string = $string; + + return $str; + } + + public function reverse(): parent + { + $str = clone $this; + $str->string = strrev($str->string); + + return $str; + } + + public function slice(int $start = 0, int $length = null): parent + { + $str = clone $this; + $str->string = (string) substr($this->string, $start, $length ?? \PHP_INT_MAX); + + return $str; + } + + public function snake(): parent + { + $str = $this->camel(); + $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): parent + { + $str = clone $this; + $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); + + return $str; + } + + public function split(string $delimiter, int $limit = null, int $flags = null): array + { + if (1 > $limit = $limit ?? \PHP_INT_MAX) { + throw new InvalidArgumentException('Split limit must be a positive integer.'); + } + + if ('' === $delimiter) { + throw new InvalidArgumentException('Split delimiter is empty.'); + } + + if (null !== $flags) { + return parent::split($delimiter, $limit, $flags); + } + + $str = clone $this; + $chunks = $this->ignoreCase + ? preg_split('{'.preg_quote($delimiter).'}iD', $this->string, $limit) + : explode($delimiter, $this->string, $limit); + + foreach ($chunks as &$chunk) { + $str->string = $chunk; + $chunk = clone $str; + } + + return $chunks; + } + + public function startsWith($prefix): bool + { + if ($prefix instanceof parent) { + $prefix = $prefix->string; + } elseif (!\is_string($prefix)) { + return parent::startsWith($prefix); + } + + return '' !== $prefix && 0 === ($this->ignoreCase ? strncasecmp($this->string, $prefix, \strlen($prefix)) : strncmp($this->string, $prefix, \strlen($prefix))); + } + + public function title(bool $allWords = false): parent + { + $str = clone $this; + $str->string = $allWords ? ucwords($str->string) : ucfirst($str->string); + + return $str; + } + + public function toUnicodeString(string $fromEncoding = null): UnicodeString + { + return new UnicodeString($this->toCodePointString($fromEncoding)->string); + } + + public function toCodePointString(string $fromEncoding = null): CodePointString + { + $u = new CodePointString(); + + if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], true) && preg_match('//u', $this->string)) { + $u->string = $this->string; + + return $u; + } + + set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); + + try { + try { + $validEncoding = false !== mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', true); + } catch (InvalidArgumentException $e) { + if (!\function_exists('iconv')) { + throw $e; + } + + $u->string = iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string); + + return $u; + } + } finally { + restore_error_handler(); + } + + if (!$validEncoding) { + throw new InvalidArgumentException(sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252')); + } + + $u->string = mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252'); + + return $u; + } + + public function trim(string $chars = " \t\n\r\0\x0B\x0C"): parent + { + $str = clone $this; + $str->string = trim($str->string, $chars); + + return $str; + } + + public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C"): parent + { + $str = clone $this; + $str->string = rtrim($str->string, $chars); + + return $str; + } + + public function trimStart(string $chars = " \t\n\r\0\x0B\x0C"): parent + { + $str = clone $this; + $str->string = ltrim($str->string, $chars); + + return $str; + } + + public function upper(): parent + { + $str = clone $this; + $str->string = strtoupper($str->string); + + return $str; + } + + public function width(bool $ignoreAnsiDecoration = true): int + { + $string = preg_match('//u', $this->string) ? $this->string : preg_replace('/[\x80-\xFF]/', '?', $this->string); + + return (new CodePointString($string))->width($ignoreAnsiDecoration); + } +} diff --git a/vendor/symfony/string/CHANGELOG.md b/vendor/symfony/string/CHANGELOG.md new file mode 100644 index 0000000..53af364 --- /dev/null +++ b/vendor/symfony/string/CHANGELOG.md @@ -0,0 +1,35 @@ +CHANGELOG +========= + +5.4 +--- + + * Add `trimSuffix()` and `trimPrefix()` methods + +5.3 +--- + + * Made `AsciiSlugger` fallback to parent locale's symbolsMap + +5.2.0 +----- + + * added a `FrenchInflector` class + +5.1.0 +----- + + * added the `AbstractString::reverse()` method + * made `AbstractString::width()` follow POSIX.1-2001 + * added `LazyString` which provides memoizing stringable objects + * The component is not marked as `@experimental` anymore + * added the `s()` helper method to get either an `UnicodeString` or `ByteString` instance, + depending of the input string UTF-8 compliancy + * added `$cut` parameter to `Symfony\Component\String\AbstractString::truncate()` + * added `AbstractString::containsAny()` + * allow passing a string of custom characters to `ByteString::fromRandom()` + +5.0.0 +----- + + * added the component as experimental diff --git a/vendor/symfony/string/CodePointString.php b/vendor/symfony/string/CodePointString.php new file mode 100644 index 0000000..8ab9209 --- /dev/null +++ b/vendor/symfony/string/CodePointString.php @@ -0,0 +1,270 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +use Symfony\Component\String\Exception\ExceptionInterface; +use Symfony\Component\String\Exception\InvalidArgumentException; + +/** + * Represents a string of Unicode code points encoded as UTF-8. + * + * @author Nicolas Grekas <p@tchwork.com> + * @author Hugo Hamon <hugohamon@neuf.fr> + * + * @throws ExceptionInterface + */ +class CodePointString extends AbstractUnicodeString +{ + public function __construct(string $string = '') + { + if ('' !== $string && !preg_match('//u', $string)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + $this->string = $string; + } + + public function append(string ...$suffix): AbstractString + { + $str = clone $this; + $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); + + if (!preg_match('//u', $str->string)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function chunk(int $length = 1): array + { + if (1 > $length) { + throw new InvalidArgumentException('The chunk length must be greater than zero.'); + } + + if ('' === $this->string) { + return []; + } + + $rx = '/('; + while (65535 < $length) { + $rx .= '.{65535}'; + $length -= 65535; + } + $rx .= '.{'.$length.'})/us'; + + $str = clone $this; + $chunks = []; + + foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { + $str->string = $chunk; + $chunks[] = clone $str; + } + + return $chunks; + } + + public function codePointsAt(int $offset): array + { + $str = $offset ? $this->slice($offset, 1) : $this; + + return '' === $str->string ? [] : [mb_ord($str->string, 'UTF-8')]; + } + + public function endsWith($suffix): bool + { + if ($suffix instanceof AbstractString) { + $suffix = $suffix->string; + } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { + return parent::endsWith($suffix); + } else { + $suffix = (string) $suffix; + } + + if ('' === $suffix || !preg_match('//u', $suffix)) { + return false; + } + + if ($this->ignoreCase) { + return preg_match('{'.preg_quote($suffix).'$}iuD', $this->string); + } + + return \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix)); + } + + public function equalsTo($string): bool + { + if ($string instanceof AbstractString) { + $string = $string->string; + } elseif (\is_array($string) || $string instanceof \Traversable) { + return parent::equalsTo($string); + } else { + $string = (string) $string; + } + + if ('' !== $string && $this->ignoreCase) { + return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8'); + } + + return $string === $this->string; + } + + public function indexOf($needle, int $offset = 0): ?int + { + if ($needle instanceof AbstractString) { + $needle = $needle->string; + } elseif (\is_array($needle) || $needle instanceof \Traversable) { + return parent::indexOf($needle, $offset); + } else { + $needle = (string) $needle; + } + + if ('' === $needle) { + return null; + } + + $i = $this->ignoreCase ? mb_stripos($this->string, $needle, $offset, 'UTF-8') : mb_strpos($this->string, $needle, $offset, 'UTF-8'); + + return false === $i ? null : $i; + } + + public function indexOfLast($needle, int $offset = 0): ?int + { + if ($needle instanceof AbstractString) { + $needle = $needle->string; + } elseif (\is_array($needle) || $needle instanceof \Traversable) { + return parent::indexOfLast($needle, $offset); + } else { + $needle = (string) $needle; + } + + if ('' === $needle) { + return null; + } + + $i = $this->ignoreCase ? mb_strripos($this->string, $needle, $offset, 'UTF-8') : mb_strrpos($this->string, $needle, $offset, 'UTF-8'); + + return false === $i ? null : $i; + } + + public function length(): int + { + return mb_strlen($this->string, 'UTF-8'); + } + + public function prepend(string ...$prefix): AbstractString + { + $str = clone $this; + $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string; + + if (!preg_match('//u', $str->string)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function replace(string $from, string $to): AbstractString + { + $str = clone $this; + + if ('' === $from || !preg_match('//u', $from)) { + return $str; + } + + if ('' !== $to && !preg_match('//u', $to)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + if ($this->ignoreCase) { + $str->string = implode($to, preg_split('{'.preg_quote($from).'}iuD', $this->string)); + } else { + $str->string = str_replace($from, $to, $this->string); + } + + return $str; + } + + public function slice(int $start = 0, int $length = null): AbstractString + { + $str = clone $this; + $str->string = mb_substr($this->string, $start, $length, 'UTF-8'); + + return $str; + } + + public function splice(string $replacement, int $start = 0, int $length = null): AbstractString + { + if (!preg_match('//u', $replacement)) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + $str = clone $this; + $start = $start ? \strlen(mb_substr($this->string, 0, $start, 'UTF-8')) : 0; + $length = $length ? \strlen(mb_substr($this->string, $start, $length, 'UTF-8')) : $length; + $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); + + return $str; + } + + public function split(string $delimiter, int $limit = null, int $flags = null): array + { + if (1 > $limit = $limit ?? \PHP_INT_MAX) { + throw new InvalidArgumentException('Split limit must be a positive integer.'); + } + + if ('' === $delimiter) { + throw new InvalidArgumentException('Split delimiter is empty.'); + } + + if (null !== $flags) { + return parent::split($delimiter.'u', $limit, $flags); + } + + if (!preg_match('//u', $delimiter)) { + throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); + } + + $str = clone $this; + $chunks = $this->ignoreCase + ? preg_split('{'.preg_quote($delimiter).'}iuD', $this->string, $limit) + : explode($delimiter, $this->string, $limit); + + foreach ($chunks as &$chunk) { + $str->string = $chunk; + $chunk = clone $str; + } + + return $chunks; + } + + public function startsWith($prefix): bool + { + if ($prefix instanceof AbstractString) { + $prefix = $prefix->string; + } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { + return parent::startsWith($prefix); + } else { + $prefix = (string) $prefix; + } + + if ('' === $prefix || !preg_match('//u', $prefix)) { + return false; + } + + if ($this->ignoreCase) { + return 0 === mb_stripos($this->string, $prefix, 0, 'UTF-8'); + } + + return 0 === strncmp($this->string, $prefix, \strlen($prefix)); + } +} diff --git a/vendor/symfony/console/Tests/Fixtures/DescriptorApplication1.php b/vendor/symfony/string/Exception/ExceptionInterface.php similarity index 62% rename from vendor/symfony/console/Tests/Fixtures/DescriptorApplication1.php rename to vendor/symfony/string/Exception/ExceptionInterface.php index 132b6d5..3619786 100644 --- a/vendor/symfony/console/Tests/Fixtures/DescriptorApplication1.php +++ b/vendor/symfony/string/Exception/ExceptionInterface.php @@ -9,10 +9,8 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Console\Tests\Fixtures; +namespace Symfony\Component\String\Exception; -use Symfony\Component\Console\Application; - -class DescriptorApplication1 extends Application +interface ExceptionInterface extends \Throwable { } diff --git a/vendor/symfony/process/Tests/SignalListener.php b/vendor/symfony/string/Exception/InvalidArgumentException.php similarity index 60% rename from vendor/symfony/process/Tests/SignalListener.php rename to vendor/symfony/string/Exception/InvalidArgumentException.php index 9e30ce3..6aa586b 100644 --- a/vendor/symfony/process/Tests/SignalListener.php +++ b/vendor/symfony/string/Exception/InvalidArgumentException.php @@ -9,13 +9,8 @@ * file that was distributed with this source code. */ -pcntl_signal(SIGUSR1, function () { echo 'SIGUSR1'; exit; }); +namespace Symfony\Component\String\Exception; -echo 'Caught '; - -$n = 0; - -while ($n++ < 400) { - usleep(10000); - pcntl_signal_dispatch(); +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ } diff --git a/vendor/symfony/string/Exception/RuntimeException.php b/vendor/symfony/string/Exception/RuntimeException.php new file mode 100644 index 0000000..77cb091 --- /dev/null +++ b/vendor/symfony/string/Exception/RuntimeException.php @@ -0,0 +1,16 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String\Exception; + +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/string/Inflector/EnglishInflector.php b/vendor/symfony/string/Inflector/EnglishInflector.php new file mode 100644 index 0000000..edd94db --- /dev/null +++ b/vendor/symfony/string/Inflector/EnglishInflector.php @@ -0,0 +1,517 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String\Inflector; + +final class EnglishInflector implements InflectorInterface +{ + /** + * Map English plural to singular suffixes. + * + * @see http://english-zone.com/spelling/plurals.html + */ + private const PLURAL_MAP = [ + // First entry: plural suffix, reversed + // Second entry: length of plural suffix + // 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), criteria (criterion), phenomena (phenomenon) + ['a', 1, true, true, ['on', 'um']], + + // nebulae (nebula) + ['ea', 2, true, true, 'a'], + + // services (service) + ['secivres', 8, true, true, 'service'], + + // mice (mouse), lice (louse) + ['eci', 3, false, true, 'ouse'], + + // geese (goose) + ['esee', 4, false, true, 'oose'], + + // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) + ['i', 1, true, true, 'us'], + + // men (man), women (woman) + ['nem', 3, true, true, 'man'], + + // children (child) + ['nerdlihc', 8, true, true, 'child'], + + // oxen (ox) + ['nexo', 4, false, false, 'ox'], + + // 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'], + + // zombies (zombie) + ['seibmoz', 7, true, true, 'zombie'], + + // movies (movie) + ['seivom', 6, true, true, 'movie'], + + // names (name) + ['seman', 5, true, false, 'name'], + + // conspectuses (conspectus), prospectuses (prospectus) + ['sesutcep', 8, true, true, 'pectus'], + + // feet (foot) + ['teef', 4, true, true, 'foot'], + + // geese (goose) + ['eseeg', 5, true, true, 'goose'], + + // teeth (tooth) + ['hteet', 5, true, true, 'tooth'], + + // news (news) + ['swen', 4, true, true, 'news'], + + // series (series) + ['seires', 6, true, true, 'series'], + + // babies (baby) + ['sei', 3, false, true, 'y'], + + // accesses (access), addresses (address), kisses (kiss) + ['sess', 4, true, false, 'ss'], + + // analyses (analysis), ellipses (ellipsis), fungi (fungus), + // neuroses (neurosis), theses (thesis), emphases (emphasis), + // oases (oasis), crises (crisis), houses (house), bases (base), + // atlases (atlas) + ['ses', 3, true, true, ['s', 'se', 'sis']], + + // objectives (objective), alternative (alternatives) + ['sevit', 5, true, true, 'tive'], + + // drives (drive) + ['sevird', 6, false, true, 'drive'], + + // lives (life), wives (wife) + ['sevi', 4, false, true, 'ife'], + + // moves (move) + ['sevom', 5, true, true, 'move'], + + // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff) + ['sev', 3, true, true, ['f', 've', 'ff']], + + // axes (axis), axes (ax), axes (axe) + ['sexa', 4, false, false, ['ax', 'axe', 'axis']], + + // indexes (index), matrixes (matrix) + ['sex', 3, true, false, 'x'], + + // quizzes (quiz) + ['sezz', 4, true, false, 'z'], + + // bureaus (bureau) + ['suae', 4, false, true, 'eau'], + + // fees (fee), trees (tree), employees (employee) + ['see', 3, true, true, 'ee'], + + // edges (edge) + ['segd', 4, true, true, 'dge'], + + // roses (rose), garages (garage), cassettes (cassette), + // waltzes (waltz), heroes (hero), bushes (bush), arches (arch), + // shoes (shoe) + ['se', 2, true, true, ['', 'e']], + + // tags (tag) + ['s', 1, true, true, ''], + + // chateaux (chateau) + ['xuae', 4, false, true, 'eau'], + + // people (person) + ['elpoep', 6, true, true, 'person'], + ]; + + /** + * Map English singular to plural suffixes. + * + * @see http://english-zone.com/spelling/plurals.html + */ + private const SINGULAR_MAP = [ + // First entry: singular suffix, reversed + // Second entry: length of singular suffix + // Third entry: Whether the suffix may succeed a vocal + // Fourth entry: Whether the suffix may succeed a consonant + // Fifth entry: plural suffix, normal + + // criterion (criteria) + ['airetirc', 8, false, false, 'criterion'], + + // nebulae (nebula) + ['aluben', 6, false, false, 'nebulae'], + + // children (child) + ['dlihc', 5, true, true, 'children'], + + // prices (price) + ['eci', 3, false, true, 'ices'], + + // services (service) + ['ecivres', 7, true, true, 'services'], + + // lives (life), wives (wife) + ['efi', 3, false, true, 'ives'], + + // selfies (selfie) + ['eifles', 6, true, true, 'selfies'], + + // movies (movie) + ['eivom', 5, true, true, 'movies'], + + // lice (louse) + ['esuol', 5, false, true, 'lice'], + + // mice (mouse) + ['esuom', 5, false, true, 'mice'], + + // geese (goose) + ['esoo', 4, false, true, 'eese'], + + // houses (house), bases (base) + ['es', 2, true, true, 'ses'], + + // geese (goose) + ['esoog', 5, true, true, 'geese'], + + // caves (cave) + ['ev', 2, true, true, 'ves'], + + // drives (drive) + ['evird', 5, false, true, 'drives'], + + // objectives (objective), alternative (alternatives) + ['evit', 4, true, true, 'tives'], + + // moves (move) + ['evom', 4, true, true, 'moves'], + + // staves (staff) + ['ffats', 5, true, true, 'staves'], + + // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) + ['ff', 2, true, true, 'ffs'], + + // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) + ['f', 1, true, true, ['fs', 'ves']], + + // arches (arch) + ['hc', 2, true, true, 'ches'], + + // bushes (bush) + ['hs', 2, true, true, 'shes'], + + // teeth (tooth) + ['htoot', 5, true, true, 'teeth'], + + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) + ['mu', 2, true, true, 'a'], + + // men (man), women (woman) + ['nam', 3, true, true, 'men'], + + // people (person) + ['nosrep', 6, true, true, ['persons', 'people']], + + // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) + ['noi', 3, true, true, 'ions'], + + // coupon (coupons) + ['nop', 3, true, true, 'pons'], + + // 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'], + + // heroes (hero) + ['oreh', 4, true, true, 'heroes'], + + // atlases (atlas) + ['salta', 5, true, true, 'atlases'], + + // irises (iris) + ['siri', 4, true, true, 'irises'], + + // analyses (analysis), ellipses (ellipsis), neuroses (neurosis) + // theses (thesis), emphases (emphasis), oases (oasis), + // crises (crisis) + ['sis', 3, true, true, 'ses'], + + // accesses (access), addresses (address), kisses (kiss) + ['ss', 2, true, false, 'sses'], + + // syllabi (syllabus) + ['suballys', 8, true, true, 'syllabi'], + + // buses (bus) + ['sub', 3, true, true, 'buses'], + + // circuses (circus) + ['suc', 3, true, true, 'cuses'], + + // conspectuses (conspectus), prospectuses (prospectus) + ['sutcep', 6, true, true, 'pectuses'], + + // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) + ['su', 2, true, true, 'i'], + + // news (news) + ['swen', 4, true, true, 'news'], + + // feet (foot) + ['toof', 4, true, true, 'feet'], + + // chateaux (chateau), bureaus (bureau) + ['uae', 3, false, true, ['eaus', 'eaux']], + + // oxen (ox) + ['xo', 2, false, false, 'oxen'], + + // hoaxes (hoax) + ['xaoh', 4, true, false, 'hoaxes'], + + // indices (index) + ['xedni', 5, false, true, ['indicies', 'indexes']], + + // boxes (box) + ['xo', 2, false, true, 'oxes'], + + // indexes (index), matrixes (matrix) + ['x', 1, true, false, ['cies', 'xes']], + + // appendices (appendix) + ['xi', 2, false, true, 'ices'], + + // babies (baby) + ['y', 1, false, true, 'ies'], + + // quizzes (quiz) + ['ziuq', 4, true, false, 'quizzes'], + + // waltzes (waltz) + ['z', 1, true, true, 'zes'], + ]; + + /** + * A list of words which should not be inflected, reversed. + */ + private const UNINFLECTED = [ + '', + + // data + 'atad', + + // deer + 'reed', + + // feedback + 'kcabdeef', + + // fish + 'hsif', + + // info + 'ofni', + + // moose + 'esoom', + + // series + 'seires', + + // sheep + 'peehs', + + // species + 'seiceps', + ]; + + /** + * {@inheritdoc} + */ + public function singularize(string $plural): array + { + $pluralRev = strrev($plural); + $lowerPluralRev = strtolower($pluralRev); + $pluralLength = \strlen($lowerPluralRev); + + // Check if the word is one which is not inflected, return early if so + if (\in_array($lowerPluralRev, self::UNINFLECTED, true)) { + return [$plural]; + } + + // The outer loop iterates over the entries of the plural table + // The inner loop $j iterates over the characters of the plural suffix + // in the plural table to compare them with the characters of the actual + // given plural suffix + foreach (self::PLURAL_MAP as $map) { + $suffix = $map[0]; + $suffixLength = $map[1]; + $j = 0; + + // Compare characters in the plural table and of the suffix of the + // given plural one by one + while ($suffix[$j] === $lowerPluralRev[$j]) { + // Let $j point to the next character + ++$j; + + // Successfully compared the last character + // Add an entry with the singular suffix to the singular array + if ($j === $suffixLength) { + // Is there any character preceding the suffix in the plural string? + if ($j < $pluralLength) { + $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]); + + if (!$map[2] && $nextIsVocal) { + // suffix may not succeed a vocal but next char is one + break; + } + + if (!$map[3] && !$nextIsVocal) { + // suffix may not succeed a consonant but next char is one + break; + } + } + + $newBase = substr($plural, 0, $pluralLength - $suffixLength); + $newSuffix = $map[4]; + + // Check whether the first character in the plural suffix + // is uppercased. If yes, uppercase the first character in + // the singular suffix too + $firstUpper = ctype_upper($pluralRev[$j - 1]); + + if (\is_array($newSuffix)) { + $singulars = []; + + foreach ($newSuffix as $newSuffixEntry) { + $singulars[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); + } + + return $singulars; + } + + return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; + } + + // Suffix is longer than word + if ($j === $pluralLength) { + break; + } + } + } + + // Assume that plural and singular is identical + return [$plural]; + } + + /** + * {@inheritdoc} + */ + public function pluralize(string $singular): array + { + $singularRev = strrev($singular); + $lowerSingularRev = strtolower($singularRev); + $singularLength = \strlen($lowerSingularRev); + + // Check if the word is one which is not inflected, return early if so + if (\in_array($lowerSingularRev, self::UNINFLECTED, true)) { + return [$singular]; + } + + // The outer loop iterates over the entries of the singular table + // The inner loop $j iterates over the characters of the singular suffix + // in the singular table to compare them with the characters of the actual + // given singular suffix + foreach (self::SINGULAR_MAP as $map) { + $suffix = $map[0]; + $suffixLength = $map[1]; + $j = 0; + + // Compare characters in the singular table and of the suffix of the + // given plural one by one + + while ($suffix[$j] === $lowerSingularRev[$j]) { + // Let $j point to the next character + ++$j; + + // Successfully compared the last character + // Add an entry with the plural suffix to the plural array + if ($j === $suffixLength) { + // Is there any character preceding the suffix in the plural string? + if ($j < $singularLength) { + $nextIsVocal = false !== strpos('aeiou', $lowerSingularRev[$j]); + + if (!$map[2] && $nextIsVocal) { + // suffix may not succeed a vocal but next char is one + break; + } + + if (!$map[3] && !$nextIsVocal) { + // suffix may not succeed a consonant but next char is one + break; + } + } + + $newBase = substr($singular, 0, $singularLength - $suffixLength); + $newSuffix = $map[4]; + + // Check whether the first character in the singular suffix + // is uppercased. If yes, uppercase the first character in + // the singular suffix too + $firstUpper = ctype_upper($singularRev[$j - 1]); + + if (\is_array($newSuffix)) { + $plurals = []; + + foreach ($newSuffix as $newSuffixEntry) { + $plurals[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); + } + + return $plurals; + } + + return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; + } + + // Suffix is longer than word + if ($j === $singularLength) { + break; + } + } + } + + // Assume that plural is singular with a trailing `s` + return [$singular.'s']; + } +} diff --git a/vendor/symfony/string/Inflector/FrenchInflector.php b/vendor/symfony/string/Inflector/FrenchInflector.php new file mode 100644 index 0000000..612c8f2 --- /dev/null +++ b/vendor/symfony/string/Inflector/FrenchInflector.php @@ -0,0 +1,157 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String\Inflector; + +/** + * French inflector. + * + * This class does only inflect nouns; not adjectives nor composed words like "soixante-dix". + */ +final class FrenchInflector implements InflectorInterface +{ + /** + * A list of all rules for pluralise. + * + * @see https://la-conjugaison.nouvelobs.com/regles/grammaire/le-pluriel-des-noms-121.php + */ + private const PLURALIZE_REGEXP = [ + // First entry: regexp + // Second entry: replacement + + // Words finishing with "s", "x" or "z" are invariables + // Les mots finissant par "s", "x" ou "z" sont invariables + ['/(s|x|z)$/i', '\1'], + + // Words finishing with "eau" are pluralized with a "x" + // Les mots finissant par "eau" prennent tous un "x" au pluriel + ['/(eau)$/i', '\1x'], + + // Words finishing with "au" are pluralized with a "x" excepted "landau" + // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" + ['/^(landau)$/i', '\1s'], + ['/(au)$/i', '\1x'], + + // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" + // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" + ['/^(pneu|bleu|émeu)$/i', '\1s'], + ['/(eu)$/i', '\1x'], + + // Words finishing with "al" are pluralized with a "aux" excepted + // Les mots finissant en "al" se terminent en "aux" sauf + ['/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\1s'], + ['/al$/i', '\1aux'], + + // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux + ['/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\1aux'], + + // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel + ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\1oux'], + + // Invariable words + ['/^(cinquante|soixante|mille)$/i', '\1'], + + // French titles + ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'mes\2s'], + ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'Mes\2s'], + ]; + + /** + * A list of all rules for singularize. + */ + private const SINGULARIZE_REGEXP = [ + // First entry: regexp + // Second entry: replacement + + // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux + ['/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\1ail'], + + // Words finishing with "eau" are pluralized with a "x" + // Les mots finissant par "eau" prennent tous un "x" au pluriel + ['/(eau)x$/i', '\1'], + + // Words finishing with "al" are pluralized with a "aux" expected + // Les mots finissant en "al" se terminent en "aux" sauf + ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\1al'], + + // Words finishing with "au" are pluralized with a "x" excepted "landau" + // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" + ['/(au)x$/i', '\1'], + + // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" + // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" + ['/(eu)x$/i', '\1'], + + // Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou + // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou + ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\1ou'], + + // French titles + ['/^mes(dame|demoiselle)s$/', 'ma\1'], + ['/^Mes(dame|demoiselle)s$/', 'Ma\1'], + ['/^mes(sieur|seigneur)s$/', 'mon\1'], + ['/^Mes(sieur|seigneur)s$/', 'Mon\1'], + + // Default rule + ['/s$/i', ''], + ]; + + /** + * 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'; + + /** + * {@inheritdoc} + */ + public function singularize(string $plural): array + { + if ($this->isInflectedWord($plural)) { + return [$plural]; + } + + foreach (self::SINGULARIZE_REGEXP as $rule) { + [$regexp, $replace] = $rule; + + if (1 === preg_match($regexp, $plural)) { + return [preg_replace($regexp, $replace, $plural)]; + } + } + + return [$plural]; + } + + /** + * {@inheritdoc} + */ + public function pluralize(string $singular): array + { + if ($this->isInflectedWord($singular)) { + return [$singular]; + } + + foreach (self::PLURALIZE_REGEXP as $rule) { + [$regexp, $replace] = $rule; + + if (1 === preg_match($regexp, $singular)) { + return [preg_replace($regexp, $replace, $singular)]; + } + } + + return [$singular.'s']; + } + + private function isInflectedWord(string $word): bool + { + return 1 === preg_match(self::UNINFLECTED, $word); + } +} diff --git a/vendor/symfony/string/Inflector/InflectorInterface.php b/vendor/symfony/string/Inflector/InflectorInterface.php new file mode 100644 index 0000000..67f2834 --- /dev/null +++ b/vendor/symfony/string/Inflector/InflectorInterface.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String\Inflector; + +interface InflectorInterface +{ + /** + * Returns the singular forms of a string. + * + * If the method can't determine the form with certainty, several possible singulars are returned. + * + * @return string[] + */ + public function singularize(string $plural): array; + + /** + * Returns the plural forms of a string. + * + * If the method can't determine the form with certainty, several possible plurals are returned. + * + * @return string[] + */ + public function pluralize(string $singular): array; +} diff --git a/vendor/symfony/string/LICENSE b/vendor/symfony/string/LICENSE new file mode 100644 index 0000000..f37c76b --- /dev/null +++ b/vendor/symfony/string/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2019-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +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/vendor/symfony/string/LazyString.php b/vendor/symfony/string/LazyString.php new file mode 100644 index 0000000..9c7a9c5 --- /dev/null +++ b/vendor/symfony/string/LazyString.php @@ -0,0 +1,164 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +/** + * A string whose value is computed lazily by a callback. + * + * @author Nicolas Grekas <p@tchwork.com> + */ +class LazyString implements \Stringable, \JsonSerializable +{ + private $value; + + /** + * @param callable|array $callback A callable or a [Closure, method] lazy-callable + * + * @return static + */ + public static function fromCallable($callback, ...$arguments): self + { + 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, &$value): string { + if (null !== $arguments) { + if (!\is_callable($callback)) { + $callback[0] = $callback[0](); + $callback[1] = $callback[1] ?? '__invoke'; + } + $value = $callback(...$arguments); + $callback = self::getPrettyName($callback); + $arguments = null; + } + + return $value ?? ''; + }; + + return $lazyString; + } + + /** + * @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']); + } + + $lazyString = new static(); + $lazyString->value = (string) $value; + + return $lazyString; + } + + /** + * Tells whether the provided value can be cast to string. + */ + final public static function isStringable($value): bool + { + 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($value): string + { + return $value; + } + + /** + * @return string + */ + public function __toString() + { + if (\is_string($this->value)) { + return $this->value; + } + + try { + return $this->value = ($this->value)(); + } catch (\Throwable $e) { + 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); + $callback = $r->getStaticVariables()['callback']; + + $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; + } + } + + public function __sleep(): array + { + $this->__toString(); + + return ['value']; + } + + public function jsonSerialize(): string + { + return $this->__toString(); + } + + private function __construct() + { + } + + private static function getPrettyName(callable $callback): string + { + if (\is_string($callback)) { + return $callback; + } + + if (\is_array($callback)) { + $class = \is_object($callback[0]) ? get_debug_type($callback[0]) : $callback[0]; + $method = $callback[1]; + } elseif ($callback instanceof \Closure) { + $r = new \ReflectionFunction($callback); + + if (false !== strpos($r->name, '{closure}') || !$class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { + return $r->name; + } + + $class = $class->name; + $method = $r->name; + } else { + $class = get_debug_type($callback); + $method = '__invoke'; + } + + return $class.'::'.$method; + } +} diff --git a/vendor/symfony/string/README.md b/vendor/symfony/string/README.md new file mode 100644 index 0000000..9c7e1e1 --- /dev/null +++ b/vendor/symfony/string/README.md @@ -0,0 +1,14 @@ +String Component +================ + +The String component provides an object-oriented API to strings and deals +with bytes, UTF-8 code points and grapheme clusters in a unified way. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/string.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/string/Resources/data/wcswidth_table_wide.php b/vendor/symfony/string/Resources/data/wcswidth_table_wide.php new file mode 100644 index 0000000..5a647e6 --- /dev/null +++ b/vendor/symfony/string/Resources/data/wcswidth_table_wide.php @@ -0,0 +1,1143 @@ +<?php + +/* + * This file has been auto-generated by the Symfony String Component for internal use. + * + * Unicode version: 15.0.0 + * Date: 2022-10-05T17:16:36+02:00 + */ + +return [ + [ + 4352, + 4447, + ], + [ + 8986, + 8987, + ], + [ + 9001, + 9001, + ], + [ + 9002, + 9002, + ], + [ + 9193, + 9196, + ], + [ + 9200, + 9200, + ], + [ + 9203, + 9203, + ], + [ + 9725, + 9726, + ], + [ + 9748, + 9749, + ], + [ + 9800, + 9811, + ], + [ + 9855, + 9855, + ], + [ + 9875, + 9875, + ], + [ + 9889, + 9889, + ], + [ + 9898, + 9899, + ], + [ + 9917, + 9918, + ], + [ + 9924, + 9925, + ], + [ + 9934, + 9934, + ], + [ + 9940, + 9940, + ], + [ + 9962, + 9962, + ], + [ + 9970, + 9971, + ], + [ + 9973, + 9973, + ], + [ + 9978, + 9978, + ], + [ + 9981, + 9981, + ], + [ + 9989, + 9989, + ], + [ + 9994, + 9995, + ], + [ + 10024, + 10024, + ], + [ + 10060, + 10060, + ], + [ + 10062, + 10062, + ], + [ + 10067, + 10069, + ], + [ + 10071, + 10071, + ], + [ + 10133, + 10135, + ], + [ + 10160, + 10160, + ], + [ + 10175, + 10175, + ], + [ + 11035, + 11036, + ], + [ + 11088, + 11088, + ], + [ + 11093, + 11093, + ], + [ + 11904, + 11929, + ], + [ + 11931, + 12019, + ], + [ + 12032, + 12245, + ], + [ + 12272, + 12283, + ], + [ + 12288, + 12288, + ], + [ + 12289, + 12291, + ], + [ + 12292, + 12292, + ], + [ + 12293, + 12293, + ], + [ + 12294, + 12294, + ], + [ + 12295, + 12295, + ], + [ + 12296, + 12296, + ], + [ + 12297, + 12297, + ], + [ + 12298, + 12298, + ], + [ + 12299, + 12299, + ], + [ + 12300, + 12300, + ], + [ + 12301, + 12301, + ], + [ + 12302, + 12302, + ], + [ + 12303, + 12303, + ], + [ + 12304, + 12304, + ], + [ + 12305, + 12305, + ], + [ + 12306, + 12307, + ], + [ + 12308, + 12308, + ], + [ + 12309, + 12309, + ], + [ + 12310, + 12310, + ], + [ + 12311, + 12311, + ], + [ + 12312, + 12312, + ], + [ + 12313, + 12313, + ], + [ + 12314, + 12314, + ], + [ + 12315, + 12315, + ], + [ + 12316, + 12316, + ], + [ + 12317, + 12317, + ], + [ + 12318, + 12319, + ], + [ + 12320, + 12320, + ], + [ + 12321, + 12329, + ], + [ + 12330, + 12333, + ], + [ + 12334, + 12335, + ], + [ + 12336, + 12336, + ], + [ + 12337, + 12341, + ], + [ + 12342, + 12343, + ], + [ + 12344, + 12346, + ], + [ + 12347, + 12347, + ], + [ + 12348, + 12348, + ], + [ + 12349, + 12349, + ], + [ + 12350, + 12350, + ], + [ + 12353, + 12438, + ], + [ + 12441, + 12442, + ], + [ + 12443, + 12444, + ], + [ + 12445, + 12446, + ], + [ + 12447, + 12447, + ], + [ + 12448, + 12448, + ], + [ + 12449, + 12538, + ], + [ + 12539, + 12539, + ], + [ + 12540, + 12542, + ], + [ + 12543, + 12543, + ], + [ + 12549, + 12591, + ], + [ + 12593, + 12686, + ], + [ + 12688, + 12689, + ], + [ + 12690, + 12693, + ], + [ + 12694, + 12703, + ], + [ + 12704, + 12735, + ], + [ + 12736, + 12771, + ], + [ + 12784, + 12799, + ], + [ + 12800, + 12830, + ], + [ + 12832, + 12841, + ], + [ + 12842, + 12871, + ], + [ + 12880, + 12880, + ], + [ + 12881, + 12895, + ], + [ + 12896, + 12927, + ], + [ + 12928, + 12937, + ], + [ + 12938, + 12976, + ], + [ + 12977, + 12991, + ], + [ + 12992, + 13055, + ], + [ + 13056, + 13311, + ], + [ + 13312, + 19903, + ], + [ + 19968, + 40959, + ], + [ + 40960, + 40980, + ], + [ + 40981, + 40981, + ], + [ + 40982, + 42124, + ], + [ + 42128, + 42182, + ], + [ + 43360, + 43388, + ], + [ + 44032, + 55203, + ], + [ + 63744, + 64109, + ], + [ + 64110, + 64111, + ], + [ + 64112, + 64217, + ], + [ + 64218, + 64255, + ], + [ + 65040, + 65046, + ], + [ + 65047, + 65047, + ], + [ + 65048, + 65048, + ], + [ + 65049, + 65049, + ], + [ + 65072, + 65072, + ], + [ + 65073, + 65074, + ], + [ + 65075, + 65076, + ], + [ + 65077, + 65077, + ], + [ + 65078, + 65078, + ], + [ + 65079, + 65079, + ], + [ + 65080, + 65080, + ], + [ + 65081, + 65081, + ], + [ + 65082, + 65082, + ], + [ + 65083, + 65083, + ], + [ + 65084, + 65084, + ], + [ + 65085, + 65085, + ], + [ + 65086, + 65086, + ], + [ + 65087, + 65087, + ], + [ + 65088, + 65088, + ], + [ + 65089, + 65089, + ], + [ + 65090, + 65090, + ], + [ + 65091, + 65091, + ], + [ + 65092, + 65092, + ], + [ + 65093, + 65094, + ], + [ + 65095, + 65095, + ], + [ + 65096, + 65096, + ], + [ + 65097, + 65100, + ], + [ + 65101, + 65103, + ], + [ + 65104, + 65106, + ], + [ + 65108, + 65111, + ], + [ + 65112, + 65112, + ], + [ + 65113, + 65113, + ], + [ + 65114, + 65114, + ], + [ + 65115, + 65115, + ], + [ + 65116, + 65116, + ], + [ + 65117, + 65117, + ], + [ + 65118, + 65118, + ], + [ + 65119, + 65121, + ], + [ + 65122, + 65122, + ], + [ + 65123, + 65123, + ], + [ + 65124, + 65126, + ], + [ + 65128, + 65128, + ], + [ + 65129, + 65129, + ], + [ + 65130, + 65131, + ], + [ + 65281, + 65283, + ], + [ + 65284, + 65284, + ], + [ + 65285, + 65287, + ], + [ + 65288, + 65288, + ], + [ + 65289, + 65289, + ], + [ + 65290, + 65290, + ], + [ + 65291, + 65291, + ], + [ + 65292, + 65292, + ], + [ + 65293, + 65293, + ], + [ + 65294, + 65295, + ], + [ + 65296, + 65305, + ], + [ + 65306, + 65307, + ], + [ + 65308, + 65310, + ], + [ + 65311, + 65312, + ], + [ + 65313, + 65338, + ], + [ + 65339, + 65339, + ], + [ + 65340, + 65340, + ], + [ + 65341, + 65341, + ], + [ + 65342, + 65342, + ], + [ + 65343, + 65343, + ], + [ + 65344, + 65344, + ], + [ + 65345, + 65370, + ], + [ + 65371, + 65371, + ], + [ + 65372, + 65372, + ], + [ + 65373, + 65373, + ], + [ + 65374, + 65374, + ], + [ + 65375, + 65375, + ], + [ + 65376, + 65376, + ], + [ + 65504, + 65505, + ], + [ + 65506, + 65506, + ], + [ + 65507, + 65507, + ], + [ + 65508, + 65508, + ], + [ + 65509, + 65510, + ], + [ + 94176, + 94177, + ], + [ + 94178, + 94178, + ], + [ + 94179, + 94179, + ], + [ + 94180, + 94180, + ], + [ + 94192, + 94193, + ], + [ + 94208, + 100343, + ], + [ + 100352, + 101119, + ], + [ + 101120, + 101589, + ], + [ + 101632, + 101640, + ], + [ + 110576, + 110579, + ], + [ + 110581, + 110587, + ], + [ + 110589, + 110590, + ], + [ + 110592, + 110847, + ], + [ + 110848, + 110882, + ], + [ + 110898, + 110898, + ], + [ + 110928, + 110930, + ], + [ + 110933, + 110933, + ], + [ + 110948, + 110951, + ], + [ + 110960, + 111355, + ], + [ + 126980, + 126980, + ], + [ + 127183, + 127183, + ], + [ + 127374, + 127374, + ], + [ + 127377, + 127386, + ], + [ + 127488, + 127490, + ], + [ + 127504, + 127547, + ], + [ + 127552, + 127560, + ], + [ + 127568, + 127569, + ], + [ + 127584, + 127589, + ], + [ + 127744, + 127776, + ], + [ + 127789, + 127797, + ], + [ + 127799, + 127868, + ], + [ + 127870, + 127891, + ], + [ + 127904, + 127946, + ], + [ + 127951, + 127955, + ], + [ + 127968, + 127984, + ], + [ + 127988, + 127988, + ], + [ + 127992, + 127994, + ], + [ + 127995, + 127999, + ], + [ + 128000, + 128062, + ], + [ + 128064, + 128064, + ], + [ + 128066, + 128252, + ], + [ + 128255, + 128317, + ], + [ + 128331, + 128334, + ], + [ + 128336, + 128359, + ], + [ + 128378, + 128378, + ], + [ + 128405, + 128406, + ], + [ + 128420, + 128420, + ], + [ + 128507, + 128511, + ], + [ + 128512, + 128591, + ], + [ + 128640, + 128709, + ], + [ + 128716, + 128716, + ], + [ + 128720, + 128722, + ], + [ + 128725, + 128727, + ], + [ + 128732, + 128735, + ], + [ + 128747, + 128748, + ], + [ + 128756, + 128764, + ], + [ + 128992, + 129003, + ], + [ + 129008, + 129008, + ], + [ + 129292, + 129338, + ], + [ + 129340, + 129349, + ], + [ + 129351, + 129535, + ], + [ + 129648, + 129660, + ], + [ + 129664, + 129672, + ], + [ + 129680, + 129725, + ], + [ + 129727, + 129733, + ], + [ + 129742, + 129755, + ], + [ + 129760, + 129768, + ], + [ + 129776, + 129784, + ], + [ + 131072, + 173791, + ], + [ + 173792, + 173823, + ], + [ + 173824, + 177977, + ], + [ + 177978, + 177983, + ], + [ + 177984, + 178205, + ], + [ + 178206, + 178207, + ], + [ + 178208, + 183969, + ], + [ + 183970, + 183983, + ], + [ + 183984, + 191456, + ], + [ + 191457, + 194559, + ], + [ + 194560, + 195101, + ], + [ + 195102, + 195103, + ], + [ + 195104, + 196605, + ], + [ + 196608, + 201546, + ], + [ + 201547, + 201551, + ], + [ + 201552, + 205743, + ], + [ + 205744, + 262141, + ], +]; diff --git a/vendor/symfony/string/Resources/data/wcswidth_table_zero.php b/vendor/symfony/string/Resources/data/wcswidth_table_zero.php new file mode 100644 index 0000000..9ae7330 --- /dev/null +++ b/vendor/symfony/string/Resources/data/wcswidth_table_zero.php @@ -0,0 +1,1415 @@ +<?php + +/* + * This file has been auto-generated by the Symfony String Component for internal use. + * + * Unicode version: 15.0.0 + * Date: 2022-10-05T17:16:37+02:00 + */ + +return [ + [ + 768, + 879, + ], + [ + 1155, + 1159, + ], + [ + 1160, + 1161, + ], + [ + 1425, + 1469, + ], + [ + 1471, + 1471, + ], + [ + 1473, + 1474, + ], + [ + 1476, + 1477, + ], + [ + 1479, + 1479, + ], + [ + 1552, + 1562, + ], + [ + 1611, + 1631, + ], + [ + 1648, + 1648, + ], + [ + 1750, + 1756, + ], + [ + 1759, + 1764, + ], + [ + 1767, + 1768, + ], + [ + 1770, + 1773, + ], + [ + 1809, + 1809, + ], + [ + 1840, + 1866, + ], + [ + 1958, + 1968, + ], + [ + 2027, + 2035, + ], + [ + 2045, + 2045, + ], + [ + 2070, + 2073, + ], + [ + 2075, + 2083, + ], + [ + 2085, + 2087, + ], + [ + 2089, + 2093, + ], + [ + 2137, + 2139, + ], + [ + 2200, + 2207, + ], + [ + 2250, + 2273, + ], + [ + 2275, + 2306, + ], + [ + 2362, + 2362, + ], + [ + 2364, + 2364, + ], + [ + 2369, + 2376, + ], + [ + 2381, + 2381, + ], + [ + 2385, + 2391, + ], + [ + 2402, + 2403, + ], + [ + 2433, + 2433, + ], + [ + 2492, + 2492, + ], + [ + 2497, + 2500, + ], + [ + 2509, + 2509, + ], + [ + 2530, + 2531, + ], + [ + 2558, + 2558, + ], + [ + 2561, + 2562, + ], + [ + 2620, + 2620, + ], + [ + 2625, + 2626, + ], + [ + 2631, + 2632, + ], + [ + 2635, + 2637, + ], + [ + 2641, + 2641, + ], + [ + 2672, + 2673, + ], + [ + 2677, + 2677, + ], + [ + 2689, + 2690, + ], + [ + 2748, + 2748, + ], + [ + 2753, + 2757, + ], + [ + 2759, + 2760, + ], + [ + 2765, + 2765, + ], + [ + 2786, + 2787, + ], + [ + 2810, + 2815, + ], + [ + 2817, + 2817, + ], + [ + 2876, + 2876, + ], + [ + 2879, + 2879, + ], + [ + 2881, + 2884, + ], + [ + 2893, + 2893, + ], + [ + 2901, + 2902, + ], + [ + 2914, + 2915, + ], + [ + 2946, + 2946, + ], + [ + 3008, + 3008, + ], + [ + 3021, + 3021, + ], + [ + 3072, + 3072, + ], + [ + 3076, + 3076, + ], + [ + 3132, + 3132, + ], + [ + 3134, + 3136, + ], + [ + 3142, + 3144, + ], + [ + 3146, + 3149, + ], + [ + 3157, + 3158, + ], + [ + 3170, + 3171, + ], + [ + 3201, + 3201, + ], + [ + 3260, + 3260, + ], + [ + 3263, + 3263, + ], + [ + 3270, + 3270, + ], + [ + 3276, + 3277, + ], + [ + 3298, + 3299, + ], + [ + 3328, + 3329, + ], + [ + 3387, + 3388, + ], + [ + 3393, + 3396, + ], + [ + 3405, + 3405, + ], + [ + 3426, + 3427, + ], + [ + 3457, + 3457, + ], + [ + 3530, + 3530, + ], + [ + 3538, + 3540, + ], + [ + 3542, + 3542, + ], + [ + 3633, + 3633, + ], + [ + 3636, + 3642, + ], + [ + 3655, + 3662, + ], + [ + 3761, + 3761, + ], + [ + 3764, + 3772, + ], + [ + 3784, + 3790, + ], + [ + 3864, + 3865, + ], + [ + 3893, + 3893, + ], + [ + 3895, + 3895, + ], + [ + 3897, + 3897, + ], + [ + 3953, + 3966, + ], + [ + 3968, + 3972, + ], + [ + 3974, + 3975, + ], + [ + 3981, + 3991, + ], + [ + 3993, + 4028, + ], + [ + 4038, + 4038, + ], + [ + 4141, + 4144, + ], + [ + 4146, + 4151, + ], + [ + 4153, + 4154, + ], + [ + 4157, + 4158, + ], + [ + 4184, + 4185, + ], + [ + 4190, + 4192, + ], + [ + 4209, + 4212, + ], + [ + 4226, + 4226, + ], + [ + 4229, + 4230, + ], + [ + 4237, + 4237, + ], + [ + 4253, + 4253, + ], + [ + 4957, + 4959, + ], + [ + 5906, + 5908, + ], + [ + 5938, + 5939, + ], + [ + 5970, + 5971, + ], + [ + 6002, + 6003, + ], + [ + 6068, + 6069, + ], + [ + 6071, + 6077, + ], + [ + 6086, + 6086, + ], + [ + 6089, + 6099, + ], + [ + 6109, + 6109, + ], + [ + 6155, + 6157, + ], + [ + 6159, + 6159, + ], + [ + 6277, + 6278, + ], + [ + 6313, + 6313, + ], + [ + 6432, + 6434, + ], + [ + 6439, + 6440, + ], + [ + 6450, + 6450, + ], + [ + 6457, + 6459, + ], + [ + 6679, + 6680, + ], + [ + 6683, + 6683, + ], + [ + 6742, + 6742, + ], + [ + 6744, + 6750, + ], + [ + 6752, + 6752, + ], + [ + 6754, + 6754, + ], + [ + 6757, + 6764, + ], + [ + 6771, + 6780, + ], + [ + 6783, + 6783, + ], + [ + 6832, + 6845, + ], + [ + 6846, + 6846, + ], + [ + 6847, + 6862, + ], + [ + 6912, + 6915, + ], + [ + 6964, + 6964, + ], + [ + 6966, + 6970, + ], + [ + 6972, + 6972, + ], + [ + 6978, + 6978, + ], + [ + 7019, + 7027, + ], + [ + 7040, + 7041, + ], + [ + 7074, + 7077, + ], + [ + 7080, + 7081, + ], + [ + 7083, + 7085, + ], + [ + 7142, + 7142, + ], + [ + 7144, + 7145, + ], + [ + 7149, + 7149, + ], + [ + 7151, + 7153, + ], + [ + 7212, + 7219, + ], + [ + 7222, + 7223, + ], + [ + 7376, + 7378, + ], + [ + 7380, + 7392, + ], + [ + 7394, + 7400, + ], + [ + 7405, + 7405, + ], + [ + 7412, + 7412, + ], + [ + 7416, + 7417, + ], + [ + 7616, + 7679, + ], + [ + 8400, + 8412, + ], + [ + 8413, + 8416, + ], + [ + 8417, + 8417, + ], + [ + 8418, + 8420, + ], + [ + 8421, + 8432, + ], + [ + 11503, + 11505, + ], + [ + 11647, + 11647, + ], + [ + 11744, + 11775, + ], + [ + 12330, + 12333, + ], + [ + 12441, + 12442, + ], + [ + 42607, + 42607, + ], + [ + 42608, + 42610, + ], + [ + 42612, + 42621, + ], + [ + 42654, + 42655, + ], + [ + 42736, + 42737, + ], + [ + 43010, + 43010, + ], + [ + 43014, + 43014, + ], + [ + 43019, + 43019, + ], + [ + 43045, + 43046, + ], + [ + 43052, + 43052, + ], + [ + 43204, + 43205, + ], + [ + 43232, + 43249, + ], + [ + 43263, + 43263, + ], + [ + 43302, + 43309, + ], + [ + 43335, + 43345, + ], + [ + 43392, + 43394, + ], + [ + 43443, + 43443, + ], + [ + 43446, + 43449, + ], + [ + 43452, + 43453, + ], + [ + 43493, + 43493, + ], + [ + 43561, + 43566, + ], + [ + 43569, + 43570, + ], + [ + 43573, + 43574, + ], + [ + 43587, + 43587, + ], + [ + 43596, + 43596, + ], + [ + 43644, + 43644, + ], + [ + 43696, + 43696, + ], + [ + 43698, + 43700, + ], + [ + 43703, + 43704, + ], + [ + 43710, + 43711, + ], + [ + 43713, + 43713, + ], + [ + 43756, + 43757, + ], + [ + 43766, + 43766, + ], + [ + 44005, + 44005, + ], + [ + 44008, + 44008, + ], + [ + 44013, + 44013, + ], + [ + 64286, + 64286, + ], + [ + 65024, + 65039, + ], + [ + 65056, + 65071, + ], + [ + 66045, + 66045, + ], + [ + 66272, + 66272, + ], + [ + 66422, + 66426, + ], + [ + 68097, + 68099, + ], + [ + 68101, + 68102, + ], + [ + 68108, + 68111, + ], + [ + 68152, + 68154, + ], + [ + 68159, + 68159, + ], + [ + 68325, + 68326, + ], + [ + 68900, + 68903, + ], + [ + 69291, + 69292, + ], + [ + 69373, + 69375, + ], + [ + 69446, + 69456, + ], + [ + 69506, + 69509, + ], + [ + 69633, + 69633, + ], + [ + 69688, + 69702, + ], + [ + 69744, + 69744, + ], + [ + 69747, + 69748, + ], + [ + 69759, + 69761, + ], + [ + 69811, + 69814, + ], + [ + 69817, + 69818, + ], + [ + 69826, + 69826, + ], + [ + 69888, + 69890, + ], + [ + 69927, + 69931, + ], + [ + 69933, + 69940, + ], + [ + 70003, + 70003, + ], + [ + 70016, + 70017, + ], + [ + 70070, + 70078, + ], + [ + 70089, + 70092, + ], + [ + 70095, + 70095, + ], + [ + 70191, + 70193, + ], + [ + 70196, + 70196, + ], + [ + 70198, + 70199, + ], + [ + 70206, + 70206, + ], + [ + 70209, + 70209, + ], + [ + 70367, + 70367, + ], + [ + 70371, + 70378, + ], + [ + 70400, + 70401, + ], + [ + 70459, + 70460, + ], + [ + 70464, + 70464, + ], + [ + 70502, + 70508, + ], + [ + 70512, + 70516, + ], + [ + 70712, + 70719, + ], + [ + 70722, + 70724, + ], + [ + 70726, + 70726, + ], + [ + 70750, + 70750, + ], + [ + 70835, + 70840, + ], + [ + 70842, + 70842, + ], + [ + 70847, + 70848, + ], + [ + 70850, + 70851, + ], + [ + 71090, + 71093, + ], + [ + 71100, + 71101, + ], + [ + 71103, + 71104, + ], + [ + 71132, + 71133, + ], + [ + 71219, + 71226, + ], + [ + 71229, + 71229, + ], + [ + 71231, + 71232, + ], + [ + 71339, + 71339, + ], + [ + 71341, + 71341, + ], + [ + 71344, + 71349, + ], + [ + 71351, + 71351, + ], + [ + 71453, + 71455, + ], + [ + 71458, + 71461, + ], + [ + 71463, + 71467, + ], + [ + 71727, + 71735, + ], + [ + 71737, + 71738, + ], + [ + 71995, + 71996, + ], + [ + 71998, + 71998, + ], + [ + 72003, + 72003, + ], + [ + 72148, + 72151, + ], + [ + 72154, + 72155, + ], + [ + 72160, + 72160, + ], + [ + 72193, + 72202, + ], + [ + 72243, + 72248, + ], + [ + 72251, + 72254, + ], + [ + 72263, + 72263, + ], + [ + 72273, + 72278, + ], + [ + 72281, + 72283, + ], + [ + 72330, + 72342, + ], + [ + 72344, + 72345, + ], + [ + 72752, + 72758, + ], + [ + 72760, + 72765, + ], + [ + 72767, + 72767, + ], + [ + 72850, + 72871, + ], + [ + 72874, + 72880, + ], + [ + 72882, + 72883, + ], + [ + 72885, + 72886, + ], + [ + 73009, + 73014, + ], + [ + 73018, + 73018, + ], + [ + 73020, + 73021, + ], + [ + 73023, + 73029, + ], + [ + 73031, + 73031, + ], + [ + 73104, + 73105, + ], + [ + 73109, + 73109, + ], + [ + 73111, + 73111, + ], + [ + 73459, + 73460, + ], + [ + 73472, + 73473, + ], + [ + 73526, + 73530, + ], + [ + 73536, + 73536, + ], + [ + 73538, + 73538, + ], + [ + 78912, + 78912, + ], + [ + 78919, + 78933, + ], + [ + 92912, + 92916, + ], + [ + 92976, + 92982, + ], + [ + 94031, + 94031, + ], + [ + 94095, + 94098, + ], + [ + 94180, + 94180, + ], + [ + 113821, + 113822, + ], + [ + 118528, + 118573, + ], + [ + 118576, + 118598, + ], + [ + 119143, + 119145, + ], + [ + 119163, + 119170, + ], + [ + 119173, + 119179, + ], + [ + 119210, + 119213, + ], + [ + 119362, + 119364, + ], + [ + 121344, + 121398, + ], + [ + 121403, + 121452, + ], + [ + 121461, + 121461, + ], + [ + 121476, + 121476, + ], + [ + 121499, + 121503, + ], + [ + 121505, + 121519, + ], + [ + 122880, + 122886, + ], + [ + 122888, + 122904, + ], + [ + 122907, + 122913, + ], + [ + 122915, + 122916, + ], + [ + 122918, + 122922, + ], + [ + 123023, + 123023, + ], + [ + 123184, + 123190, + ], + [ + 123566, + 123566, + ], + [ + 123628, + 123631, + ], + [ + 124140, + 124143, + ], + [ + 125136, + 125142, + ], + [ + 125252, + 125258, + ], + [ + 917760, + 917999, + ], +]; diff --git a/vendor/symfony/string/Resources/functions.php b/vendor/symfony/string/Resources/functions.php new file mode 100644 index 0000000..c950894 --- /dev/null +++ b/vendor/symfony/string/Resources/functions.php @@ -0,0 +1,38 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +if (!\function_exists(u::class)) { + function u(?string $string = ''): UnicodeString + { + return new UnicodeString($string ?? ''); + } +} + +if (!\function_exists(b::class)) { + function b(?string $string = ''): ByteString + { + return new ByteString($string ?? ''); + } +} + +if (!\function_exists(s::class)) { + /** + * @return UnicodeString|ByteString + */ + function s(?string $string = ''): AbstractString + { + $string = $string ?? ''; + + return preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string); + } +} diff --git a/vendor/symfony/string/Slugger/AsciiSlugger.php b/vendor/symfony/string/Slugger/AsciiSlugger.php new file mode 100644 index 0000000..5aecfeb --- /dev/null +++ b/vendor/symfony/string/Slugger/AsciiSlugger.php @@ -0,0 +1,183 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String\Slugger; + +use Symfony\Component\String\AbstractUnicodeString; +use Symfony\Component\String\UnicodeString; +use Symfony\Contracts\Translation\LocaleAwareInterface; + +if (!interface_exists(LocaleAwareInterface::class)) { + throw new \LogicException('You cannot use the "Symfony\Component\String\Slugger\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".'); +} + +/** + * @author Titouan Galopin <galopintitouan@gmail.com> + */ +class AsciiSlugger implements SluggerInterface, LocaleAwareInterface +{ + private const LOCALE_TO_TRANSLITERATOR_ID = [ + 'am' => 'Amharic-Latin', + 'ar' => 'Arabic-Latin', + 'az' => 'Azerbaijani-Latin', + 'be' => 'Belarusian-Latin', + 'bg' => 'Bulgarian-Latin', + 'bn' => 'Bengali-Latin', + 'de' => 'de-ASCII', + 'el' => 'Greek-Latin', + 'fa' => 'Persian-Latin', + 'he' => 'Hebrew-Latin', + 'hy' => 'Armenian-Latin', + 'ka' => 'Georgian-Latin', + 'kk' => 'Kazakh-Latin', + 'ky' => 'Kirghiz-Latin', + 'ko' => 'Korean-Latin', + 'mk' => 'Macedonian-Latin', + 'mn' => 'Mongolian-Latin', + 'or' => 'Oriya-Latin', + 'ps' => 'Pashto-Latin', + 'ru' => 'Russian-Latin', + 'sr' => 'Serbian-Latin', + 'sr_Cyrl' => 'Serbian-Latin', + 'th' => 'Thai-Latin', + 'tk' => 'Turkmen-Latin', + 'uk' => 'Ukrainian-Latin', + 'uz' => 'Uzbek-Latin', + 'zh' => 'Han-Latin', + ]; + + private $defaultLocale; + private $symbolsMap = [ + 'en' => ['@' => 'at', '&' => 'and'], + ]; + + /** + * Cache of transliterators per locale. + * + * @var \Transliterator[] + */ + private $transliterators = []; + + /** + * @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; + } + + /** + * {@inheritdoc} + */ + public function setLocale($locale) + { + $this->defaultLocale = $locale; + } + + /** + * {@inheritdoc} + */ + public function getLocale() + { + return $this->defaultLocale; + } + + /** + * {@inheritdoc} + */ + public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString + { + $locale = $locale ?? $this->defaultLocale; + + $transliterator = []; + 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 ($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 function ($s) use ($symbolsMap, $locale) { + return $symbolsMap($s, $locale); + }); + } + + $unicodeString = (new UnicodeString($string))->ascii($transliterator); + + if (\is_array($this->symbolsMap)) { + $map = null; + if (isset($this->symbolsMap[$locale])) { + $map = $this->symbolsMap[$locale]; + } else { + $parent = self::getParentLocale($locale); + if ($parent && isset($this->symbolsMap[$parent])) { + $map = $this->symbolsMap[$parent]; + } + } + if ($map) { + foreach ($map as $char => $replace) { + $unicodeString = $unicodeString->replace($char, ' '.$replace.' '); + } + } + } + + return $unicodeString + ->replaceMatches('/[^A-Za-z0-9]++/', $separator) + ->trim($separator) + ; + } + + private function createTransliterator(string $locale): ?\Transliterator + { + if (\array_key_exists($locale, $this->transliterators)) { + return $this->transliterators[$locale]; + } + + // Exact locale supported, cache and return + if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) { + return $this->transliterators[$locale] = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id); + } + + // Locale not supported and no parent, fallback to any-latin + if (!$parent = self::getParentLocale($locale)) { + return $this->transliterators[$locale] = null; + } + + // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales + if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) { + $transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id); + } + + return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null; + } + + private static function getParentLocale(?string $locale): ?string + { + if (!$locale) { + return null; + } + if (false === $str = strrchr($locale, '_')) { + // no parent locale + return null; + } + + return substr($locale, 0, -\strlen($str)); + } +} diff --git a/vendor/symfony/string/Slugger/SluggerInterface.php b/vendor/symfony/string/Slugger/SluggerInterface.php new file mode 100644 index 0000000..c679ed9 --- /dev/null +++ b/vendor/symfony/string/Slugger/SluggerInterface.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String\Slugger; + +use Symfony\Component\String\AbstractUnicodeString; + +/** + * Creates a URL-friendly slug from a given string. + * + * @author Titouan Galopin <galopintitouan@gmail.com> + */ +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; +} diff --git a/vendor/symfony/string/UnicodeString.php b/vendor/symfony/string/UnicodeString.php new file mode 100644 index 0000000..9b906c6 --- /dev/null +++ b/vendor/symfony/string/UnicodeString.php @@ -0,0 +1,377 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\String; + +use Symfony\Component\String\Exception\ExceptionInterface; +use Symfony\Component\String\Exception\InvalidArgumentException; + +/** + * Represents a string of Unicode grapheme clusters encoded as UTF-8. + * + * A letter followed by combining characters (accents typically) form what Unicode defines + * as a grapheme cluster: a character as humans mean it in written texts. This class knows + * about the concept and won't split a letter apart from its combining accents. It also + * ensures all string comparisons happen on their canonically-composed representation, + * ignoring e.g. the order in which accents are listed when a letter has many of them. + * + * @see https://unicode.org/reports/tr15/ + * + * @author Nicolas Grekas <p@tchwork.com> + * @author Hugo Hamon <hugohamon@neuf.fr> + * + * @throws ExceptionInterface + */ +class UnicodeString extends AbstractUnicodeString +{ + public function __construct(string $string = '') + { + $this->string = normalizer_is_normalized($string) ? $string : normalizer_normalize($string); + + if (false === $this->string) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + } + + 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 (false === $str->string) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function chunk(int $length = 1): array + { + if (1 > $length) { + throw new InvalidArgumentException('The chunk length must be greater than zero.'); + } + + if ('' === $this->string) { + return []; + } + + $rx = '/('; + while (65535 < $length) { + $rx .= '\X{65535}'; + $length -= 65535; + } + $rx .= '\X{'.$length.'})/u'; + + $str = clone $this; + $chunks = []; + + foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { + $str->string = $chunk; + $chunks[] = clone $str; + } + + return $chunks; + } + + public function endsWith($suffix): bool + { + if ($suffix instanceof AbstractString) { + $suffix = $suffix->string; + } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { + return parent::endsWith($suffix); + } else { + $suffix = (string) $suffix; + } + + $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; + normalizer_is_normalized($suffix, $form) ?: $suffix = normalizer_normalize($suffix, $form); + + if ('' === $suffix || false === $suffix) { + return false; + } + + if ($this->ignoreCase) { + return 0 === mb_stripos(grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)), $suffix, 0, 'UTF-8'); + } + + return $suffix === grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)); + } + + public function equalsTo($string): bool + { + if ($string instanceof AbstractString) { + $string = $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; + normalizer_is_normalized($string, $form) ?: $string = normalizer_normalize($string, $form); + + if ('' !== $string && false !== $string && $this->ignoreCase) { + return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8'); + } + + return $string === $this->string; + } + + public function indexOf($needle, int $offset = 0): ?int + { + if ($needle instanceof AbstractString) { + $needle = $needle->string; + } elseif (\is_array($needle) || $needle instanceof \Traversable) { + return parent::indexOf($needle, $offset); + } else { + $needle = (string) $needle; + } + + $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; + normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form); + + if ('' === $needle || false === $needle) { + return null; + } + + try { + $i = $this->ignoreCase ? grapheme_stripos($this->string, $needle, $offset) : grapheme_strpos($this->string, $needle, $offset); + } catch (\ValueError $e) { + return null; + } + + return false === $i ? null : $i; + } + + public function indexOfLast($needle, int $offset = 0): ?int + { + if ($needle instanceof AbstractString) { + $needle = $needle->string; + } elseif (\is_array($needle) || $needle instanceof \Traversable) { + return parent::indexOfLast($needle, $offset); + } else { + $needle = (string) $needle; + } + + $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; + normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form); + + if ('' === $needle || false === $needle) { + return null; + } + + $string = $this->string; + + if (0 > $offset) { + // workaround https://bugs.php.net/74264 + if (0 > $offset += grapheme_strlen($needle)) { + $string = grapheme_substr($string, 0, $offset); + } + $offset = 0; + } + + $i = $this->ignoreCase ? grapheme_strripos($string, $needle, $offset) : grapheme_strrpos($string, $needle, $offset); + + return false === $i ? null : $i; + } + + 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); + + return $str; + } + + public function length(): int + { + return grapheme_strlen($this->string); + } + + /** + * @return static + */ + public function normalize(int $form = self::NFC): parent + { + $str = clone $this; + + if (\in_array($form, [self::NFC, self::NFKC], true)) { + normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form); + } elseif (!\in_array($form, [self::NFD, self::NFKD], true)) { + throw new InvalidArgumentException('Unsupported normalization form.'); + } elseif (!normalizer_is_normalized($str->string, $form)) { + $str->string = normalizer_normalize($str->string, $form); + $str->ignoreCase = null; + } + + return $str; + } + + 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 (false === $str->string) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function replace(string $from, string $to): AbstractString + { + $str = clone $this; + normalizer_is_normalized($from) ?: $from = normalizer_normalize($from); + + if ('' !== $from && false !== $from) { + $tail = $str->string; + $result = ''; + $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; + + while ('' !== $tail && false !== $i = $indexOf($tail, $from)) { + $slice = grapheme_substr($tail, 0, $i); + $result .= $slice.$to; + $tail = substr($tail, \strlen($slice) + \strlen($from)); + } + + $str->string = $result.$tail; + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); + + if (false === $str->string) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + } + + return $str; + } + + public function replaceMatches(string $fromRegexp, $to): AbstractString + { + $str = parent::replaceMatches($fromRegexp, $to); + normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); + + return $str; + } + + 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): 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 (false === $str->string) { + throw new InvalidArgumentException('Invalid UTF-8 string.'); + } + + return $str; + } + + public function split(string $delimiter, int $limit = null, int $flags = null): array + { + if (1 > $limit = $limit ?? 2147483647) { + throw new InvalidArgumentException('Split limit must be a positive integer.'); + } + + if ('' === $delimiter) { + throw new InvalidArgumentException('Split delimiter is empty.'); + } + + if (null !== $flags) { + return parent::split($delimiter.'u', $limit, $flags); + } + + normalizer_is_normalized($delimiter) ?: $delimiter = normalizer_normalize($delimiter); + + if (false === $delimiter) { + throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); + } + + $str = clone $this; + $tail = $this->string; + $chunks = []; + $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; + + while (1 < $limit && false !== $i = $indexOf($tail, $delimiter)) { + $str->string = grapheme_substr($tail, 0, $i); + $chunks[] = clone $str; + $tail = substr($tail, \strlen($str->string) + \strlen($delimiter)); + --$limit; + } + + $str->string = $tail; + $chunks[] = clone $str; + + return $chunks; + } + + public function startsWith($prefix): bool + { + if ($prefix instanceof AbstractString) { + $prefix = $prefix->string; + } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { + return parent::startsWith($prefix); + } else { + $prefix = (string) $prefix; + } + + $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; + normalizer_is_normalized($prefix, $form) ?: $prefix = normalizer_normalize($prefix, $form); + + if ('' === $prefix || false === $prefix) { + return false; + } + + if ($this->ignoreCase) { + return 0 === mb_stripos(grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES), $prefix, 0, 'UTF-8'); + } + + return $prefix === grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES); + } + + public function __wakeup() + { + if (!\is_string($this->string)) { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string); + } + + public function __clone() + { + if (null === $this->ignoreCase) { + normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string); + } + + $this->ignoreCase = false; + } +} diff --git a/vendor/symfony/string/composer.json b/vendor/symfony/string/composer.json new file mode 100644 index 0000000..2b88fd5 --- /dev/null +++ b/vendor/symfony/string/composer.json @@ -0,0 +1,43 @@ +{ + "name": "symfony/string", + "type": "library", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "keywords": ["string", "utf8", "utf-8", "grapheme", "i18n", "unicode"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "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-php80": "~1.15" + }, + "require-dev": { + "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": ">=3.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\String\\": "" }, + "files": [ "Resources/functions.php" ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/vendor/symfony/yaml/CHANGELOG.md b/vendor/symfony/yaml/CHANGELOG.md index 1b07b23..fd41c9d 100644 --- a/vendor/symfony/yaml/CHANGELOG.md +++ b/vendor/symfony/yaml/CHANGELOG.md @@ -113,7 +113,7 @@ CHANGELOG * Added support for customizing the dumped YAML string through an optional bit field: ```php - Yaml::dump(array('foo' => new A(), 'bar' => 1), 0, 0, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE | Yaml::DUMP_OBJECT); + Yaml::dump(['foo' => new A(), 'bar' => 1], 0, 0, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE | Yaml::DUMP_OBJECT); ``` 3.0.0 diff --git a/vendor/symfony/yaml/Command/LintCommand.php b/vendor/symfony/yaml/Command/LintCommand.php index 36e7e8b..fb8e3e6 100644 --- a/vendor/symfony/yaml/Command/LintCommand.php +++ b/vendor/symfony/yaml/Command/LintCommand.php @@ -91,14 +91,14 @@ protected function execute(InputInterface $input, OutputInterface $output) throw new RuntimeException('Please provide a filename or pipe file content to STDIN.'); } - return $this->display($io, array($this->validate($stdin, $flags))); + return $this->display($io, [$this->validate($stdin, $flags)]); } if (!$this->isReadable($filename)) { throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename)); } - $filesInfo = array(); + $filesInfo = []; foreach ($this->getFiles($filename) as $file) { $filesInfo[] = $this->validate(file_get_contents($file), $flags, $file); } @@ -109,7 +109,7 @@ protected function execute(InputInterface $input, OutputInterface $output) private function validate($content, $flags, $file = null) { $prevErrorHandler = set_error_handler(function ($level, $message, $file, $line) use (&$prevErrorHandler) { - if (E_USER_DEPRECATED === $level) { + if (\E_USER_DEPRECATED === $level) { throw new ParseException($message, $this->getParser()->getRealCurrentLineNb() + 1); } @@ -119,12 +119,12 @@ private function validate($content, $flags, $file = null) try { $this->getParser()->parse($content, Yaml::PARSE_CONSTANT | $flags); } catch (ParseException $e) { - return array('file' => $file, 'line' => $e->getParsedLine(), 'valid' => false, 'message' => $e->getMessage()); + return ['file' => $file, 'line' => $e->getParsedLine(), 'valid' => false, 'message' => $e->getMessage()]; } finally { restore_error_handler(); } - return array('file' => $file, 'valid' => true); + return ['file' => $file, 'valid' => true]; } private function display(SymfonyStyle $io, array $files) @@ -174,7 +174,7 @@ private function displayJson(SymfonyStyle $io, array $filesInfo) } }); - $io->writeln(json_encode($filesInfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + $io->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)); return min($errors, 1); } @@ -188,7 +188,7 @@ private function getFiles($fileOrDirectory) } foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) { - if (!\in_array($file->getExtension(), array('yml', 'yaml'))) { + if (!\in_array($file->getExtension(), ['yml', 'yaml'])) { continue; } @@ -196,15 +196,18 @@ private function getFiles($fileOrDirectory) } } + /** + * @return string|null + */ private function getStdin() { - if (0 !== ftell(STDIN)) { - return; + if (0 !== ftell(\STDIN)) { + return null; } $inputs = ''; - while (!feof(STDIN)) { - $inputs .= fread(STDIN, 1024); + while (!feof(\STDIN)) { + $inputs .= fread(\STDIN, 1024); } return $inputs; diff --git a/vendor/symfony/yaml/Dumper.php b/vendor/symfony/yaml/Dumper.php index d2a2ebc..336e39c 100644 --- a/vendor/symfony/yaml/Dumper.php +++ b/vendor/symfony/yaml/Dumper.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Yaml; +use Symfony\Component\Yaml\Tag\TaggedValue; + /** * Dumper dumps PHP variables to YAML strings. * @@ -48,7 +50,7 @@ public function __construct($indentation = 4) */ public function setIndentation($num) { - @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 3.1 and will be removed in 4.0. Pass the indentation to the constructor instead.', E_USER_DEPRECATED); + @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 3.1 and will be removed in 4.0. Pass the indentation to the constructor instead.', \E_USER_DEPRECATED); $this->indentation = (int) $num; } @@ -66,7 +68,7 @@ public function setIndentation($num) public function dump($input, $inline = 0, $indent = 0, $flags = 0) { if (\is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', \E_USER_DEPRECATED); if ($flags) { $flags = Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE; @@ -76,7 +78,7 @@ public function dump($input, $inline = 0, $indent = 0, $flags = 0) } if (\func_num_args() >= 5) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', \E_USER_DEPRECATED); if (func_get_arg(4)) { $flags |= Yaml::DUMP_OBJECT; @@ -91,25 +93,51 @@ public function dump($input, $inline = 0, $indent = 0, $flags = 0) $dumpObjectAsInlineMap = empty((array) $input); } - if ($inline <= 0 || (!\is_array($input) && $dumpObjectAsInlineMap) || empty($input)) { + if ($inline <= 0 || (!\is_array($input) && !$input instanceof TaggedValue && $dumpObjectAsInlineMap) || empty($input)) { $output .= $prefix.Inline::dump($input, $flags); } else { $dumpAsMap = Inline::isHash($input); foreach ($input as $key => $value) { - if ($inline >= 1 && Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r\n")) { + if ($inline >= 1 && Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r")) { // 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 : ''; $output .= sprintf("%s%s%s |%s\n", $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', '', $blockIndentationIndicator); - foreach (preg_split('/\n|\r\n/', $value) as $row) { + foreach (explode("\n", $value) as $row) { $output .= sprintf("%s%s%s\n", $prefix, str_repeat(' ', $this->indentation), $row); } continue; } + if ($value instanceof TaggedValue) { + $output .= sprintf('%s%s !%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', $value->getTag()); + + if ($inline >= 1 && Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && false !== strpos($value->getValue(), "\n") && false === strpos($value->getValue(), "\r\n")) { + // 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\n", $blockIndentationIndicator); + + foreach (explode("\n", $value->getValue()) as $row) { + $output .= sprintf("%s%s%s\n", $prefix, str_repeat(' ', $this->indentation), $row); + } + + continue; + } + + if ($inline - 1 <= 0 || null === $value->getValue() || is_scalar($value->getValue())) { + $output .= ' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n"; + } else { + $output .= "\n"; + $output .= $this->dump($value->getValue(), $inline - 1, $dumpAsMap ? $indent + $this->indentation : $indent + 2, $flags); + } + + continue; + } + $dumpObjectAsInlineMap = true; if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \ArrayObject || $value instanceof \stdClass)) { diff --git a/vendor/symfony/yaml/Escaper.php b/vendor/symfony/yaml/Escaper.php index 2b1321f..9413d7a 100644 --- a/vendor/symfony/yaml/Escaper.php +++ b/vendor/symfony/yaml/Escaper.php @@ -22,26 +22,28 @@ class Escaper { // Characters that would cause a dumped string to require double quoting. - const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9"; + const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\x7f|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9"; // Mapping arrays for escaping a double quoted string. The backslash is // first to ensure proper escaping because str_replace operates iteratively // on the input arrays. This ordering of the characters avoids the use of strtr, // which performs more slowly. - private static $escapees = array('\\', '\\\\', '\\"', '"', + private static $escapees = ['\\', '\\\\', '\\"', '"', "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f", "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f", + "\x7f", "\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9", - ); - private static $escaped = array('\\\\', '\\"', '\\\\', '\\"', + ]; + private static $escaped = ['\\\\', '\\"', '\\\\', '\\"', '\\0', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\a', '\\b', '\\t', '\\n', '\\v', '\\f', '\\r', '\\x0e', '\\x0f', '\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17', '\\x18', '\\x19', '\\x1a', '\\e', '\\x1c', '\\x1d', '\\x1e', '\\x1f', + '\\x7f', '\\N', '\\_', '\\L', '\\P', - ); + ]; /** * Determines if a PHP value would require double quoting in YAML. @@ -78,7 +80,7 @@ public static function requiresSingleQuoting($value) { // Determines if a PHP value is entirely composed of a value that would // require single quoting in YAML. - if (\in_array(strtolower($value), array('null', '~', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off'))) { + if (\in_array(strtolower($value), ['null', '~', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off'])) { return true; } diff --git a/vendor/symfony/yaml/Exception/ParseException.php b/vendor/symfony/yaml/Exception/ParseException.php index be79960..4207d9a 100644 --- a/vendor/symfony/yaml/Exception/ParseException.php +++ b/vendor/symfony/yaml/Exception/ParseException.php @@ -121,7 +121,7 @@ private function updateRepr() } if (null !== $this->parsedFile) { - $this->message .= sprintf(' in %s', json_encode($this->parsedFile, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); + $this->message .= sprintf(' in %s', json_encode($this->parsedFile, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); } if ($this->parsedLine >= 0) { diff --git a/vendor/symfony/yaml/Inline.php b/vendor/symfony/yaml/Inline.php index 0aa7e9f..64ac48a 100644 --- a/vendor/symfony/yaml/Inline.php +++ b/vendor/symfony/yaml/Inline.php @@ -63,10 +63,10 @@ public static function initialize($flags, $parsedLineNumber = null, $parsedFilen * * @throws ParseException */ - public static function parse($value, $flags = 0, $references = array()) + public static function parse($value, $flags = 0, $references = []) { if (\is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', \E_USER_DEPRECATED); if ($flags) { $flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE; @@ -76,14 +76,14 @@ public static function parse($value, $flags = 0, $references = array()) } if (\func_num_args() >= 3 && !\is_array($references)) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', \E_USER_DEPRECATED); if ($references) { $flags |= Yaml::PARSE_OBJECT; } if (\func_num_args() >= 4) { - @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', \E_USER_DEPRECATED); if (func_get_arg(3)) { $flags |= Yaml::PARSE_OBJECT_FOR_MAP; @@ -93,7 +93,7 @@ public static function parse($value, $flags = 0, $references = array()) if (\func_num_args() >= 5) { $references = func_get_arg(4); } else { - $references = array(); + $references = []; } } @@ -110,35 +110,37 @@ public static function parse($value, $flags = 0, $references = array()) mb_internal_encoding('ASCII'); } - $i = 0; - $tag = self::parseTag($value, $i, $flags); - switch ($value[$i]) { - case '[': - $result = self::parseSequence($value, $flags, $i, $references); - ++$i; - break; - case '{': - $result = self::parseMapping($value, $flags, $i, $references); - ++$i; - break; - default: - $result = self::parseScalar($value, $flags, null, $i, null === $tag, $references); - } + try { + $i = 0; + $tag = self::parseTag($value, $i, $flags); + switch ($value[$i]) { + case '[': + $result = self::parseSequence($value, $flags, $i, $references); + ++$i; + break; + case '{': + $result = self::parseMapping($value, $flags, $i, $references); + ++$i; + break; + default: + $result = self::parseScalar($value, $flags, null, $i, null === $tag, $references); + } - if (null !== $tag) { - return new TaggedValue($tag, $result); - } + // some comments are allowed at the end + if (preg_replace('/\s*#.*$/A', '', substr($value, $i))) { + throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)), self::$parsedLineNumber + 1, $value, self::$parsedFilename); + } - // some comments are allowed at the end - if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) { - throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)), self::$parsedLineNumber + 1, $value, self::$parsedFilename); - } + if (null !== $tag) { + return new TaggedValue($tag, $result); + } - if (isset($mbEncoding)) { - mb_internal_encoding($mbEncoding); + return $result; + } finally { + if (isset($mbEncoding)) { + mb_internal_encoding($mbEncoding); + } } - - return $result; } /** @@ -154,7 +156,7 @@ public static function parse($value, $flags = 0, $references = array()) public static function dump($value, $flags = 0) { if (\is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', \E_USER_DEPRECATED); if ($flags) { $flags = Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE; @@ -164,7 +166,7 @@ public static function dump($value, $flags = 0) } if (\func_num_args() >= 3) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', \E_USER_DEPRECATED); if (func_get_arg(2)) { $flags |= Yaml::DUMP_OBJECT; @@ -208,10 +210,10 @@ public static function dump($value, $flags = 0) return 'false'; case ctype_digit($value): return \is_string($value) ? "'$value'" : (int) $value; - case is_numeric($value): - $locale = setlocale(LC_NUMERIC, 0); + case is_numeric($value) && false === strpos($value, "\f") && false === strpos($value, "\n") && false === strpos($value, "\r") && false === strpos($value, "\t") && false === strpos($value, "\v"): + $locale = setlocale(\LC_NUMERIC, 0); if (false !== $locale) { - setlocale(LC_NUMERIC, 'C'); + setlocale(\LC_NUMERIC, 'C'); } if (\is_float($value)) { $repr = (string) $value; @@ -225,7 +227,7 @@ public static function dump($value, $flags = 0) $repr = \is_string($value) ? "'$value'" : (string) $value; } if (false !== $locale) { - setlocale(LC_NUMERIC, $locale); + setlocale(\LC_NUMERIC, $locale); } return $repr; @@ -283,7 +285,7 @@ private static function dumpArray($value, $flags) { // array if (($value || Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE & $flags) && !self::isHash($value)) { - $output = array(); + $output = []; foreach ($value as $val) { $output[] = self::dump($val, $flags); } @@ -292,7 +294,7 @@ private static function dumpArray($value, $flags) } // hash - $output = array(); + $output = []; foreach ($value as $key => $val) { $output[] = sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags)); } @@ -316,16 +318,16 @@ private static function dumpArray($value, $flags) * * @internal */ - public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i = 0, $evaluate = true, $references = array(), $legacyOmittedKeySupport = false) + public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i = 0, $evaluate = true, $references = [], $legacyOmittedKeySupport = false) { - if (\in_array($scalar[$i], array('"', "'"))) { + if (\in_array($scalar[$i], ['"', "'"])) { // quoted scalar $output = self::parseQuotedScalar($scalar, $i); if (null !== $delimiters) { $tmp = ltrim(substr($scalar, $i), ' '); if ('' === $tmp) { - throw new ParseException(sprintf('Unexpected end of line, expected one of "%s".', implode($delimiters)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); + throw new ParseException(sprintf('Unexpected end of line, expected one of "%s".', implode('', $delimiters)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } if (!\in_array($tmp[0], $delimiters)) { throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); @@ -338,14 +340,14 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i $i += \strlen($output); // remove comments - if (Parser::preg_match('/[ \t]+#/', $output, $match, PREG_OFFSET_CAPTURE)) { + if (Parser::preg_match('/[ \t]+#/', $output, $match, \PREG_OFFSET_CAPTURE)) { $output = substr($output, 0, $match[0][1]); } } elseif (Parser::preg_match('/^(.'.($legacyOmittedKeySupport ? '+' : '*').'?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { $output = $match[1]; $i += \strlen($output); } else { - throw new ParseException(sprintf('Malformed inline YAML string: %s.', $scalar), self::$parsedLineNumber + 1, null, self::$parsedFilename); + throw new ParseException(sprintf('Malformed inline YAML string: "%s".', $scalar), self::$parsedLineNumber + 1, null, self::$parsedFilename); } // a non-quoted string cannot start with @ or ` (reserved) nor with a scalar indicator (| or >) @@ -354,7 +356,7 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i } if ($output && '%' === $output[0]) { - @trigger_error(self::getDeprecationMessage(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.', $output)), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.', $output)), \E_USER_DEPRECATED); } if ($evaluate) { @@ -378,7 +380,7 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i private static function parseQuotedScalar($scalar, &$i) { if (!Parser::preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { - throw new ParseException(sprintf('Malformed inline YAML string: %s.', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); + throw new ParseException(sprintf('Malformed inline YAML string: "%s".', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } $output = substr($match[0], 1, \strlen($match[0]) - 2); @@ -407,9 +409,9 @@ private static function parseQuotedScalar($scalar, &$i) * * @throws ParseException When malformed inline YAML string is parsed */ - private static function parseSequence($sequence, $flags, &$i = 0, $references = array()) + private static function parseSequence($sequence, $flags, &$i = 0, $references = []) { - $output = array(); + $output = []; $len = \strlen($sequence); ++$i; @@ -435,8 +437,8 @@ private static function parseSequence($sequence, $flags, &$i = 0, $references = $value = self::parseMapping($sequence, $flags, $i, $references); break; default: - $isQuoted = \in_array($sequence[$i], array('"', "'")); - $value = self::parseScalar($sequence, $flags, array(',', ']'), $i, null === $tag, $references); + $isQuoted = \in_array($sequence[$i], ['"', "'"]); + $value = self::parseScalar($sequence, $flags, [',', ']'], $i, null === $tag, $references); // the value can be an array if a reference has been resolved to an array var if (\is_string($value) && !$isQuoted && false !== strpos($value, ': ')) { @@ -461,7 +463,7 @@ private static function parseSequence($sequence, $flags, &$i = 0, $references = ++$i; } - throw new ParseException(sprintf('Malformed inline YAML string: %s.', $sequence), self::$parsedLineNumber + 1, null, self::$parsedFilename); + throw new ParseException(sprintf('Malformed inline YAML string: "%s".', $sequence), self::$parsedLineNumber + 1, null, self::$parsedFilename); } /** @@ -476,9 +478,9 @@ private static function parseSequence($sequence, $flags, &$i = 0, $references = * * @throws ParseException When malformed inline YAML string is parsed */ - private static function parseMapping($mapping, $flags, &$i = 0, $references = array()) + private static function parseMapping($mapping, $flags, &$i = 0, $references = []) { - $output = array(); + $output = []; $len = \strlen($mapping); ++$i; $allowOverwrite = false; @@ -499,27 +501,37 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar } // key - $isKeyQuoted = \in_array($mapping[$i], array('"', "'"), true); - $key = self::parseScalar($mapping, $flags, array(':', ' '), $i, false, array(), true); + $isKeyQuoted = \in_array($mapping[$i], ['"', "'"], true); + $key = self::parseScalar($mapping, $flags, [':', ' '], $i, false, [], true); + + if ('!php/const' === $key) { + $key .= self::parseScalar($mapping, $flags, [':', ' '], $i, false, [], true); + if ('!php/const:' === $key && ':' !== $mapping[$i]) { + $key = ''; + --$i; + } else { + $key = self::evaluateScalar($key, $flags); + } + } if (':' !== $key && false === $i = strpos($mapping, ':', $i)) { break; } if (':' === $key) { - @trigger_error(self::getDeprecationMessage('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.'), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.'), \E_USER_DEPRECATED); } if (!$isKeyQuoted) { $evaluatedKey = self::evaluateScalar($key, $flags, $references); if ('' !== $key && $evaluatedKey !== $key && !\is_string($evaluatedKey) && !\is_int($evaluatedKey)) { - @trigger_error(self::getDeprecationMessage('Implicit casting of incompatible mapping keys to strings is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.'), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Implicit casting of incompatible mapping keys to strings is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.'), \E_USER_DEPRECATED); } } - if (':' !== $key && !$isKeyQuoted && (!isset($mapping[$i + 1]) || !\in_array($mapping[$i + 1], array(' ', ',', '[', ']', '{', '}'), true))) { - @trigger_error(self::getDeprecationMessage('Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since Symfony 3.2 and will throw a ParseException in 4.0.'), E_USER_DEPRECATED); + if (':' !== $key && !$isKeyQuoted && (!isset($mapping[$i + 1]) || !\in_array($mapping[$i + 1], [' ', ',', '[', ']', '{', '}'], true))) { + @trigger_error(self::getDeprecationMessage('Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since Symfony 3.2 and will throw a ParseException in 4.0.'), \E_USER_DEPRECATED); } if ('<<' === $key) { @@ -553,7 +565,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar $output[$key] = $value; } } elseif (isset($output[$key])) { - @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), \E_USER_DEPRECATED); } break; case '{': @@ -572,11 +584,11 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar $output[$key] = $value; } } elseif (isset($output[$key])) { - @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), \E_USER_DEPRECATED); } break; default: - $value = self::parseScalar($mapping, $flags, array(',', '}'), $i, null === $tag, $references); + $value = self::parseScalar($mapping, $flags, [',', '}'], $i, null === $tag, $references); // Spec: Keys MUST be unique; first one wins. // Parser cannot abort this mapping earlier, since lines // are processed sequentially. @@ -590,7 +602,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar $output[$key] = $value; } } elseif (isset($output[$key])) { - @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), \E_USER_DEPRECATED); } --$i; } @@ -600,7 +612,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar } } - throw new ParseException(sprintf('Malformed inline YAML string: %s.', $mapping), self::$parsedLineNumber + 1, null, self::$parsedFilename); + throw new ParseException(sprintf('Malformed inline YAML string: "%s".', $mapping), self::$parsedLineNumber + 1, null, self::$parsedFilename); } /** @@ -614,7 +626,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar * * @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($scalar, $flags, $references = array()) + private static function evaluateScalar($scalar, $flags, $references = []) { $scalar = trim($scalar); $scalarLower = strtolower($scalar); @@ -631,7 +643,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) throw new ParseException('A reference must contain at least one character.', self::$parsedLineNumber + 1, $value, self::$parsedFilename); } - if (!array_key_exists($value, $references)) { + if (!\array_key_exists($value, $references)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $value), self::$parsedLineNumber + 1, $value, self::$parsedFilename); } @@ -642,7 +654,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case 'null' === $scalarLower: case '' === $scalar: case '~' === $scalar: - return; + return null; case 'true' === $scalarLower: return true; case 'false' === $scalarLower: @@ -650,18 +662,18 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case '!' === $scalar[0]: switch (true) { case 0 === strpos($scalar, '!str'): - @trigger_error(self::getDeprecationMessage('Support for the !str tag is deprecated since Symfony 3.4. Use the !!str tag instead.'), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Support for the !str tag is deprecated since Symfony 3.4. Use the !!str tag instead.'), \E_USER_DEPRECATED); return (string) substr($scalar, 5); case 0 === strpos($scalar, '!!str '): return (string) substr($scalar, 6); case 0 === strpos($scalar, '! '): - @trigger_error(self::getDeprecationMessage('Using the non-specific tag "!" is deprecated since Symfony 3.4 as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or !!float instead.'), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Using the non-specific tag "!" is deprecated since Symfony 3.4 as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or !!float instead.'), \E_USER_DEPRECATED); return (int) self::parseScalar(substr($scalar, 2), $flags); case 0 === strpos($scalar, '!php/object:'): if (self::$objectSupport) { - @trigger_error(self::getDeprecationMessage('The !php/object: tag to indicate dumped PHP objects is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('The !php/object: tag to indicate dumped PHP objects is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), \E_USER_DEPRECATED); return unserialize(substr($scalar, 12)); } @@ -670,10 +682,10 @@ private static function evaluateScalar($scalar, $flags, $references = array()) throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } - return; + return null; case 0 === strpos($scalar, '!!php/object:'): if (self::$objectSupport) { - @trigger_error(self::getDeprecationMessage('The !!php/object: tag to indicate dumped PHP objects is deprecated since Symfony 3.1 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('The !!php/object: tag to indicate dumped PHP objects is deprecated since Symfony 3.1 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), \E_USER_DEPRECATED); return unserialize(substr($scalar, 13)); } @@ -682,9 +694,13 @@ private static function evaluateScalar($scalar, $flags, $references = array()) throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } - return; + return null; case 0 === strpos($scalar, '!php/object'): if (self::$objectSupport) { + if (!isset($scalar[12])) { + return false; + } + return unserialize(self::parseScalar(substr($scalar, 12))); } @@ -692,10 +708,10 @@ private static function evaluateScalar($scalar, $flags, $references = array()) throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } - return; + return null; case 0 === strpos($scalar, '!php/const:'): if (self::$constantSupport) { - @trigger_error(self::getDeprecationMessage('The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead.'), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead.'), \E_USER_DEPRECATED); if (\defined($const = substr($scalar, 11))) { return \constant($const); @@ -704,12 +720,16 @@ private static function evaluateScalar($scalar, $flags, $references = array()) throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } if (self::$exceptionOnInvalidType) { - throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); + throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Did you forget to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } - return; + return null; case 0 === strpos($scalar, '!php/const'): if (self::$constantSupport) { + if (!isset($scalar[11])) { + return ''; + } + $i = 0; if (\defined($const = self::parseScalar(substr($scalar, 11), 0, null, $i, false))) { return \constant($const); @@ -718,36 +738,42 @@ private static function evaluateScalar($scalar, $flags, $references = array()) throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } if (self::$exceptionOnInvalidType) { - throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); + throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Did you forget to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } - return; + return null; case 0 === strpos($scalar, '!!float '): return (float) substr($scalar, 8); case 0 === strpos($scalar, '!!binary '): return self::evaluateBinaryScalar(substr($scalar, 9)); default: - @trigger_error(self::getDeprecationMessage(sprintf('Using the unquoted scalar value "%s" is deprecated since Symfony 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar)), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage(sprintf('Using the unquoted scalar value "%s" is deprecated since Symfony 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar)), \E_USER_DEPRECATED); } // Optimize for returning strings. // no break case '+' === $scalar[0] || '-' === $scalar[0] || '.' === $scalar[0] || is_numeric($scalar[0]): + if (Parser::preg_match('{^[+-]?[0-9][0-9_]*$}', $scalar)) { + $scalar = str_replace('_', '', (string) $scalar); + } + switch (true) { - case Parser::preg_match('{^[+-]?[0-9][0-9_]*$}', $scalar): - $scalar = str_replace('_', '', (string) $scalar); - // omitting the break / return as integers are handled in the next case - // no break case ctype_digit($scalar): - $raw = $scalar; + if (preg_match('/^0[0-7]+$/', $scalar)) { + return octdec($scalar); + } + $cast = (int) $scalar; - return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); + return ($scalar === (string) $cast) ? $cast : $scalar; case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)): - $raw = $scalar; + if (preg_match('/^-0[0-7]+$/', $scalar)) { + return -octdec(substr($scalar, 1)); + } + $cast = (int) $scalar; - return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw === (string) $cast) ? $cast : $raw); + return ($scalar === (string) $cast) ? $cast : $scalar; case is_numeric($scalar): case Parser::preg_match(self::getHexRegex(), $scalar): $scalar = str_replace('_', '', $scalar); @@ -761,10 +787,10 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case Parser::preg_match('/^(-|\+)?[0-9][0-9,]*(\.[0-9_]+)?$/', $scalar): case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar): if (false !== strpos($scalar, ',')) { - @trigger_error(self::getDeprecationMessage('Using the comma as a group separator for floats is deprecated since Symfony 3.2 and will be removed in 4.0.'), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Using the comma as a group separator for floats is deprecated since Symfony 3.2 and will be removed in 4.0.'), \E_USER_DEPRECATED); } - return (float) str_replace(array(',', '_'), '', $scalar); + return (float) str_replace([',', '_'], '', $scalar); case Parser::preg_match(self::getTimestampRegex(), $scalar): if (Yaml::PARSE_DATETIME & $flags) { // When no timezone is provided in the parsed date, YAML spec says we must assume UTC. @@ -788,12 +814,12 @@ private static function evaluateScalar($scalar, $flags, $references = array()) * @param int &$i * @param int $flags * - * @return null|string + * @return string|null */ private static function parseTag($value, &$i, $flags) { if ('!' !== $value[$i]) { - return; + return null; } $tagLength = strcspn($value, " \t\n", $i + 1); @@ -803,9 +829,9 @@ private static function parseTag($value, &$i, $flags) $nextOffset += strspn($value, ' ', $nextOffset); // Is followed by a scalar - if ((!isset($value[$nextOffset]) || !\in_array($value[$nextOffset], array('[', '{'), true)) && 'tagged' !== $tag) { + if ((!isset($value[$nextOffset]) || !\in_array($value[$nextOffset], ['[', '{'], true)) && 'tagged' !== $tag) { // Manage non-whitelisted scalars in {@link self::evaluateScalar()} - return; + return null; } // Built-in tags diff --git a/vendor/symfony/yaml/LICENSE b/vendor/symfony/yaml/LICENSE index 21d7fb9..9e936ec 100644 --- a/vendor/symfony/yaml/LICENSE +++ b/vendor/symfony/yaml/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-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/vendor/symfony/yaml/Parser.php b/vendor/symfony/yaml/Parser.php index 284af1f..ddd8567 100644 --- a/vendor/symfony/yaml/Parser.php +++ b/vendor/symfony/yaml/Parser.php @@ -29,17 +29,18 @@ class Parser private $filename; private $offset = 0; private $totalNumberOfLines; - private $lines = array(); + private $lines = []; private $currentLineNb = -1; private $currentLine = ''; - private $refs = array(); - private $skippedLineNumbers = array(); - private $locallySkippedLineNumbers = array(); + private $refs = []; + private $skippedLineNumbers = []; + private $locallySkippedLineNumbers = []; + private $refsBeingParsed = []; public function __construct() { if (\func_num_args() > 0) { - @trigger_error(sprintf('The constructor arguments $offset, $totalNumberOfLines, $skippedLineNumbers of %s are deprecated and will be removed in 4.0', self::class), E_USER_DEPRECATED); + @trigger_error(sprintf('The constructor arguments $offset, $totalNumberOfLines, $skippedLineNumbers of %s are deprecated and will be removed in 4.0', self::class), \E_USER_DEPRECATED); $this->offset = func_get_arg(0); if (\func_num_args() > 1) { @@ -93,7 +94,7 @@ public function parseFile($filename, $flags = 0) public function parse($value, $flags = 0) { if (\is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', \E_USER_DEPRECATED); if ($flags) { $flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE; @@ -103,7 +104,7 @@ public function parse($value, $flags = 0) } if (\func_num_args() >= 3) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', \E_USER_DEPRECATED); if (func_get_arg(2)) { $flags |= Yaml::PARSE_OBJECT; @@ -111,7 +112,7 @@ public function parse($value, $flags = 0) } if (\func_num_args() >= 4) { - @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', \E_USER_DEPRECATED); if (func_get_arg(3)) { $flags |= Yaml::PARSE_OBJECT_FOR_MAP; @@ -119,14 +120,14 @@ public function parse($value, $flags = 0) } if (Yaml::PARSE_KEYS_AS_STRINGS & $flags) { - @trigger_error('Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since Symfony 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead.', E_USER_DEPRECATED); + @trigger_error('Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since Symfony 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead.', \E_USER_DEPRECATED); } if (false === preg_match('//u', $value)) { throw new ParseException('The YAML value does not appear to be valid UTF-8.', -1, null, $this->filename); } - $this->refs = array(); + $this->refs = []; $mbEncoding = null; $e = null; @@ -147,11 +148,12 @@ public function parse($value, $flags = 0) mb_internal_encoding($mbEncoding); } - $this->lines = array(); + $this->lines = []; $this->currentLine = ''; - $this->refs = array(); - $this->skippedLineNumbers = array(); - $this->locallySkippedLineNumbers = array(); + $this->refs = []; + $this->skippedLineNumbers = []; + $this->locallySkippedLineNumbers = []; + $this->totalNumberOfLines = null; if (null !== $e) { throw $e; @@ -166,7 +168,7 @@ private function doParse($value, $flags) $this->currentLine = ''; $value = $this->cleanup($value); $this->lines = explode("\n", $value); - $this->locallySkippedLineNumbers = array(); + $this->locallySkippedLineNumbers = []; if (null === $this->totalNumberOfLines) { $this->totalNumberOfLines = \count($this->lines); @@ -176,7 +178,7 @@ private function doParse($value, $flags) return null; } - $data = array(); + $data = []; $context = null; $allowOverwrite = false; @@ -206,17 +208,18 @@ private function doParse($value, $flags) $isRef = $mergeNode = false; if (self::preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+))?$#u', rtrim($this->currentLine), $values)) { if ($context && 'mapping' == $context) { - throw new ParseException('You cannot define a sequence item when in a mapping', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); + throw new ParseException('You cannot define a sequence item when in a mapping.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } $context = 'sequence'; if (isset($values['value']) && self::preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; + $this->refsBeingParsed[] = $isRef; $values['value'] = $matches['value']; } if (isset($values['value'][1]) && '?' === $values['value'][0] && ' ' === $values['value'][1]) { - @trigger_error($this->getDeprecationMessage('Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.'), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage('Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.'), \E_USER_DEPRECATED); } // array @@ -228,8 +231,12 @@ private function doParse($value, $flags) $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(null, true), $flags) ); } else { - if (isset($values['leadspaces']) - && self::preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $this->trimTag($values['value']), $matches) + if ( + isset($values['leadspaces']) + && ( + '!' === $values['value'][0] + || self::preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $this->trimTag($values['value']), $matches) + ) ) { // this is a compact notation element, add to next block and parse $block = $values['value']; @@ -244,13 +251,14 @@ private function doParse($value, $flags) } if ($isRef) { $this->refs[$isRef] = end($data); + array_pop($this->refsBeingParsed); } } elseif ( self::preg_match('#^(?P<key>(?:![^\s]++\s++)?(?:'.Inline::REGEX_QUOTED_STRING.'|(?:!?!php/const:)?[^ \'"\[\{!].*?)) *\:(\s++(?P<value>.+))?$#u', rtrim($this->currentLine), $values) - && (false === strpos($values['key'], ' #') || \in_array($values['key'][0], array('"', "'"))) + && (false === strpos($values['key'], ' #') || \in_array($values['key'][0], ['"', "'"])) ) { if ($context && 'sequence' == $context) { - throw new ParseException('You cannot define a mapping item when in a sequence', $this->currentLineNb + 1, $this->currentLine, $this->filename); + throw new ParseException('You cannot define a mapping item when in a sequence.', $this->currentLineNb + 1, $this->currentLine, $this->filename); } $context = 'mapping'; @@ -273,7 +281,7 @@ private function doParse($value, $flags) if (!\is_string($key) && !\is_int($key)) { $keyType = is_numeric($key) ? 'numeric key' : 'non-string key'; - @trigger_error($this->getDeprecationMessage(sprintf('Implicit casting of %s to string is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', $keyType)), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage(sprintf('Implicit casting of %s to string is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', $keyType)), \E_USER_DEPRECATED); } // Convert float keys to strings, to avoid being converted to integers by PHP @@ -286,7 +294,11 @@ private function doParse($value, $flags) $allowOverwrite = true; if (isset($values['value'][0]) && '*' === $values['value'][0]) { $refName = substr(rtrim($values['value']), 1); - if (!array_key_exists($refName, $this->refs)) { + if (!\array_key_exists($refName, $this->refs)) { + if (false !== $pos = array_search($refName, $this->refsBeingParsed, true)) { + throw new ParseException(sprintf('Circular reference [%s, %s] detected for reference "%s".', implode(', ', \array_slice($this->refsBeingParsed, $pos)), $refName, $refName), $this->currentLineNb + 1, $this->currentLine, $this->filename); + } + throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } @@ -340,6 +352,7 @@ private function doParse($value, $flags) } } elseif ('<<' !== $key && isset($values['value']) && self::preg_match('#^&(?P<ref>[^ ]++) *+(?P<value>.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; + $this->refsBeingParsed[] = $isRef; $values['value'] = $matches['value']; } @@ -359,7 +372,7 @@ private function doParse($value, $flags) $data[$key] = null; } } else { - @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), \E_USER_DEPRECATED); } } else { $value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $flags); @@ -380,7 +393,7 @@ private function doParse($value, $flags) $data[$key] = $value; } } else { - @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), \E_USER_DEPRECATED); } } } else { @@ -390,11 +403,12 @@ private function doParse($value, $flags) if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; } else { - @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since Symfony 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), \E_USER_DEPRECATED); } } if ($isRef) { $this->refs[$isRef] = $data[$key]; + array_pop($this->refsBeingParsed); } } else { // multiple documents are not supported @@ -403,7 +417,7 @@ private function doParse($value, $flags) } if ($deprecatedUsage = (isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1])) { - @trigger_error($this->getDeprecationMessage('Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.'), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage('Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.'), \E_USER_DEPRECATED); } // 1-liner optionally followed by newline(s) @@ -427,6 +441,9 @@ private function doParse($value, $flags) $value = ''; foreach ($this->lines as $line) { + if ('' !== ltrim($line) && '#' === ltrim($line)[0]) { + continue; + } // If the indentation is not consistent at offset 0, it is to be considered as a ParseError if (0 === $this->offset && !$deprecatedUsage && isset($line[0]) && ' ' === $line[0]) { throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); @@ -500,6 +517,7 @@ private function parseBlock($offset, $yaml, $flags) $parser->totalNumberOfLines = $this->totalNumberOfLines; $parser->skippedLineNumbers = $skippedLineNumbers; $parser->refs = &$this->refs; + $parser->refsBeingParsed = $this->refsBeingParsed; return $parser->doParse($yaml, $flags); } @@ -549,14 +567,9 @@ private function getCurrentLineIndentation() private function getNextEmbedBlock($indentation = null, $inSequence = false) { $oldLineIndentation = $this->getCurrentLineIndentation(); - $blockScalarIndentations = array(); - - if ($this->isBlockScalarHeader()) { - $blockScalarIndentations[] = $oldLineIndentation; - } if (!$this->moveToNextLine()) { - return; + return ''; } if (null === $indentation) { @@ -591,7 +604,7 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) $newIndent = $indentation; } - $data = array(); + $data = []; if ($this->getCurrentLineIndentation() >= $newIndent) { $data[] = substr($this->currentLine, $newIndent); } elseif ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()) { @@ -599,7 +612,7 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) } else { $this->moveToPreviousLine(); - return; + return ''; } if ($inSequence && $oldLineIndentation === $newIndent && isset($data[0][0]) && '-' === $data[0][0]) { @@ -607,34 +620,19 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) // and therefore no nested list or mapping $this->moveToPreviousLine(); - return; + return ''; } $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem(); - - if (empty($blockScalarIndentations) && $this->isBlockScalarHeader()) { - $blockScalarIndentations[] = $this->getCurrentLineIndentation(); - } - - $previousLineIndentation = $this->getCurrentLineIndentation(); + $isItComment = $this->isCurrentLineComment(); while ($this->moveToNextLine()) { - $indent = $this->getCurrentLineIndentation(); - - // terminate all block scalars that are more indented than the current line - if (!empty($blockScalarIndentations) && $indent < $previousLineIndentation && '' !== trim($this->currentLine)) { - foreach ($blockScalarIndentations as $key => $blockScalarIndentation) { - if ($blockScalarIndentation >= $indent) { - unset($blockScalarIndentations[$key]); - } - } + if ($isItComment && !$isItUnindentedCollection) { + $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem(); + $isItComment = $this->isCurrentLineComment(); } - if (empty($blockScalarIndentations) && !$this->isCurrentLineComment() && $this->isBlockScalarHeader()) { - $blockScalarIndentations[] = $indent; - } - - $previousLineIndentation = $indent; + $indent = $this->getCurrentLineIndentation(); if ($isItUnindentedCollection && !$this->isCurrentLineEmpty() && !$this->isStringUnIndentedCollectionItem() && $newIndent === $indent) { $this->moveToPreviousLine(); @@ -714,7 +712,11 @@ private function parseValue($value, $flags, $context) $value = substr($value, 1); } - if (!array_key_exists($value, $this->refs)) { + if (!\array_key_exists($value, $this->refs)) { + if (false !== $pos = array_search($value, $this->refsBeingParsed, true)) { + throw new ParseException(sprintf('Circular reference [%s, %s] detected for reference "%s".', implode(', ', \array_slice($this->refsBeingParsed, $pos)), $value, $value), $this->currentLineNb + 1, $this->currentLine, $this->filename); + } + throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine, $this->filename); } @@ -724,7 +726,7 @@ private function parseValue($value, $flags, $context) if (self::preg_match('/^(?:'.self::TAG_PATTERN.' +)?'.self::BLOCK_SCALAR_HEADER_PATTERN.'$/', $value, $matches)) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; - $data = $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); + $data = $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), abs((int) $modifiers)); if ('' !== $matches['tag']) { if ('!!binary' === $matches['tag']) { @@ -732,7 +734,7 @@ private function parseValue($value, $flags, $context) } elseif ('tagged' === $matches['tag']) { return new TaggedValue(substr($matches['tag'], 1), $data); } elseif ('!' !== $matches['tag']) { - @trigger_error($this->getDeprecationMessage(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since Symfony 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class)), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since Symfony 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class)), \E_USER_DEPRECATED); } } @@ -747,7 +749,7 @@ private function parseValue($value, $flags, $context) return Inline::parse($value, $flags, $this->refs); } - $lines = array(); + $lines = []; while ($this->moveToNextLine()) { // unquoted strings end before the first unindented line @@ -760,7 +762,8 @@ private function parseValue($value, $flags, $context) $lines[] = trim($this->currentLine); // quoted string values end with a line that is terminated with the quotation character - if ('' !== $this->currentLine && substr($this->currentLine, -1) === $quotation) { + $escapedLine = str_replace(['\\\\', '\\"'], '', $this->currentLine); + if ('' !== $escapedLine && substr($escapedLine, -1) === $quotation) { break; } } @@ -812,7 +815,7 @@ private function parseBlockScalar($style, $chomping = '', $indentation = 0) } $isCurrentLineBlank = $this->isCurrentLineBlank(); - $blockLines = array(); + $blockLines = []; // leading blank lines are consumed before determining indentation while ($notEOF && $isCurrentLineBlank) { @@ -984,7 +987,7 @@ private function isCurrentLineLastLineInDocument() */ private function cleanup($value) { - $value = str_replace(array("\r\n", "\r"), "\n", $value); + $value = str_replace(["\r\n", "\r"], "\n", $value); // strip YAML header $count = 0; @@ -1054,16 +1057,6 @@ private function isStringUnIndentedCollectionItem() return '-' === rtrim($this->currentLine) || 0 === strpos($this->currentLine, '- '); } - /** - * Tests whether or not the current line is the header of a block scalar. - * - * @return bool - */ - private function isBlockScalarHeader() - { - return (bool) self::preg_match('~'.self::BLOCK_SCALAR_HEADER_PATTERN.'$~', $this->currentLine); - } - /** * A local wrapper for `preg_match` which will throw a ParseException if there * is an internal error in the PCRE engine. @@ -1081,19 +1074,19 @@ public static function preg_match($pattern, $subject, &$matches = null, $flags = { if (false === $ret = preg_match($pattern, $subject, $matches, $flags, $offset)) { switch (preg_last_error()) { - case PREG_INTERNAL_ERROR: + case \PREG_INTERNAL_ERROR: $error = 'Internal PCRE error.'; break; - case PREG_BACKTRACK_LIMIT_ERROR: + case \PREG_BACKTRACK_LIMIT_ERROR: $error = 'pcre.backtrack_limit reached.'; break; - case PREG_RECURSION_LIMIT_ERROR: + case \PREG_RECURSION_LIMIT_ERROR: $error = 'pcre.recursion_limit reached.'; break; - case PREG_BAD_UTF8_ERROR: + case \PREG_BAD_UTF8_ERROR: $error = 'Malformed UTF-8 data.'; break; - case PREG_BAD_UTF8_OFFSET_ERROR: + case \PREG_BAD_UTF8_OFFSET_ERROR: $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.'; break; default: @@ -1121,14 +1114,17 @@ private function trimTag($value) return $value; } + /** + * @return string|null + */ private function getLineTag($value, $flags, $nextLineCheck = true) { if ('' === $value || '!' !== $value[0] || 1 !== self::preg_match('/^'.self::TAG_PATTERN.' *( +#.*)?$/', $value, $matches)) { - return; + return null; } if ($nextLineCheck && !$this->isNextLineIndented()) { - return; + return null; } $tag = substr($matches['tag'], 1); diff --git a/vendor/symfony/yaml/README.md b/vendor/symfony/yaml/README.md index 0d32488..b914e78 100644 --- a/vendor/symfony/yaml/README.md +++ b/vendor/symfony/yaml/README.md @@ -6,7 +6,7 @@ The Yaml component loads and dumps YAML files. Resources --------- - * [Documentation](https://symfony.com/doc/current/components/yaml/index.html) + * [Documentation](https://symfony.com/doc/current/components/yaml.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) diff --git a/vendor/symfony/yaml/Tests/Command/LintCommandTest.php b/vendor/symfony/yaml/Tests/Command/LintCommandTest.php index a5baf23..98c63b6 100644 --- a/vendor/symfony/yaml/Tests/Command/LintCommandTest.php +++ b/vendor/symfony/yaml/Tests/Command/LintCommandTest.php @@ -31,10 +31,10 @@ public function testLintCorrectFile() $tester = $this->createCommandTester(); $filename = $this->createFile('foo: bar'); - $ret = $tester->execute(array('filename' => $filename), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)); + $ret = $tester->execute(['filename' => $filename], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]); $this->assertEquals(0, $ret, 'Returns 0 in case of success'); - $this->assertRegExp('/^\/\/ OK in /', trim($tester->getDisplay())); + $this->assertMatchesRegularExpression('/^\/\/ OK in /', trim($tester->getDisplay())); } public function testLintIncorrectFile() @@ -45,10 +45,10 @@ public function testLintIncorrectFile() $tester = $this->createCommandTester(); $filename = $this->createFile($incorrectContent); - $ret = $tester->execute(array('filename' => $filename), array('decorated' => false)); + $ret = $tester->execute(['filename' => $filename], ['decorated' => false]); $this->assertEquals(1, $ret, 'Returns 1 in case of error'); - $this->assertContains('Unable to parse at line 3 (near "bar").', trim($tester->getDisplay())); + $this->assertStringContainsString('Unable to parse at line 3 (near "bar").', trim($tester->getDisplay())); } public function testConstantAsKey() @@ -56,7 +56,7 @@ public function testConstantAsKey() $yaml = <<<YAML !php/const 'Symfony\Component\Yaml\Tests\Command\Foo::TEST': bar YAML; - $ret = $this->createCommandTester()->execute(array('filename' => $this->createFile($yaml)), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)); + $ret = $this->createCommandTester()->execute(['filename' => $this->createFile($yaml)], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]); $this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success'); } @@ -65,7 +65,7 @@ public function testCustomTags() $yaml = <<<YAML foo: !my_tag {foo: bar} YAML; - $ret = $this->createCommandTester()->execute(array('filename' => $this->createFile($yaml), '--parse-tags' => true), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)); + $ret = $this->createCommandTester()->execute(['filename' => $this->createFile($yaml), '--parse-tags' => true], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]); $this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success'); } @@ -74,20 +74,18 @@ public function testCustomTagsError() $yaml = <<<YAML foo: !my_tag {foo: bar} YAML; - $ret = $this->createCommandTester()->execute(array('filename' => $this->createFile($yaml)), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)); + $ret = $this->createCommandTester()->execute(['filename' => $this->createFile($yaml)], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]); $this->assertSame(1, $ret, 'lint:yaml exits with code 1 in case of error'); } - /** - * @expectedException \RuntimeException - */ public function testLintFileNotReadable() { + $this->expectException('RuntimeException'); $tester = $this->createCommandTester(); $filename = $this->createFile(''); unlink($filename); - $ret = $tester->execute(array('filename' => $filename), array('decorated' => false)); + $tester->execute(['filename' => $filename], ['decorated' => false]); } /** @@ -117,7 +115,7 @@ protected function createCommandTester() protected function setUp() { - $this->files = array(); + $this->files = []; @mkdir(sys_get_temp_dir().'/framework-yml-lint-test'); } @@ -125,11 +123,11 @@ protected function tearDown() { foreach ($this->files as $file) { if (file_exists($file)) { - unlink($file); + @unlink($file); } } - rmdir(sys_get_temp_dir().'/framework-yml-lint-test'); + @rmdir(sys_get_temp_dir().'/framework-yml-lint-test'); } } diff --git a/vendor/symfony/yaml/Tests/DumperTest.php b/vendor/symfony/yaml/Tests/DumperTest.php index d84a140..e4dc49f 100644 --- a/vendor/symfony/yaml/Tests/DumperTest.php +++ b/vendor/symfony/yaml/Tests/DumperTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Yaml\Dumper; use Symfony\Component\Yaml\Parser; +use Symfony\Component\Yaml\Tag\TaggedValue; use Symfony\Component\Yaml\Yaml; class DumperTest extends TestCase @@ -22,20 +23,20 @@ class DumperTest extends TestCase protected $dumper; protected $path; - protected $array = array( + protected $array = [ '' => 'bar', 'foo' => '#bar', - 'foo\'bar' => array(), - 'bar' => array(1, 'foo'), - 'foobar' => array( + 'foo\'bar' => [], + 'bar' => [1, 'foo'], + 'foobar' => [ 'foo' => 'bar', - 'bar' => array(1, 'foo'), - 'foobar' => array( + 'bar' => [1, 'foo'], + 'foobar' => [ 'foo' => 'bar', - 'bar' => array(1, 'foo'), - ), - ), - ); + 'bar' => [1, 'foo'], + ], + ], + ]; protected function setUp() { @@ -208,7 +209,7 @@ public function testInlineLevel() public function testObjectSupportEnabled() { - $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, Yaml::DUMP_OBJECT); + $dump = $this->dumper->dump(['foo' => new A(), 'bar' => 1], 0, 0, Yaml::DUMP_OBJECT); $this->assertEquals('{ foo: !php/object \'O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}\', bar: 1 }', $dump, '->dump() is able to dump objects'); } @@ -218,44 +219,42 @@ public function testObjectSupportEnabled() */ public function testObjectSupportEnabledPassingTrue() { - $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, false, true); + $dump = $this->dumper->dump(['foo' => new A(), 'bar' => 1], 0, 0, false, true); $this->assertEquals('{ foo: !php/object \'O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}\', bar: 1 }', $dump, '->dump() is able to dump objects'); } public function testObjectSupportDisabledButNoExceptions() { - $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1)); + $dump = $this->dumper->dump(['foo' => new A(), 'bar' => 1]); $this->assertEquals('{ foo: null, bar: 1 }', $dump, '->dump() does not dump objects when disabled'); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\DumpException - */ public function testObjectSupportDisabledWithExceptions() { - $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE); + $this->expectException('Symfony\Component\Yaml\Exception\DumpException'); + $this->dumper->dump(['foo' => new A(), 'bar' => 1], 0, 0, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE); } /** * @group legacy - * @expectedException \Symfony\Component\Yaml\Exception\DumpException */ public function testObjectSupportDisabledWithExceptionsPassingTrue() { - $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, true); + $this->expectException('Symfony\Component\Yaml\Exception\DumpException'); + $this->dumper->dump(['foo' => new A(), 'bar' => 1], 0, 0, true); } public function testEmptyArray() { - $dump = $this->dumper->dump(array()); + $dump = $this->dumper->dump([]); $this->assertEquals('{ }', $dump); - $dump = $this->dumper->dump(array(), 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE); + $dump = $this->dumper->dump([], 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE); $this->assertEquals('[]', $dump); - $dump = $this->dumper->dump(array(), 9, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE); + $dump = $this->dumper->dump([], 9, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE); $this->assertEquals('[]', $dump); $dump = $this->dumper->dump(new \ArrayObject(), 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE | Yaml::DUMP_OBJECT_AS_MAP); @@ -275,27 +274,28 @@ public function testEscapedEscapeSequencesInQuotedScalar($input, $expected) public function getEscapeSequences() { - return array( - 'empty string' => array('', "''"), - 'null' => array("\x0", '"\\0"'), - 'bell' => array("\x7", '"\\a"'), - 'backspace' => array("\x8", '"\\b"'), - 'horizontal-tab' => array("\t", '"\\t"'), - 'line-feed' => array("\n", '"\\n"'), - 'vertical-tab' => array("\v", '"\\v"'), - 'form-feed' => array("\xC", '"\\f"'), - 'carriage-return' => array("\r", '"\\r"'), - 'escape' => array("\x1B", '"\\e"'), - 'space' => array(' ', "' '"), - 'double-quote' => array('"', "'\"'"), - 'slash' => array('/', '/'), - 'backslash' => array('\\', '\\'), - 'next-line' => array("\xC2\x85", '"\\N"'), - 'non-breaking-space' => array("\xc2\xa0", '"\\_"'), - 'line-separator' => array("\xE2\x80\xA8", '"\\L"'), - 'paragraph-separator' => array("\xE2\x80\xA9", '"\\P"'), - 'colon' => array(':', "':'"), - ); + return [ + 'empty string' => ['', "''"], + 'null' => ["\x0", '"\\0"'], + 'bell' => ["\x7", '"\\a"'], + 'backspace' => ["\x8", '"\\b"'], + 'horizontal-tab' => ["\t", '"\\t"'], + 'line-feed' => ["\n", '"\\n"'], + 'vertical-tab' => ["\v", '"\\v"'], + 'form-feed' => ["\xC", '"\\f"'], + 'carriage-return' => ["\r", '"\\r"'], + 'escape' => ["\x1B", '"\\e"'], + 'space' => [' ', "' '"], + 'double-quote' => ['"', "'\"'"], + 'slash' => ['/', '/'], + 'backslash' => ['\\', '\\'], + 'del' => ["\x7f", '"\x7f"'], + 'next-line' => ["\xC2\x85", '"\\N"'], + 'non-breaking-space' => ["\xc2\xa0", '"\\_"'], + 'line-separator' => ["\xE2\x80\xA8", '"\\L"'], + 'paragraph-separator' => ["\xE2\x80\xA9", '"\\P"'], + 'colon' => [':', "':'"], + ]; } public function testBinaryDataIsDumpedBase64Encoded() @@ -303,7 +303,7 @@ public function testBinaryDataIsDumpedBase64Encoded() $binaryData = file_get_contents(__DIR__.'/Fixtures/arrow.gif'); $expected = '{ data: !!binary '.base64_encode($binaryData).' }'; - $this->assertSame($expected, $this->dumper->dump(array('data' => $binaryData))); + $this->assertSame($expected, $this->dumper->dump(['data' => $binaryData])); } public function testNonUtf8DataIsDumpedBase64Encoded() @@ -324,18 +324,18 @@ public function testDumpObjectAsMap($object, $expected) public function objectAsMapProvider() { - $tests = array(); + $tests = []; $bar = new \stdClass(); $bar->class = 'classBar'; - $bar->args = array('bar'); + $bar->args = ['bar']; $zar = new \stdClass(); $foo = new \stdClass(); $foo->bar = $bar; $foo->zar = $zar; $object = new \stdClass(); $object->foo = $foo; - $tests['stdClass'] = array($object, $object); + $tests['stdClass'] = [$object, $object]; $arrayObject = new \ArrayObject(); $arrayObject['foo'] = 'bar'; @@ -343,19 +343,19 @@ public function objectAsMapProvider() $parsedArrayObject = new \stdClass(); $parsedArrayObject->foo = 'bar'; $parsedArrayObject->baz = 'foobar'; - $tests['ArrayObject'] = array($arrayObject, $parsedArrayObject); + $tests['ArrayObject'] = [$arrayObject, $parsedArrayObject]; $a = new A(); - $tests['arbitrary-object'] = array($a, null); + $tests['arbitrary-object'] = [$a, null]; return $tests; } public function testDumpingArrayObjectInstancesRespectsInlineLevel() { - $deep = new \ArrayObject(array('deep1' => 'd', 'deep2' => 'e')); - $inner = new \ArrayObject(array('inner1' => 'b', 'inner2' => 'c', 'inner3' => $deep)); - $outer = new \ArrayObject(array('outer1' => 'a', 'outer2' => $inner)); + $deep = new \ArrayObject(['deep1' => 'd', 'deep2' => 'e']); + $inner = new \ArrayObject(['inner1' => 'b', 'inner2' => 'c', 'inner3' => $deep]); + $outer = new \ArrayObject(['outer1' => 'a', 'outer2' => $inner]); $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP); @@ -372,9 +372,9 @@ public function testDumpingArrayObjectInstancesRespectsInlineLevel() public function testDumpingArrayObjectInstancesWithNumericKeysInlined() { - $deep = new \ArrayObject(array('d', 'e')); - $inner = new \ArrayObject(array('b', 'c', $deep)); - $outer = new \ArrayObject(array('a', $inner)); + $deep = new \ArrayObject(['d', 'e']); + $inner = new \ArrayObject(['b', 'c', $deep]); + $outer = new \ArrayObject(['a', $inner]); $yaml = $this->dumper->dump($outer, 0, 0, Yaml::DUMP_OBJECT_AS_MAP); $expected = <<<YAML @@ -385,9 +385,9 @@ public function testDumpingArrayObjectInstancesWithNumericKeysInlined() public function testDumpingArrayObjectInstancesWithNumericKeysRespectsInlineLevel() { - $deep = new \ArrayObject(array('d', 'e')); - $inner = new \ArrayObject(array('b', 'c', $deep)); - $outer = new \ArrayObject(array('a', $inner)); + $deep = new \ArrayObject(['d', 'e']); + $inner = new \ArrayObject(['b', 'c', $deep]); + $outer = new \ArrayObject(['a', $inner]); $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP); $expected = <<<YAML 0: a @@ -438,53 +438,213 @@ public function testDumpingStdClassInstancesRespectsInlineLevel() $this->assertSame($expected, $yaml); } + public function testDumpingTaggedValueSequenceRespectsInlineLevel() + { + $data = [ + new TaggedValue('user', [ + 'username' => 'jane', + ]), + new TaggedValue('user', [ + 'username' => 'john', + ]), + ]; + + $yaml = $this->dumper->dump($data, 2); + + $expected = <<<YAML +- !user + username: jane +- !user + username: john + +YAML; + $this->assertSame($expected, $yaml); + } + + public function testDumpingTaggedValueSequenceWithInlinedTagValues() + { + $data = [ + new TaggedValue('user', [ + 'username' => 'jane', + ]), + new TaggedValue('user', [ + 'username' => 'john', + ]), + ]; + + $yaml = $this->dumper->dump($data, 1); + + $expected = <<<YAML +- !user { username: jane } +- !user { username: john } + +YAML; + $this->assertSame($expected, $yaml); + } + + public function testDumpingTaggedValueMapRespectsInlineLevel() + { + $data = [ + 'user1' => new TaggedValue('user', [ + 'username' => 'jane', + ]), + 'user2' => new TaggedValue('user', [ + 'username' => 'john', + ]), + ]; + + $yaml = $this->dumper->dump($data, 2); + + $expected = <<<YAML +user1: !user + username: jane +user2: !user + username: john + +YAML; + $this->assertSame($expected, $yaml); + } + + public function testDumpingTaggedValueMapWithInlinedTagValues() + { + $data = [ + 'user1' => new TaggedValue('user', [ + 'username' => 'jane', + ]), + 'user2' => new TaggedValue('user', [ + 'username' => 'john', + ]), + ]; + + $yaml = $this->dumper->dump($data, 1); + + $expected = <<<YAML +user1: !user { username: jane } +user2: !user { username: john } + +YAML; + $this->assertSame($expected, $yaml); + } + + public function testDumpingNotInlinedScalarTaggedValue() + { + $data = [ + 'user1' => new TaggedValue('user', 'jane'), + 'user2' => new TaggedValue('user', 'john'), + ]; + $expected = <<<YAML +user1: !user jane +user2: !user john + +YAML; + + $this->assertSame($expected, $this->dumper->dump($data, 2)); + } + + public function testDumpingNotInlinedNullTaggedValue() + { + $data = [ + 'foo' => new TaggedValue('bar', null), + ]; + $expected = <<<YAML +foo: !bar null + +YAML; + + $this->assertSame($expected, $this->dumper->dump($data, 2)); + } + + public function testDumpingMultiLineStringAsScalarBlockTaggedValue() + { + $data = [ + 'foo' => new TaggedValue('bar', "foo\nline with trailing spaces:\n \nbar\ninteger like line:\n123456789\nempty line:\n\nbaz"), + ]; + $expected = <<<YAML +foo: !bar | + foo + line with trailing spaces: + + bar + integer like line: + 123456789 + empty line: + + baz + +YAML; + + $this->assertSame($expected, $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); + } + + public function testDumpingInlinedMultiLineIfRnBreakLineInTaggedValue() + { + $data = [ + 'data' => [ + 'foo' => new TaggedValue('bar', "foo\r\nline with trailing spaces:\n \nbar\ninteger like line:\n123456789\nempty line:\n\nbaz"), + ], + ]; + + $this->assertSame(file_get_contents(__DIR__.'/Fixtures/multiple_lines_as_literal_block_for_tagged_values.yml'), $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); + } + public function testDumpMultiLineStringAsScalarBlock() { - $data = array( - 'data' => array( + $data = [ + 'data' => [ 'single_line' => 'foo bar baz', 'multi_line' => "foo\nline with trailing spaces:\n \nbar\ninteger like line:\n123456789\nempty line:\n\nbaz", 'multi_line_with_carriage_return' => "foo\nbar\r\nbaz", - 'nested_inlined_multi_line_string' => array( + 'nested_inlined_multi_line_string' => [ 'inlined_multi_line' => "foo\nbar\r\nempty line:\n\nbaz", - ), - ), - ); + ], + ], + ]; $this->assertSame(file_get_contents(__DIR__.'/Fixtures/multiple_lines_as_literal_block.yml'), $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); } public function testDumpMultiLineStringAsScalarBlockWhenFirstLineHasLeadingSpace() { - $data = array( - 'data' => array( + $data = [ + 'data' => [ 'multi_line' => " the first line has leading spaces\nThe second line does not.", - ), - ); + ], + ]; $this->assertSame(file_get_contents(__DIR__.'/Fixtures/multiple_lines_as_literal_block_leading_space_in_first_line.yml'), $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); } - public function testCarriageReturnIsMaintainedWhenDumpingAsMultiLineLiteralBlock() + public function testCarriageReturnFollowedByNewlineIsMaintainedWhenDumpingAsMultiLineLiteralBlock() { - $this->assertSame("- \"a\\r\\nb\\nc\"\n", $this->dumper->dump(array("a\r\nb\nc"), 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); + $this->assertSame("- \"a\\r\\nb\\nc\"\n", $this->dumper->dump(["a\r\nb\nc"], 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); + } + + public function testCarriageReturnNotFollowedByNewlineIsPreservedWhenDumpingAsMultiLineLiteralBlock() + { + $expected = <<<'YAML' +parent: + foo: "bar\n\rbaz: qux" + +YAML; + + $this->assertSame($expected, $this->dumper->dump([ + 'parent' => [ + 'foo' => "bar\n\rbaz: qux", + ], + ], 4, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The indentation must be greater than zero - */ public function testZeroIndentationThrowsException() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The indentation must be greater than zero'); new Dumper(0); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The indentation must be greater than zero - */ public function testNegativeIndentationThrowsException() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The indentation must be greater than zero'); new Dumper(-4); } } diff --git a/vendor/symfony/yaml/Tests/Fixtures/YtsAnchorAlias.yml b/vendor/symfony/yaml/Tests/Fixtures/YtsAnchorAlias.yml index 5f9c942..81b4129 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/YtsAnchorAlias.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/YtsAnchorAlias.yml @@ -14,7 +14,7 @@ yaml: | - Oren - *showell php: | - array('Steve', 'Clark', 'Brian', 'Oren', 'Steve') + ['Steve', 'Clark', 'Brian', 'Oren', 'Steve'] --- test: Alias of a Mapping @@ -28,4 +28,4 @@ yaml: | - banana - *hello php: | - array(array('Meat'=>'pork', 'Starch'=>'potato'), 'banana', array('Meat'=>'pork', 'Starch'=>'potato')) + [['Meat'=>'pork', 'Starch'=>'potato'], 'banana', ['Meat'=>'pork', 'Starch'=>'potato']] diff --git a/vendor/symfony/yaml/Tests/Fixtures/YtsBasicTests.yml b/vendor/symfony/yaml/Tests/Fixtures/YtsBasicTests.yml index dfd9302..1a08d8e 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/YtsBasicTests.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/YtsBasicTests.yml @@ -9,7 +9,7 @@ yaml: | - banana - carrot php: | - array('apple', 'banana', 'carrot') + ['apple', 'banana', 'carrot'] --- test: Sequence With Item Being Null In The Middle brief: | @@ -21,7 +21,7 @@ yaml: | - - carrot php: | - array('apple', null, 'carrot') + ['apple', null, 'carrot'] --- test: Sequence With Last Item Being Null brief: | @@ -33,7 +33,7 @@ yaml: | - banana - php: | - array('apple', 'banana', null) + ['apple', 'banana', null] --- test: Nested Sequences brief: | @@ -46,7 +46,7 @@ yaml: | - bar - baz php: | - array(array('foo', 'bar', 'baz')) + [['foo', 'bar', 'baz']] --- test: Mixed Sequences brief: | @@ -61,7 +61,7 @@ yaml: | - banana - carrot php: | - array('apple', array('foo', 'bar', 'x123'), 'banana', 'carrot') + ['apple', ['foo', 'bar', 'x123'], 'banana', 'carrot'] --- test: Deeply Nested Sequences brief: | @@ -74,7 +74,7 @@ yaml: | - uno - dos php: | - array(array(array('uno', 'dos'))) + [[['uno', 'dos']]] --- test: Simple Mapping brief: | @@ -87,7 +87,7 @@ yaml: | foo: whatever bar: stuff php: | - array('foo' => 'whatever', 'bar' => 'stuff') + ['foo' => 'whatever', 'bar' => 'stuff'] --- test: Sequence in a Mapping brief: | @@ -98,7 +98,7 @@ yaml: | - uno - dos php: | - array('foo' => 'whatever', 'bar' => array('uno', 'dos')) + ['foo' => 'whatever', 'bar' => ['uno', 'dos']] --- test: Nested Mappings brief: | @@ -110,14 +110,14 @@ yaml: | name: steve sport: baseball php: | - array( + [ 'foo' => 'whatever', - 'bar' => array( + 'bar' => [ 'fruit' => 'apple', 'name' => 'steve', 'sport' => 'baseball' - ) - ) + ] + ] --- test: Mixed Mapping brief: | @@ -136,22 +136,22 @@ yaml: | perl: papers ruby: scissorses php: | - array( + [ 'foo' => 'whatever', - 'bar' => array( - array( + 'bar' => [ + [ 'fruit' => 'apple', 'name' => 'steve', 'sport' => 'baseball' - ), + ], 'more', - array( + [ 'python' => 'rocks', 'perl' => 'papers', 'ruby' => 'scissorses' - ) - ) - ) + ] + ] + ] --- test: Mapping-in-Sequence Shortcut todo: true @@ -163,7 +163,7 @@ yaml: | - work on YAML.py: - work on Store php: | - array(array('work on YAML.py' => array('work on Store'))) + [['work on YAML.py' => ['work on Store']]] --- test: Sequence-in-Mapping Shortcut todo: true @@ -177,7 +177,7 @@ yaml: | - '%.sourceforge.net' - '%.freepan.org' php: | - array('allow' => array('localhost', '%.sourceforge.net', '%.freepan.org')) + ['allow' => ['localhost', '%.sourceforge.net', '%.freepan.org']] --- todo: true test: Merge key @@ -192,11 +192,11 @@ yaml: | <<: age: 38 php: | - array( + [ 'mapping' => - array( + [ 'name' => 'Joe', 'job' => 'Accountant', 'age' => 38 - ) - ) + ] + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/YtsBlockMapping.yml b/vendor/symfony/yaml/Tests/Fixtures/YtsBlockMapping.yml index f7ca469..1f3a2e5 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/YtsBlockMapping.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/YtsBlockMapping.yml @@ -5,7 +5,7 @@ brief: | yaml: | foo: bar php: | - array('foo' => 'bar') + ['foo' => 'bar'] --- test: Multi Element Mapping brief: | @@ -15,11 +15,11 @@ yaml: | white: walls blue: berries php: | - array( + [ 'red' => 'baron', 'white' => 'walls', 'blue' => 'berries', - ) + ] --- test: Values aligned brief: | @@ -30,11 +30,11 @@ yaml: | white: walls blue: berries php: | - array( + [ 'red' => 'baron', 'white' => 'walls', 'blue' => 'berries', - ) + ] --- test: Colons aligned brief: | @@ -44,8 +44,8 @@ yaml: | white : walls blue : berries php: | - array( + [ 'red' => 'baron', 'white' => 'walls', 'blue' => 'berries', - ) + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/YtsDocumentSeparator.yml b/vendor/symfony/yaml/Tests/Fixtures/YtsDocumentSeparator.yml index d988102..67cb47a 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/YtsDocumentSeparator.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/YtsDocumentSeparator.yml @@ -49,7 +49,7 @@ yaml: | foo: 1 bar: 2 php: | - array('foo' => 1, 'bar' => 2) + ['foo' => 1, 'bar' => 2] documents: 1 --- @@ -63,7 +63,7 @@ yaml: | foo: | --- php: | - array('foo' => "---\n") + ['foo' => "---\n"] --- test: Multiple Document Separators in Block @@ -79,7 +79,7 @@ yaml: | bar: | fooness php: | - array( + [ 'foo' => "---\nfoo: bar\n---\nyo: baz\n", 'bar' => "fooness\n" - ) + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/YtsErrorTests.yml b/vendor/symfony/yaml/Tests/Fixtures/YtsErrorTests.yml index e8506fc..e8697f9 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/YtsErrorTests.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/YtsErrorTests.yml @@ -22,4 +22,4 @@ yaml: | firstline: 1 secondline: 2 php: | - array('foo' => null, 'firstline' => 1, 'secondline' => 2) + ['foo' => null, 'firstline' => 1, 'secondline' => 2] diff --git a/vendor/symfony/yaml/Tests/Fixtures/YtsFlowCollections.yml b/vendor/symfony/yaml/Tests/Fixtures/YtsFlowCollections.yml index 03090e4..cc562cd 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/YtsFlowCollections.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/YtsFlowCollections.yml @@ -8,7 +8,7 @@ brief: > yaml: | seq: [ a, b, c ] php: | - array('seq' => array('a', 'b', 'c')) + ['seq' => ['a', 'b', 'c']] --- test: Simple Inline Hash brief: > @@ -21,7 +21,7 @@ brief: > yaml: | hash: { name: Steve, foo: bar } php: | - array('hash' => array('name' => 'Steve', 'foo' => 'bar')) + ['hash' => ['name' => 'Steve', 'foo' => 'bar']] --- test: Multi-line Inline Collections todo: true @@ -38,15 +38,15 @@ yaml: | Python: python.org, Perl: use.perl.org } php: | - array( - 'languages' => array('Ruby', 'Perl', 'Python'), - 'websites' => array( + [ + 'languages' => ['Ruby', 'Perl', 'Python'], + 'websites' => [ 'YAML' => 'yaml.org', 'Ruby' => 'ruby-lang.org', 'Python' => 'python.org', 'Perl' => 'use.perl.org' - ) - ) + ] + ] --- test: Commas in Values (not in the spec!) todo: true @@ -57,4 +57,4 @@ brief: > yaml: | attendances: [ 45,123, 70,000, 17,222 ] php: | - array('attendances' => array(45123, 70000, 17222)) + ['attendances' => [45123, 70000, 17222]] diff --git a/vendor/symfony/yaml/Tests/Fixtures/YtsFoldedScalars.yml b/vendor/symfony/yaml/Tests/Fixtures/YtsFoldedScalars.yml index a14735a..2895202 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/YtsFoldedScalars.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/YtsFoldedScalars.yml @@ -12,7 +12,7 @@ yaml: | Foo Bar php: | - array('this' => "Foo\nBar\n") + ['this' => "Foo\nBar\n"] --- test: The '+' indicator brief: > @@ -28,11 +28,11 @@ yaml: | dummy: value php: | - array( + [ 'normal' => "extra new lines not kept\n", 'preserving' => "extra new lines are kept\n\n\n", 'dummy' => 'value' - ) + ] --- test: Three trailing newlines in literals brief: > @@ -64,14 +64,14 @@ yaml: | same as "kept" above: "This has four newlines.\n\n\n\n" php: | - array( + [ 'clipped' => "This has one newline.\n", 'same as "clipped" above' => "This has one newline.\n", 'stripped' => 'This has no newline.', 'same as "stripped" above' => 'This has no newline.', 'kept' => "This has four newlines.\n\n\n\n", 'same as "kept" above' => "This has four newlines.\n\n\n\n" - ) + ] --- test: Extra trailing newlines with spaces todo: true @@ -95,8 +95,8 @@ yaml: | php: | - array('this' => "Foo\n\n \n", - 'kept' => "Foo\n\n \n" ) + ['this' => "Foo\n\n \n", + 'kept' => "Foo\n\n \n"] --- test: Folded Block in a Sequence @@ -115,12 +115,12 @@ yaml: | hmm - dog php: | - array( + [ 'apple', 'banana', "can't you see the beauty of yaml? hmm\n", 'dog' - ) + ] --- test: Folded Block as a Mapping Value brief: > @@ -135,10 +135,10 @@ yaml: | by a knee injury. source: espn php: | - array( + [ 'quote' => "Mark McGwire's year was crippled by a knee injury.\n", 'source' => 'espn' - ) + ] --- test: Three trailing newlines in folded blocks brief: > @@ -166,11 +166,11 @@ yaml: | same as "kept" above: "This has four newlines.\n\n\n\n" php: | - array( + [ 'clipped' => "This has one newline.\n", 'same as "clipped" above' => "This has one newline.\n", 'stripped' => 'This has no newline.', 'same as "stripped" above' => 'This has no newline.', 'kept' => "This has four newlines.\n\n\n\n", 'same as "kept" above' => "This has four newlines.\n\n\n\n" - ) + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/YtsNullsAndEmpties.yml b/vendor/symfony/yaml/Tests/Fixtures/YtsNullsAndEmpties.yml index 9a5300f..ea8e36e 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/YtsNullsAndEmpties.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/YtsNullsAndEmpties.yml @@ -6,7 +6,7 @@ brief: > yaml: | empty: [] php: | - array('empty' => array()) + ['empty' => []] --- test: Empty Mapping brief: > @@ -15,19 +15,19 @@ brief: > yaml: | empty: {} php: | - array('empty' => array()) + ['empty' => []] --- test: Empty Sequence as Entire Document yaml: | [] php: | - array() + [] --- test: Empty Mapping as Entire Document yaml: | {} php: | - array() + [] --- test: Null as Document yaml: | diff --git a/vendor/symfony/yaml/Tests/Fixtures/YtsSpecificationExamples.yml b/vendor/symfony/yaml/Tests/Fixtures/YtsSpecificationExamples.yml index 3f93c98..dd2d776 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/YtsSpecificationExamples.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/YtsSpecificationExamples.yml @@ -6,7 +6,7 @@ yaml: | - Sammy Sosa - Ken Griffey php: | - array('Mark McGwire', 'Sammy Sosa', 'Ken Griffey') + ['Mark McGwire', 'Sammy Sosa', 'Ken Griffey'] --- test: Mapping of scalars to scalars spec: 2.2 @@ -15,7 +15,7 @@ yaml: | avg: 0.278 rbi: 147 php: | - array('hr' => 65, 'avg' => 0.278, 'rbi' => 147) + ['hr' => 65, 'avg' => 0.278, 'rbi' => 147] --- test: Mapping of scalars to sequences spec: 2.3 @@ -29,13 +29,13 @@ yaml: | - Chicago Cubs - Atlanta Braves php: | - array('american' => - array( 'Boston Red Sox', 'Detroit Tigers', - 'New York Yankees' ), + ['american' => + ['Boston Red Sox', 'Detroit Tigers', + 'New York Yankees'], 'national' => - array( 'New York Mets', 'Chicago Cubs', - 'Atlanta Braves' ) - ) + ['New York Mets', 'Chicago Cubs', + 'Atlanta Braves'] + ] --- test: Sequence of mappings spec: 2.4 @@ -49,10 +49,10 @@ yaml: | hr: 63 avg: 0.288 php: | - array( - array('name' => 'Mark McGwire', 'hr' => 65, 'avg' => 0.278), - array('name' => 'Sammy Sosa', 'hr' => 63, 'avg' => 0.288) - ) + [ + ['name' => 'Mark McGwire', 'hr' => 65, 'avg' => 0.278], + ['name' => 'Sammy Sosa', 'hr' => 63, 'avg' => 0.288] + ] --- test: Legacy A5 todo: true @@ -72,7 +72,7 @@ yaml: | - 2001-07-23 perl-busted: > YAML.pm will be able to emulate this behavior soon. In this regard - it may be somewhat more correct than Python's native behaviour which + it may be somewhat more correct than Python's native behavior which can only use tuples as mapping keys. PyYAML will also need to figure out some clever way to roundtrip structured keys. python: | @@ -134,11 +134,11 @@ yaml: | - [ Mark McGwire , 65 , 0.278 ] - [ Sammy Sosa , 63 , 0.288 ] php: | - array( - array( 'name', 'hr', 'avg' ), - array( 'Mark McGwire', 65, 0.278 ), - array( 'Sammy Sosa', 63, 0.288 ) - ) + [ + [ 'name', 'hr', 'avg' ], + [ 'Mark McGwire', 65, 0.278 ], + [ 'Sammy Sosa', 63, 0.288 ] + ] --- test: Mapping of mappings todo: true @@ -150,12 +150,12 @@ yaml: | avg: 0.288 } php: | - array( + [ 'Mark McGwire' => - array( 'hr' => 65, 'avg' => 0.278 ), + [ 'hr' => 65, 'avg' => 0.278 ], 'Sammy Sosa' => - array( 'hr' => 63, 'avg' => 0.288 ) - ) + [ 'hr' => 63, 'avg' => 0.288 ] + ] --- test: Two documents in a stream each with a leading comment todo: true @@ -208,10 +208,10 @@ yaml: | - Sammy Sosa - Ken Griffey php: | - array( - 'hr' => array( 'Mark McGwire', 'Sammy Sosa' ), - 'rbi' => array( 'Sammy Sosa', 'Ken Griffey' ) - ) + [ + 'hr' => [ 'Mark McGwire', 'Sammy Sosa' ], + 'rbi' => [ 'Sammy Sosa', 'Ken Griffey' ] + ] --- test: Node for Sammy Sosa appears twice in this document spec: 2.10 @@ -225,12 +225,12 @@ yaml: | - *SS # Subsequent occurrence - Ken Griffey php: | - array( + [ 'hr' => - array('Mark McGwire', 'Sammy Sosa'), + ['Mark McGwire', 'Sammy Sosa'], 'rbi' => - array('Sammy Sosa', 'Ken Griffey') - ) + ['Sammy Sosa', 'Ken Griffey'] + ] --- test: Mapping between sequences todo: true @@ -297,20 +297,20 @@ yaml: | - item : Big Shoes quantity: 1 php: | - array ( - array ( + [ + [ 'item' => 'Super Hoop', 'quantity' => 1, - ), - array ( + ], + [ 'item' => 'Basketball', 'quantity' => 4, - ), - array ( + ], + [ 'item' => 'Big Shoes', 'quantity' => 1, - ) - ) + ] + ] perl: | [ { item => 'Super Hoop', quantity => 1 }, @@ -462,11 +462,11 @@ yaml: | 65 Home Runs 0.278 Batting Average php: | - array( + [ 'name' => 'Mark McGwire', 'accomplishment' => "Mark set a major league home run record in 1998.\n", 'stats' => "65 Home Runs\n0.278 Batting Average\n" - ) + ] --- test: Quoted scalars todo: true @@ -512,11 +512,11 @@ yaml: | octal: 014 hexadecimal: 0xC php: | - array( + [ 'canonical' => 12345, 'octal' => 014, 'hexadecimal' => 0xC - ) + ] --- test: Decimal Integer deprecated: true @@ -524,9 +524,9 @@ spec: 2.19 yaml: | decimal: +12,345 php: | - array( + [ 'decimal' => 12345.0, - ) + ] --- # FIX: spec shows parens around -inf and NaN test: Floating point @@ -538,13 +538,13 @@ yaml: | not a number: .NaN float as whole number: !!float 1 php: | - array( + [ 'canonical' => 1230.15, 'exponential' => 1230.15, 'negative infinity' => log(0), 'not a number' => -log(0), 'float as whole number' => (float) 1 - ) + ] --- test: Fixed Floating point deprecated: true @@ -552,9 +552,9 @@ spec: 2.20 yaml: | fixed: 1,230.15 php: | - array( + [ 'fixed' => 1230.15, - ) + ] --- test: Timestamps todo: true @@ -565,12 +565,12 @@ yaml: | spaced: 2001-12-14 21:59:43.10 -05:00 date: 2002-12-14 # Time is noon UTC php: | - array( + [ 'canonical' => YAML::mktime( 2001, 12, 15, 2, 59, 43, 0.10 ), 'iso8601' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ), 'spaced' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ), 'date' => Date.new( 2002, 12, 14 ) - ) + ] --- test: legacy Timestamps test todo: true @@ -581,12 +581,12 @@ yaml: | spaced: 2001-12-14 21:59:43.00 -05:00 date: 2002-12-14 php: | - array( + [ 'canonical' => Time::utc( 2001, 12, 15, 2, 59, 43, 0 ), 'iso8601' => YAML::mktime( 2001, 2, 28, 21, 59, 43, 0, "-05:00" ), 'spaced' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0, "-05:00" ), 'date' => Date.new( 2002, 12, 14 ) - ) + ] --- test: Various explicit families todo: true @@ -754,20 +754,20 @@ yaml: | Backup contact is Nancy Billsmer @ 338-4338. php: | - array( + [ 'invoice' => 34843, 'date' => gmmktime(0, 0, 0, 1, 23, 2001), 'bill-to' => - array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) ) + [ 'given' => 'Chris', 'family' => 'Dumars', 'address' => [ 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ] ] , 'ship-to' => - array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) ) + [ 'given' => 'Chris', 'family' => 'Dumars', 'address' => [ 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ] ] , 'product' => - array( - array( 'sku' => 'BL394D', 'quantity' => 4, 'description' => 'Basketball', 'price' => 450.00 ), - array( 'sku' => 'BL4438H', 'quantity' => 1, 'description' => 'Super Hoop', 'price' => 2392.00 ) - ), + [ + [ 'sku' => 'BL394D', 'quantity' => 4, 'description' => 'Basketball', 'price' => 450.00 ], + [ 'sku' => 'BL4438H', 'quantity' => 1, 'description' => 'Super Hoop', 'price' => 2392.00 ] + ], 'tax' => 251.42, 'total' => 4443.52, 'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n" - ) + ] --- test: Log file todo: true @@ -826,9 +826,9 @@ yaml: | # These are three throwaway comment # lines (the first line is empty). php: | - array( + [ 'this' => "contains three lines of text.\nThe third one starts with a\n# character. This isn't a comment.\n" - ) + ] --- test: Document with a single value todo: true @@ -878,11 +878,11 @@ yaml: | date : 2001-01-23 total : 4443.52 php: | - array( + [ 'invoice' => 34843, 'date' => gmmktime(0, 0, 0, 1, 23, 2001), 'total' => 4443.52 - ) + ] --- test: Single-line documents todo: true @@ -934,7 +934,7 @@ yaml: | also int: ! "12" string: !!str 12 php: | - array( 'integer' => 12, 'also int' => 12, 'string' => '12' ) + [ 'integer' => 12, 'also int' => 12, 'string' => '12' ] --- test: Private types todo: true @@ -966,7 +966,7 @@ yaml: | # The URI is 'tag:yaml.org,2002:str' - !!str a Unicode string php: | - array( 'a Unicode string' ) + [ 'a Unicode string' ] --- test: Type family under perl.yaml.org todo: true @@ -1039,9 +1039,9 @@ yaml: | repeated use of this value. alias : *A001 php: | - array( 'anchor' => 'This scalar has an anchor.', + [ 'anchor' => 'This scalar has an anchor.', 'override' => "The alias node below is a repeated use of this value.\n", - 'alias' => "The alias node below is a repeated use of this value.\n" ) + 'alias' => "The alias node below is a repeated use of this value.\n"] --- test: Flow and block formatting todo: true @@ -1152,12 +1152,12 @@ yaml: | redundant: |2 This value is indented 2 spaces. php: | - array( + [ 'leading spaces' => " This value starts with four spaces.\n", 'leading line break' => "\nThis value starts with a line break.\n", 'leading comment indicator' => "# first line starts with a\n# character.\n", 'redundant' => "This value is indented 2 spaces.\n" - ) + ] --- test: Chomping and keep modifiers yaml: | @@ -1176,14 +1176,14 @@ yaml: | same as "kept" above: "This has two newlines.\n\n" php: | - array( + [ 'clipped' => "This has one newline.\n", 'same as "clipped" above' => "This has one newline.\n", 'stripped' => 'This has no newline.', 'same as "stripped" above' => 'This has no newline.', 'kept' => "This has two newlines.\n\n", 'same as "kept" above' => "This has two newlines.\n\n" - ) + ] --- test: Literal combinations todo: true @@ -1221,7 +1221,7 @@ yaml: | both are equal to: " This has no newline." php: | - array( + [ 'empty' => '', 'literal' => "The \\ ' \" characters may be\nfreely used. Leading white\n space " + "is significant.\n\nLine breaks are significant.\nThus this value contains one\n" + @@ -1232,7 +1232,7 @@ php: | 'indented and chomped' => ' This has no newline.', 'also written as' => ' This has no newline.', 'both are equal to' => ' This has no newline.' - ) + [ --- test: Folded combinations todo: true @@ -1288,7 +1288,7 @@ yaml: | # Explicit comments may follow # but must be less indented. php: | - array( + [ 'empty' => '', 'one paragraph' => 'Line feeds are converted to spaces, so this value'. " contains no line breaks except for the final one.\n", @@ -1300,7 +1300,7 @@ php: | 'above is equal to' => "This is a folded paragraph followed by a list:\n". " * first entry\n * second entry\nFollowed by another folded paragraph, ". "another list:\n\n * first entry\n\n * second entry\n\nAnd a final folded paragraph.\n" - ) + ] --- test: Single quotes todo: true @@ -1315,13 +1315,13 @@ yaml: | line break' is same as: "this contains six spaces\nand one line break" php: | - array( + [ 'empty' => '', 'second' => '! : \\ etc. can be used freely.', 'third' => "a single quote ' must be escaped.", 'span' => "this contains six spaces\nand one line break", 'is same as' => "this contains six spaces\nand one line break" - ) + ] --- test: Double quotes todo: true @@ -1335,14 +1335,14 @@ yaml: | spaces" is equal to: "this contains four spaces" php: | - array( + [ 'empty' => '', 'second' => '! : etc. can be used freely.', 'third' => 'a " or a \\ must be escaped.', 'fourth' => "this value ends with an LF.\n", 'span' => "this contains four spaces", 'is equal to' => "this contains four spaces" - ) + ] --- test: Unquoted strings todo: true @@ -1371,7 +1371,7 @@ yaml: | note: { one-line keys: but multi-line values } php: | - array( + [ 'first' => 'There is no unquoted empty string.', 'second' => 12, 'third' => '12', @@ -1379,7 +1379,7 @@ php: | 'indicators' => "this has no comments. #:foo and bar# are both text.", 'flow' => [ 'can span lines', 'like this' ], 'note' => { 'one-line keys' => 'but multi-line values' } - ) + ] --- test: Spanning sequences todo: true @@ -1393,11 +1393,11 @@ yaml: | - one - two php: | - array( + [ 'flow' => [ 'one', 'two' ], 'spanning' => [ 'one', 'two' ], 'block' => [ 'one', 'two' ] - ) + ] --- test: Flow mappings yaml: | @@ -1408,10 +1408,10 @@ yaml: | one: 1 two: 2 php: | - array( - 'flow' => array( 'one' => 1, 'two' => 2 ), - 'block' => array( 'one' => 1, 'two' => 2 ) - ) + [ + 'flow' => [ 'one' => 1, 'two' => 2 ], + 'block' => [ 'one' => 1, 'two' => 2 ] + ] --- test: Representations of 12 todo: true @@ -1433,7 +1433,7 @@ yaml: | - foo/bar - /a.*b/ php: | - array( 12, '12', '12', '12', '12', '/foo/bar', 'd:/foo/bar', 'foo/bar', '/a.*b/' ) + [ 12, '12', '12', '12', '12', '/foo/bar', 'd:/foo/bar', 'foo/bar', '/a.*b/' ] --- test: "Null" todo: true @@ -1455,12 +1455,12 @@ yaml: | only two with values. php: | - array ( + [ 'canonical' => null, 'english' => null, - 'sparse' => array( null, '2nd entry', null, '4th entry', null ]), + 'sparse' => [ null, '2nd entry', null, '4th entry', null ]], 'four' => 'This mapping has five keys, only two with values.' - ) + ] --- test: Omap todo: true @@ -1525,29 +1525,29 @@ yaml: | octal: 014 hexadecimal: 0xC php: | - array( + [ 'canonical' => 12345, 'octal' => 12, 'hexadecimal' => 12 - ) + ] --- test: Decimal deprecated: true yaml: | decimal: +12,345 php: | - array( + [ 'decimal' => 12345.0, - ) + ] --- test: Fixed Float deprecated: true yaml: | fixed: 1,230.15 php: | - array( + [ 'fixed' => 1230.15, - ) + ] --- test: Float yaml: | @@ -1556,12 +1556,12 @@ yaml: | negative infinity: -.inf not a number: .NaN php: | - array( + [ 'canonical' => 1230.15, 'exponential' => 1230.15, 'negative infinity' => log(0), 'not a number' => -log(0) - ) + ] --- test: Timestamp todo: true @@ -1571,12 +1571,12 @@ yaml: | space separated: 2001-12-14 21:59:43.10 -05:00 date (noon UTC): 2002-12-14 ruby: | - array( + [ 'canonical' => YAML::mktime( 2001, 12, 15, 2, 59, 43, 0.10 ), 'valid iso8601' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ), 'space separated' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ), 'date (noon UTC)' => Date.new( 2002, 12, 14 ) - ) + ] --- test: Binary todo: true diff --git a/vendor/symfony/yaml/Tests/Fixtures/YtsTypeTransfers.yml b/vendor/symfony/yaml/Tests/Fixtures/YtsTypeTransfers.yml index dea0be0..e96b553 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/YtsTypeTransfers.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/YtsTypeTransfers.yml @@ -25,14 +25,14 @@ yaml: | - No, I mean, "And what about Yaml?" - Oh, oh yeah. Uh.. Yaml for Ruby. php: | - array( + [ "What's Yaml?", "It's for writing data structures in plain text.", "And?", "And what? That's not good enough for you?", "No, I mean, \"And what about Yaml?\"", "Oh, oh yeah. Uh.. Yaml for Ruby." - ) + ] --- test: Indicators in Strings brief: > @@ -43,11 +43,11 @@ yaml: | same for the pound sign: here we have it#in a string the comma can, honestly, be used in most cases: [ but not in, inline collections ] php: | - array( + [ 'the colon followed by space is an indicator' => 'but is a string:right here', 'same for the pound sign' => 'here we have it#in a string', - 'the comma can, honestly, be used in most cases' => array('but not in', 'inline collections') - ) + 'the comma can, honestly, be used in most cases' => ['but not in', 'inline collections'] + ] --- test: Forcing Strings brief: > @@ -57,10 +57,10 @@ yaml: | date string: !!str 2001-08-01 number string: !!str 192 php: | - array( + [ 'date string' => '2001-08-01', 'number string' => '192' - ) + ] --- test: Single-quoted Strings brief: > @@ -75,12 +75,12 @@ yaml: | why do i hate them?: 'it''s very hard to explain' entities: '£ me' php: | - array( + [ 'all my favorite symbols' => '#:!/%.)', 'a few i hate' => '&(*', 'why do i hate them?' => 'it\'s very hard to explain', 'entities' => '£ me' - ) + ] --- test: Double-quoted Strings brief: > @@ -90,9 +90,9 @@ brief: > yaml: | i know where i want my line breaks: "one here\nand another here\n" php: | - array( + [ 'i know where i want my line breaks' => "one here\nand another here\n" - ) + ] --- test: Multi-line Quoted Strings todo: true @@ -106,10 +106,10 @@ yaml: | let it go on and on to other lines until i end it with a quote." php: | - array('i want a long string' => "so i'm going to ". + ['i want a long string' => "so i'm going to ". "let it go on and on to other lines ". "until i end it with a quote." - ) + ] --- test: Plain scalars @@ -128,7 +128,7 @@ yaml: | - This would impair my skiing ability somewhat for the duration, as can be imagined. php: | - array( + [ "My little toe is broken in two places;", "I'm crazy to have skied this way;", "I'm not the craziest he's seen, since there was always ". @@ -139,7 +139,7 @@ php: | "He's going to put my foot in plaster for a month;", "This would impair my skiing ability somewhat for the duration, ". "as can be imagined." - ) + ] --- test: 'Null' brief: > @@ -149,11 +149,11 @@ yaml: | hosted by: Bob and David date of next season: ~ php: | - array( + [ 'name' => 'Mr. Show', 'hosted by' => 'Bob and David', 'date of next season' => null - ) + ] --- test: Boolean brief: > @@ -162,10 +162,10 @@ yaml: | Is Gus a Liar?: true Do I rely on Gus for Sustenance?: false php: | - array( + [ 'Is Gus a Liar?' => true, 'Do I rely on Gus for Sustenance?' => false - ) + ] --- test: Integers dump_skip: true @@ -177,10 +177,10 @@ yaml: | zero: 0 simple: 12 php: | - array( + [ 'zero' => 0, 'simple' => 12, - ) + ] --- test: Positive Big Integer deprecated: true @@ -192,9 +192,9 @@ brief: > yaml: | one-thousand: 1,000 php: | - array( + [ 'one-thousand' => 1000.0, - ) + ] --- test: Negative Big Integer deprecated: true @@ -206,9 +206,9 @@ brief: > yaml: | negative one-thousand: -1,000 php: | - array( + [ 'negative one-thousand' => -1000.0 - ) + ] --- test: Floats dump_skip: true @@ -220,10 +220,10 @@ yaml: | a simple float: 2.00 scientific notation: 1.00009e+3 php: | - array( + [ 'a simple float' => 2.0, 'scientific notation' => 1000.09 - ) + ] --- test: Larger Float dump_skip: true @@ -235,9 +235,9 @@ brief: > yaml: | larger float: 1,000.09 php: | - array( + [ 'larger float' => 1000.09, - ) + ] --- test: Time todo: true @@ -250,10 +250,10 @@ yaml: | iso8601: 2001-12-14t21:59:43.10-05:00 space separated: 2001-12-14 21:59:43.10 -05:00 php: | - array( + [ 'iso8601' => mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ), 'space separated' => mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ) - ) + ] --- test: Date todo: true diff --git a/vendor/symfony/yaml/Tests/Fixtures/booleanMappingKeys.yml b/vendor/symfony/yaml/Tests/Fixtures/booleanMappingKeys.yml index 26799e8..88287f1 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/booleanMappingKeys.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/booleanMappingKeys.yml @@ -5,7 +5,7 @@ yaml: | true: true false: false php: | - array( + [ 'true' => true, 'false' => false, - ) + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/escapedCharacters.yml b/vendor/symfony/yaml/Tests/Fixtures/escapedCharacters.yml index cc0356d..87d352d 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/escapedCharacters.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/escapedCharacters.yml @@ -142,14 +142,14 @@ test: Double quotes with a line feed yaml: | { double: "some value\n \"some quoted string\" and 'some single quotes one'" } php: | - array( + [ 'double' => "some value\n \"some quoted string\" and 'some single quotes one'" - ) + ] --- test: Backslashes yaml: | { single: 'foo\Var', no-quotes: foo\Var, double: "foo\\Var" } php: | - array( + [ 'single' => 'foo\Var', 'no-quotes' => 'foo\Var', 'double' => 'foo\Var' - ) + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/legacyBooleanMappingKeys.yml b/vendor/symfony/yaml/Tests/Fixtures/legacyBooleanMappingKeys.yml index 5e8d091..db95016 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/legacyBooleanMappingKeys.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/legacyBooleanMappingKeys.yml @@ -5,10 +5,10 @@ yaml: | true: true false: false php: | - array( + [ 1 => true, 0 => false, - ) + ] --- test: Boolean yaml: | @@ -16,8 +16,8 @@ yaml: | logical: true answer: false php: | - array( + [ false => 'used as key', 'logical' => true, 'answer' => false - ) + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/legacyNullMappingKey.yml b/vendor/symfony/yaml/Tests/Fixtures/legacyNullMappingKey.yml index 551a620..14f93c2 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/legacyNullMappingKey.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/legacyNullMappingKey.yml @@ -4,6 +4,6 @@ spec: 2.21 yaml: | null: ~ php: | - array( + [ '' => null, - ) + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/multiple_lines_as_literal_block_for_tagged_values.yml b/vendor/symfony/yaml/Tests/Fixtures/multiple_lines_as_literal_block_for_tagged_values.yml new file mode 100644 index 0000000..f8c9112 --- /dev/null +++ b/vendor/symfony/yaml/Tests/Fixtures/multiple_lines_as_literal_block_for_tagged_values.yml @@ -0,0 +1,2 @@ +data: + foo: !bar "foo\r\nline with trailing spaces:\n \nbar\ninteger like line:\n123456789\nempty line:\n\nbaz" diff --git a/vendor/symfony/yaml/Tests/Fixtures/nullMappingKey.yml b/vendor/symfony/yaml/Tests/Fixtures/nullMappingKey.yml index 7dcadc7..cd90f7b 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/nullMappingKey.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/nullMappingKey.yml @@ -4,6 +4,6 @@ spec: 2.21 yaml: | null: ~ php: | - array( + [ 'null' => null, - ) + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/numericMappingKeys.yml b/vendor/symfony/yaml/Tests/Fixtures/numericMappingKeys.yml index 9cfb771..246447e 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/numericMappingKeys.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/numericMappingKeys.yml @@ -6,7 +6,7 @@ yaml: | 1: foo 0: bar php: | - array(1 => 'foo', 0 => 'bar') + [1 => 'foo', 0 => 'bar'] --- test: Integers as Map Keys brief: > @@ -16,8 +16,8 @@ yaml: | 2: two 3: three php: | - array( + [ 1 => 'one', 2 => 'two', 3 => 'three' - ) + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/sfComments.yml b/vendor/symfony/yaml/Tests/Fixtures/sfComments.yml index b72a9b6..4b0c91c 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/sfComments.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/sfComments.yml @@ -11,7 +11,7 @@ yaml: | ex6: foo#foo # comment here ex7: foo # ignore me # and me php: | - array('ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo', 'ex5' => 'foo', 'ex6' => 'foo#foo', 'ex7' => 'foo') + ['ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo', 'ex5' => 'foo', 'ex6' => 'foo#foo', 'ex7' => 'foo'] --- test: Comments in the middle brief: > @@ -24,7 +24,7 @@ yaml: | # some comment # some comment php: | - array('foo' => array('bar' => 'foo')) + ['foo' => ['bar' => 'foo']] --- test: Comments on a hash line brief: > @@ -33,7 +33,7 @@ yaml: | foo: # a comment foo: bar # a comment php: | - array('foo' => array('foo' => 'bar')) + ['foo' => ['foo' => 'bar']] --- test: 'Value starting with a #' brief: > @@ -41,7 +41,7 @@ brief: > yaml: | foo: '#bar' php: | - array('foo' => '#bar') + ['foo' => '#bar'] --- test: Document starting with a comment and a separator brief: > @@ -51,7 +51,7 @@ yaml: | --- foo: bar # a comment php: | - array('foo' => 'bar') + ['foo' => 'bar'] --- test: Comment containing a colon on a hash line brief: > @@ -65,7 +65,7 @@ brief: > 'Hash key containing a #' yaml: 'foo#bar: baz' php: | - array('foo#bar' => 'baz') + ['foo#bar' => 'baz'] --- test: 'Hash key ending with a space and a #' brief: > @@ -73,4 +73,18 @@ brief: > yaml: | 'foo #': baz php: | - array('foo #' => 'baz') + ['foo #' => 'baz'] +--- +test: Comment before first item in unindented collection +brief: > + Comment directly before unindented collection is allowed +yaml: | + collection1: + # comment + - a + - b + collection2: + - a + - b +php: | + ['collection1' => ['a', 'b'], 'collection2' => ['a', 'b']] diff --git a/vendor/symfony/yaml/Tests/Fixtures/sfCompact.yml b/vendor/symfony/yaml/Tests/Fixtures/sfCompact.yml index 1339d23..8cadae2 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/sfCompact.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/sfCompact.yml @@ -13,22 +13,22 @@ yaml: | nick: Biggies quantity: 1 php: | - array ( - array ( + [ + [ 'item' => 'Super Hoop', - ), - array ( + ], + [ 'item' => 'Basketball', 'quantity' => 1, - ), - array ( - 'item' => array( + ], + [ + 'item' => [ 'name' => 'Big Shoes', 'nick' => 'Biggies' - ), + ], 'quantity' => 1 - ) - ) + ] + ] --- test: Compact notation combined with inline notation brief: | @@ -39,18 +39,18 @@ yaml: | - { item: Super Hoop, quantity: 1 } - [ Basketball, Big Shoes ] php: | - array ( - 'items' => array ( - array ( + [ + 'items' => [ + [ 'item' => 'Super Hoop', 'quantity' => 1, - ), - array ( + ], + [ 'Basketball', 'Big Shoes' - ) - ) - ) + ] + ] + ] --- %YAML:1.0 test: Compact notation brief: | @@ -66,22 +66,22 @@ yaml: | nick: Biggies quantity: 1 php: | - array ( - array ( + [ + [ 'item' => 'Super Hoop', - ), - array ( + ], + [ 'item' => 'Basketball', 'quantity' => 1, - ), - array ( - 'item' => array( + ], + [ + 'item' => [ 'name' => 'Big Shoes', 'nick' => 'Biggies' - ), + ], 'quantity' => 1 - ) - ) + ] + ] --- test: Compact notation combined with inline notation brief: | @@ -92,18 +92,18 @@ yaml: | - { item: Super Hoop, quantity: 1 } - [ Basketball, Big Shoes ] php: | - array ( - 'items' => array ( - array ( + [ + 'items' => [ + [ 'item' => 'Super Hoop', 'quantity' => 1, - ), - array ( + ], + [ 'Basketball', 'Big Shoes' - ) - ) - ) + ] + ] + ] --- %YAML:1.0 test: Compact notation brief: | @@ -119,22 +119,22 @@ yaml: | nick: Biggies quantity: 1 php: | - array ( - array ( + [ + [ 'item' => 'Super Hoop', - ), - array ( + ], + [ 'item' => 'Basketball', 'quantity' => 1, - ), - array ( - 'item' => array( + ], + [ + 'item' => [ 'name' => 'Big Shoes', 'nick' => 'Biggies' - ), + ], 'quantity' => 1 - ) - ) + ] + ] --- test: Compact notation combined with inline notation brief: | @@ -145,15 +145,15 @@ yaml: | - { item: Super Hoop, quantity: 1 } - [ Basketball, Big Shoes ] php: | - array ( - 'items' => array ( - array ( + [ + 'items' => [ + [ 'item' => 'Super Hoop', 'quantity' => 1, - ), - array ( + ], + [ 'Basketball', 'Big Shoes' - ) - ) - ) + ] + ] + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/sfMergeKey.yml b/vendor/symfony/yaml/Tests/Fixtures/sfMergeKey.yml index 83264cf..af787ae 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/sfMergeKey.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/sfMergeKey.yml @@ -46,16 +46,16 @@ yaml: | head_inline: &head_inline { <<: [ *foo , *dong , *foo2 ] } recursive_inline: { <<: *head_inline, c: { <<: *foo2 } } php: | - array( - 'foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull'), - 'bar' => array('a' => 'before', 'd' => 'other', 'e' => null, 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'), - 'bar_inline' => array('a' => 'before', 'd' => 'other', 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'e' => 'notnull', 'x' => 'Oren'), - 'foo2' => array('a' => 'Ballmer'), - 'ding' => array('fi', 'fei', 'fo', 'fam'), - 'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'), - 'head' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'), - 'taz' => array('a' => 'Steve', 'w' => array('p' => 1234)), - 'nested' => array('a' => 'Steve', 'w' => array('p' => 12345), 'd' => 'Doug', 'z' => array('p' => 12345)), - 'head_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'), - 'recursive_inline' => array('a' => 'Steve', 'b' => 'Clark', 'c' => array('a' => 'Ballmer'), 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'), - ) + [ + 'foo' => ['a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull'], + 'bar' => ['a' => 'before', 'd' => 'other', 'e' => null, 'b' => 'new', 'c' => ['foo' => 'bar', 'bar' => 'foo'], 'x' => 'Oren'], + 'bar_inline' => ['a' => 'before', 'd' => 'other', 'b' => 'new', 'c' => ['foo' => 'bar', 'bar' => 'foo'], 'e' => 'notnull', 'x' => 'Oren'], + 'foo2' => ['a' => 'Ballmer'], + 'ding' => ['fi', 'fei', 'fo', 'fam'], + 'check' => ['a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'], + 'head' => ['a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'], + 'taz' => ['a' => 'Steve', 'w' => ['p' => 1234]], + 'nested' => ['a' => 'Steve', 'w' => ['p' => 12345], 'd' => 'Doug', 'z' => ['p' => 12345]], + 'head_inline' => ['a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'], + 'recursive_inline' => ['a' => 'Steve', 'b' => 'Clark', 'c' => ['a' => 'Ballmer'], 'e' => 'notnull', 'fi', 'fei', 'fo', 'fam'], + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/sfObjects.yml b/vendor/symfony/yaml/Tests/Fixtures/sfObjects.yml index ee124b2..144615f 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/sfObjects.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/sfObjects.yml @@ -8,4 +8,4 @@ yaml: | ex3: 'foo # bar' # comment ex4: foo # comment php: | - array('ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo') + ['ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo'] diff --git a/vendor/symfony/yaml/Tests/Fixtures/sfQuotes.yml b/vendor/symfony/yaml/Tests/Fixtures/sfQuotes.yml index 7c60bae..c8326fd 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/sfQuotes.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/sfQuotes.yml @@ -5,7 +5,7 @@ brief: > yaml: | foo: '| bar' php: | - array('foo' => '| bar') + ['foo' => '| bar'] --- test: A key can be a quoted string brief: > @@ -19,15 +19,15 @@ yaml: | "foo4: ": bar foo5: { "foo \" bar: ": bar, 'foo '' bar: ': bar } php: | - array( + [ 'foo1' => 'bar', 'foo2' => 'bar', 'foo " bar' => 'bar', 'foo \' bar' => 'bar', 'foo3: ' => 'bar', 'foo4: ' => 'bar', - 'foo5' => array( + 'foo5' => [ 'foo " bar: ' => 'bar', 'foo \' bar: ' => 'bar', - ), - ) + ], + ] diff --git a/vendor/symfony/yaml/Tests/Fixtures/sfTests.yml b/vendor/symfony/yaml/Tests/Fixtures/sfTests.yml index 2a0b9c8..2ea417a 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/sfTests.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/sfTests.yml @@ -5,19 +5,19 @@ brief: > yaml: | stripped_title: { name: "foo bar", help: "bar foo" } php: | - array('stripped_title' => array('name' => 'foo bar', 'help' => 'bar foo')) + ['stripped_title' => ['name' => 'foo bar', 'help' => 'bar foo']] --- test: Empty sequence yaml: | foo: [ ] php: | - array('foo' => array()) + ['foo' => []] --- test: Empty value yaml: | foo: php: | - array('foo' => null) + ['foo' => null] --- test: Inline string parsing brief: > @@ -25,7 +25,7 @@ brief: > yaml: | test: ['complex: string', 'another [string]'] php: | - array('test' => array('complex: string', 'another [string]')) + ['test' => ['complex: string', 'another [string]']] --- test: Boolean brief: > @@ -40,7 +40,7 @@ yaml: | - 'null' - '~' php: | - array( + [ false, true, null, @@ -49,7 +49,7 @@ php: | 'true', 'null', '~', - ) + ] --- test: Empty lines in literal blocks brief: > @@ -63,7 +63,7 @@ yaml: | bar php: | - array('foo' => array('bar' => "foo\n\n\n \nbar\n")) + ['foo' => ['bar' => "foo\n\n\n \nbar\n"]] --- test: Empty lines in folded blocks brief: > @@ -77,7 +77,7 @@ yaml: | bar php: | - array('foo' => array('bar' => "\nfoo\n\nbar\n")) + ['foo' => ['bar' => "\nfoo\n\nbar\n"]] --- test: IP addresses brief: > @@ -85,7 +85,7 @@ brief: > yaml: | foo: 10.0.0.2 php: | - array('foo' => '10.0.0.2') + ['foo' => '10.0.0.2'] --- test: A sequence with an embedded mapping brief: > @@ -94,28 +94,28 @@ yaml: | - foo - bar: { bar: foo } php: | - array('foo', array('bar' => array('bar' => 'foo'))) + ['foo', ['bar' => ['bar' => 'foo']]] --- test: Octal brief: as in spec example 2.19, octal value is converted yaml: | foo: 0123 php: | - array('foo' => 83) + ['foo' => 83] --- test: Octal strings brief: Octal notation in a string must remain a string yaml: | foo: "0123" php: | - array('foo' => '0123') + ['foo' => '0123'] --- test: Octal strings brief: Octal notation in a string must remain a string yaml: | foo: '0123' php: | - array('foo' => '0123') + ['foo' => '0123'] --- test: Octal strings brief: Octal notation in a string must remain a string @@ -123,18 +123,18 @@ yaml: | foo: | 0123 php: | - array('foo' => "0123\n") + ['foo' => "0123\n"] --- test: Document as a simple hash brief: Document as a simple hash yaml: | { foo: bar } php: | - array('foo' => 'bar') + ['foo' => 'bar'] --- test: Document as a simple array brief: Document as a simple array yaml: | [ foo, bar ] php: | - array('foo', 'bar') + ['foo', 'bar'] diff --git a/vendor/symfony/yaml/Tests/Fixtures/unindentedCollections.yml b/vendor/symfony/yaml/Tests/Fixtures/unindentedCollections.yml index 0c96108..c85952d 100644 --- a/vendor/symfony/yaml/Tests/Fixtures/unindentedCollections.yml +++ b/vendor/symfony/yaml/Tests/Fixtures/unindentedCollections.yml @@ -8,7 +8,7 @@ yaml: | - item2 - item3 php: | - array('collection' => array('item1', 'item2', 'item3')) + ['collection' => ['item1', 'item2', 'item3']] --- test: Nested unindented collection (two levels) brief: > @@ -20,7 +20,7 @@ yaml: | - b - c php: | - array('collection' => array('key' => array('a', 'b', 'c'))) + ['collection' => ['key' => ['a', 'b', 'c']]] --- test: Nested unindented collection (three levels) brief: > @@ -33,7 +33,7 @@ yaml: | - two - three php: | - array('collection' => array('key' => array('subkey' => array('one', 'two', 'three')))) + ['collection' => ['key' => ['subkey' => ['one', 'two', 'three']]]] --- test: Key/value after unindented collection (1) brief: > @@ -46,7 +46,7 @@ yaml: | - c foo: bar php: | - array('collection' => array('key' => array('a', 'b', 'c')), 'foo' => 'bar') + ['collection' => ['key' => ['a', 'b', 'c']], 'foo' => 'bar'] --- test: Key/value after unindented collection (at the same level) brief: > @@ -59,7 +59,7 @@ yaml: | - c foo: bar php: | - array('collection' => array('key' => array('a', 'b', 'c'), 'foo' => 'bar')) + ['collection' => ['key' => ['a', 'b', 'c'], 'foo' => 'bar']] --- test: Shortcut Key after unindented collection brief: > @@ -69,7 +69,7 @@ yaml: | - key: foo foo: bar php: | - array('collection' => array(array('key' => 'foo', 'foo' => 'bar'))) + ['collection' => [['key' => 'foo', 'foo' => 'bar']]] --- test: Shortcut Key after unindented collection with custom spaces brief: > @@ -79,4 +79,4 @@ yaml: | - key: foo foo: bar php: | - array('collection' => array(array('key' => 'foo', 'foo' => 'bar'))) + ['collection' => [['key' => 'foo', 'foo' => 'bar']]] diff --git a/vendor/symfony/yaml/Tests/InlineTest.php b/vendor/symfony/yaml/Tests/InlineTest.php index f2c4ab6..f64cc68 100644 --- a/vendor/symfony/yaml/Tests/InlineTest.php +++ b/vendor/symfony/yaml/Tests/InlineTest.php @@ -53,30 +53,27 @@ public function testParsePhpConstants($yaml, $value) public function getTestsForParsePhpConstants() { - return array( - array('!php/const Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT), - array('!php/const PHP_INT_MAX', PHP_INT_MAX), - array('[!php/const PHP_INT_MAX]', array(PHP_INT_MAX)), - array('{ foo: !php/const PHP_INT_MAX }', array('foo' => PHP_INT_MAX)), - array('!php/const NULL', null), - ); + return [ + ['!php/const Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT], + ['!php/const PHP_INT_MAX', \PHP_INT_MAX], + ['[!php/const PHP_INT_MAX]', [\PHP_INT_MAX]], + ['{ foo: !php/const PHP_INT_MAX }', ['foo' => \PHP_INT_MAX]], + ['{ !php/const PHP_INT_MAX: foo }', [\PHP_INT_MAX => 'foo']], + ['!php/const NULL', null], + ]; } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage The constant "WRONG_CONSTANT" is not defined - */ public function testParsePhpConstantThrowsExceptionWhenUndefined() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('The constant "WRONG_CONSTANT" is not defined'); Inline::parse('!php/const WRONG_CONSTANT', Yaml::PARSE_CONSTANT); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessageRegExp #The string "!php/const PHP_INT_MAX" could not be parsed as a constant.*# - */ public function testParsePhpConstantThrowsExceptionOnInvalidType() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessageMatches('#The string "!php/const PHP_INT_MAX" could not be parsed as a constant.*#'); Inline::parse('!php/const PHP_INT_MAX', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); } @@ -92,13 +89,14 @@ public function testDeprecatedConstantTag($yaml, $expectedValue) public function getTestsForParseLegacyPhpConstants() { - return array( - array('!php/const:Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT), - array('!php/const:PHP_INT_MAX', PHP_INT_MAX), - array('[!php/const:PHP_INT_MAX]', array(PHP_INT_MAX)), - array('{ foo: !php/const:PHP_INT_MAX }', array('foo' => PHP_INT_MAX)), - array('!php/const:NULL', null), - ); + return [ + ['!php/const:Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT], + ['!php/const:PHP_INT_MAX', \PHP_INT_MAX], + ['[!php/const:PHP_INT_MAX]', [\PHP_INT_MAX]], + ['{ foo: !php/const:PHP_INT_MAX }', ['foo' => \PHP_INT_MAX]], + ['{ !php/const:PHP_INT_MAX: foo }', [\PHP_INT_MAX => 'foo']], + ['!php/const:NULL', null], + ]; } /** @@ -124,21 +122,21 @@ public function testDump($yaml, $value, $parseFlags = 0) public function testDumpNumericValueWithLocale() { - $locale = setlocale(LC_NUMERIC, 0); + $locale = setlocale(\LC_NUMERIC, 0); if (false === $locale) { $this->markTestSkipped('Your platform does not support locales.'); } try { - $requiredLocales = array('fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252'); - if (false === setlocale(LC_NUMERIC, $requiredLocales)) { + $requiredLocales = ['fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252']; + if (false === setlocale(\LC_NUMERIC, $requiredLocales)) { $this->markTestSkipped('Could not set any of required locales: '.implode(', ', $requiredLocales)); } $this->assertEquals('1.2', Inline::dump(1.2)); - $this->assertContains('fr', strtolower(setlocale(LC_NUMERIC, 0))); + $this->assertStringContainsStringIgnoringCase('fr', setlocale(\LC_NUMERIC, 0)); } finally { - setlocale(LC_NUMERIC, $locale); + setlocale(\LC_NUMERIC, $locale); } } @@ -149,46 +147,36 @@ public function testHashStringsResemblingExponentialNumericsShouldNotBeChangedTo $this->assertSame($value, Inline::parse(Inline::dump($value))); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage Found unknown escape character "\V". - */ public function testParseScalarWithNonEscapedBlackslashShouldThrowException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('Found unknown escape character "\V".'); Inline::parse('"Foo\Var"'); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ public function testParseScalarWithNonEscapedBlackslashAtTheEndShouldThrowException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); Inline::parse('"Foo\\"'); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ public function testParseScalarWithIncorrectlyQuotedStringShouldThrowException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); $value = "'don't do somthin' like that'"; Inline::parse($value); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ public function testParseScalarWithIncorrectlyDoubleQuotedStringShouldThrowException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); $value = '"don"t do somthin" like that"'; Inline::parse($value); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ public function testParseInvalidMappingKeyShouldThrowException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); $value = '{ "foo " bar": "bar" }'; Inline::parse($value); } @@ -203,22 +191,24 @@ public function testParseMappingKeyWithColonNotFollowedBySpace() Inline::parse('{1:""}'); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ public function testParseInvalidMappingShouldThrowException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); Inline::parse('[foo] bar'); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ public function testParseInvalidSequenceShouldThrowException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); Inline::parse('{ foo: bar } bar'); } + public function testParseInvalidTaggedSequenceShouldThrowException() + { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + Inline::parse('!foo { bar: baz } qux', Yaml::PARSE_CUSTOM_TAGS); + } + public function testParseScalarWithCorrectlyQuotedStringShouldReturnString() { $value = "'don''t do somthin'' like that'"; @@ -232,7 +222,7 @@ public function testParseScalarWithCorrectlyQuotedStringShouldReturnString() */ public function testParseReferences($yaml, $expected) { - $this->assertSame($expected, Inline::parse($yaml, 0, array('var' => 'var-value'))); + $this->assertSame($expected, Inline::parse($yaml, 0, ['var' => 'var-value'])); } /** @@ -241,31 +231,31 @@ public function testParseReferences($yaml, $expected) */ public function testParseReferencesAsFifthArgument($yaml, $expected) { - $this->assertSame($expected, Inline::parse($yaml, false, false, false, array('var' => 'var-value'))); + $this->assertSame($expected, Inline::parse($yaml, false, false, false, ['var' => 'var-value'])); } public function getDataForParseReferences() { - return array( - 'scalar' => array('*var', 'var-value'), - 'list' => array('[ *var ]', array('var-value')), - 'list-in-list' => array('[[ *var ]]', array(array('var-value'))), - 'map-in-list' => array('[ { key: *var } ]', array(array('key' => 'var-value'))), - 'embedded-mapping-in-list' => array('[ key: *var ]', array(array('key' => 'var-value'))), - 'map' => array('{ key: *var }', array('key' => 'var-value')), - 'list-in-map' => array('{ key: [*var] }', array('key' => array('var-value'))), - 'map-in-map' => array('{ foo: { bar: *var } }', array('foo' => array('bar' => 'var-value'))), - ); + return [ + 'scalar' => ['*var', 'var-value'], + 'list' => ['[ *var ]', ['var-value']], + 'list-in-list' => ['[[ *var ]]', [['var-value']]], + 'map-in-list' => ['[ { key: *var } ]', [['key' => 'var-value']]], + 'embedded-mapping-in-list' => ['[ key: *var ]', [['key' => 'var-value']]], + 'map' => ['{ key: *var }', ['key' => 'var-value']], + 'list-in-map' => ['{ key: [*var] }', ['key' => ['var-value']]], + 'map-in-map' => ['{ foo: { bar: *var } }', ['foo' => ['bar' => 'var-value']]], + ]; } public function testParseMapReferenceInSequence() { - $foo = array( + $foo = [ 'a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', - ); - $this->assertSame(array($foo), Inline::parse('[*foo]', 0, array('foo' => $foo))); + ]; + $this->assertSame([$foo], Inline::parse('[*foo]', 0, ['foo' => $foo])); } /** @@ -273,29 +263,25 @@ public function testParseMapReferenceInSequence() */ public function testParseMapReferenceInSequenceAsFifthArgument() { - $foo = array( + $foo = [ 'a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', - ); - $this->assertSame(array($foo), Inline::parse('[*foo]', false, false, false, array('foo' => $foo))); + ]; + $this->assertSame([$foo], Inline::parse('[*foo]', false, false, false, ['foo' => $foo])); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage A reference must contain at least one character at line 1. - */ public function testParseUnquotedAsterisk() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('A reference must contain at least one character at line 1.'); Inline::parse('{ foo: * }'); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage A reference must contain at least one character at line 1. - */ public function testParseUnquotedAsteriskFollowedByAComment() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('A reference must contain at least one character at line 1.'); Inline::parse('{ foo: * #foo }'); } @@ -304,19 +290,15 @@ public function testParseUnquotedAsteriskFollowedByAComment() */ public function testParseUnquotedScalarStartingWithReservedIndicator($indicator) { - if (method_exists($this, 'expectExceptionMessage')) { - $this->expectException(ParseException::class); - $this->expectExceptionMessage(sprintf('cannot start a plain scalar; you need to quote the scalar at line 1 (near "%sfoo ").', $indicator)); - } else { - $this->setExpectedException(ParseException::class, sprintf('cannot start a plain scalar; you need to quote the scalar at line 1 (near "%sfoo ").', $indicator)); - } + $this->expectException(ParseException::class); + $this->expectExceptionMessage(sprintf('cannot start a plain scalar; you need to quote the scalar at line 1 (near "%sfoo ").', $indicator)); Inline::parse(sprintf('{ foo: %sfoo }', $indicator)); } public function getReservedIndicators() { - return array(array('@'), array('`')); + return [['@'], ['`']]; } /** @@ -324,19 +306,15 @@ public function getReservedIndicators() */ public function testParseUnquotedScalarStartingWithScalarIndicator($indicator) { - if (method_exists($this, 'expectExceptionMessage')) { - $this->expectException(ParseException::class); - $this->expectExceptionMessage(sprintf('cannot start a plain scalar; you need to quote the scalar at line 1 (near "%sfoo ").', $indicator)); - } else { - $this->setExpectedException(ParseException::class, sprintf('cannot start a plain scalar; you need to quote the scalar at line 1 (near "%sfoo ").', $indicator)); - } + $this->expectException(ParseException::class); + $this->expectExceptionMessage(sprintf('cannot start a plain scalar; you need to quote the scalar at line 1 (near "%sfoo ").', $indicator)); Inline::parse(sprintf('{ foo: %sfoo }', $indicator)); } public function getScalarIndicators() { - return array(array('|'), array('>')); + return [['|'], ['>']]; } /** @@ -359,240 +337,248 @@ public function testIsHash($array, $expected) public function getDataForIsHash() { - return array( - array(array(), false), - array(array(1, 2, 3), false), - array(array(2 => 1, 1 => 2, 0 => 3), true), - array(array('foo' => 1, 'bar' => 2), true), - ); + return [ + [[], false], + [[1, 2, 3], false], + [[2 => 1, 1 => 2, 0 => 3], true], + [['foo' => 1, 'bar' => 2], true], + ]; } public function getTestsForParse() { - return array( - array('', ''), - array('null', null), - array('false', false), - array('true', true), - array('12', 12), - array('-12', -12), - array('1_2', 12), - array('_12', '_12'), - array('12_', 12), - array('"quoted string"', 'quoted string'), - array("'quoted string'", 'quoted string'), - array('12.30e+02', 12.30e+02), - array('123.45_67', 123.4567), - array('0x4D2', 0x4D2), - array('0x_4_D_2_', 0x4D2), - array('02333', 02333), - array('0_2_3_3_3', 02333), - array('.Inf', -log(0)), - array('-.Inf', log(0)), - array("'686e444'", '686e444'), - array('686e444', 646e444), - array('123456789123456789123456789123456789', '123456789123456789123456789123456789'), - array('"foo\r\nbar"', "foo\r\nbar"), - array("'foo#bar'", 'foo#bar'), - array("'foo # bar'", 'foo # bar'), - array("'#cfcfcf'", '#cfcfcf'), - array('::form_base.html.twig', '::form_base.html.twig'), + return [ + ['', ''], + ['null', null], + ['false', false], + ['true', true], + ['12', 12], + ['-12', -12], + ['1_2', 12], + ['_12', '_12'], + ['12_', 12], + ['"quoted string"', 'quoted string'], + ["'quoted string'", 'quoted string'], + ['12.30e+02', 12.30e+02], + ['123.45_67', 123.4567], + ['0x4D2', 0x4D2], + ['0x_4_D_2_', 0x4D2], + ['02333', 02333], + ['0_2_3_3_3', 02333], + ['.Inf', -log(0)], + ['-.Inf', log(0)], + ["'686e444'", '686e444'], + ['686e444', 646e444], + ['123456789123456789123456789123456789', '123456789123456789123456789123456789'], + ['"foo\r\nbar"', "foo\r\nbar"], + ["'foo#bar'", 'foo#bar'], + ["'foo # bar'", 'foo # bar'], + ["'#cfcfcf'", '#cfcfcf'], + ['::form_base.html.twig', '::form_base.html.twig'], // Pre-YAML-1.2 booleans - array("'y'", 'y'), - array("'n'", 'n'), - array("'yes'", 'yes'), - array("'no'", 'no'), - array("'on'", 'on'), - array("'off'", 'off'), - - array('2007-10-30', gmmktime(0, 0, 0, 10, 30, 2007)), - array('2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)), - array('2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)), - array('1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)), - array('1730-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 1730)), - - array('"a \\"string\\" with \'quoted strings inside\'"', 'a "string" with \'quoted strings inside\''), - array("'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''), + ["'y'", 'y'], + ["'n'", 'n'], + ["'yes'", 'yes'], + ["'no'", 'no'], + ["'on'", 'on'], + ["'off'", 'off'], + + ['2007-10-30', gmmktime(0, 0, 0, 10, 30, 2007)], + ['2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)], + ['2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)], + ['1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)], + ['1730-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 1730)], + + ['"a \\"string\\" with \'quoted strings inside\'"', 'a "string" with \'quoted strings inside\''], + ["'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''], // sequences // urls are no key value mapping. see #3609. Valid yaml "key: value" mappings require a space after the colon - array('[foo, http://urls.are/no/mappings, false, null, 12]', array('foo', 'http://urls.are/no/mappings', false, null, 12)), - array('[ foo , bar , false , null , 12 ]', array('foo', 'bar', false, null, 12)), - array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')), + ['[foo, http://urls.are/no/mappings, false, null, 12]', ['foo', 'http://urls.are/no/mappings', false, null, 12]], + ['[ foo , bar , false , null , 12 ]', ['foo', 'bar', false, null, 12]], + ['[\'foo,bar\', \'foo bar\']', ['foo,bar', 'foo bar']], // mappings - array('{foo: bar,bar: foo,"false": false, "null": null,integer: 12}', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)), - array('{ foo : bar, bar : foo, "false" : false, "null" : null, integer : 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)), - array('{foo: \'bar\', bar: \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')), - array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')), - array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', array('foo\'' => 'bar', 'bar"' => 'foo: bar')), - array('{\'foo: \': \'bar\', "bar: ": \'foo: bar\'}', array('foo: ' => 'bar', 'bar: ' => 'foo: bar')), - array('{"foo:bar": "baz"}', array('foo:bar' => 'baz')), - array('{"foo":"bar"}', array('foo' => 'bar')), + ['{foo: bar,bar: foo,"false": false, "null": null,integer: 12}', ['foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12]], + ['{ foo : bar, bar : foo, "false" : false, "null" : null, integer : 12 }', ['foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12]], + ['{foo: \'bar\', bar: \'foo: bar\'}', ['foo' => 'bar', 'bar' => 'foo: bar']], + ['{\'foo\': \'bar\', "bar": \'foo: bar\'}', ['foo' => 'bar', 'bar' => 'foo: bar']], + ['{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', ['foo\'' => 'bar', 'bar"' => 'foo: bar']], + ['{\'foo: \': \'bar\', "bar: ": \'foo: bar\'}', ['foo: ' => 'bar', 'bar: ' => 'foo: bar']], + ['{"foo:bar": "baz"}', ['foo:bar' => 'baz']], + ['{"foo":"bar"}', ['foo' => 'bar']], // nested sequences and mappings - array('[foo, [bar, foo]]', array('foo', array('bar', 'foo'))), - array('[foo, {bar: foo}]', array('foo', array('bar' => 'foo'))), - array('{ foo: {bar: foo} }', array('foo' => array('bar' => 'foo'))), - array('{ foo: [bar, foo] }', array('foo' => array('bar', 'foo'))), - array('{ foo:{bar: foo} }', array('foo' => array('bar' => 'foo'))), - array('{ foo:[bar, foo] }', array('foo' => array('bar', 'foo'))), + ['[foo, [bar, foo]]', ['foo', ['bar', 'foo']]], + ['[foo, {bar: foo}]', ['foo', ['bar' => 'foo']]], + ['{ foo: {bar: foo} }', ['foo' => ['bar' => 'foo']]], + ['{ foo: [bar, foo] }', ['foo' => ['bar', 'foo']]], + ['{ foo:{bar: foo} }', ['foo' => ['bar' => 'foo']]], + ['{ foo:[bar, foo] }', ['foo' => ['bar', 'foo']]], - array('[ foo, [ bar, foo ] ]', array('foo', array('bar', 'foo'))), + ['[ foo, [ bar, foo ] ]', ['foo', ['bar', 'foo']]], - array('[{ foo: {bar: foo} }]', array(array('foo' => array('bar' => 'foo')))), + ['[{ foo: {bar: foo} }]', [['foo' => ['bar' => 'foo']]]], - array('[foo, [bar, [foo, [bar, foo]], foo]]', array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo'))), + ['[foo, [bar, [foo, [bar, foo]], foo]]', ['foo', ['bar', ['foo', ['bar', 'foo']], 'foo']]], - array('[foo, {bar: foo, foo: [foo, {bar: foo}]}, [foo, {bar: foo}]]', array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo')))), + ['[foo, {bar: foo, foo: [foo, {bar: foo}]}, [foo, {bar: foo}]]', ['foo', ['bar' => 'foo', 'foo' => ['foo', ['bar' => 'foo']]], ['foo', ['bar' => 'foo']]]], - array('[foo, bar: { foo: bar }]', array('foo', '1' => array('bar' => array('foo' => 'bar')))), - array('[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, '@service_container')), - ); + ['[foo, bar: { foo: bar }]', ['foo', '1' => ['bar' => ['foo' => 'bar']]]], + ['[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', ['foo', '@foo.baz', ['%foo%' => 'foo is %foo%', 'bar' => '%foo%'], true, '@service_container']], + ]; } public function getTestsForParseWithMapObjects() { - return array( - array('', ''), - array('null', null), - array('false', false), - array('true', true), - array('12', 12), - array('-12', -12), - array('"quoted string"', 'quoted string'), - array("'quoted string'", 'quoted string'), - array('12.30e+02', 12.30e+02), - array('0x4D2', 0x4D2), - array('02333', 02333), - array('.Inf', -log(0)), - array('-.Inf', log(0)), - array("'686e444'", '686e444'), - array('686e444', 646e444), - array('123456789123456789123456789123456789', '123456789123456789123456789123456789'), - array('"foo\r\nbar"', "foo\r\nbar"), - array("'foo#bar'", 'foo#bar'), - array("'foo # bar'", 'foo # bar'), - array("'#cfcfcf'", '#cfcfcf'), - array('::form_base.html.twig', '::form_base.html.twig'), - - array('2007-10-30', gmmktime(0, 0, 0, 10, 30, 2007)), - array('2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)), - array('2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)), - array('1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)), - array('1730-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 1730)), - - array('"a \\"string\\" with \'quoted strings inside\'"', 'a "string" with \'quoted strings inside\''), - array("'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''), + return [ + ['', ''], + ['null', null], + ['false', false], + ['true', true], + ['12', 12], + ['-12', -12], + ['"quoted string"', 'quoted string'], + ["'quoted string'", 'quoted string'], + ['12.30e+02', 12.30e+02], + ['0x4D2', 0x4D2], + ['02333', 02333], + ['.Inf', -log(0)], + ['-.Inf', log(0)], + ["'686e444'", '686e444'], + ['686e444', 646e444], + ['123456789123456789123456789123456789', '123456789123456789123456789123456789'], + ['"foo\r\nbar"', "foo\r\nbar"], + ["'foo#bar'", 'foo#bar'], + ["'foo # bar'", 'foo # bar'], + ["'#cfcfcf'", '#cfcfcf'], + ['::form_base.html.twig', '::form_base.html.twig'], + + ['2007-10-30', gmmktime(0, 0, 0, 10, 30, 2007)], + ['2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)], + ['2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)], + ['1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)], + ['1730-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 1730)], + + ['"a \\"string\\" with \'quoted strings inside\'"', 'a "string" with \'quoted strings inside\''], + ["'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''], // sequences // urls are no key value mapping. see #3609. Valid yaml "key: value" mappings require a space after the colon - array('[foo, http://urls.are/no/mappings, false, null, 12]', array('foo', 'http://urls.are/no/mappings', false, null, 12)), - array('[ foo , bar , false , null , 12 ]', array('foo', 'bar', false, null, 12)), - array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')), + ['[foo, http://urls.are/no/mappings, false, null, 12]', ['foo', 'http://urls.are/no/mappings', false, null, 12]], + ['[ foo , bar , false , null , 12 ]', ['foo', 'bar', false, null, 12]], + ['[\'foo,bar\', \'foo bar\']', ['foo,bar', 'foo bar']], // mappings - array('{foo: bar,bar: foo,"false": false,"null": null,integer: 12}', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP), - array('{ foo : bar, bar : foo, "false" : false, "null" : null, integer : 12 }', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP), - array('{foo: \'bar\', bar: \'foo: bar\'}', (object) array('foo' => 'bar', 'bar' => 'foo: bar')), - array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', (object) array('foo' => 'bar', 'bar' => 'foo: bar')), - array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', (object) array('foo\'' => 'bar', 'bar"' => 'foo: bar')), - array('{\'foo: \': \'bar\', "bar: ": \'foo: bar\'}', (object) array('foo: ' => 'bar', 'bar: ' => 'foo: bar')), - array('{"foo:bar": "baz"}', (object) array('foo:bar' => 'baz')), - array('{"foo":"bar"}', (object) array('foo' => 'bar')), + ['{foo: bar,bar: foo,"false": false,"null": null,integer: 12}', (object) ['foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12], Yaml::PARSE_OBJECT_FOR_MAP], + ['{ foo : bar, bar : foo, "false" : false, "null" : null, integer : 12 }', (object) ['foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12], Yaml::PARSE_OBJECT_FOR_MAP], + ['{foo: \'bar\', bar: \'foo: bar\'}', (object) ['foo' => 'bar', 'bar' => 'foo: bar']], + ['{\'foo\': \'bar\', "bar": \'foo: bar\'}', (object) ['foo' => 'bar', 'bar' => 'foo: bar']], + ['{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', (object) ['foo\'' => 'bar', 'bar"' => 'foo: bar']], + ['{\'foo: \': \'bar\', "bar: ": \'foo: bar\'}', (object) ['foo: ' => 'bar', 'bar: ' => 'foo: bar']], + ['{"foo:bar": "baz"}', (object) ['foo:bar' => 'baz']], + ['{"foo":"bar"}', (object) ['foo' => 'bar']], // nested sequences and mappings - array('[foo, [bar, foo]]', array('foo', array('bar', 'foo'))), - array('[foo, {bar: foo}]', array('foo', (object) array('bar' => 'foo'))), - array('{ foo: {bar: foo} }', (object) array('foo' => (object) array('bar' => 'foo'))), - array('{ foo: [bar, foo] }', (object) array('foo' => array('bar', 'foo'))), + ['[foo, [bar, foo]]', ['foo', ['bar', 'foo']]], + ['[foo, {bar: foo}]', ['foo', (object) ['bar' => 'foo']]], + ['{ foo: {bar: foo} }', (object) ['foo' => (object) ['bar' => 'foo']]], + ['{ foo: [bar, foo] }', (object) ['foo' => ['bar', 'foo']]], - array('[ foo, [ bar, foo ] ]', array('foo', array('bar', 'foo'))), + ['[ foo, [ bar, foo ] ]', ['foo', ['bar', 'foo']]], - array('[{ foo: {bar: foo} }]', array((object) array('foo' => (object) array('bar' => 'foo')))), + ['[{ foo: {bar: foo} }]', [(object) ['foo' => (object) ['bar' => 'foo']]]], - array('[foo, [bar, [foo, [bar, foo]], foo]]', array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo'))), + ['[foo, [bar, [foo, [bar, foo]], foo]]', ['foo', ['bar', ['foo', ['bar', 'foo']], 'foo']]], - array('[foo, {bar: foo, foo: [foo, {bar: foo}]}, [foo, {bar: foo}]]', array('foo', (object) array('bar' => 'foo', 'foo' => array('foo', (object) array('bar' => 'foo'))), array('foo', (object) array('bar' => 'foo')))), + ['[foo, {bar: foo, foo: [foo, {bar: foo}]}, [foo, {bar: foo}]]', ['foo', (object) ['bar' => 'foo', 'foo' => ['foo', (object) ['bar' => 'foo']]], ['foo', (object) ['bar' => 'foo']]]], - array('[foo, bar: { foo: bar }]', array('foo', '1' => (object) array('bar' => (object) array('foo' => 'bar')))), - array('[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', array('foo', '@foo.baz', (object) array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, '@service_container')), + ['[foo, bar: { foo: bar }]', ['foo', '1' => (object) ['bar' => (object) ['foo' => 'bar']]]], + ['[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', ['foo', '@foo.baz', (object) ['%foo%' => 'foo is %foo%', 'bar' => '%foo%'], true, '@service_container']], - array('{}', new \stdClass()), - array('{ foo : bar, bar : {} }', (object) array('foo' => 'bar', 'bar' => new \stdClass())), - array('{ foo : [], bar : {} }', (object) array('foo' => array(), 'bar' => new \stdClass())), - array('{foo: \'bar\', bar: {} }', (object) array('foo' => 'bar', 'bar' => new \stdClass())), - array('{\'foo\': \'bar\', "bar": {}}', (object) array('foo' => 'bar', 'bar' => new \stdClass())), - array('{\'foo\': \'bar\', "bar": \'{}\'}', (object) array('foo' => 'bar', 'bar' => '{}')), + ['{}', new \stdClass()], + ['{ foo : bar, bar : {} }', (object) ['foo' => 'bar', 'bar' => new \stdClass()]], + ['{ foo : [], bar : {} }', (object) ['foo' => [], 'bar' => new \stdClass()]], + ['{foo: \'bar\', bar: {} }', (object) ['foo' => 'bar', 'bar' => new \stdClass()]], + ['{\'foo\': \'bar\', "bar": {}}', (object) ['foo' => 'bar', 'bar' => new \stdClass()]], + ['{\'foo\': \'bar\', "bar": \'{}\'}', (object) ['foo' => 'bar', 'bar' => '{}']], - array('[foo, [{}, {}]]', array('foo', array(new \stdClass(), new \stdClass()))), - array('[foo, [[], {}]]', array('foo', array(array(), new \stdClass()))), - array('[foo, [[{}, {}], {}]]', array('foo', array(array(new \stdClass(), new \stdClass()), new \stdClass()))), - array('[foo, {bar: {}}]', array('foo', '1' => (object) array('bar' => new \stdClass()))), - ); + ['[foo, [{}, {}]]', ['foo', [new \stdClass(), new \stdClass()]]], + ['[foo, [[], {}]]', ['foo', [[], new \stdClass()]]], + ['[foo, [[{}, {}], {}]]', ['foo', [[new \stdClass(), new \stdClass()], new \stdClass()]]], + ['[foo, {bar: {}}]', ['foo', '1' => (object) ['bar' => new \stdClass()]]], + ]; } public function getTestsForDump() { - return array( - array('null', null), - array('false', false), - array('true', true), - array('12', 12), - array("'1_2'", '1_2'), - array('_12', '_12'), - array("'12_'", '12_'), - array("'quoted string'", 'quoted string'), - array('!!float 1230', 12.30e+02), - array('1234', 0x4D2), - array('1243', 02333), - array("'0x_4_D_2_'", '0x_4_D_2_'), - array("'0_2_3_3_3'", '0_2_3_3_3'), - array('.Inf', -log(0)), - array('-.Inf', log(0)), - array("'686e444'", '686e444'), - array('"foo\r\nbar"', "foo\r\nbar"), - array("'foo#bar'", 'foo#bar'), - array("'foo # bar'", 'foo # bar'), - array("'#cfcfcf'", '#cfcfcf'), - - array("'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''), - - array("'-dash'", '-dash'), - array("'-'", '-'), + return [ + ['null', null], + ['false', false], + ['true', true], + ['12', 12], + ["'1_2'", '1_2'], + ['_12', '_12'], + ["'12_'", '12_'], + ["'quoted string'", 'quoted string'], + ['!!float 1230', 12.30e+02], + ['1234', 0x4D2], + ['1243', 02333], + ["'0x_4_D_2_'", '0x_4_D_2_'], + ["'0_2_3_3_3'", '0_2_3_3_3'], + ['.Inf', -log(0)], + ['-.Inf', log(0)], + ["'686e444'", '686e444'], + ['"foo\r\nbar"', "foo\r\nbar"], + ["'foo#bar'", 'foo#bar'], + ["'foo # bar'", 'foo # bar'], + ["'#cfcfcf'", '#cfcfcf'], + + ["'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''], + + ["'-dash'", '-dash'], + ["'-'", '-'], // Pre-YAML-1.2 booleans - array("'y'", 'y'), - array("'n'", 'n'), - array("'yes'", 'yes'), - array("'no'", 'no'), - array("'on'", 'on'), - array("'off'", 'off'), + ["'y'", 'y'], + ["'n'", 'n'], + ["'yes'", 'yes'], + ["'no'", 'no'], + ["'on'", 'on'], + ["'off'", 'off'], // sequences - array('[foo, bar, false, null, 12]', array('foo', 'bar', false, null, 12)), - array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')), + ['[foo, bar, false, null, 12]', ['foo', 'bar', false, null, 12]], + ['[\'foo,bar\', \'foo bar\']', ['foo,bar', 'foo bar']], // mappings - array('{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)), - array('{ foo: bar, bar: \'foo: bar\' }', array('foo' => 'bar', 'bar' => 'foo: bar')), + ['{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }', ['foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12]], + ['{ foo: bar, bar: \'foo: bar\' }', ['foo' => 'bar', 'bar' => 'foo: bar']], // nested sequences and mappings - array('[foo, [bar, foo]]', array('foo', array('bar', 'foo'))), + ['[foo, [bar, foo]]', ['foo', ['bar', 'foo']]], + + ['[foo, [bar, [foo, [bar, foo]], foo]]', ['foo', ['bar', ['foo', ['bar', 'foo']], 'foo']]], - array('[foo, [bar, [foo, [bar, foo]], foo]]', array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo'))), + ['{ foo: { bar: foo } }', ['foo' => ['bar' => 'foo']]], - array('{ foo: { bar: foo } }', array('foo' => array('bar' => 'foo'))), + ['[foo, { bar: foo }]', ['foo', ['bar' => 'foo']]], - array('[foo, { bar: foo }]', array('foo', array('bar' => 'foo'))), + ['[foo, { bar: foo, foo: [foo, { bar: foo }] }, [foo, { bar: foo }]]', ['foo', ['bar' => 'foo', 'foo' => ['foo', ['bar' => 'foo']]], ['foo', ['bar' => 'foo']]]], - array('[foo, { bar: foo, foo: [foo, { bar: foo }] }, [foo, { bar: foo }]]', array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo')))), + ['[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', ['foo', '@foo.baz', ['%foo%' => 'foo is %foo%', 'bar' => '%foo%'], true, '@service_container']], - array('[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, '@service_container')), + ['{ foo: { bar: { 1: 2, baz: 3 } } }', ['foo' => ['bar' => [1 => 2, 'baz' => 3]]]], - array('{ foo: { bar: { 1: 2, baz: 3 } } }', array('foo' => array('bar' => array(1 => 2, 'baz' => 3)))), - ); + // numeric strings with trailing whitespaces + ["'0123 '", '0123 '], + ['"0123\f"', "0123\f"], + ['"0123\n"', "0123\n"], + ['"0123\r"', "0123\r"], + ['"0123\t"', "0123\t"], + ['"0123\v"', "0123\v"], + ]; } /** @@ -625,12 +611,12 @@ public function testParseTimestampAsDateTimeObject($yaml, $year, $month, $day, $ public function getTimestampTests() { - return array( - 'canonical' => array('2001-12-15T02:59:43.1Z', 2001, 12, 15, 2, 59, 43.1, '+0000'), - 'ISO-8601' => array('2001-12-15t21:59:43.10-05:00', 2001, 12, 16, 2, 59, 43.1, '-0500'), - 'spaced' => array('2001-12-15 21:59:43.10 -5', 2001, 12, 16, 2, 59, 43.1, '-0500'), - 'date' => array('2001-12-15', 2001, 12, 15, 0, 0, 0, '+0000'), - ); + return [ + 'canonical' => ['2001-12-15T02:59:43.1Z', 2001, 12, 15, 2, 59, 43.1, '+0000'], + 'ISO-8601' => ['2001-12-15t21:59:43.10-05:00', 2001, 12, 16, 2, 59, 43.1, '-0500'], + 'spaced' => ['2001-12-15 21:59:43.10 -5', 2001, 12, 16, 2, 59, 43.1, '-0500'], + 'date' => ['2001-12-15', 2001, 12, 15, 0, 0, 0, '+0000'], + ]; } /** @@ -647,7 +633,7 @@ public function testParseNestedTimestampListAsDateTimeObject($yaml, $year, $mont $expected->setTime($hour, $minute, $second); } - $expectedNested = array('nested' => array($expected)); + $expectedNested = ['nested' => [$expected]]; $yamlNested = "{nested: [$yaml]}"; $this->assertEquals($expectedNested, Inline::parse($yamlNested, Yaml::PARSE_DATETIME)); @@ -663,13 +649,13 @@ public function testDumpDateTime($dateTime, $expected) public function getDateTimeDumpTests() { - $tests = array(); + $tests = []; $dateTime = new \DateTime('2001-12-15 21:59:43', new \DateTimeZone('UTC')); - $tests['date-time-utc'] = array($dateTime, '2001-12-15T21:59:43+00:00'); + $tests['date-time-utc'] = [$dateTime, '2001-12-15T21:59:43+00:00']; $dateTime = new \DateTimeImmutable('2001-07-15 21:59:43', new \DateTimeZone('Europe/Berlin')); - $tests['immutable-date-time-europe-berlin'] = array($dateTime, '2001-07-15T21:59:43+02:00'); + $tests['immutable-date-time-europe-berlin'] = [$dateTime, '2001-07-15T21:59:43+02:00']; return $tests; } @@ -684,44 +670,38 @@ public function testParseBinaryData($data) public function getBinaryData() { - return array( - 'enclosed with double quotes' => array('!!binary "SGVsbG8gd29ybGQ="'), - 'enclosed with single quotes' => array("!!binary 'SGVsbG8gd29ybGQ='"), - 'containing spaces' => array('!!binary "SGVs bG8gd 29ybGQ="'), - ); + return [ + 'enclosed with double quotes' => ['!!binary "SGVsbG8gd29ybGQ="'], + 'enclosed with single quotes' => ["!!binary 'SGVsbG8gd29ybGQ='"], + 'containing spaces' => ['!!binary "SGVs bG8gd 29ybGQ="'], + ]; } /** * @dataProvider getInvalidBinaryData - * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testParseInvalidBinaryData($data, $expectedMessage) { - if (method_exists($this, 'expectException')) { - $this->expectExceptionMessageRegExp($expectedMessage); - } else { - $this->setExpectedExceptionRegExp(ParseException::class, $expectedMessage); - } + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessageMatches($expectedMessage); Inline::parse($data); } public function getInvalidBinaryData() { - return array( - 'length not a multiple of four' => array('!!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'), - 'invalid characters' => array('!!binary "SGVsbG8#d29ybGQ="', '/The base64 encoded data \(.*\) contains invalid characters/'), - 'too many equals characters' => array('!!binary "SGVsbG8gd29yb==="', '/The base64 encoded data \(.*\) contains invalid characters/'), - 'misplaced equals character' => array('!!binary "SGVsbG8gd29ybG=Q"', '/The base64 encoded data \(.*\) contains invalid characters/'), - ); + return [ + 'length not a multiple of four' => ['!!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'], + 'invalid characters' => ['!!binary "SGVsbG8#d29ybGQ="', '/The base64 encoded data \(.*\) contains invalid characters/'], + 'too many equals characters' => ['!!binary "SGVsbG8gd29yb==="', '/The base64 encoded data \(.*\) contains invalid characters/'], + 'misplaced equals character' => ['!!binary "SGVsbG8gd29ybG=Q"', '/The base64 encoded data \(.*\) contains invalid characters/'], + ]; } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage Malformed inline YAML string: {this, is not, supported} at line 1. - */ public function testNotSupportedMissingValue() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('Malformed inline YAML string: "{this, is not, supported}" at line 1.'); Inline::parse('{this, is not, supported}'); } @@ -729,7 +709,7 @@ public function testVeryLongQuotedStrings() { $longStringWithQuotes = str_repeat("x\r\n\\\"x\"x", 1000); - $yamlString = Inline::dump(array('longStringWithQuotes' => $longStringWithQuotes)); + $yamlString = Inline::dump(['longStringWithQuotes' => $longStringWithQuotes]); $arrayFromYaml = Inline::parse($yamlString); $this->assertEquals($longStringWithQuotes, $arrayFromYaml['longStringWithQuotes']); @@ -741,7 +721,7 @@ public function testVeryLongQuotedStrings() */ public function testOmittedMappingKeyIsParsedAsColon() { - $this->assertSame(array(':' => 'foo'), Inline::parse('{: foo}')); + $this->assertSame([':' => 'foo'], Inline::parse('{: foo}')); } /** @@ -754,15 +734,15 @@ public function testParseMissingMappingValueAsNull($yaml, $expected) public function getTestsForNullValues() { - return array( - 'null before closing curly brace' => array('{foo:}', array('foo' => null)), - 'null before comma' => array('{foo:, bar: baz}', array('foo' => null, 'bar' => 'baz')), - ); + return [ + 'null before closing curly brace' => ['{foo:}', ['foo' => null]], + 'null before comma' => ['{foo:, bar: baz}', ['foo' => null, 'bar' => 'baz']], + ]; } public function testTheEmptyStringIsAValidMappingKey() { - $this->assertSame(array('' => 'foo'), Inline::parse('{ "": foo }')); + $this->assertSame(['' => 'foo'], Inline::parse('{ "": foo }')); } /** @@ -788,12 +768,12 @@ public function testExplicitStringCastingOfMappingKeys($yaml, $expected) public function getNotPhpCompatibleMappingKeyData() { - return array( - 'boolean-true' => array('{true: "foo"}', array('true' => 'foo')), - 'boolean-false' => array('{false: "foo"}', array('false' => 'foo')), - 'null' => array('{null: "foo"}', array('null' => 'foo')), - 'float' => array('{0.25: "foo"}', array('0.25' => 'foo')), - ); + return [ + 'boolean-true' => ['{true: "foo"}', ['true' => 'foo']], + 'boolean-false' => ['{false: "foo"}', ['false' => 'foo']], + 'null' => ['{null: "foo"}', ['null' => 'foo']], + 'float' => ['{0.25: "foo"}', ['0.25' => 'foo']], + ]; } /** @@ -802,15 +782,92 @@ public function getNotPhpCompatibleMappingKeyData() */ public function testDeprecatedStrTag() { - $this->assertSame(array('foo' => 'bar'), Inline::parse('{ foo: !str bar }')); + $this->assertSame(['foo' => 'bar'], Inline::parse('{ foo: !str bar }')); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage Unexpected end of line, expected one of ",}" at line 1 (near "{abc: 'def'"). - */ public function testUnfinishedInlineMap() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('Unexpected end of line, expected one of ",}" at line 1 (near "{abc: \'def\'").'); Inline::parse("{abc: 'def'"); } + + /** + * @dataProvider getTestsForOctalNumbers + */ + public function testParseOctalNumbers($expected, $yaml) + { + self::assertSame($expected, Inline::parse($yaml)); + } + + public function getTestsForOctalNumbers() + { + return [ + 'positive octal number' => [28, '034'], + 'negative octal number' => [-28, '-034'], + ]; + } + + /** + * @dataProvider phpObjectTagWithEmptyValueProvider + */ + public function testPhpObjectWithEmptyValue($expected, $value) + { + $this->assertSame($expected, Inline::parse($value, Yaml::PARSE_OBJECT)); + } + + public function phpObjectTagWithEmptyValueProvider() + { + return [ + [false, '!php/object'], + [false, '!php/object '], + [false, '!php/object '], + [[false], '[!php/object]'], + [[false], '[!php/object ]'], + [[false, 'foo'], '[!php/object , foo]'], + ]; + } + + /** + * @dataProvider phpConstTagWithEmptyValueProvider + */ + public function testPhpConstTagWithEmptyValue($expected, $value) + { + $this->assertSame($expected, Inline::parse($value, Yaml::PARSE_CONSTANT)); + } + + public function phpConstTagWithEmptyValueProvider() + { + return [ + ['', '!php/const'], + ['', '!php/const '], + ['', '!php/const '], + [[''], '[!php/const]'], + [[''], '[!php/const ]'], + [['', 'foo'], '[!php/const , foo]'], + [['' => 'foo'], '{!php/const: foo}'], + [['' => 'foo'], '{!php/const : foo}'], + [['' => 'foo', 'bar' => 'ccc'], '{!php/const : foo, bar: ccc}'], + ]; + } + + public function testParsePositiveOctalNumberContainingInvalidDigits() + { + self::assertSame('0123456789', Inline::parse('0123456789')); + } + + public function testParseNegativeOctalNumberContainingInvalidDigits() + { + self::assertSame('-0123456789', Inline::parse('-0123456789')); + } + + public function testParseCommentNotPrefixedBySpaces() + { + self::assertSame('foo', Inline::parse('"foo"#comment')); + } + + public function testParseUnquotedStringContainingHashTagNotPrefixedBySpace() + { + self::assertSame('foo#nocomment', Inline::parse('foo#nocomment')); + } } diff --git a/vendor/symfony/yaml/Tests/ParserTest.php b/vendor/symfony/yaml/Tests/ParserTest.php index c9aff59..7fa6ed1 100644 --- a/vendor/symfony/yaml/Tests/ParserTest.php +++ b/vendor/symfony/yaml/Tests/ParserTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Yaml\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser; use Symfony\Component\Yaml\Tag\TaggedValue; use Symfony\Component\Yaml\Yaml; @@ -39,21 +38,19 @@ protected function tearDown() */ public function testSpecifications($expected, $yaml, $comment, $deprecated) { - $deprecations = array(); + $deprecations = []; if ($deprecated) { set_error_handler(function ($type, $msg) use (&$deprecations) { - if (E_USER_DEPRECATED !== $type) { + if (\E_USER_DEPRECATED !== $type) { restore_error_handler(); - if (class_exists('PHPUnit_Util_ErrorHandler')) { - return \call_user_func_array('PHPUnit_Util_ErrorHandler::handleError', \func_get_args()); - } - return \call_user_func_array('PHPUnit\Util\ErrorHandler::handleError', \func_get_args()); } $deprecations[] = $msg; + + return null; }); } @@ -63,7 +60,7 @@ public function testSpecifications($expected, $yaml, $comment, $deprecated) restore_error_handler(); $this->assertCount(1, $deprecations); - $this->assertContains(true !== $deprecated ? $deprecated : 'Using the comma as a group separator for floats is deprecated since Symfony 3.2 and will be removed in 4.0 on line 1.', $deprecations[0]); + $this->assertStringContainsString(true !== $deprecated ? $deprecated : 'Using the comma as a group separator for floats is deprecated since Symfony 3.2 and will be removed in 4.0 on line 1.', $deprecations[0]); } } @@ -104,16 +101,16 @@ public function getLegacyNonStringMappingKeysData() public function testTabsInYaml() { // test tabs in YAML - $yamls = array( + $yamls = [ "foo:\n bar", "foo:\n bar", "foo:\n bar", "foo:\n bar", - ); + ]; foreach ($yamls as $yaml) { try { - $content = $this->parser->parse($yaml); + $this->parser->parse($yaml); $this->fail('YAML files must not contain tabs'); } catch (\Exception $e) { @@ -136,7 +133,7 @@ public function testEndOfTheDocumentMarker() public function getBlockChompingTests() { - $tests = array(); + $tests = []; $yaml = <<<'EOF' foo: |- @@ -147,11 +144,11 @@ public function getBlockChompingTests() two EOF; - $expected = array( + $expected = [ 'foo' => "one\ntwo", 'bar' => "one\ntwo", - ); - $tests['Literal block chomping strip with single trailing newline'] = array($expected, $yaml); + ]; + $tests['Literal block chomping strip with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: |- @@ -164,19 +161,19 @@ public function getBlockChompingTests() EOF; - $expected = array( + $expected = [ 'foo' => "one\ntwo", 'bar' => "one\ntwo", - ); - $tests['Literal block chomping strip with multiple trailing newlines'] = array($expected, $yaml); + ]; + $tests['Literal block chomping strip with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' {} EOF; - $expected = array(); - $tests['Literal block chomping strip with multiple trailing newlines after a 1-liner'] = array($expected, $yaml); + $expected = []; + $tests['Literal block chomping strip with multiple trailing newlines after a 1-liner'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: |- @@ -186,11 +183,11 @@ public function getBlockChompingTests() one two EOF; - $expected = array( + $expected = [ 'foo' => "one\ntwo", 'bar' => "one\ntwo", - ); - $tests['Literal block chomping strip without trailing newline'] = array($expected, $yaml); + ]; + $tests['Literal block chomping strip without trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: | @@ -201,11 +198,11 @@ public function getBlockChompingTests() two EOF; - $expected = array( + $expected = [ 'foo' => "one\ntwo\n", 'bar' => "one\ntwo\n", - ); - $tests['Literal block chomping clip with single trailing newline'] = array($expected, $yaml); + ]; + $tests['Literal block chomping clip with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: | @@ -218,11 +215,11 @@ public function getBlockChompingTests() EOF; - $expected = array( + $expected = [ 'foo' => "one\ntwo\n", 'bar' => "one\ntwo\n", - ); - $tests['Literal block chomping clip with multiple trailing newlines'] = array($expected, $yaml); + ]; + $tests['Literal block chomping clip with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: @@ -231,14 +228,14 @@ public function getBlockChompingTests() two EOF; - $expected = array( - 'foo' => array( - array( + $expected = [ + 'foo' => [ + [ 'bar' => "one\n\ntwo", - ), - ), - ); - $tests['Literal block chomping clip with embedded blank line inside unindented collection'] = array($expected, $yaml); + ], + ], + ]; + $tests['Literal block chomping clip with embedded blank line inside unindented collection'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: | @@ -248,11 +245,11 @@ public function getBlockChompingTests() one two EOF; - $expected = array( + $expected = [ 'foo' => "one\ntwo\n", 'bar' => "one\ntwo", - ); - $tests['Literal block chomping clip without trailing newline'] = array($expected, $yaml); + ]; + $tests['Literal block chomping clip without trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: |+ @@ -263,11 +260,11 @@ public function getBlockChompingTests() two EOF; - $expected = array( + $expected = [ 'foo' => "one\ntwo\n", 'bar' => "one\ntwo\n", - ); - $tests['Literal block chomping keep with single trailing newline'] = array($expected, $yaml); + ]; + $tests['Literal block chomping keep with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: |+ @@ -280,11 +277,11 @@ public function getBlockChompingTests() EOF; - $expected = array( + $expected = [ 'foo' => "one\ntwo\n\n", 'bar' => "one\ntwo\n\n", - ); - $tests['Literal block chomping keep with multiple trailing newlines'] = array($expected, $yaml); + ]; + $tests['Literal block chomping keep with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: |+ @@ -294,11 +291,11 @@ public function getBlockChompingTests() one two EOF; - $expected = array( + $expected = [ 'foo' => "one\ntwo\n", 'bar' => "one\ntwo", - ); - $tests['Literal block chomping keep without trailing newline'] = array($expected, $yaml); + ]; + $tests['Literal block chomping keep without trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: >- @@ -309,11 +306,11 @@ public function getBlockChompingTests() two EOF; - $expected = array( + $expected = [ 'foo' => 'one two', 'bar' => 'one two', - ); - $tests['Folded block chomping strip with single trailing newline'] = array($expected, $yaml); + ]; + $tests['Folded block chomping strip with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: >- @@ -326,11 +323,11 @@ public function getBlockChompingTests() EOF; - $expected = array( + $expected = [ 'foo' => 'one two', 'bar' => 'one two', - ); - $tests['Folded block chomping strip with multiple trailing newlines'] = array($expected, $yaml); + ]; + $tests['Folded block chomping strip with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: >- @@ -340,11 +337,11 @@ public function getBlockChompingTests() one two EOF; - $expected = array( + $expected = [ 'foo' => 'one two', 'bar' => 'one two', - ); - $tests['Folded block chomping strip without trailing newline'] = array($expected, $yaml); + ]; + $tests['Folded block chomping strip without trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: > @@ -355,11 +352,11 @@ public function getBlockChompingTests() two EOF; - $expected = array( + $expected = [ 'foo' => "one two\n", 'bar' => "one two\n", - ); - $tests['Folded block chomping clip with single trailing newline'] = array($expected, $yaml); + ]; + $tests['Folded block chomping clip with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: > @@ -372,11 +369,11 @@ public function getBlockChompingTests() EOF; - $expected = array( + $expected = [ 'foo' => "one two\n", 'bar' => "one two\n", - ); - $tests['Folded block chomping clip with multiple trailing newlines'] = array($expected, $yaml); + ]; + $tests['Folded block chomping clip with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: > @@ -386,11 +383,11 @@ public function getBlockChompingTests() one two EOF; - $expected = array( + $expected = [ 'foo' => "one two\n", 'bar' => 'one two', - ); - $tests['Folded block chomping clip without trailing newline'] = array($expected, $yaml); + ]; + $tests['Folded block chomping clip without trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: >+ @@ -401,11 +398,11 @@ public function getBlockChompingTests() two EOF; - $expected = array( + $expected = [ 'foo' => "one two\n", 'bar' => "one two\n", - ); - $tests['Folded block chomping keep with single trailing newline'] = array($expected, $yaml); + ]; + $tests['Folded block chomping keep with single trailing newline'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: >+ @@ -418,11 +415,11 @@ public function getBlockChompingTests() EOF; - $expected = array( + $expected = [ 'foo' => "one two\n\n", 'bar' => "one two\n\n", - ); - $tests['Folded block chomping keep with multiple trailing newlines'] = array($expected, $yaml); + ]; + $tests['Folded block chomping keep with multiple trailing newlines'] = [$expected, $yaml]; $yaml = <<<'EOF' foo: >+ @@ -432,11 +429,11 @@ public function getBlockChompingTests() one two EOF; - $expected = array( + $expected = [ 'foo' => "one two\n", 'bar' => 'one two', - ); - $tests['Folded block chomping keep without trailing newline'] = array($expected, $yaml); + ]; + $tests['Folded block chomping keep without trailing newline'] = [$expected, $yaml]; return $tests; } @@ -463,9 +460,9 @@ public function testBlockLiteralWithLeadingNewlines() bar EOF; - $expected = array( + $expected = [ 'foo' => "\n\nbar", - ); + ]; $this->assertSame($expected, $this->parser->parse($yaml)); } @@ -476,7 +473,7 @@ public function testObjectSupportEnabled() foo: !php/object O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";} bar: 1 EOF; - $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); + $this->assertEquals(['foo' => new B(), 'bar' => 1], $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); } /** @@ -488,7 +485,7 @@ public function testObjectSupportEnabledPassingTrue() foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";} bar: 1 EOF; - $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, false, true), '->parse() is able to parse objects'); + $this->assertEquals(['foo' => new B(), 'bar' => 1], $this->parser->parse($input, false, true), '->parse() is able to parse objects'); } /** @@ -497,25 +494,25 @@ public function testObjectSupportEnabledPassingTrue() */ public function testObjectSupportEnabledWithDeprecatedTag($yaml) { - $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($yaml, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); + $this->assertEquals(['foo' => new B(), 'bar' => 1], $this->parser->parse($yaml, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); } public function deprecatedObjectValueProvider() { - return array( - array( + return [ + [ <<<YAML foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";} bar: 1 YAML - ), - array( + ], + [ <<<YAML foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";} bar: 1 YAML - ), - ); + ], + ]; } /** @@ -523,7 +520,7 @@ public function deprecatedObjectValueProvider() */ public function testObjectSupportDisabledButNoExceptions($input) { - $this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects'); + $this->assertEquals(['foo' => null, 'bar' => 1], $this->parser->parse($input), '->parse() does not parse objects'); } /** @@ -547,7 +544,7 @@ public function testObjectForMapEnabledWithMappingUsingBooleanToggles($yaml, $ex public function getObjectForMapTests() { - $tests = array(); + $tests = []; $yaml = <<<'EOF' foo: @@ -555,20 +552,20 @@ public function getObjectForMapTests() EOF; $expected = new \stdClass(); $expected->foo = new \stdClass(); - $expected->foo->fiz = array('cat'); - $tests['mapping'] = array($yaml, $expected); + $expected->foo->fiz = ['cat']; + $tests['mapping'] = [$yaml, $expected]; $yaml = '{ "foo": "bar", "fiz": "cat" }'; $expected = new \stdClass(); $expected->foo = 'bar'; $expected->fiz = 'cat'; - $tests['inline-mapping'] = array($yaml, $expected); + $tests['inline-mapping'] = [$yaml, $expected]; $yaml = "foo: bar\nbaz: foobar"; $expected = new \stdClass(); $expected->foo = 'bar'; $expected->baz = 'foobar'; - $tests['object-for-map-is-applied-after-parsing'] = array($yaml, $expected); + $tests['object-for-map-is-applied-after-parsing'] = [$yaml, $expected]; $yaml = <<<'EOT' array: @@ -576,12 +573,12 @@ public function getObjectForMapTests() - key: two EOT; $expected = new \stdClass(); - $expected->array = array(); + $expected->array = []; $expected->array[0] = new \stdClass(); $expected->array[0]->key = 'one'; $expected->array[1] = new \stdClass(); $expected->array[1]->key = 'two'; - $tests['nest-map-and-sequence'] = array($yaml, $expected); + $tests['nest-map-and-sequence'] = [$yaml, $expected]; $yaml = <<<'YAML' map: @@ -592,7 +589,7 @@ public function getObjectForMapTests() $expected->map = new \stdClass(); $expected->map->{1} = 'one'; $expected->map->{2} = 'two'; - $tests['numeric-keys'] = array($yaml, $expected); + $tests['numeric-keys'] = [$yaml, $expected]; $yaml = <<<'YAML' map: @@ -603,17 +600,17 @@ public function getObjectForMapTests() $expected->map = new \stdClass(); $expected->map->{0} = 'one'; $expected->map->{1} = 'two'; - $tests['zero-indexed-numeric-keys'] = array($yaml, $expected); + $tests['zero-indexed-numeric-keys'] = [$yaml, $expected]; return $tests; } /** * @dataProvider invalidDumpedObjectProvider - * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testObjectsSupportDisabledWithExceptions($yaml) { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); $this->parser->parse($yaml, Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); } @@ -621,9 +618,9 @@ public function testCanParseContentWithTrailingSpaces() { $yaml = "items: \n foo: bar"; - $expected = array( - 'items' => array('foo' => 'bar'), - ); + $expected = [ + 'items' => ['foo' => 'bar'], + ]; $this->assertSame($expected, $this->parser->parse($yaml)); } @@ -631,10 +628,10 @@ public function testCanParseContentWithTrailingSpaces() /** * @group legacy * @dataProvider invalidDumpedObjectProvider - * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testObjectsSupportDisabledWithExceptionsUsingBooleanToggles($yaml) { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); $this->parser->parse($yaml, true); } @@ -649,10 +646,10 @@ public function invalidDumpedObjectProvider() bar: 1 EOF; - return array( - 'yaml-tag' => array($yamlTag), - 'local-tag' => array($localTag), - ); + return [ + 'yaml-tag' => [$yamlTag], + 'local-tag' => [$localTag], + ]; } /** @@ -660,11 +657,11 @@ public function invalidDumpedObjectProvider() */ public function testNonUtf8Exception() { - $yamls = array( + $yamls = [ iconv('UTF-8', 'ISO-8859-1', "foo: 'äöüß'"), iconv('UTF-8', 'ISO-8859-15', "euro: '€'"), iconv('UTF-8', 'CP1252', "cp1252: '©ÉÇáñ'"), - ); + ]; foreach ($yamls as $yaml) { try { @@ -677,11 +674,9 @@ public function testNonUtf8Exception() } } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ public function testUnindentedCollectionException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); $yaml = <<<'EOF' collection: @@ -694,11 +689,9 @@ public function testUnindentedCollectionException() $this->parser->parse($yaml); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ public function testShortcutKeyUnindentedCollectionException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); $yaml = <<<'EOF' collection: @@ -710,12 +703,10 @@ public function testShortcutKeyUnindentedCollectionException() $this->parser->parse($yaml); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessageRegExp /^Multiple documents are not supported.+/ - */ public function testMultipleDocumentsNotSupportedException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessageMatches('/^Multiple documents are not supported.+/'); Yaml::parse(<<<'EOL' # Ranking of 1998 home runs --- @@ -731,11 +722,9 @@ public function testMultipleDocumentsNotSupportedException() ); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ public function testSequenceInAMapping() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); Yaml::parse(<<<'EOF' yaml: hash: me @@ -755,19 +744,19 @@ public function testSequenceInMappingStartedBySingleDashLine() - foo d: e EOT; - $expected = array( - 'a' => array( - array( - 'b' => array( - array( + $expected = [ + 'a' => [ + [ + 'b' => [ + [ 'bar' => 'baz', - ), - ), - ), + ], + ], + ], 'foo', - ), + ], 'd' => 'e', - ); + ]; $this->assertSame($expected, $this->parser->parse($yaml)); } @@ -781,12 +770,12 @@ public function testSequenceFollowedByCommentEmbeddedInMapping() # comment d: e EOT; - $expected = array( - 'a' => array( - 'b' => array('c'), + $expected = [ + 'a' => [ + 'b' => ['c'], 'd' => 'e', - ), - ); + ], + ]; $this->assertSame($expected, $this->parser->parse($yaml)); } @@ -802,25 +791,25 @@ public function testNonStringFollowedByCommentEmbeddedInMapping() 1.1 # another comment EOT; - $expected = array( - 'a' => array( - 'b' => array(), + $expected = [ + 'a' => [ + 'b' => [], 'd' => 1.1, - ), - ); + ], + ]; $this->assertSame($expected, $this->parser->parse($yaml)); } public function getParseExceptionNotAffectedMultiLineStringLastResortParsing() { - $tests = array(); + $tests = []; $yaml = <<<'EOT' a b: EOT; - $tests['parse error on first line'] = array($yaml); + $tests['parse error on first line'] = [$yaml]; $yaml = <<<'EOT' a @@ -828,22 +817,22 @@ public function getParseExceptionNotAffectedMultiLineStringLastResortParsing() b c: EOT; - $tests['parse error due to inconsistent indentation'] = array($yaml); + $tests['parse error due to inconsistent indentation'] = [$yaml]; $yaml = <<<'EOT' & * ! | > ' " % @ ` #, { asd a;sdasd }-@^qw3 EOT; - $tests['symfony/symfony/issues/22967#issuecomment-322067742'] = array($yaml); + $tests['symfony/symfony/issues/22967#issuecomment-322067742'] = [$yaml]; return $tests; } /** * @dataProvider getParseExceptionNotAffectedMultiLineStringLastResortParsing - * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testParseExceptionNotAffectedByMultiLineStringLastResortParsing($yaml) { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); $this->parser->parse($yaml); } @@ -855,9 +844,9 @@ public function testMultiLineStringLastResortParsing() true yes you can EOT; - $expected = array( + $expected = [ 'test' => 'You can have things that don\'t look like strings here true yes you can', - ); + ]; $this->assertSame($expected, $this->parser->parse($yaml)); @@ -866,18 +855,16 @@ public function testMultiLineStringLastResortParsing() b c EOT; - $expected = array( + $expected = [ 'a' => 'b c', - ); + ]; $this->assertSame($expected, $this->parser->parse($yaml)); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ public function testMappingInASequence() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); Yaml::parse(<<<'EOF' yaml: - array stuff @@ -886,12 +873,10 @@ public function testMappingInASequence() ); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage missing colon - */ public function testScalarInSequence() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('missing colon'); Yaml::parse(<<<'EOF' foo: - bar @@ -922,11 +907,11 @@ public function testMappingDuplicateKeyBlock() child: duplicate child: duplicate EOD; - $expected = array( - 'parent' => array( + $expected = [ + 'parent' => [ 'child' => 'first', - ), - ); + ], + ]; $this->assertSame($expected, Yaml::parse($input)); } @@ -939,11 +924,11 @@ public function testMappingDuplicateKeyFlow() parent: { child: first, child: duplicate } parent: { child: duplicate, child: duplicate } EOD; - $expected = array( - 'parent' => array( + $expected = [ + 'parent' => [ 'child' => 'first', - ), - ); + ], + ]; $this->assertSame($expected, Yaml::parse($input)); } @@ -960,30 +945,30 @@ public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber public function getParseExceptionOnDuplicateData() { - $tests = array(); + $tests = []; $yaml = <<<EOD parent: { child: first, child: duplicate } EOD; - $tests[] = array($yaml, 'child', 1); + $tests[] = [$yaml, 'child', 1]; $yaml = <<<EOD parent: child: first, child: duplicate EOD; - $tests[] = array($yaml, 'child', 3); + $tests[] = [$yaml, 'child', 3]; $yaml = <<<EOD parent: { child: foo } parent: { child: bar } EOD; - $tests[] = array($yaml, 'parent', 2); + $tests[] = [$yaml, 'parent', 2]; $yaml = <<<EOD parent: { child_mapping: { value: bar}, child_mapping: { value: bar} } EOD; - $tests[] = array($yaml, 'child_mapping', 1); + $tests[] = [$yaml, 'child_mapping', 1]; $yaml = <<<EOD parent: @@ -992,12 +977,12 @@ public function getParseExceptionOnDuplicateData() child_mapping: value: bar EOD; - $tests[] = array($yaml, 'child_mapping', 4); + $tests[] = [$yaml, 'child_mapping', 4]; $yaml = <<<EOD parent: { child_sequence: ['key1', 'key2', 'key3'], child_sequence: ['key1', 'key2', 'key3'] } EOD; - $tests[] = array($yaml, 'child_sequence', 1); + $tests[] = [$yaml, 'child_sequence', 1]; $yaml = <<<EOD parent: @@ -1010,7 +995,7 @@ public function getParseExceptionOnDuplicateData() - key2 - key3 EOD; - $tests[] = array($yaml, 'child_sequence', 6); + $tests[] = [$yaml, 'child_sequence', 6]; return $tests; } @@ -1021,21 +1006,21 @@ public function testEmptyValue() hash: EOF; - $this->assertEquals(array('hash' => null), Yaml::parse($input)); + $this->assertEquals(['hash' => null], Yaml::parse($input)); } public function testCommentAtTheRootIndent() { - $this->assertEquals(array( - 'services' => array( - 'app.foo_service' => array( + $this->assertEquals([ + 'services' => [ + 'app.foo_service' => [ 'class' => 'Foo', - ), - 'app/bar_service' => array( + ], + 'app/bar_service' => [ 'class' => 'Bar', - ), - ), - ), Yaml::parse(<<<'EOF' + ], + ], + ], Yaml::parse(<<<'EOF' # comment 1 services: # comment 2 @@ -1052,7 +1037,7 @@ class: Bar public function testStringBlockWithComments() { - $this->assertEquals(array('content' => <<<'EOT' + $this->assertEquals(['content' => <<<'EOT' # comment 1 header @@ -1063,7 +1048,7 @@ public function testStringBlockWithComments() footer # comment3 EOT - ), Yaml::parse(<<<'EOF' + ], Yaml::parse(<<<'EOF' content: | # comment 1 header @@ -1080,7 +1065,7 @@ public function testStringBlockWithComments() public function testFoldedStringBlockWithComments() { - $this->assertEquals(array(array('content' => <<<'EOT' + $this->assertEquals([['content' => <<<'EOT' # comment 1 header @@ -1091,7 +1076,7 @@ public function testFoldedStringBlockWithComments() footer # comment3 EOT - )), Yaml::parse(<<<'EOF' + ]], Yaml::parse(<<<'EOF' - content: | # comment 1 @@ -1109,7 +1094,7 @@ public function testFoldedStringBlockWithComments() public function testNestedFoldedStringBlockWithComments() { - $this->assertEquals(array(array( + $this->assertEquals([[ 'title' => 'some title', 'content' => <<<'EOT' # comment 1 @@ -1122,7 +1107,7 @@ public function testNestedFoldedStringBlockWithComments() footer # comment3 EOT - )), Yaml::parse(<<<'EOF' + ]], Yaml::parse(<<<'EOF' - title: some title content: | @@ -1141,17 +1126,17 @@ public function testNestedFoldedStringBlockWithComments() public function testReferenceResolvingInInlineStrings() { - $this->assertEquals(array( + $this->assertEquals([ 'var' => 'var-value', 'scalar' => 'var-value', - 'list' => array('var-value'), - 'list_in_list' => array(array('var-value')), - 'map_in_list' => array(array('key' => 'var-value')), - 'embedded_mapping' => array(array('key' => 'var-value')), - 'map' => array('key' => 'var-value'), - 'list_in_map' => array('key' => array('var-value')), - 'map_in_map' => array('foo' => array('bar' => 'var-value')), - ), Yaml::parse(<<<'EOF' + 'list' => ['var-value'], + 'list_in_list' => [['var-value']], + 'map_in_list' => [['key' => 'var-value']], + 'embedded_mapping' => [['key' => 'var-value']], + 'map' => ['key' => 'var-value'], + 'list_in_map' => ['key' => ['var-value']], + 'map_in_map' => ['foo' => ['bar' => 'var-value']], + ], Yaml::parse(<<<'EOF' var: &var var-value scalar: *var list: [ *var ] @@ -1173,7 +1158,7 @@ public function testYamlDirective() foo: 1 bar: 2 EOF; - $this->assertEquals(array('foo' => 1, 'bar' => 2), $this->parser->parse($yaml)); + $this->assertEquals(['foo' => 1, 'bar' => 2], $this->parser->parse($yaml)); } /** @@ -1188,12 +1173,12 @@ public function testFloatKeys() 1.3: "baz" EOF; - $expected = array( - 'foo' => array( + $expected = [ + 'foo' => [ '1.2' => 'bar', '1.3' => 'baz', - ), - ); + ], + ]; $this->assertEquals($expected, $this->parser->parse($yaml)); } @@ -1209,10 +1194,10 @@ public function testBooleanKeys() false: bar EOF; - $expected = array( + $expected = [ 1 => 'foo', 0 => 'bar', - ); + ]; $this->assertEquals($expected, $this->parser->parse($yaml)); } @@ -1230,24 +1215,22 @@ public function testExplicitStringCasting() '~': 'null' EOF; - $expected = array( + $expected = [ '1.2' => 'bar', '1.3' => 'baz', 'true' => 'foo', 'false' => 'bar', 'null' => 'null', '~' => 'null', - ); + ]; $this->assertEquals($expected, $this->parser->parse($yaml)); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage A colon cannot be used in an unquoted mapping value - */ public function testColonInMappingValueException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('A colon cannot be used in an unquoted mapping value'); $yaml = <<<'EOF' foo: bar: baz EOF; @@ -1262,7 +1245,7 @@ public function testColonInMappingValueExceptionNotTriggeredByColonInComment() bar: foobar # Note: a comment after a colon EOT; - $this->assertSame(array('foo' => array('bar' => 'foobar')), $this->parser->parse($yaml)); + $this->assertSame(['foo' => ['bar' => 'foobar']], $this->parser->parse($yaml)); } /** @@ -1275,7 +1258,7 @@ public function testCommentLikeStringsAreNotStrippedInBlockScalars($yaml, $expec public function getCommentLikeStringInScalarBlockData() { - $tests = array(); + $tests = []; $yaml = <<<'EOT' pages: @@ -1292,9 +1275,9 @@ public function getCommentLikeStringInScalarBlockData() footer # comment3 EOT; - $expected = array( - 'pages' => array( - array( + $expected = [ + 'pages' => [ + [ 'title' => 'some title', 'content' => <<<'EOT' # comment 1 @@ -1308,10 +1291,10 @@ public function getCommentLikeStringInScalarBlockData() footer # comment3 EOT , - ), - ), - ); - $tests[] = array($yaml, $expected); + ], + ], + ]; + $tests[] = [$yaml, $expected]; $yaml = <<<'EOT' test: | @@ -1328,7 +1311,7 @@ public function getCommentLikeStringInScalarBlockData() # bar baz EOT; - $expected = array( + $expected = [ 'test' => <<<'EOT' foo # bar @@ -1336,8 +1319,8 @@ public function getCommentLikeStringInScalarBlockData() EOT , - 'collection' => array( - array( + 'collection' => [ + [ 'one' => <<<'EOT' foo # bar @@ -1345,18 +1328,18 @@ public function getCommentLikeStringInScalarBlockData() EOT , - ), - array( + ], + [ 'two' => <<<'EOT' foo # bar baz EOT , - ), - ), - ); - $tests[] = array($yaml, $expected); + ], + ], + ]; + $tests[] = [$yaml, $expected]; $yaml = <<<'EOT' foo: @@ -1368,17 +1351,17 @@ public function getCommentLikeStringInScalarBlockData() # comment foobar: ~ EOT; - $expected = array( - 'foo' => array( - 'bar' => array( + $expected = [ + 'foo' => [ + 'bar' => [ 'scalar-block' => "line1 line2>\n", - ), - 'baz' => array( + ], + 'baz' => [ 'foobar' => null, - ), - ), - ); - $tests[] = array($yaml, $expected); + ], + ], + ]; + $tests[] = [$yaml, $expected]; $yaml = <<<'EOT' a: @@ -1388,13 +1371,13 @@ public function getCommentLikeStringInScalarBlockData() # second row d: hello EOT; - $expected = array( - 'a' => array( + $expected = [ + 'a' => [ 'b' => 'hello', 'd' => 'hello', - ), - ); - $tests[] = array($yaml, $expected); + ], + ]; + $tests[] = [$yaml, $expected]; return $tests; } @@ -1412,13 +1395,13 @@ public function testBlankLinesAreParsedAsNewLinesInFoldedBlocks() EOT; $this->assertSame( - array( + [ 'test' => <<<'EOT' <h2>A heading</h2> <ul> <li>a list</li> <li>may be a good example</li> </ul> EOT , - ), + ], $this->parser->parse($yaml) ); } @@ -1436,7 +1419,7 @@ public function testAdditionallyIndentedLinesAreParsedAsNewLinesInFoldedBlocks() EOT; $this->assertSame( - array( + [ 'test' => <<<'EOT' <h2>A heading</h2> <ul> @@ -1445,7 +1428,7 @@ public function testAdditionallyIndentedLinesAreParsedAsNewLinesInFoldedBlocks() </ul> EOT , - ), + ], $this->parser->parse($yaml) ); } @@ -1455,85 +1438,81 @@ public function testAdditionallyIndentedLinesAreParsedAsNewLinesInFoldedBlocks() */ public function testParseBinaryData($data) { - $this->assertSame(array('data' => 'Hello world'), $this->parser->parse($data)); + $this->assertSame(['data' => 'Hello world'], $this->parser->parse($data)); } public function getBinaryData() { - return array( - 'enclosed with double quotes' => array('data: !!binary "SGVsbG8gd29ybGQ="'), - 'enclosed with single quotes' => array("data: !!binary 'SGVsbG8gd29ybGQ='"), - 'containing spaces' => array('data: !!binary "SGVs bG8gd 29ybGQ="'), - 'in block scalar' => array( + return [ + 'enclosed with double quotes' => ['data: !!binary "SGVsbG8gd29ybGQ="'], + 'enclosed with single quotes' => ["data: !!binary 'SGVsbG8gd29ybGQ='"], + 'containing spaces' => ['data: !!binary "SGVs bG8gd 29ybGQ="'], + 'in block scalar' => [ <<<'EOT' data: !!binary | SGVsbG8gd29ybGQ= EOT - ), - 'containing spaces in block scalar' => array( + ], + 'containing spaces in block scalar' => [ <<<'EOT' data: !!binary | SGVs bG8gd 29ybGQ= EOT - ), - ); + ], + ]; } /** * @dataProvider getInvalidBinaryData - * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ public function testParseInvalidBinaryData($data, $expectedMessage) { - if (method_exists($this, 'expectException')) { - $this->expectExceptionMessageRegExp($expectedMessage); - } else { - $this->setExpectedExceptionRegExp(ParseException::class, $expectedMessage); - } + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessageMatches($expectedMessage); $this->parser->parse($data); } public function getInvalidBinaryData() { - return array( - 'length not a multiple of four' => array('data: !!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'), - 'invalid characters' => array('!!binary "SGVsbG8#d29ybGQ="', '/The base64 encoded data \(.*\) contains invalid characters/'), - 'too many equals characters' => array('data: !!binary "SGVsbG8gd29yb==="', '/The base64 encoded data \(.*\) contains invalid characters/'), - 'misplaced equals character' => array('data: !!binary "SGVsbG8gd29ybG=Q"', '/The base64 encoded data \(.*\) contains invalid characters/'), - 'length not a multiple of four in block scalar' => array( + return [ + 'length not a multiple of four' => ['data: !!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'], + 'invalid characters' => ['!!binary "SGVsbG8#d29ybGQ="', '/The base64 encoded data \(.*\) contains invalid characters/'], + 'too many equals characters' => ['data: !!binary "SGVsbG8gd29yb==="', '/The base64 encoded data \(.*\) contains invalid characters/'], + 'misplaced equals character' => ['data: !!binary "SGVsbG8gd29ybG=Q"', '/The base64 encoded data \(.*\) contains invalid characters/'], + 'length not a multiple of four in block scalar' => [ <<<'EOT' data: !!binary | SGVsbG8d29ybGQ= EOT , '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/', - ), - 'invalid characters in block scalar' => array( + ], + 'invalid characters in block scalar' => [ <<<'EOT' data: !!binary | SGVsbG8#d29ybGQ= EOT , '/The base64 encoded data \(.*\) contains invalid characters/', - ), - 'too many equals characters in block scalar' => array( + ], + 'too many equals characters in block scalar' => [ <<<'EOT' data: !!binary | SGVsbG8gd29yb=== EOT , '/The base64 encoded data \(.*\) contains invalid characters/', - ), - 'misplaced equals character in block scalar' => array( + ], + 'misplaced equals character in block scalar' => [ <<<'EOT' data: !!binary | SGVsbG8gd29ybG=Q EOT , '/The base64 encoded data \(.*\) contains invalid characters/', - ), - ); + ], + ]; } public function testParseDateAsMappingValue() @@ -1546,7 +1525,7 @@ public function testParseDateAsMappingValue() $expectedDate->setDate(2002, 12, 14); $expectedDate->setTime(0, 0, 0); - $this->assertEquals(array('date' => $expectedDate), $this->parser->parse($yaml, Yaml::PARSE_DATETIME)); + $this->assertEquals(['date' => $expectedDate], $this->parser->parse($yaml, Yaml::PARSE_DATETIME)); } /** @@ -1556,20 +1535,16 @@ public function testParseDateAsMappingValue() */ public function testParserThrowsExceptionWithCorrectLineNumber($lineNumber, $yaml) { - if (method_exists($this, 'expectException')) { - $this->expectException('\Symfony\Component\Yaml\Exception\ParseException'); - $this->expectExceptionMessage(sprintf('Unexpected characters near "," at line %d (near "bar: "123",").', $lineNumber)); - } else { - $this->setExpectedException('\Symfony\Component\Yaml\Exception\ParseException', sprintf('Unexpected characters near "," at line %d (near "bar: "123",").', $lineNumber)); - } + $this->expectException('\Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage(sprintf('Unexpected characters near "," at line %d (near "bar: "123",").', $lineNumber)); $this->parser->parse($yaml); } public function parserThrowsExceptionWithCorrectLineNumberProvider() { - return array( - array( + return [ + [ 4, <<<'YAML' foo: @@ -1577,8 +1552,8 @@ public function parserThrowsExceptionWithCorrectLineNumberProvider() # bar bar: "123", YAML - ), - array( + ], + [ 5, <<<'YAML' foo: @@ -1587,8 +1562,8 @@ public function parserThrowsExceptionWithCorrectLineNumberProvider() # bar bar: "123", YAML - ), - array( + ], + [ 8, <<<'YAML' foo: @@ -1600,8 +1575,8 @@ public function parserThrowsExceptionWithCorrectLineNumberProvider() # bar bar: "123", YAML - ), - array( + ], + [ 10, <<<'YAML' foo: @@ -1615,8 +1590,8 @@ public function parserThrowsExceptionWithCorrectLineNumberProvider() # bar bar: "123", YAML - ), - ); + ], + ]; } public function testParseMultiLineQuotedString() @@ -1629,7 +1604,7 @@ public function testParseMultiLineQuotedString() bar: baz EOT; - $this->assertSame(array('foo' => 'bar baz foobar foo', 'bar' => 'baz'), $this->parser->parse($yaml)); + $this->assertSame(['foo' => 'bar baz foobar foo', 'bar' => 'baz'], $this->parser->parse($yaml)); } public function testMultiLineQuotedStringWithTrailingBackslash() @@ -1640,7 +1615,7 @@ public function testMultiLineQuotedStringWithTrailingBackslash() bar" YAML; - $this->assertSame(array('foobar' => 'foobar'), $this->parser->parse($yaml)); + $this->assertSame(['foobar' => 'foobar'], $this->parser->parse($yaml)); } public function testCommentCharactersInMultiLineQuotedStrings() @@ -1651,12 +1626,12 @@ public function testCommentCharactersInMultiLineQuotedStrings() #bar' bar: baz YAML; - $expected = array( - 'foo' => array( + $expected = [ + 'foo' => [ 'foobar' => 'foo #bar', 'bar' => 'baz', - ), - ); + ], + ]; $this->assertSame($expected, $this->parser->parse($yaml)); } @@ -1668,9 +1643,36 @@ public function testBlankLinesInQuotedMultiLineString() bar' YAML; - $expected = array( + $expected = [ 'foobar' => "foo\nbar", - ); + ]; + + $this->assertSame($expected, $this->parser->parse($yaml)); + } + + public function testEscapedQuoteInQuotedMultiLineString() + { + $yaml = <<<YAML +foobar: "foo + \\"bar\\" + baz" +YAML; + $expected = [ + 'foobar' => 'foo "bar" baz', + ]; + + $this->assertSame($expected, $this->parser->parse($yaml)); + } + + public function testBackslashInQuotedMultiLineString() + { + $yaml = <<<YAML +foobar: "foo + bar\\\\" +YAML; + $expected = [ + 'foobar' => 'foo bar\\', + ]; $this->assertSame($expected, $this->parser->parse($yaml)); } @@ -1685,7 +1687,7 @@ public function testParseMultiLineUnquotedString() bar: baz EOT; - $this->assertSame(array('foo' => 'bar baz foobar foo', 'bar' => 'baz'), $this->parser->parse($yaml)); + $this->assertSame(['foo' => 'bar baz foobar foo', 'bar' => 'baz'], $this->parser->parse($yaml)); } public function testParseMultiLineString() @@ -1703,7 +1705,7 @@ public function testParseMultiLineMappingValue($yaml, $expected, $parseError) public function multiLineDataProvider() { - $tests = array(); + $tests = []; $yaml = <<<'EOF' foo: @@ -1713,15 +1715,15 @@ public function multiLineDataProvider() two three EOF; - $expected = array( - 'foo' => array( - array( + $expected = [ + 'foo' => [ + [ 'bar' => "one\ntwo three", - ), - ), - ); + ], + ], + ]; - $tests[] = array($yaml, $expected, false); + $tests[] = [$yaml, $expected, false]; $yaml = <<<'EOF' bar @@ -1729,7 +1731,7 @@ public function multiLineDataProvider() EOF; $expected = 'bar "foo"'; - $tests[] = array($yaml, $expected, false); + $tests[] = [$yaml, $expected, false]; $yaml = <<<'EOF' bar @@ -1737,7 +1739,7 @@ public function multiLineDataProvider() EOF; $expected = 'bar "foo'; - $tests[] = array($yaml, $expected, false); + $tests[] = [$yaml, $expected, false]; $yaml = <<<'EOF' bar @@ -1746,7 +1748,7 @@ public function multiLineDataProvider() EOF; $expected = "bar\n'foo'"; - $tests[] = array($yaml, $expected, false); + $tests[] = [$yaml, $expected, false]; $yaml = <<<'EOF' bar @@ -1755,14 +1757,14 @@ public function multiLineDataProvider() EOF; $expected = "bar\nfoo'"; - $tests[] = array($yaml, $expected, false); + $tests[] = [$yaml, $expected, false]; return $tests; } public function testTaggedInlineMapping() { - $this->assertEquals(new TaggedValue('foo', array('foo' => 'bar')), $this->parser->parse('!foo {foo: bar}', Yaml::PARSE_CUSTOM_TAGS)); + $this->assertEquals(new TaggedValue('foo', ['foo' => 'bar']), $this->parser->parse('!foo {foo: bar}', Yaml::PARSE_CUSTOM_TAGS)); } /** @@ -1775,40 +1777,38 @@ public function testCustomTagSupport($expected, $yaml) public function taggedValuesProvider() { - return array( - 'sequences' => array( - array(new TaggedValue('foo', array('yaml')), new TaggedValue('quz', array('bar'))), + return [ + 'sequences' => [ + [new TaggedValue('foo', ['yaml']), new TaggedValue('quz', ['bar'])], <<<YAML - !foo - yaml - !quz [bar] YAML - ), - 'mappings' => array( - new TaggedValue('foo', array('foo' => new TaggedValue('quz', array('bar')), 'quz' => new TaggedValue('foo', array('quz' => 'bar')))), + ], + 'mappings' => [ + new TaggedValue('foo', ['foo' => new TaggedValue('quz', ['bar']), 'quz' => new TaggedValue('foo', ['quz' => 'bar'])]), <<<YAML !foo foo: !quz [bar] quz: !foo quz: bar YAML - ), - 'inline' => array( - array(new TaggedValue('foo', array('foo', 'bar')), new TaggedValue('quz', array('foo' => 'bar', 'quz' => new TaggedValue('bar', array('one' => 'bar'))))), + ], + 'inline' => [ + [new TaggedValue('foo', ['foo', 'bar']), new TaggedValue('quz', ['foo' => 'bar', 'quz' => new TaggedValue('bar', ['one' => 'bar'])])], <<<YAML - !foo [foo, bar] - !quz {foo: bar, quz: !bar {one: bar}} YAML - ), - ); + ], + ]; } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator [foo]"). - */ public function testCustomTagsDisabled() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator [foo]").'); $this->parser->parse('!iterator [foo]'); } @@ -1821,12 +1821,10 @@ public function testUnsupportedTagWithScalar() $this->assertEquals('!iterator foo', $this->parser->parse('!iterator foo')); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage The built-in tag "!!foo" is not implemented at line 1 (near "!!foo"). - */ - public function testExceptionWhenUsingUnsuportedBuiltInTags() + public function testExceptionWhenUsingUnsupportedBuiltInTags() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('The built-in tag "!!foo" is not implemented at line 1 (near "!!foo").'); $this->parser->parse('!!foo'); } @@ -1876,12 +1874,10 @@ public function testComplexMappingNestedInSequenceThrowsParseException() $this->parser->parse($yaml); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage Unable to parse at line 1 (near "[parameters]"). - */ public function testParsingIniThrowsException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('Unable to parse at line 1 (near "[parameters]").'); $ini = <<<INI [parameters] foo = bar @@ -1895,7 +1891,7 @@ private function loadTestsFromFixtureFiles($testsFile) { $parser = new Parser(); - $tests = array(); + $tests = []; $files = $parser->parseFile(__DIR__.'/Fixtures/'.$testsFile); foreach ($files as $file) { $yamls = file_get_contents(__DIR__.'/Fixtures/'.$file.'.yml'); @@ -1912,7 +1908,7 @@ private function loadTestsFromFixtureFiles($testsFile) } else { eval('$expected = '.trim($test['php']).';'); - $tests[] = array(var_export($expected, true), $test['yaml'], $test['test'], isset($test['deprecated']) ? $test['deprecated'] : false); + $tests[] = [var_export($expected, true), $test['yaml'], $test['test'], isset($test['deprecated']) ? $test['deprecated'] : false]; } } } @@ -1923,7 +1919,7 @@ private function loadTestsFromFixtureFiles($testsFile) public function testCanParseVeryLongValue() { $longStringWithSpaces = str_repeat('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ', 20000); - $trickyVal = array('x' => $longStringWithSpaces); + $trickyVal = ['x' => $longStringWithSpaces]; $yamlString = Yaml::dump($trickyVal); $arrayFromYaml = $this->parser->parse($yamlString); @@ -1931,12 +1927,10 @@ public function testCanParseVeryLongValue() $this->assertEquals($trickyVal, $arrayFromYaml); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage Reference "foo" does not exist at line 2 - */ public function testParserCleansUpReferencesBetweenRuns() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('Reference "foo" does not exist at line 2'); $yaml = <<<YAML foo: &foo baz: foobar @@ -1961,16 +1955,16 @@ public function testPhpConstantTagMappingKey() - !php/const 'Symfony\Component\Yaml\Tests\B::BAR' to: !php/const 'Symfony\Component\Yaml\Tests\B::BAZ' YAML; - $expected = array( - 'transitions' => array( - 'foo' => array( - 'from' => array( + $expected = [ + 'transitions' => [ + 'foo' => [ + 'from' => [ 'bar', - ), + ], 'to' => 'baz', - ), - ), - ); + ], + ], + ]; $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT)); } @@ -1990,16 +1984,16 @@ public function testDeprecatedPhpConstantTagMappingKey() - !php/const:Symfony\Component\Yaml\Tests\B::BAR to: !php/const:Symfony\Component\Yaml\Tests\B::BAZ YAML; - $expected = array( - 'transitions' => array( - 'foo' => array( - 'from' => array( + $expected = [ + 'transitions' => [ + 'foo' => [ + 'from' => [ 'bar', - ), + ], 'to' => 'baz', - ), - ), - ); + ], + ], + ]; $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT)); } @@ -2017,20 +2011,48 @@ public function testPhpConstantTagMappingKeyWithKeysCastToStrings() - !php/const 'Symfony\Component\Yaml\Tests\B::BAR' to: !php/const 'Symfony\Component\Yaml\Tests\B::BAZ' YAML; - $expected = array( - 'transitions' => array( - 'foo' => array( - 'from' => array( + $expected = [ + 'transitions' => [ + 'foo' => [ + 'from' => [ 'bar', - ), + ], 'to' => 'baz', - ), - ), - ); + ], + ], + ]; $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT | Yaml::PARSE_KEYS_AS_STRINGS)); } + public function testPhpConstantTagMappingAsScalarKey() + { + $yaml = <<<YAML +map1: + - foo: 'value_0' + !php/const 'Symfony\Component\Yaml\Tests\B::BAR': 'value_1' +map2: + - !php/const 'Symfony\Component\Yaml\Tests\B::FOO': 'value_0' + bar: 'value_1' +YAML; + $this->assertSame([ + 'map1' => [['foo' => 'value_0', 'bar' => 'value_1']], + 'map2' => [['foo' => 'value_0', 'bar' => 'value_1']], + ], $this->parser->parse($yaml, Yaml::PARSE_CONSTANT)); + } + + public function testTagMappingAsScalarKey() + { + $yaml = <<<YAML +map1: + - !!str 0: 'value_0' + !!str 1: 'value_1' +YAML; + $this->assertSame([ + 'map1' => [['0' => 'value_0', '1' => 'value_1']], + ], $this->parser->parse($yaml)); + } + public function testMergeKeysWhenMappingsAreParsedAsObjects() { $yaml = <<<YAML @@ -2047,23 +2069,23 @@ public function testMergeKeysWhenMappingsAreParsedAsObjects() bar: ~ <<: [*FOO, *BAR] YAML; - $expected = (object) array( - 'foo' => (object) array( + $expected = (object) [ + 'foo' => (object) [ 'bar' => 1, - ), - 'bar' => (object) array( + ], + 'bar' => (object) [ 'baz' => 2, 'bar' => 1, - ), - 'baz' => (object) array( + ], + 'baz' => (object) [ 'baz_foo' => 3, 'baz_bar' => 4, - ), - 'foobar' => (object) array( + ], + 'foobar' => (object) [ 'bar' => null, 'baz' => 2, - ), - ); + ], + ]; $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP)); } @@ -2077,28 +2099,28 @@ public function testFilenamesAreParsedAsStringsWithoutFlag() public function testParseFile() { - $this->assertInternalType('array', $this->parser->parseFile(__DIR__.'/Fixtures/index.yml')); + $this->assertIsArray($this->parser->parseFile(__DIR__.'/Fixtures/index.yml')); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessageRegExp #^File ".+/Fixtures/nonexistent.yml" does not exist\.$# - */ public function testParsingNonExistentFilesThrowsException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessageMatches('#^File ".+/Fixtures/nonexistent.yml" does not exist\.$#'); $this->parser->parseFile(__DIR__.'/Fixtures/nonexistent.yml'); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessageRegExp #^File ".+/Fixtures/not_readable.yml" cannot be read\.$# - */ public function testParsingNotReadableFilesThrowsException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessageMatches('#^File ".+/Fixtures/not_readable.yml" cannot be read\.$#'); if ('\\' === \DIRECTORY_SEPARATOR) { $this->markTestSkipped('chmod is not supported on Windows'); } + if (!getenv('USER') || 'root' === getenv('USER')) { + $this->markTestSkipped('This test will fail if run under superuser'); + } + $file = __DIR__.'/Fixtures/not_readable.yml'; chmod($file, 0200); @@ -2117,18 +2139,18 @@ public function testParseReferencesOnMergeKeys() d: quux <<: *quux YAML; - $expected = array( - 'mergekeyrefdef' => array( + $expected = [ + 'mergekeyrefdef' => [ 'a' => 'foo', 'b' => 'bar', 'c' => 'baz', - ), - 'mergekeyderef' => array( + ], + 'mergekeyderef' => [ 'd' => 'quux', 'b' => 'bar', 'c' => 'baz', - ), - ); + ], + ]; $this->assertSame($expected, $this->parser->parse($yaml)); } @@ -2145,34 +2167,74 @@ public function testParseReferencesOnMergeKeysWithMappingsParsedAsObjects() d: quux <<: *quux YAML; - $expected = (object) array( - 'mergekeyrefdef' => (object) array( + $expected = (object) [ + 'mergekeyrefdef' => (object) [ 'a' => 'foo', 'b' => 'bar', 'c' => 'baz', - ), - 'mergekeyderef' => (object) array( + ], + 'mergekeyderef' => (object) [ 'd' => 'quux', 'b' => 'bar', 'c' => 'baz', - ), - ); + ], + ]; $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP)); } - /** - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage Reference "foo" does not exist - */ public function testEvalRefException() { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('Reference "foo" does not exist'); $yaml = <<<EOE foo: { &foo { a: Steve, <<: *foo} } EOE; $this->parser->parse($yaml); } + /** + * @dataProvider circularReferenceProvider + */ + public function testDetectCircularReferences($yaml) + { + $this->expectException('Symfony\Component\Yaml\Exception\ParseException'); + $this->expectExceptionMessage('Circular reference [foo, bar, foo] detected'); + $this->parser->parse($yaml, Yaml::PARSE_CUSTOM_TAGS); + } + + public function circularReferenceProvider() + { + $tests = []; + + $yaml = <<<YAML +foo: + - &foo + - &bar + bar: foobar + baz: *foo +YAML; + $tests['sequence'] = [$yaml]; + + $yaml = <<<YAML +foo: &foo + bar: &bar + foobar: baz + baz: *foo +YAML; + $tests['mapping'] = [$yaml]; + + $yaml = <<<YAML +foo: &foo + bar: &bar + foobar: baz + <<: *foo +YAML; + $tests['mapping with merge key'] = [$yaml]; + + return $tests; + } + /** * @dataProvider indentedMappingData */ @@ -2183,7 +2245,7 @@ public function testParseIndentedMappings($yaml, $expected) public function indentedMappingData() { - $tests = array(); + $tests = []; $yaml = <<<YAML foo: @@ -2191,15 +2253,15 @@ public function indentedMappingData() # A comment baz: "foobaz" YAML; - $expected = array( - 'foo' => array( - array( + $expected = [ + 'foo' => [ + [ 'bar' => 'foobar', 'baz' => 'foobaz', - ), - ), - ); - $tests['comment line is first line in indented block'] = array($yaml, $expected); + ], + ], + ]; + $tests['comment line is first line in indented block'] = [$yaml, $expected]; $yaml = <<<YAML foo: @@ -2207,45 +2269,126 @@ public function indentedMappingData() # comment baz: [1, 2, 3] YAML; - $expected = array( - 'foo' => array( - array( - 'bar' => array( - 'baz' => array(1, 2, 3), - ), - ), - ), - ); - $tests['mapping value on new line starting with a comment line'] = array($yaml, $expected); + $expected = [ + 'foo' => [ + [ + 'bar' => [ + 'baz' => [1, 2, 3], + ], + ], + ], + ]; + $tests['mapping value on new line starting with a comment line'] = [$yaml, $expected]; $yaml = <<<YAML foo: - bar: foobar YAML; - $expected = array( - 'foo' => array( - array( + $expected = [ + 'foo' => [ + [ 'bar' => 'foobar', - ), - ), - ); - $tests['mapping in sequence starting on a new line'] = array($yaml, $expected); + ], + ], + ]; + $tests['mapping in sequence starting on a new line'] = [$yaml, $expected]; $yaml = <<<YAML foo: bar: baz YAML; - $expected = array( - 'foo' => array( + $expected = [ + 'foo' => [ 'bar' => 'baz', - ), - ); - $tests['blank line at the beginning of an indented mapping value'] = array($yaml, $expected); + ], + ]; + $tests['blank line at the beginning of an indented mapping value'] = [$yaml, $expected]; return $tests; } + + public function testMultiLineComment() + { + $yaml = <<<YAML +parameters: + abc + +# Comment +YAML; + + $this->assertSame(['parameters' => 'abc'], $this->parser->parse($yaml)); + } + + public function testParseValueWithModifiers() + { + $yaml = <<<YAML +parameters: + abc: |+5 # plus five spaces indent + one + two + three + four + five +YAML; + $this->assertSame( + [ + 'parameters' => [ + 'abc' => implode("\n", ['one', 'two', 'three', 'four', 'five']), + ], + ], + $this->parser->parse($yaml) + ); + } + + public function testParseValueWithNegativeModifiers() + { + $yaml = <<<YAML +parameters: + abc: |-3 # minus + one + two + three + four + five +YAML; + $this->assertSame( + [ + 'parameters' => [ + 'abc' => implode("\n", ['one', 'two', 'three', 'four', 'five']), + ], + ], + $this->parser->parse($yaml) + ); + } + + /** + * This is a regression test for a bug where a YAML block with a nested multiline string using | was parsed without + * a trailing \n when a shorter YAML document was parsed before. + * + * When a shorter document was parsed before, the nested string did not have a \n at the end of the string, because + * the Parser thought it was the end of the file, even though it is not. + */ + public function testParsingMultipleDocuments() + { + $shortDocument = 'foo: bar'; + $longDocument = <<<YAML +a: + b: | + row + row2 +c: d +YAML; + + // The first parsing set and fixed the totalNumberOfLines in the Parser before, so parsing the short document here + // to reproduce the issue. If the issue would not have been fixed, the next assertion will fail + $this->parser->parse($shortDocument); + + // After the total number of lines has been reset the result will be the same as if a new parser was used + // (before, there was no \n after row2) + $this->assertSame(['a' => ['b' => "row\nrow2\n"], 'c' => 'd'], $this->parser->parse($longDocument)); + } } class B diff --git a/vendor/symfony/yaml/Tests/YamlTest.php b/vendor/symfony/yaml/Tests/YamlTest.php index 3f6c252..7be1266 100644 --- a/vendor/symfony/yaml/Tests/YamlTest.php +++ b/vendor/symfony/yaml/Tests/YamlTest.php @@ -18,27 +18,23 @@ class YamlTest extends TestCase { public function testParseAndDump() { - $data = array('lorem' => 'ipsum', 'dolor' => 'sit'); + $data = ['lorem' => 'ipsum', 'dolor' => 'sit']; $yml = Yaml::dump($data); $parsed = Yaml::parse($yml); $this->assertEquals($data, $parsed); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The indentation must be greater than zero - */ public function testZeroIndentationThrowsException() { - Yaml::dump(array('lorem' => 'ipsum', 'dolor' => 'sit'), 2, 0); + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The indentation must be greater than zero'); + Yaml::dump(['lorem' => 'ipsum', 'dolor' => 'sit'], 2, 0); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The indentation must be greater than zero - */ public function testNegativeIndentationThrowsException() { - Yaml::dump(array('lorem' => 'ipsum', 'dolor' => 'sit'), 2, -4); + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The indentation must be greater than zero'); + Yaml::dump(['lorem' => 'ipsum', 'dolor' => 'sit'], 2, -4); } } diff --git a/vendor/symfony/yaml/Yaml.php b/vendor/symfony/yaml/Yaml.php index 97abd66..8719083 100644 --- a/vendor/symfony/yaml/Yaml.php +++ b/vendor/symfony/yaml/Yaml.php @@ -42,11 +42,10 @@ class Yaml /** * Parses a YAML file into a PHP value. * - * Usage: - * <code> - * $array = Yaml::parseFile('config.yml'); - * print_r($array); - * </code> + * Usage: + * + * $array = Yaml::parseFile('config.yml'); + * print_r($array); * * @param string $filename The path to the YAML file to be parsed * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior @@ -81,7 +80,7 @@ public static function parseFile($filename, $flags = 0) public static function parse($input, $flags = 0) { if (\is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', \E_USER_DEPRECATED); if ($flags) { $flags = self::PARSE_EXCEPTION_ON_INVALID_TYPE; @@ -91,7 +90,7 @@ public static function parse($input, $flags = 0) } if (\func_num_args() >= 3) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the PARSE_OBJECT flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the PARSE_OBJECT flag instead.', \E_USER_DEPRECATED); if (func_get_arg(2)) { $flags |= self::PARSE_OBJECT; @@ -99,7 +98,7 @@ public static function parse($input, $flags = 0) } if (\func_num_args() >= 4) { - @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', \E_USER_DEPRECATED); if (func_get_arg(3)) { $flags |= self::PARSE_OBJECT_FOR_MAP; @@ -127,7 +126,7 @@ public static function parse($input, $flags = 0) public static function dump($input, $inline = 2, $indent = 4, $flags = 0) { if (\is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since Symfony 3.1 and will be removed in 4.0. Use the DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', \E_USER_DEPRECATED); if ($flags) { $flags = self::DUMP_EXCEPTION_ON_INVALID_TYPE; @@ -137,7 +136,7 @@ public static function dump($input, $inline = 2, $indent = 4, $flags = 0) } if (\func_num_args() >= 5) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the DUMP_OBJECT flag instead.', E_USER_DEPRECATED); + @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the DUMP_OBJECT flag instead.', \E_USER_DEPRECATED); if (func_get_arg(4)) { $flags |= self::DUMP_OBJECT; diff --git a/vendor/symfony/yaml/composer.json b/vendor/symfony/yaml/composer.json index 933547d..b2f0286 100644 --- a/vendor/symfony/yaml/composer.json +++ b/vendor/symfony/yaml/composer.json @@ -34,10 +34,5 @@ "/Tests/" ] }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - } + "minimum-stability": "dev" } diff --git a/vendor/symfony/yaml/phpunit.xml.dist b/vendor/symfony/yaml/phpunit.xml.dist index 7c732f8..b5d4d91 100644 --- a/vendor/symfony/yaml/phpunit.xml.dist +++ b/vendor/symfony/yaml/phpunit.xml.dist @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" + xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="vendor/autoload.php" diff --git a/vendor/webmozart/assert/.composer-auth.json b/vendor/webmozart/assert/.composer-auth.json deleted file mode 100644 index eea8001..0000000 --- a/vendor/webmozart/assert/.composer-auth.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "github-oauth": { - "github.com": "PLEASE DO NOT USE THIS TOKEN IN YOUR OWN PROJECTS/FORKS", - "github.com": "This token is reserved for testing the webmozart/* repositories", - "github.com": "a9debbffdd953ee9b3b82dbc3b807cde2086bb86" - } -} diff --git a/vendor/webmozart/assert/.styleci.yml b/vendor/webmozart/assert/.styleci.yml deleted file mode 100644 index c2ad4a5..0000000 --- a/vendor/webmozart/assert/.styleci.yml +++ /dev/null @@ -1,11 +0,0 @@ -preset: symfony - -finder: - exclude: - - "tests" - -enabled: - - ordered_use - -disabled: - - phpdoc_annotation_without_dot # This is still buggy: https://github.com/symfony/symfony/pull/19198 diff --git a/vendor/webmozart/assert/CHANGELOG.md b/vendor/webmozart/assert/CHANGELOG.md index 65fbc8f..56c8011 100644 --- a/vendor/webmozart/assert/CHANGELOG.md +++ b/vendor/webmozart/assert/CHANGELOG.md @@ -3,7 +3,157 @@ Changelog ## UNRELEASED -### Added +## 1.11.0 + +### Added + +* Added explicit (non magic) `allNullOr*` methods, with `@psalm-assert` annotations, for better Psalm support. + +### Changed + +* Trait methods will now check the assertion themselves, instead of using `__callStatic` +* `isList` will now deal correctly with (modified) lists that contain `NaN` +* `reportInvalidArgument` now has a return type of `never`. + +### Removed + +* Removed `symfony/polyfill-ctype` as a dependency, and require `ext-cytpe` instead. + * You can still require the `symfony/polyfill-ctype` in your project if you need it, as it provides `ext-ctype` + +## 1.10.0 + +### Added + +* On invalid assertion, we throw a `Webmozart\Assert\InvalidArgumentException` +* Added `Assert::positiveInteger()` + +### Changed + +* Using a trait with real implementations of `all*()` and `nullOr*()` methods to improve psalm compatibility. + +### Removed + +* Support for PHP <7.2 + +## 1.9.1 + +## Fixed + +* provisional support for PHP 8.0 + +## 1.9.0 + +* added better Psalm support for `all*` & `nullOr*` methods +* These methods are now understood by Psalm through a mixin. You may need a newer version of Psalm in order to use this +* added `@psalm-pure` annotation to `Assert::notFalse()` +* added more `@psalm-assert` annotations where appropriate + +## Changed + +* the `all*` & `nullOr*` methods are now declared on an interface, instead of `@method` annotations. +This interface is linked to the `Assert` class with a `@mixin` annotation. Most IDE's have supported this +for a long time, and you should not lose any autocompletion capabilities. PHPStan has supported this since +version `0.12.20`. This package is marked incompatible (with a composer conflict) with phpstan version prior to that. +If you do not use PHPStan than this does not matter. + +## 1.8.0 + +### Added + +* added `Assert::notStartsWith()` +* added `Assert::notEndsWith()` +* added `Assert::inArray()` +* added `@psalm-pure` annotations to pure assertions + +### Fixed + +* Exception messages of comparisons between `DateTime(Immutable)` objects now display their date & time. +* Custom Exception messages for `Assert::count()` now use the values to render the exception message. + +## 1.7.0 (2020-02-14) + +### Added + +* added `Assert::notFalse()` +* added `Assert::isAOf()` +* added `Assert::isAnyOf()` +* added `Assert::isNotA()` + +## 1.6.0 (2019-11-24) + +### Added + +* added `Assert::validArrayKey()` +* added `Assert::isNonEmptyList()` +* added `Assert::isNonEmptyMap()` +* added `@throws InvalidArgumentException` annotations to all methods that throw. +* added `@psalm-assert` for the list type to the `isList` assertion. + +### Fixed + +* `ResourceBundle` & `SimpleXMLElement` now pass the `isCountable` assertions. +They are countable, without implementing the `Countable` interface. +* The doc block of `range` now has the proper variables. +* An empty array will now pass `isList` and `isMap`. As it is a valid form of both. +If a non-empty variant is needed, use `isNonEmptyList` or `isNonEmptyMap`. + +### Changed + +* Removed some `@psalm-assert` annotations, that were 'side effect' assertions See: + * [#144](https://github.com/webmozart/assert/pull/144) + * [#145](https://github.com/webmozart/assert/issues/145) + * [#146](https://github.com/webmozart/assert/pull/146) + * [#150](https://github.com/webmozart/assert/pull/150) +* If you use Psalm, the minimum version needed is `3.6.0`. Which is enforced through a composer conflict. +If you don't use Psalm, then this has no impact. + +## 1.5.0 (2019-08-24) + +### Added + +* added `Assert::uniqueValues()` +* added `Assert::unicodeLetters()` +* added: `Assert::email()` +* added support for [Psalm](https://github.com/vimeo/psalm), by adding `@psalm-assert` annotations where appropriate. + +### Fixed + +* `Assert::endsWith()` would not give the correct result when dealing with a multibyte suffix. +* `Assert::length(), minLength, maxLength, lengthBetween` would not give the correct result when dealing with multibyte characters. + +**NOTE**: These 2 changes may break your assertions if you relied on the fact that multibyte characters didn't behave correctly. + +### Changed + +* The names of some variables have been updated to better reflect what they are. +* All function calls are now in their FQN form, slightly increasing performance. +* Tests are now properly ran against HHVM-3.30 and PHP nightly. + +### Deprecation + +* deprecated `Assert::isTraversable()` in favor of `Assert::isIterable()` + * This was already done in 1.3.0, but it was only done through a silenced `trigger_error`. It is now annotated as well. + +## 1.4.0 (2018-12-25) + +### Added + +* added `Assert::ip()` +* added `Assert::ipv4()` +* added `Assert::ipv6()` +* added `Assert::notRegex()` +* added `Assert::interfaceExists()` +* added `Assert::isList()` +* added `Assert::isMap()` +* added polyfill for ctype + +### Fixed + +* Special case when comparing objects implementing `__toString()` + +## 1.3.0 (2018-01-29) + +### Added * added `Assert::minCount()` * added `Assert::maxCount()` @@ -20,6 +170,10 @@ Changelog * `stringNotEmpty` will no longer report "0" is an empty string +### Deprecation + +* deprecated `Assert::isTraversable()` in favor of `Assert::isIterable()` + ## 1.2.0 (2016-11-23) * added `Assert::throws()` diff --git a/vendor/webmozart/assert/README.md b/vendor/webmozart/assert/README.md index 1c1ede7..3b2397a 100644 --- a/vendor/webmozart/assert/README.md +++ b/vendor/webmozart/assert/README.md @@ -1,21 +1,14 @@ Webmozart Assert ================ -[![Build Status](https://travis-ci.org/webmozart/assert.svg?branch=master)](https://travis-ci.org/webmozart/assert) -[![Build status](https://ci.appveyor.com/api/projects/status/lyg83bcsisrr94se/branch/master?svg=true)](https://ci.appveyor.com/project/webmozart/assert/branch/master) [![Latest Stable Version](https://poser.pugx.org/webmozart/assert/v/stable.svg)](https://packagist.org/packages/webmozart/assert) [![Total Downloads](https://poser.pugx.org/webmozart/assert/downloads.svg)](https://packagist.org/packages/webmozart/assert) -[![Dependency Status](https://www.versioneye.com/php/webmozart:assert/1.2.0/badge.svg)](https://www.versioneye.com/php/webmozart:assert/1.2.0) - -Latest release: [1.2.0](https://packagist.org/packages/webmozart/assert#1.2.0) - -PHP >= 5.3.9 This library contains efficient assertions to test the input and output of your methods. With these assertions, you can greatly reduce the amount of coding needed to write a safe implementation. -All assertions in the [`Assert`] class throw an `\InvalidArgumentException` if +All assertions in the [`Assert`] class throw an `Webmozart\Assert\InvalidArgumentException` if they fail. FAQ @@ -27,21 +20,21 @@ This library is heavily inspired by Benjamin Eberlei's wonderful [assert package but fixes a usability issue with error messages that can't be fixed there without breaking backwards compatibility. -This package features usable error messages by default. However, you can also +This package features usable error messages by default. However, you can also easily write custom error messages: ``` Assert::string($path, 'The path is expected to be a string. Got: %s'); ``` -In [beberlei/assert], the ordering of the `%s` placeholders is different for -every assertion. This package, on the contrary, provides consistent placeholder +In [beberlei/assert], the ordering of the `%s` placeholders is different for +every assertion. This package, on the contrary, provides consistent placeholder ordering for all assertions: * `%s`: The tested value as string, e.g. `"/foo/bar"`. * `%2$s`, `%3$s`, ...: Additional assertion-specific values, e.g. the minimum/maximum length, allowed values, etc. - + Check the source code of the assertions to find out details about the additional available placeholders. @@ -50,8 +43,8 @@ Installation Use [Composer] to install the package: -``` -$ composer require webmozart/assert +```bash +composer require webmozart/assert ``` Example @@ -74,11 +67,11 @@ If you create an employee with an invalid ID, an exception is thrown: ```php new Employee('foobar'); -// => InvalidArgumentException: +// => Webmozart\Assert\InvalidArgumentException: // The employee ID must be an integer. Got: string new Employee(-10); -// => InvalidArgumentException: +// => Webmozart\Assert\InvalidArgumentException: // The employee ID must be a positive integer. Got: -10 ``` @@ -95,6 +88,7 @@ Method | Description `stringNotEmpty($value, $message = '')` | Check that a value is a non-empty string `integer($value, $message = '')` | Check that a value is an integer `integerish($value, $message = '')` | Check that a value casts to an integer +`positiveInteger($value, $message = '')` | Check that a value is a positive (non-zero) integer `float($value, $message = '')` | Check that a value is a float `numeric($value, $message = '')` | Check that a value is numeric `natural($value, $message= ''')` | Check that a value is a non-negative integer @@ -108,16 +102,21 @@ Method | Description `isIterable($value, $message = '')` | Check that a value is an array or a `\Traversable` `isCountable($value, $message = '')` | Check that a value is an array or a `\Countable` `isInstanceOf($value, $class, $message = '')` | Check that a value is an `instanceof` a class -`isInstanceOfAny($value, array $classes, $message = '')` | Check that a value is an `instanceof` a at least one class on the array of classes +`isInstanceOfAny($value, array $classes, $message = '')` | Check that a value is an `instanceof` at least one class on the array of classes `notInstanceOf($value, $class, $message = '')` | Check that a value is not an `instanceof` a class +`isAOf($value, $class, $message = '')` | Check that a value is of the class or has one of its parents +`isAnyOf($value, array $classes, $message = '')` | Check that a value is of at least one of the classes or has one of its parents +`isNotA($value, $class, $message = '')` | Check that a value is not of the class or has not one of its parents `isArrayAccessible($value, $message = '')` | Check that a value can be accessed as an array +`uniqueValues($values, $message = '')` | Check that the given array contains unique values ### Comparison Assertions Method | Description ------------------------------------------------ | -------------------------------------------------- +----------------------------------------------- | ------------------------------------------------------------------ `true($value, $message = '')` | Check that a value is `true` `false($value, $message = '')` | Check that a value is `false` +`notFalse($value, $message = '')` | Check that a value is not `false` `null($value, $message = '')` | Check that a value is `null` `notNull($value, $message = '')` | Check that a value is not `null` `isEmpty($value, $message = '')` | Check that a value is `empty()` @@ -131,7 +130,8 @@ Method | Description `lessThan($value, $value2, $message = '')` | Check that a value is less than another `lessThanEq($value, $value2, $message = '')` | Check that a value is less than or equal to another `range($value, $min, $max, $message = '')` | Check that a value is within a range -`oneOf($value, array $values, $message = '')` | Check that a value is one of a list of values +`inArray($value, array $values, $message = '')` | Check that a value is one of a list of values +`oneOf($value, array $values, $message = '')` | Check that a value is one of a list of values (alias of `inArray`) ### String Assertions @@ -141,11 +141,15 @@ any of the following assertions. Method | Description --------------------------------------------------- | ----------------------------------------------------------------- `contains($value, $subString, $message = '')` | Check that a string contains a substring -`notContains($value, $subString, $message = '')` | Check that a string does not contains a substring +`notContains($value, $subString, $message = '')` | Check that a string does not contain a substring `startsWith($value, $prefix, $message = '')` | Check that a string has a prefix +`notStartsWith($value, $prefix, $message = '')` | Check that a string does not have a prefix `startsWithLetter($value, $message = '')` | Check that a string starts with a letter `endsWith($value, $suffix, $message = '')` | Check that a string has a suffix +`notEndsWith($value, $suffix, $message = '')` | Check that a string does not have a suffix `regex($value, $pattern, $message = '')` | Check that a string matches a regular expression +`notRegex($value, $pattern, $message = '')` | Check that a string does not match a regular expression +`unicodeLetters($value, $message = '')` | Check that a string contains Unicode letters only `alpha($value, $message = '')` | Check that a string contains letters only `digits($value, $message = '')` | Check that a string contains digits only `alnum($value, $message = '')` | Check that a string contains letters and digits only @@ -156,6 +160,10 @@ Method | Description `maxLength($value, $max, $message = '')` | Check that a string has at most a certain number of characters `lengthBetween($value, $min, $max, $message = '')` | Check that a string has a length in the given range `uuid($value, $message = '')` | Check that a string is a valid UUID +`ip($value, $message = '')` | Check that a string is a valid IP (either IPv4 or IPv6) +`ipv4($value, $message = '')` | Check that a string is a valid IPv4 +`ipv6($value, $message = '')` | Check that a string is a valid IPv6 +`email($value, $message = '')` | Check that a string is a valid e-mail address `notWhitespaceOnly($value, $message = '')` | Check that a string contains at least one non-whitespace character ### File Assertions @@ -174,6 +182,7 @@ Method | Description ----------------------------------------------------- | -------------------------------------------------- `classExists($value, $message = '')` | Check that a value is an existing class name `subclassOf($value, $class, $message = '')` | Check that a class is a subclass of another +`interfaceExists($value, $message = '')` | Check that a value is an existing interface name `implementsInterface($value, $class, $message = '')` | Check that a class implements an interface `propertyExists($value, $property, $message = '')` | Check that a property exists in a class/object `propertyNotExists($value, $property, $message = '')` | Check that a property does not exist in a class/object @@ -186,10 +195,15 @@ Method | Description -------------------------------------------------- | ------------------------------------------------------------------ `keyExists($array, $key, $message = '')` | Check that a key exists in an array `keyNotExists($array, $key, $message = '')` | Check that a key does not exist in an array +`validArrayKey($key, $message = '')` | Check that a value is a valid array key (int or string) `count($array, $number, $message = '')` | Check that an array contains a specific number of elements `minCount($array, $min, $message = '')` | Check that an array contains at least a certain number of elements `maxCount($array, $max, $message = '')` | Check that an array contains at most a certain number of elements `countBetween($array, $min, $max, $message = '')` | Check that an array has a count in the given range +`isList($array, $message = '')` | Check that an array is a non-associative list +`isNonEmptyList($array, $message = '')` | Check that an array is a non-associative list, and not empty +`isMap($array, $message = '')` | Check that an array is associative and has strings as keys +`isNonEmptyMap($array, $message = '')` | Check that an array is associative and has strings as keys, and is not empty ### Function Assertions @@ -215,6 +229,33 @@ assertion only if it the value is not `null`: Assert::nullOrString($middleName, 'The middle name must be a string or null. Got: %s'); ``` +### Extending Assert + +The `Assert` class comes with a few methods, which can be overridden to change the class behaviour. You can also extend it to +add your own assertions. + +#### Overriding methods + +Overriding the following methods in your assertion class allows you to change the behaviour of the assertions: + +* `public static function __callStatic($name, $arguments)` + * This method is used to 'create' the `nullOr` and `all` versions of the assertions. +* `protected static function valueToString($value)` + * This method is used for error messages, to convert the value to a string value for displaying. You could use this for representing a value object with a `__toString` method for example. +* `protected static function typeToString($value)` + * This method is used for error messages, to convert the a value to a string representing its type. +* `protected static function strlen($value)` + * This method is used to calculate string length for relevant methods, using the `mb_strlen` if available and useful. +* `protected static function reportInvalidArgument($message)` + * This method is called when an assertion fails, with the specified error message. Here you can throw your own exception, or log something. + +## Static analysis support + +Where applicable, assertion functions are annotated to support Psalm's +[Assertion syntax](https://psalm.dev/docs/annotating_code/assertion_syntax/). +A dedicated [PHPStan Plugin](https://github.com/phpstan/phpstan-webmozart-assert) is +required for proper type support. + Authors ------- @@ -229,12 +270,6 @@ Contributions to the package are always welcome! * Report any bugs or issues you find on the [issue tracker]. * You can grab the source code at the package's [Git repository]. -Support -------- - -If you are having problems, send a mail to bschussek@gmail.com or shout out to -[@webmozart] on Twitter. - License ------- @@ -243,7 +278,7 @@ All contents of this package are licensed under the [MIT license]. [beberlei/assert]: https://github.com/beberlei/assert [assert package]: https://github.com/beberlei/assert [Composer]: https://getcomposer.org -[Bernhard Schussek]: http://webmozarts.com +[Bernhard Schussek]: https://webmozarts.com [The Community Contributors]: https://github.com/webmozart/assert/graphs/contributors [issue tracker]: https://github.com/webmozart/assert/issues [Git repository]: https://github.com/webmozart/assert diff --git a/vendor/webmozart/assert/composer.json b/vendor/webmozart/assert/composer.json index c49e623..b340452 100644 --- a/vendor/webmozart/assert/composer.json +++ b/vendor/webmozart/assert/composer.json @@ -1,8 +1,12 @@ { "name": "webmozart/assert", "description": "Assertions to validate method input/output with nice error messages.", - "keywords": ["assert", "check", "validate"], "license": "MIT", + "keywords": [ + "assert", + "check", + "validate" + ], "authors": [ { "name": "Bernhard Schussek", @@ -10,11 +14,15 @@ } ], "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.2 || ^8.0", + "ext-ctype": "*" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "phpunit/phpunit": "^8.5.13" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" }, "autoload": { "psr-4": { @@ -23,12 +31,13 @@ }, "autoload-dev": { "psr-4": { - "Webmozart\\Assert\\Tests\\": "tests/" + "Webmozart\\Assert\\Tests\\": "tests/", + "Webmozart\\Assert\\Bin\\": "bin/src" } }, "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.10-dev" } } } diff --git a/vendor/webmozart/assert/src/Assert.php b/vendor/webmozart/assert/src/Assert.php index e2f89c0..db1f3a5 100644 --- a/vendor/webmozart/assert/src/Assert.php +++ b/vendor/webmozart/assert/src/Assert.php @@ -15,264 +15,251 @@ use BadMethodCallException; use Closure; use Countable; +use DateTime; +use DateTimeImmutable; use Exception; -use InvalidArgumentException; +use ResourceBundle; +use SimpleXMLElement; use Throwable; use Traversable; /** * Efficient assertions to validate the input/output of your methods. * - * @method static void nullOrString($value, $message = '') - * @method static void nullOrStringNotEmpty($value, $message = '') - * @method static void nullOrInteger($value, $message = '') - * @method static void nullOrIntegerish($value, $message = '') - * @method static void nullOrFloat($value, $message = '') - * @method static void nullOrNumeric($value, $message = '') - * @method static void nullOrBoolean($value, $message = '') - * @method static void nullOrScalar($value, $message = '') - * @method static void nullOrObject($value, $message = '') - * @method static void nullOrResource($value, $type = null, $message = '') - * @method static void nullOrIsCallable($value, $message = '') - * @method static void nullOrIsArray($value, $message = '') - * @method static void nullOrIsTraversable($value, $message = '') - * @method static void nullOrIsArrayAccessible($value, $message = '') - * @method static void nullOrIsCountable($value, $message = '') - * @method static void nullOrIsInstanceOf($value, $class, $message = '') - * @method static void nullOrNotInstanceOf($value, $class, $message = '') - * @method static void nullOrIsInstanceOfAny($value, $classes, $message = '') - * @method static void nullOrIsEmpty($value, $message = '') - * @method static void nullOrNotEmpty($value, $message = '') - * @method static void nullOrTrue($value, $message = '') - * @method static void nullOrFalse($value, $message = '') - * @method static void nullOrEq($value, $value2, $message = '') - * @method static void nullOrNotEq($value,$value2, $message = '') - * @method static void nullOrSame($value, $value2, $message = '') - * @method static void nullOrNotSame($value, $value2, $message = '') - * @method static void nullOrGreaterThan($value, $value2, $message = '') - * @method static void nullOrGreaterThanEq($value, $value2, $message = '') - * @method static void nullOrLessThan($value, $value2, $message = '') - * @method static void nullOrLessThanEq($value, $value2, $message = '') - * @method static void nullOrRange($value, $min, $max, $message = '') - * @method static void nullOrOneOf($value, $values, $message = '') - * @method static void nullOrContains($value, $subString, $message = '') - * @method static void nullOrNotContains($value, $subString, $message = '') - * @method static void nullOrNotWhitespaceOnly($value, $message = '') - * @method static void nullOrStartsWith($value, $prefix, $message = '') - * @method static void nullOrStartsWithLetter($value, $message = '') - * @method static void nullOrEndsWith($value, $suffix, $message = '') - * @method static void nullOrRegex($value, $pattern, $message = '') - * @method static void nullOrAlpha($value, $message = '') - * @method static void nullOrDigits($value, $message = '') - * @method static void nullOrAlnum($value, $message = '') - * @method static void nullOrLower($value, $message = '') - * @method static void nullOrUpper($value, $message = '') - * @method static void nullOrLength($value, $length, $message = '') - * @method static void nullOrMinLength($value, $min, $message = '') - * @method static void nullOrMaxLength($value, $max, $message = '') - * @method static void nullOrLengthBetween($value, $min, $max, $message = '') - * @method static void nullOrFileExists($value, $message = '') - * @method static void nullOrFile($value, $message = '') - * @method static void nullOrDirectory($value, $message = '') - * @method static void nullOrReadable($value, $message = '') - * @method static void nullOrWritable($value, $message = '') - * @method static void nullOrClassExists($value, $message = '') - * @method static void nullOrSubclassOf($value, $class, $message = '') - * @method static void nullOrImplementsInterface($value, $interface, $message = '') - * @method static void nullOrPropertyExists($value, $property, $message = '') - * @method static void nullOrPropertyNotExists($value, $property, $message = '') - * @method static void nullOrMethodExists($value, $method, $message = '') - * @method static void nullOrMethodNotExists($value, $method, $message = '') - * @method static void nullOrKeyExists($value, $key, $message = '') - * @method static void nullOrKeyNotExists($value, $key, $message = '') - * @method static void nullOrCount($value, $key, $message = '') - * @method static void nullOrMinCount($value, $min, $message = '') - * @method static void nullOrMaxCount($value, $max, $message = '') - * @method static void nullCountBetween($value, $min, $max, $message = '') - * @method static void nullOrUuid($values, $message = '') - * @method static void allString($values, $message = '') - * @method static void allStringNotEmpty($values, $message = '') - * @method static void allInteger($values, $message = '') - * @method static void allIntegerish($values, $message = '') - * @method static void allFloat($values, $message = '') - * @method static void allNumeric($values, $message = '') - * @method static void allBoolean($values, $message = '') - * @method static void allScalar($values, $message = '') - * @method static void allObject($values, $message = '') - * @method static void allResource($values, $type = null, $message = '') - * @method static void allIsCallable($values, $message = '') - * @method static void allIsArray($values, $message = '') - * @method static void allIsTraversable($values, $message = '') - * @method static void allIsArrayAccessible($values, $message = '') - * @method static void allIsCountable($values, $message = '') - * @method static void allIsInstanceOf($values, $class, $message = '') - * @method static void allNotInstanceOf($values, $class, $message = '') - * @method static void allIsInstanceOfAny($values, $classes, $message = '') - * @method static void allNull($values, $message = '') - * @method static void allNotNull($values, $message = '') - * @method static void allIsEmpty($values, $message = '') - * @method static void allNotEmpty($values, $message = '') - * @method static void allTrue($values, $message = '') - * @method static void allFalse($values, $message = '') - * @method static void allEq($values, $value2, $message = '') - * @method static void allNotEq($values,$value2, $message = '') - * @method static void allSame($values, $value2, $message = '') - * @method static void allNotSame($values, $value2, $message = '') - * @method static void allGreaterThan($values, $value2, $message = '') - * @method static void allGreaterThanEq($values, $value2, $message = '') - * @method static void allLessThan($values, $value2, $message = '') - * @method static void allLessThanEq($values, $value2, $message = '') - * @method static void allRange($values, $min, $max, $message = '') - * @method static void allOneOf($values, $values, $message = '') - * @method static void allContains($values, $subString, $message = '') - * @method static void allNotContains($values, $subString, $message = '') - * @method static void allNotWhitespaceOnly($values, $message = '') - * @method static void allStartsWith($values, $prefix, $message = '') - * @method static void allStartsWithLetter($values, $message = '') - * @method static void allEndsWith($values, $suffix, $message = '') - * @method static void allRegex($values, $pattern, $message = '') - * @method static void allAlpha($values, $message = '') - * @method static void allDigits($values, $message = '') - * @method static void allAlnum($values, $message = '') - * @method static void allLower($values, $message = '') - * @method static void allUpper($values, $message = '') - * @method static void allLength($values, $length, $message = '') - * @method static void allMinLength($values, $min, $message = '') - * @method static void allMaxLength($values, $max, $message = '') - * @method static void allLengthBetween($values, $min, $max, $message = '') - * @method static void allFileExists($values, $message = '') - * @method static void allFile($values, $message = '') - * @method static void allDirectory($values, $message = '') - * @method static void allReadable($values, $message = '') - * @method static void allWritable($values, $message = '') - * @method static void allClassExists($values, $message = '') - * @method static void allSubclassOf($values, $class, $message = '') - * @method static void allImplementsInterface($values, $interface, $message = '') - * @method static void allPropertyExists($values, $property, $message = '') - * @method static void allPropertyNotExists($values, $property, $message = '') - * @method static void allMethodExists($values, $method, $message = '') - * @method static void allMethodNotExists($values, $method, $message = '') - * @method static void allKeyExists($values, $key, $message = '') - * @method static void allKeyNotExists($values, $key, $message = '') - * @method static void allCount($values, $key, $message = '') - * @method static void allMinCount($values, $min, $message = '') - * @method static void allMaxCount($values, $max, $message = '') - * @method static void allCountBetween($values, $min, $max, $message = '') - * @method static void allUuid($values, $message = '') - * * @since 1.0 * * @author Bernhard Schussek <bschussek@gmail.com> */ class Assert { + use Mixin; + + /** + * @psalm-pure + * @psalm-assert string $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function string($value, $message = '') { - if (!is_string($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_string($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a string. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert non-empty-string $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function stringNotEmpty($value, $message = '') { static::string($value, $message); static::notEq($value, '', $message); } + /** + * @psalm-pure + * @psalm-assert int $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function integer($value, $message = '') { - if (!is_int($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_int($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an integer. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert numeric $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function integerish($value, $message = '') { - if (!is_numeric($value) || $value != (int) $value) { - static::reportInvalidArgument(sprintf( + if (!\is_numeric($value) || $value != (int) $value) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an integerish value. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert positive-int $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function positiveInteger($value, $message = '') + { + if (!(\is_int($value) && $value > 0)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a positive integer. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-assert float $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function float($value, $message = '') { - if (!is_float($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_float($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a float. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert numeric $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function numeric($value, $message = '') { - if (!is_numeric($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_numeric($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a numeric. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert positive-int|0 $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function natural($value, $message = '') { - if (!is_int($value) || $value < 0) { - static::reportInvalidArgument(sprintf( - $message ?: 'Expected a non-negative integer. Got %s', + if (!\is_int($value) || $value < 0) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a non-negative integer. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert bool $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function boolean($value, $message = '') { - if (!is_bool($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_bool($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a boolean. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert scalar $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function scalar($value, $message = '') { - if (!is_scalar($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_scalar($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a scalar. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert object $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function object($value, $message = '') { - if (!is_object($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_object($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an object. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert resource $value + * + * @param mixed $value + * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php + * @param string $message + * + * @throws InvalidArgumentException + */ public static function resource($value, $type = null, $message = '') { - if (!is_resource($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_resource($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a resource. Got: %s', static::typeToString($value) )); } - if ($type && $type !== get_resource_type($value)) { - static::reportInvalidArgument(sprintf( + if ($type && $type !== \get_resource_type($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a resource of type %2$s. Got: %s', static::typeToString($value), $type @@ -280,78 +267,151 @@ public static function resource($value, $type = null, $message = '') } } + /** + * @psalm-pure + * @psalm-assert callable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function isCallable($value, $message = '') { - if (!is_callable($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_callable($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a callable. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert array $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function isArray($value, $message = '') { - if (!is_array($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_array($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @deprecated use "isIterable" or "isInstanceOf" instead + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function isTraversable($value, $message = '') { - @trigger_error( - sprintf( + @\trigger_error( + \sprintf( 'The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.', __METHOD__ ), - E_USER_DEPRECATED + \E_USER_DEPRECATED ); - if (!is_array($value) && !($value instanceof Traversable)) { - static::reportInvalidArgument(sprintf( + if (!\is_array($value) && !($value instanceof Traversable)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a traversable. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert array|ArrayAccess $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function isArrayAccessible($value, $message = '') { - if (!is_array($value) && !($value instanceof ArrayAccess)) { - static::reportInvalidArgument(sprintf( + if (!\is_array($value) && !($value instanceof ArrayAccess)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array accessible. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert countable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function isCountable($value, $message = '') { - if (!is_array($value) && !($value instanceof Countable)) { - static::reportInvalidArgument(sprintf( + if ( + !\is_array($value) + && !($value instanceof Countable) + && !($value instanceof ResourceBundle) + && !($value instanceof SimpleXMLElement) + ) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a countable. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert iterable $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function isIterable($value, $message = '') { - if (!is_array($value) && !($value instanceof Traversable)) { - static::reportInvalidArgument(sprintf( + if (!\is_array($value) && !($value instanceof Traversable)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an iterable. Got: %s', static::typeToString($value) )); } } + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert ExpectedType $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + */ public static function isInstanceOf($value, $class, $message = '') { if (!($value instanceof $class)) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an instance of %2$s. Got: %s', static::typeToString($value), $class @@ -359,10 +419,22 @@ public static function isInstanceOf($value, $class, $message = '') } } + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert !ExpectedType $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + */ public static function notInstanceOf($value, $class, $message = '') { if ($value instanceof $class) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an instance other than %2$s. Got: %s', static::typeToString($value), $class @@ -370,6 +442,16 @@ public static function notInstanceOf($value, $class, $message = '') } } + /** + * @psalm-pure + * @psalm-param array<class-string> $classes + * + * @param mixed $value + * @param array<object|string> $classes + * @param string $message + * + * @throws InvalidArgumentException + */ public static function isInstanceOfAny($value, array $classes, $message = '') { foreach ($classes as $class) { @@ -378,43 +460,157 @@ public static function isInstanceOfAny($value, array $classes, $message = '') } } - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an instance of any of %2$s. Got: %s', static::typeToString($value), - implode(', ', array_map(array('static', 'valueToString'), $classes)) + \implode(', ', \array_map(array(static::class, 'valueToString'), $classes)) + )); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert ExpectedType|class-string<ExpectedType> $value + * + * @param object|string $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isAOf($value, $class, $message = '') + { + static::string($class, 'Expected class as a string. Got: %s'); + + if (!\is_a($value, $class, \is_string($value))) { + static::reportInvalidArgument(sprintf( + $message ?: 'Expected an instance of this class or to this class among its parents "%2$s". Got: %s', + static::valueToString($value), + $class + )); + } + } + + /** + * @psalm-pure + * @psalm-template UnexpectedType of object + * @psalm-param class-string<UnexpectedType> $class + * @psalm-assert !UnexpectedType $value + * @psalm-assert !class-string<UnexpectedType> $value + * + * @param object|string $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isNotA($value, $class, $message = '') + { + static::string($class, 'Expected class as a string. Got: %s'); + + if (\is_a($value, $class, \is_string($value))) { + static::reportInvalidArgument(sprintf( + $message ?: 'Expected an instance of this class or to this class among its parents other than "%2$s". Got: %s', + static::valueToString($value), + $class + )); + } + } + + /** + * @psalm-pure + * @psalm-param array<class-string> $classes + * + * @param object|string $value + * @param string[] $classes + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isAnyOf($value, array $classes, $message = '') + { + foreach ($classes as $class) { + static::string($class, 'Expected class as a string. Got: %s'); + + if (\is_a($value, $class, \is_string($value))) { + return; + } + } + + static::reportInvalidArgument(sprintf( + $message ?: 'Expected an instance of any of this classes or any of those classes among their parents "%2$s". Got: %s', + static::valueToString($value), + \implode(', ', $classes) )); } + /** + * @psalm-pure + * @psalm-assert empty $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function isEmpty($value, $message = '') { if (!empty($value)) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an empty value. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert !empty $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function notEmpty($value, $message = '') { if (empty($value)) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a non-empty value. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function null($value, $message = '') { if (null !== $value) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected null. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert !null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function notNull($value, $message = '') { if (null === $value) { @@ -424,72 +620,237 @@ public static function notNull($value, $message = '') } } + /** + * @psalm-pure + * @psalm-assert true $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function true($value, $message = '') { if (true !== $value) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to be true. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert false $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function false($value, $message = '') { if (false !== $value) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to be false. Got: %s', static::valueToString($value) )); } } - public static function eq($value, $value2, $message = '') + /** + * @psalm-pure + * @psalm-assert !false $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notFalse($value, $message = '') { - if ($value2 != $value) { - static::reportInvalidArgument(sprintf( + if (false === $value) { + static::reportInvalidArgument( + $message ?: 'Expected a value other than false.' + ); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function ip($value, $message = '') + { + if (false === \filter_var($value, \FILTER_VALIDATE_IP)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to be an IP. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function ipv4($value, $message = '') + { + if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to be an IPv4. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function ipv6($value, $message = '') + { + if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to be an IPv6. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function email($value, $message = '') + { + if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to be a valid e-mail address. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion. + * + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function uniqueValues(array $values, $message = '') + { + $allValues = \count($values); + $uniqueValues = \count(\array_unique($values)); + + if ($allValues !== $uniqueValues) { + $difference = $allValues - $uniqueValues; + + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an array of unique values, but %s of them %s duplicated', + $difference, + (1 === $difference ? 'is' : 'are') + )); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function eq($value, $expect, $message = '') + { + if ($expect != $value) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value equal to %2$s. Got: %s', static::valueToString($value), - static::valueToString($value2) + static::valueToString($expect) )); } } - public static function notEq($value, $value2, $message = '') + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notEq($value, $expect, $message = '') { - if ($value2 == $value) { - static::reportInvalidArgument(sprintf( + if ($expect == $value) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a different value than %s.', - static::valueToString($value2) + static::valueToString($expect) )); } } - public static function same($value, $value2, $message = '') + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function same($value, $expect, $message = '') { - if ($value2 !== $value) { - static::reportInvalidArgument(sprintf( + if ($expect !== $value) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value identical to %2$s. Got: %s', static::valueToString($value), - static::valueToString($value2) + static::valueToString($expect) )); } } - public static function notSame($value, $value2, $message = '') + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notSame($value, $expect, $message = '') { - if ($value2 === $value) { - static::reportInvalidArgument(sprintf( + if ($expect === $value) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value not identical to %s.', - static::valueToString($value2) + static::valueToString($expect) )); } } + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + */ public static function greaterThan($value, $limit, $message = '') { if ($value <= $limit) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value greater than %2$s. Got: %s', static::valueToString($value), static::valueToString($limit) @@ -497,10 +858,19 @@ public static function greaterThan($value, $limit, $message = '') } } + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + */ public static function greaterThanEq($value, $limit, $message = '') { if ($value < $limit) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value greater than or equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($limit) @@ -508,10 +878,19 @@ public static function greaterThanEq($value, $limit, $message = '') } } + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + */ public static function lessThan($value, $limit, $message = '') { if ($value >= $limit) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value less than %2$s. Got: %s', static::valueToString($value), static::valueToString($limit) @@ -519,10 +898,19 @@ public static function lessThan($value, $limit, $message = '') } } + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + */ public static function lessThanEq($value, $limit, $message = '') { if ($value > $limit) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value less than or equal to %2$s. Got: %s', static::valueToString($value), static::valueToString($limit) @@ -530,10 +918,22 @@ public static function lessThanEq($value, $limit, $message = '') } } + /** + * Inclusive range, so Assert::(3, 3, 5) passes. + * + * @psalm-pure + * + * @param mixed $value + * @param mixed $min + * @param mixed $max + * @param string $message + * + * @throws InvalidArgumentException + */ public static function range($value, $min, $max, $message = '') { if ($value < $min || $value > $max) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value between %2$s and %3$s. Got: %s', static::valueToString($value), static::valueToString($min), @@ -542,21 +942,57 @@ public static function range($value, $min, $max, $message = '') } } + /** + * A more human-readable alias of Assert::inArray(). + * + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + */ public static function oneOf($value, array $values, $message = '') { - if (!in_array($value, $values, true)) { - static::reportInvalidArgument(sprintf( + static::inArray($value, $values, $message); + } + + /** + * Does strict comparison, so Assert::inArray(3, ['3']) does not pass the assertion. + * + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function inArray($value, array $values, $message = '') + { + if (!\in_array($value, $values, true)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected one of: %2$s. Got: %s', static::valueToString($value), - implode(', ', array_map(array('static', 'valueToString'), $values)) + \implode(', ', \array_map(array(static::class, 'valueToString'), $values)) )); } } + /** + * @psalm-pure + * + * @param string $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + */ public static function contains($value, $subString, $message = '') { - if (false === strpos($value, $subString)) { - static::reportInvalidArgument(sprintf( + if (false === \strpos($value, $subString)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain %2$s. Got: %s', static::valueToString($value), static::valueToString($subString) @@ -564,10 +1000,19 @@ public static function contains($value, $subString, $message = '') } } + /** + * @psalm-pure + * + * @param string $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + */ public static function notContains($value, $subString, $message = '') { - if (false !== strpos($value, $subString)) { - static::reportInvalidArgument(sprintf( + if (false !== \strpos($value, $subString)) { + static::reportInvalidArgument(\sprintf( $message ?: '%2$s was not expected to be contained in a value. Got: %s', static::valueToString($value), static::valueToString($subString) @@ -575,20 +1020,37 @@ public static function notContains($value, $subString, $message = '') } } + /** + * @psalm-pure + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function notWhitespaceOnly($value, $message = '') { - if (preg_match('/^\s*$/', $value)) { - static::reportInvalidArgument(sprintf( + if (\preg_match('/^\s*$/', $value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a non-whitespace string. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * + * @param string $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + */ public static function startsWith($value, $prefix, $message = '') { - if (0 !== strpos($value, $prefix)) { - static::reportInvalidArgument(sprintf( + if (0 !== \strpos($value, $prefix)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to start with %2$s. Got: %s', static::valueToString($value), static::valueToString($prefix) @@ -596,29 +1058,68 @@ public static function startsWith($value, $prefix, $message = '') } } + /** + * @psalm-pure + * + * @param string $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notStartsWith($value, $prefix, $message = '') + { + if (0 === \strpos($value, $prefix)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value not to start with %2$s. Got: %s', + static::valueToString($value), + static::valueToString($prefix) + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function startsWithLetter($value, $message = '') { + static::string($value); + $valid = isset($value[0]); if ($valid) { - $locale = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'C'); - $valid = ctype_alpha($value[0]); - setlocale(LC_CTYPE, $locale); + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = \ctype_alpha($value[0]); + \setlocale(LC_CTYPE, $locale); } if (!$valid) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to start with a letter. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * + * @param string $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + */ public static function endsWith($value, $suffix, $message = '') { - if ($suffix !== substr($value, -static::strlen($suffix))) { - static::reportInvalidArgument(sprintf( + if ($suffix !== \substr($value, -\strlen($suffix))) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to end with %2$s. Got: %s', static::valueToString($value), static::valueToString($suffix) @@ -626,95 +1127,218 @@ public static function endsWith($value, $suffix, $message = '') } } + /** + * @psalm-pure + * + * @param string $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notEndsWith($value, $suffix, $message = '') + { + if ($suffix === \substr($value, -\strlen($suffix))) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value not to end with %2$s. Got: %s', + static::valueToString($value), + static::valueToString($suffix) + )); + } + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + */ public static function regex($value, $pattern, $message = '') { - if (!preg_match($pattern, $value)) { - static::reportInvalidArgument(sprintf( + if (!\preg_match($pattern, $value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'The value %s does not match the expected pattern.', static::valueToString($value) )); } } + /** + * @psalm-pure + * + * @param string $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function notRegex($value, $pattern, $message = '') + { + if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'The value %s matches the pattern %s (at offset %d).', + static::valueToString($value), + static::valueToString($pattern), + $matches[0][1] + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function unicodeLetters($value, $message = '') + { + static::string($value); + + if (!\preg_match('/^\p{L}+$/u', $value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected a value to contain only Unicode letters. Got: %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function alpha($value, $message = '') { - $locale = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'C'); - $valid = !ctype_alpha($value); - setlocale(LC_CTYPE, $locale); + static::string($value); + + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = !\ctype_alpha($value); + \setlocale(LC_CTYPE, $locale); if ($valid) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain only letters. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function digits($value, $message = '') { - $locale = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'C'); - $valid = !ctype_digit($value); - setlocale(LC_CTYPE, $locale); + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = !\ctype_digit($value); + \setlocale(LC_CTYPE, $locale); if ($valid) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain digits only. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function alnum($value, $message = '') { - $locale = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'C'); - $valid = !ctype_alnum($value); - setlocale(LC_CTYPE, $locale); + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = !\ctype_alnum($value); + \setlocale(LC_CTYPE, $locale); if ($valid) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain letters and digits only. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert lowercase-string $value + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function lower($value, $message = '') { - $locale = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'C'); - $valid = !ctype_lower($value); - setlocale(LC_CTYPE, $locale); + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = !\ctype_lower($value); + \setlocale(LC_CTYPE, $locale); if ($valid) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain lowercase characters only. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * @psalm-assert !lowercase-string $value + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function upper($value, $message = '') { - $locale = setlocale(LC_CTYPE, 0); - setlocale(LC_CTYPE, 'C'); - $valid = !ctype_upper($value); - setlocale(LC_CTYPE, $locale); + $locale = \setlocale(LC_CTYPE, 0); + \setlocale(LC_CTYPE, 'C'); + $valid = !\ctype_upper($value); + \setlocale(LC_CTYPE, $locale); if ($valid) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain uppercase characters only. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * + * @param string $value + * @param int $length + * @param string $message + * + * @throws InvalidArgumentException + */ public static function length($value, $length, $message = '') { if ($length !== static::strlen($value)) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain %2$s characters. Got: %s', static::valueToString($value), $length @@ -722,10 +1346,21 @@ public static function length($value, $length, $message = '') } } + /** + * Inclusive min. + * + * @psalm-pure + * + * @param string $value + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + */ public static function minLength($value, $min, $message = '') { if (static::strlen($value) < $min) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain at least %2$s characters. Got: %s', static::valueToString($value), $min @@ -733,10 +1368,21 @@ public static function minLength($value, $min, $message = '') } } + /** + * Inclusive max. + * + * @psalm-pure + * + * @param string $value + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + */ public static function maxLength($value, $max, $message = '') { if (static::strlen($value) > $max) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain at most %2$s characters. Got: %s', static::valueToString($value), $max @@ -744,12 +1390,24 @@ public static function maxLength($value, $max, $message = '') } } + /** + * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion. + * + * @psalm-pure + * + * @param string $value + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + */ public static function lengthBetween($value, $min, $max, $message = '') { $length = static::strlen($value); if ($length < $min || $length > $max) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s', static::valueToString($value), $min, @@ -758,76 +1416,128 @@ public static function lengthBetween($value, $min, $max, $message = '') } } + /** + * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file. + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function fileExists($value, $message = '') { static::string($value); - if (!file_exists($value)) { - static::reportInvalidArgument(sprintf( + if (!\file_exists($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'The file %s does not exist.', static::valueToString($value) )); } } + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function file($value, $message = '') { static::fileExists($value, $message); - if (!is_file($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_file($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'The path %s is not a file.', static::valueToString($value) )); } } + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function directory($value, $message = '') { static::fileExists($value, $message); - if (!is_dir($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_dir($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'The path %s is no directory.', static::valueToString($value) )); } } + /** + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function readable($value, $message = '') { - if (!is_readable($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_readable($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'The path %s is not readable.', static::valueToString($value) )); } } + /** + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function writable($value, $message = '') { - if (!is_writable($value)) { - static::reportInvalidArgument(sprintf( + if (!\is_writable($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'The path %s is not writable.', static::valueToString($value) )); } } + /** + * @psalm-assert class-string $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function classExists($value, $message = '') { - if (!class_exists($value)) { - static::reportInvalidArgument(sprintf( + if (!\class_exists($value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an existing class name. Got: %s', static::valueToString($value) )); } } + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert class-string<ExpectedType>|ExpectedType $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + */ public static function subclassOf($value, $class, $message = '') { - if (!is_subclass_of($value, $class)) { - static::reportInvalidArgument(sprintf( + if (!\is_subclass_of($value, $class)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected a sub-class of %2$s. Got: %s', static::valueToString($value), static::valueToString($class) @@ -835,10 +1545,40 @@ public static function subclassOf($value, $class, $message = '') } } + /** + * @psalm-assert class-string $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function interfaceExists($value, $message = '') + { + if (!\interface_exists($value)) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected an existing interface name. got %s', + static::valueToString($value) + )); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $interface + * @psalm-assert class-string<ExpectedType> $value + * + * @param mixed $value + * @param mixed $interface + * @param string $message + * + * @throws InvalidArgumentException + */ public static function implementsInterface($value, $interface, $message = '') { - if (!in_array($interface, class_implements($value))) { - static::reportInvalidArgument(sprintf( + if (!\in_array($interface, \class_implements($value))) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an implementation of %2$s. Got: %s', static::valueToString($value), static::valueToString($interface) @@ -846,103 +1586,223 @@ public static function implementsInterface($value, $interface, $message = '') } } + /** + * @psalm-pure + * @psalm-param class-string|object $classOrObject + * + * @param string|object $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + */ public static function propertyExists($classOrObject, $property, $message = '') { - if (!property_exists($classOrObject, $property)) { - static::reportInvalidArgument(sprintf( + if (!\property_exists($classOrObject, $property)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected the property %s to exist.', static::valueToString($property) )); } } + /** + * @psalm-pure + * @psalm-param class-string|object $classOrObject + * + * @param string|object $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + */ public static function propertyNotExists($classOrObject, $property, $message = '') { - if (property_exists($classOrObject, $property)) { - static::reportInvalidArgument(sprintf( + if (\property_exists($classOrObject, $property)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected the property %s to not exist.', static::valueToString($property) )); } } + /** + * @psalm-pure + * @psalm-param class-string|object $classOrObject + * + * @param string|object $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + */ public static function methodExists($classOrObject, $method, $message = '') { - if (!method_exists($classOrObject, $method)) { - static::reportInvalidArgument(sprintf( + if (!(\is_string($classOrObject) || \is_object($classOrObject)) || !\method_exists($classOrObject, $method)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected the method %s to exist.', static::valueToString($method) )); } } + /** + * @psalm-pure + * @psalm-param class-string|object $classOrObject + * + * @param string|object $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + */ public static function methodNotExists($classOrObject, $method, $message = '') { - if (method_exists($classOrObject, $method)) { - static::reportInvalidArgument(sprintf( + if ((\is_string($classOrObject) || \is_object($classOrObject)) && \method_exists($classOrObject, $method)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected the method %s to not exist.', static::valueToString($method) )); } } + /** + * @psalm-pure + * + * @param array $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + */ public static function keyExists($array, $key, $message = '') { - if (!array_key_exists($key, $array)) { - static::reportInvalidArgument(sprintf( + if (!(isset($array[$key]) || \array_key_exists($key, $array))) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected the key %s to exist.', static::valueToString($key) )); } } + /** + * @psalm-pure + * + * @param array $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + */ public static function keyNotExists($array, $key, $message = '') { - if (array_key_exists($key, $array)) { - static::reportInvalidArgument(sprintf( + if (isset($array[$key]) || \array_key_exists($key, $array)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected the key %s to not exist.', static::valueToString($key) )); } } + /** + * Checks if a value is a valid array key (int or string). + * + * @psalm-pure + * @psalm-assert array-key $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function validArrayKey($value, $message = '') + { + if (!(\is_int($value) || \is_string($value))) { + static::reportInvalidArgument(\sprintf( + $message ?: 'Expected string or integer. Got: %s', + static::typeToString($value) + )); + } + } + + /** + * Does not check if $array is countable, this can generate a warning on php versions after 7.2. + * + * @param Countable|array $array + * @param int $number + * @param string $message + * + * @throws InvalidArgumentException + */ public static function count($array, $number, $message = '') { static::eq( - count($array), + \count($array), $number, - $message ?: sprintf('Expected an array to contain %d elements. Got: %d.', $number, count($array)) + \sprintf( + $message ?: 'Expected an array to contain %d elements. Got: %d.', + $number, + \count($array) + ) ); } + /** + * Does not check if $array is countable, this can generate a warning on php versions after 7.2. + * + * @param Countable|array $array + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + */ public static function minCount($array, $min, $message = '') { - if (count($array) < $min) { - static::reportInvalidArgument(sprintf( + if (\count($array) < $min) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array to contain at least %2$d elements. Got: %d', - count($array), + \count($array), $min )); } } + /** + * Does not check if $array is countable, this can generate a warning on php versions after 7.2. + * + * @param Countable|array $array + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + */ public static function maxCount($array, $max, $message = '') { - if (count($array) > $max) { - static::reportInvalidArgument(sprintf( + if (\count($array) > $max) { + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array to contain at most %2$d elements. Got: %d', - count($array), + \count($array), $max )); } } + /** + * Does not check if $array is countable, this can generate a warning on php versions after 7.2. + * + * @param Countable|array $array + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + */ public static function countBetween($array, $min, $max, $message = '') { - $count = count($array); + $count = \count($array); if ($count < $min || $count > $max) { - static::reportInvalidArgument(sprintf( + static::reportInvalidArgument(\sprintf( $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d', $count, $min, @@ -951,9 +1811,104 @@ public static function countBetween($array, $min, $max, $message = '') } } + /** + * @psalm-pure + * @psalm-assert list $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isList($array, $message = '') + { + if (!\is_array($array)) { + static::reportInvalidArgument( + $message ?: 'Expected list - non-associative array.' + ); + } + + if ($array === \array_values($array)) { + return; + } + + $nextKey = -1; + foreach ($array as $k => $v) { + if ($k !== ++$nextKey) { + static::reportInvalidArgument( + $message ?: 'Expected list - non-associative array.' + ); + } + } + } + + /** + * @psalm-pure + * @psalm-assert non-empty-list $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isNonEmptyList($array, $message = '') + { + static::isList($array, $message); + static::notEmpty($array, $message); + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param mixed|array<T> $array + * @psalm-assert array<string, T> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isMap($array, $message = '') + { + if ( + !\is_array($array) || + \array_keys($array) !== \array_filter(\array_keys($array), '\is_string') + ) { + static::reportInvalidArgument( + $message ?: 'Expected map - associative array with string keys.' + ); + } + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param mixed|array<T> $array + * @psalm-assert array<string, T> $array + * @psalm-assert !empty $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + */ + public static function isNonEmptyMap($array, $message = '') + { + static::isMap($array, $message); + static::notEmpty($array, $message); + } + + /** + * @psalm-pure + * + * @param string $value + * @param string $message + * + * @throws InvalidArgumentException + */ public static function uuid($value, $message = '') { - $value = str_replace(array('urn:', 'uuid:', '{', '}'), '', $value); + $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value); // The nil UUID is special form of UUID that is specified to have all // 128 bits set to zero. @@ -961,14 +1916,23 @@ public static function uuid($value, $message = '') return; } - if (!preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) { - static::reportInvalidArgument(sprintf( + if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) { + static::reportInvalidArgument(\sprintf( $message ?: 'Value %s is not a valid UUID.', static::valueToString($value) )); } } + /** + * @psalm-param class-string<Throwable> $class + * + * @param Closure $expression + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + */ public static function throws(Closure $expression, $class = 'Exception', $message = '') { static::string($class); @@ -978,45 +1942,48 @@ public static function throws(Closure $expression, $class = 'Exception', $messag try { $expression(); } catch (Exception $e) { - $actual = get_class($e); + $actual = \get_class($e); if ($e instanceof $class) { return; } } catch (Throwable $e) { - $actual = get_class($e); + $actual = \get_class($e); if ($e instanceof $class) { return; } } - static::reportInvalidArgument($message ?: sprintf( + static::reportInvalidArgument($message ?: \sprintf( 'Expected to throw "%s", got "%s"', $class, $actual )); } + /** + * @throws BadMethodCallException + */ public static function __callStatic($name, $arguments) { - if ('nullOr' === substr($name, 0, 6)) { + if ('nullOr' === \substr($name, 0, 6)) { if (null !== $arguments[0]) { - $method = lcfirst(substr($name, 6)); - call_user_func_array(array('static', $method), $arguments); + $method = \lcfirst(\substr($name, 6)); + \call_user_func_array(array(static::class, $method), $arguments); } return; } - if ('all' === substr($name, 0, 3)) { + if ('all' === \substr($name, 0, 3)) { static::isIterable($arguments[0]); - $method = lcfirst(substr($name, 3)); + $method = \lcfirst(\substr($name, 3)); $args = $arguments; foreach ($arguments[0] as $entry) { $args[0] = $entry; - call_user_func_array(array('static', $method), $args); + \call_user_func_array(array(static::class, $method), $args); } return; @@ -1025,6 +1992,11 @@ public static function __callStatic($name, $arguments) throw new BadMethodCallException('No such method: '.$name); } + /** + * @param mixed $value + * + * @return string + */ protected static function valueToString($value) { if (null === $value) { @@ -1039,43 +2011,64 @@ protected static function valueToString($value) return 'false'; } - if (is_array($value)) { + if (\is_array($value)) { return 'array'; } - if (is_object($value)) { - return get_class($value); + if (\is_object($value)) { + if (\method_exists($value, '__toString')) { + return \get_class($value).': '.self::valueToString($value->__toString()); + } + + if ($value instanceof DateTime || $value instanceof DateTimeImmutable) { + return \get_class($value).': '.self::valueToString($value->format('c')); + } + + return \get_class($value); } - if (is_resource($value)) { + if (\is_resource($value)) { return 'resource'; } - if (is_string($value)) { + if (\is_string($value)) { return '"'.$value.'"'; } return (string) $value; } + /** + * @param mixed $value + * + * @return string + */ protected static function typeToString($value) { - return is_object($value) ? get_class($value) : gettype($value); + return \is_object($value) ? \get_class($value) : \gettype($value); } protected static function strlen($value) { - if (!function_exists('mb_detect_encoding')) { - return strlen($value); + if (!\function_exists('mb_detect_encoding')) { + return \strlen($value); } - if (false === $encoding = mb_detect_encoding($value)) { - return strlen($value); + if (false === $encoding = \mb_detect_encoding($value)) { + return \strlen($value); } - return mb_strwidth($value, $encoding); + return \mb_strlen($value, $encoding); } + /** + * @param string $message + * + * @throws InvalidArgumentException + * + * @psalm-pure this method is not supposed to perform side-effects + * @psalm-return never + */ protected static function reportInvalidArgument($message) { throw new InvalidArgumentException($message); diff --git a/vendor/webmozart/assert/src/InvalidArgumentException.php b/vendor/webmozart/assert/src/InvalidArgumentException.php new file mode 100644 index 0000000..9d95a58 --- /dev/null +++ b/vendor/webmozart/assert/src/InvalidArgumentException.php @@ -0,0 +1,16 @@ +<?php + +/* + * This file is part of the webmozart/assert package. + * + * (c) Bernhard Schussek <bschussek@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webmozart\Assert; + +class InvalidArgumentException extends \InvalidArgumentException +{ +} diff --git a/vendor/webmozart/assert/src/Mixin.php b/vendor/webmozart/assert/src/Mixin.php new file mode 100644 index 0000000..0f0a75e --- /dev/null +++ b/vendor/webmozart/assert/src/Mixin.php @@ -0,0 +1,5089 @@ +<?php + +namespace Webmozart\Assert; + +use ArrayAccess; +use Closure; +use Countable; +use Throwable; + +/** + * This trait provides nurllOr*, all* and allNullOr* variants of assertion base methods. + * Do not use this trait directly: it will change, and is not designed for reuse. + */ +trait Mixin +{ + /** + * @psalm-pure + * @psalm-assert string|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrString($value, $message = '') + { + null === $value || static::string($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<string> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allString($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::string($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<string|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrString($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::string($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert non-empty-string|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrStringNotEmpty($value, $message = '') + { + null === $value || static::stringNotEmpty($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<non-empty-string> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allStringNotEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::stringNotEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<non-empty-string|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrStringNotEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::stringNotEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert int|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrInteger($value, $message = '') + { + null === $value || static::integer($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<int> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allInteger($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::integer($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<int|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrInteger($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::integer($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert numeric|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIntegerish($value, $message = '') + { + null === $value || static::integerish($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<numeric> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIntegerish($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::integerish($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<numeric|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIntegerish($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::integerish($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert positive-int|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrPositiveInteger($value, $message = '') + { + null === $value || static::positiveInteger($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<positive-int> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allPositiveInteger($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::positiveInteger($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<positive-int|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrPositiveInteger($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::positiveInteger($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert float|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrFloat($value, $message = '') + { + null === $value || static::float($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<float> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allFloat($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::float($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<float|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrFloat($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::float($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert numeric|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNumeric($value, $message = '') + { + null === $value || static::numeric($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<numeric> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNumeric($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::numeric($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<numeric|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNumeric($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::numeric($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert positive-int|0|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNatural($value, $message = '') + { + null === $value || static::natural($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<positive-int|0> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNatural($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::natural($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<positive-int|0|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNatural($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::natural($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert bool|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrBoolean($value, $message = '') + { + null === $value || static::boolean($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<bool> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allBoolean($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::boolean($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<bool|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrBoolean($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::boolean($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert scalar|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrScalar($value, $message = '') + { + null === $value || static::scalar($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<scalar> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allScalar($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::scalar($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<scalar|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrScalar($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::scalar($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert object|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrObject($value, $message = '') + { + null === $value || static::object($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<object> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allObject($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::object($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<object|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrObject($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::object($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert resource|null $value + * + * @param mixed $value + * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrResource($value, $type = null, $message = '') + { + null === $value || static::resource($value, $type, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<resource> $value + * + * @param mixed $value + * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allResource($value, $type = null, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::resource($entry, $type, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<resource|null> $value + * + * @param mixed $value + * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrResource($value, $type = null, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::resource($entry, $type, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert callable|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsCallable($value, $message = '') + { + null === $value || static::isCallable($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<callable> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsCallable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isCallable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<callable|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsCallable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isCallable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert array|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsArray($value, $message = '') + { + null === $value || static::isArray($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<array> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsArray($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isArray($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<array|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsArray($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isArray($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable|null $value + * + * @deprecated use "isIterable" or "isInstanceOf" instead + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsTraversable($value, $message = '') + { + null === $value || static::isTraversable($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<iterable> $value + * + * @deprecated use "isIterable" or "isInstanceOf" instead + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsTraversable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isTraversable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<iterable|null> $value + * + * @deprecated use "isIterable" or "isInstanceOf" instead + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsTraversable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isTraversable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert array|ArrayAccess|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsArrayAccessible($value, $message = '') + { + null === $value || static::isArrayAccessible($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<array|ArrayAccess> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsArrayAccessible($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isArrayAccessible($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<array|ArrayAccess|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsArrayAccessible($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isArrayAccessible($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert countable|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsCountable($value, $message = '') + { + null === $value || static::isCountable($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<countable> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsCountable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isCountable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<countable|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsCountable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isCountable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsIterable($value, $message = '') + { + null === $value || static::isIterable($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<iterable> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsIterable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isIterable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<iterable|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsIterable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isIterable($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert ExpectedType|null $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsInstanceOf($value, $class, $message = '') + { + null === $value || static::isInstanceOf($value, $class, $message); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert iterable<ExpectedType> $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsInstanceOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isInstanceOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert iterable<ExpectedType|null> $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsInstanceOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isInstanceOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotInstanceOf($value, $class, $message = '') + { + null === $value || static::notInstanceOf($value, $class, $message); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotInstanceOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notInstanceOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert iterable<!ExpectedType|null> $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotInstanceOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notInstanceOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-param array<class-string> $classes + * + * @param mixed $value + * @param array<object|string> $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsInstanceOfAny($value, $classes, $message = '') + { + null === $value || static::isInstanceOfAny($value, $classes, $message); + } + + /** + * @psalm-pure + * @psalm-param array<class-string> $classes + * + * @param mixed $value + * @param array<object|string> $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsInstanceOfAny($value, $classes, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isInstanceOfAny($entry, $classes, $message); + } + } + + /** + * @psalm-pure + * @psalm-param array<class-string> $classes + * + * @param mixed $value + * @param array<object|string> $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsInstanceOfAny($value, $classes, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isInstanceOfAny($entry, $classes, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert ExpectedType|class-string<ExpectedType>|null $value + * + * @param object|string|null $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsAOf($value, $class, $message = '') + { + null === $value || static::isAOf($value, $class, $message); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert iterable<ExpectedType|class-string<ExpectedType>> $value + * + * @param iterable<object|string> $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsAOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isAOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert iterable<ExpectedType|class-string<ExpectedType>|null> $value + * + * @param iterable<object|string|null> $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsAOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isAOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template UnexpectedType of object + * @psalm-param class-string<UnexpectedType> $class + * + * @param object|string|null $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsNotA($value, $class, $message = '') + { + null === $value || static::isNotA($value, $class, $message); + } + + /** + * @psalm-pure + * @psalm-template UnexpectedType of object + * @psalm-param class-string<UnexpectedType> $class + * + * @param iterable<object|string> $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsNotA($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isNotA($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template UnexpectedType of object + * @psalm-param class-string<UnexpectedType> $class + * @psalm-assert iterable<!UnexpectedType|null> $value + * @psalm-assert iterable<!class-string<UnexpectedType>|null> $value + * + * @param iterable<object|string|null> $value + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsNotA($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isNotA($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-param array<class-string> $classes + * + * @param object|string|null $value + * @param string[] $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsAnyOf($value, $classes, $message = '') + { + null === $value || static::isAnyOf($value, $classes, $message); + } + + /** + * @psalm-pure + * @psalm-param array<class-string> $classes + * + * @param iterable<object|string> $value + * @param string[] $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsAnyOf($value, $classes, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isAnyOf($entry, $classes, $message); + } + } + + /** + * @psalm-pure + * @psalm-param array<class-string> $classes + * + * @param iterable<object|string|null> $value + * @param string[] $classes + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsAnyOf($value, $classes, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isAnyOf($entry, $classes, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert empty $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsEmpty($value, $message = '') + { + null === $value || static::isEmpty($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<empty> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::isEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<empty|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::isEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotEmpty($value, $message = '') + { + null === $value || static::notEmpty($value, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<!empty|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotEmpty($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notEmpty($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNull($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::null($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotNull($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notNull($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert true|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrTrue($value, $message = '') + { + null === $value || static::true($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<true> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allTrue($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::true($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<true|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrTrue($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::true($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert false|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrFalse($value, $message = '') + { + null === $value || static::false($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<false> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allFalse($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::false($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<false|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrFalse($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::false($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotFalse($value, $message = '') + { + null === $value || static::notFalse($value, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotFalse($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notFalse($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<!false|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotFalse($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notFalse($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIp($value, $message = '') + { + null === $value || static::ip($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIp($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::ip($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIp($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::ip($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIpv4($value, $message = '') + { + null === $value || static::ipv4($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIpv4($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::ipv4($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIpv4($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::ipv4($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIpv6($value, $message = '') + { + null === $value || static::ipv6($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIpv6($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::ipv6($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIpv6($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::ipv6($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrEmail($value, $message = '') + { + null === $value || static::email($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allEmail($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::email($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrEmail($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::email($entry, $message); + } + } + + /** + * @param array|null $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrUniqueValues($values, $message = '') + { + null === $values || static::uniqueValues($values, $message); + } + + /** + * @param iterable<array> $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allUniqueValues($values, $message = '') + { + static::isIterable($values); + + foreach ($values as $entry) { + static::uniqueValues($entry, $message); + } + } + + /** + * @param iterable<array|null> $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrUniqueValues($values, $message = '') + { + static::isIterable($values); + + foreach ($values as $entry) { + null === $entry || static::uniqueValues($entry, $message); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrEq($value, $expect, $message = '') + { + null === $value || static::eq($value, $expect, $message); + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allEq($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::eq($entry, $expect, $message); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrEq($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::eq($entry, $expect, $message); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotEq($value, $expect, $message = '') + { + null === $value || static::notEq($value, $expect, $message); + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotEq($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notEq($entry, $expect, $message); + } + } + + /** + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotEq($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notEq($entry, $expect, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrSame($value, $expect, $message = '') + { + null === $value || static::same($value, $expect, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allSame($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::same($entry, $expect, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrSame($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::same($entry, $expect, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotSame($value, $expect, $message = '') + { + null === $value || static::notSame($value, $expect, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotSame($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notSame($entry, $expect, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $expect + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotSame($value, $expect, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notSame($entry, $expect, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrGreaterThan($value, $limit, $message = '') + { + null === $value || static::greaterThan($value, $limit, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allGreaterThan($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::greaterThan($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrGreaterThan($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::greaterThan($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrGreaterThanEq($value, $limit, $message = '') + { + null === $value || static::greaterThanEq($value, $limit, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allGreaterThanEq($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::greaterThanEq($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrGreaterThanEq($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::greaterThanEq($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrLessThan($value, $limit, $message = '') + { + null === $value || static::lessThan($value, $limit, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allLessThan($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::lessThan($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrLessThan($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::lessThan($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrLessThanEq($value, $limit, $message = '') + { + null === $value || static::lessThanEq($value, $limit, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allLessThanEq($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::lessThanEq($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $limit + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrLessThanEq($value, $limit, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::lessThanEq($entry, $limit, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $min + * @param mixed $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrRange($value, $min, $max, $message = '') + { + null === $value || static::range($value, $min, $max, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $min + * @param mixed $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allRange($value, $min, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::range($entry, $min, $max, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param mixed $min + * @param mixed $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrRange($value, $min, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::range($entry, $min, $max, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrOneOf($value, $values, $message = '') + { + null === $value || static::oneOf($value, $values, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allOneOf($value, $values, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::oneOf($entry, $values, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrOneOf($value, $values, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::oneOf($entry, $values, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrInArray($value, $values, $message = '') + { + null === $value || static::inArray($value, $values, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allInArray($value, $values, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::inArray($entry, $values, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param array $values + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrInArray($value, $values, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::inArray($entry, $values, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrContains($value, $subString, $message = '') + { + null === $value || static::contains($value, $subString, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allContains($value, $subString, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::contains($entry, $subString, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrContains($value, $subString, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::contains($entry, $subString, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotContains($value, $subString, $message = '') + { + null === $value || static::notContains($value, $subString, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotContains($value, $subString, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notContains($entry, $subString, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $subString + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotContains($value, $subString, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notContains($entry, $subString, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotWhitespaceOnly($value, $message = '') + { + null === $value || static::notWhitespaceOnly($value, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotWhitespaceOnly($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notWhitespaceOnly($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotWhitespaceOnly($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notWhitespaceOnly($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrStartsWith($value, $prefix, $message = '') + { + null === $value || static::startsWith($value, $prefix, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allStartsWith($value, $prefix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::startsWith($entry, $prefix, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrStartsWith($value, $prefix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::startsWith($entry, $prefix, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotStartsWith($value, $prefix, $message = '') + { + null === $value || static::notStartsWith($value, $prefix, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotStartsWith($value, $prefix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notStartsWith($entry, $prefix, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $prefix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotStartsWith($value, $prefix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notStartsWith($entry, $prefix, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrStartsWithLetter($value, $message = '') + { + null === $value || static::startsWithLetter($value, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allStartsWithLetter($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::startsWithLetter($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrStartsWithLetter($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::startsWithLetter($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrEndsWith($value, $suffix, $message = '') + { + null === $value || static::endsWith($value, $suffix, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allEndsWith($value, $suffix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::endsWith($entry, $suffix, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrEndsWith($value, $suffix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::endsWith($entry, $suffix, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotEndsWith($value, $suffix, $message = '') + { + null === $value || static::notEndsWith($value, $suffix, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotEndsWith($value, $suffix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notEndsWith($entry, $suffix, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $suffix + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotEndsWith($value, $suffix, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notEndsWith($entry, $suffix, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrRegex($value, $pattern, $message = '') + { + null === $value || static::regex($value, $pattern, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allRegex($value, $pattern, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::regex($entry, $pattern, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrRegex($value, $pattern, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::regex($entry, $pattern, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrNotRegex($value, $pattern, $message = '') + { + null === $value || static::notRegex($value, $pattern, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNotRegex($value, $pattern, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::notRegex($entry, $pattern, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $pattern + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrNotRegex($value, $pattern, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::notRegex($entry, $pattern, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrUnicodeLetters($value, $message = '') + { + null === $value || static::unicodeLetters($value, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allUnicodeLetters($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::unicodeLetters($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrUnicodeLetters($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::unicodeLetters($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrAlpha($value, $message = '') + { + null === $value || static::alpha($value, $message); + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allAlpha($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::alpha($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrAlpha($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::alpha($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrDigits($value, $message = '') + { + null === $value || static::digits($value, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allDigits($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::digits($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrDigits($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::digits($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrAlnum($value, $message = '') + { + null === $value || static::alnum($value, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allAlnum($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::alnum($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrAlnum($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::alnum($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert lowercase-string|null $value + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrLower($value, $message = '') + { + null === $value || static::lower($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<lowercase-string> $value + * + * @param iterable<string> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allLower($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::lower($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<lowercase-string|null> $value + * + * @param iterable<string|null> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrLower($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::lower($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrUpper($value, $message = '') + { + null === $value || static::upper($value, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allUpper($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::upper($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<!lowercase-string|null> $value + * + * @param iterable<string|null> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrUpper($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::upper($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param int $length + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrLength($value, $length, $message = '') + { + null === $value || static::length($value, $length, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param int $length + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allLength($value, $length, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::length($entry, $length, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param int $length + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrLength($value, $length, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::length($entry, $length, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMinLength($value, $min, $message = '') + { + null === $value || static::minLength($value, $min, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMinLength($value, $min, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::minLength($entry, $min, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMinLength($value, $min, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::minLength($entry, $min, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMaxLength($value, $max, $message = '') + { + null === $value || static::maxLength($value, $max, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMaxLength($value, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::maxLength($entry, $max, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMaxLength($value, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::maxLength($entry, $max, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrLengthBetween($value, $min, $max, $message = '') + { + null === $value || static::lengthBetween($value, $min, $max, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allLengthBetween($value, $min, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::lengthBetween($entry, $min, $max, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrLengthBetween($value, $min, $max, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::lengthBetween($entry, $min, $max, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrFileExists($value, $message = '') + { + null === $value || static::fileExists($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allFileExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::fileExists($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrFileExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::fileExists($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrFile($value, $message = '') + { + null === $value || static::file($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allFile($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::file($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrFile($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::file($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrDirectory($value, $message = '') + { + null === $value || static::directory($value, $message); + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allDirectory($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::directory($entry, $message); + } + } + + /** + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrDirectory($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::directory($entry, $message); + } + } + + /** + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrReadable($value, $message = '') + { + null === $value || static::readable($value, $message); + } + + /** + * @param iterable<string> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allReadable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::readable($entry, $message); + } + } + + /** + * @param iterable<string|null> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrReadable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::readable($entry, $message); + } + } + + /** + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrWritable($value, $message = '') + { + null === $value || static::writable($value, $message); + } + + /** + * @param iterable<string> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allWritable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::writable($entry, $message); + } + } + + /** + * @param iterable<string|null> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrWritable($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::writable($entry, $message); + } + } + + /** + * @psalm-assert class-string|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrClassExists($value, $message = '') + { + null === $value || static::classExists($value, $message); + } + + /** + * @psalm-assert iterable<class-string> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allClassExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::classExists($entry, $message); + } + } + + /** + * @psalm-assert iterable<class-string|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrClassExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::classExists($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert class-string<ExpectedType>|ExpectedType|null $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrSubclassOf($value, $class, $message = '') + { + null === $value || static::subclassOf($value, $class, $message); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert iterable<class-string<ExpectedType>|ExpectedType> $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allSubclassOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::subclassOf($entry, $class, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $class + * @psalm-assert iterable<class-string<ExpectedType>|ExpectedType|null> $value + * + * @param mixed $value + * @param string|object $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrSubclassOf($value, $class, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::subclassOf($entry, $class, $message); + } + } + + /** + * @psalm-assert class-string|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrInterfaceExists($value, $message = '') + { + null === $value || static::interfaceExists($value, $message); + } + + /** + * @psalm-assert iterable<class-string> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allInterfaceExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::interfaceExists($entry, $message); + } + } + + /** + * @psalm-assert iterable<class-string|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrInterfaceExists($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::interfaceExists($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $interface + * @psalm-assert class-string<ExpectedType>|null $value + * + * @param mixed $value + * @param mixed $interface + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrImplementsInterface($value, $interface, $message = '') + { + null === $value || static::implementsInterface($value, $interface, $message); + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $interface + * @psalm-assert iterable<class-string<ExpectedType>> $value + * + * @param mixed $value + * @param mixed $interface + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allImplementsInterface($value, $interface, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::implementsInterface($entry, $interface, $message); + } + } + + /** + * @psalm-pure + * @psalm-template ExpectedType of object + * @psalm-param class-string<ExpectedType> $interface + * @psalm-assert iterable<class-string<ExpectedType>|null> $value + * + * @param mixed $value + * @param mixed $interface + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrImplementsInterface($value, $interface, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::implementsInterface($entry, $interface, $message); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object|null $classOrObject + * + * @param string|object|null $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrPropertyExists($classOrObject, $property, $message = '') + { + null === $classOrObject || static::propertyExists($classOrObject, $property, $message); + } + + /** + * @psalm-pure + * @psalm-param iterable<class-string|object> $classOrObject + * + * @param iterable<string|object> $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allPropertyExists($classOrObject, $property, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + static::propertyExists($entry, $property, $message); + } + } + + /** + * @psalm-pure + * @psalm-param iterable<class-string|object|null> $classOrObject + * + * @param iterable<string|object|null> $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrPropertyExists($classOrObject, $property, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + null === $entry || static::propertyExists($entry, $property, $message); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object|null $classOrObject + * + * @param string|object|null $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrPropertyNotExists($classOrObject, $property, $message = '') + { + null === $classOrObject || static::propertyNotExists($classOrObject, $property, $message); + } + + /** + * @psalm-pure + * @psalm-param iterable<class-string|object> $classOrObject + * + * @param iterable<string|object> $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allPropertyNotExists($classOrObject, $property, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + static::propertyNotExists($entry, $property, $message); + } + } + + /** + * @psalm-pure + * @psalm-param iterable<class-string|object|null> $classOrObject + * + * @param iterable<string|object|null> $classOrObject + * @param mixed $property + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrPropertyNotExists($classOrObject, $property, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + null === $entry || static::propertyNotExists($entry, $property, $message); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object|null $classOrObject + * + * @param string|object|null $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMethodExists($classOrObject, $method, $message = '') + { + null === $classOrObject || static::methodExists($classOrObject, $method, $message); + } + + /** + * @psalm-pure + * @psalm-param iterable<class-string|object> $classOrObject + * + * @param iterable<string|object> $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMethodExists($classOrObject, $method, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + static::methodExists($entry, $method, $message); + } + } + + /** + * @psalm-pure + * @psalm-param iterable<class-string|object|null> $classOrObject + * + * @param iterable<string|object|null> $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMethodExists($classOrObject, $method, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + null === $entry || static::methodExists($entry, $method, $message); + } + } + + /** + * @psalm-pure + * @psalm-param class-string|object|null $classOrObject + * + * @param string|object|null $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMethodNotExists($classOrObject, $method, $message = '') + { + null === $classOrObject || static::methodNotExists($classOrObject, $method, $message); + } + + /** + * @psalm-pure + * @psalm-param iterable<class-string|object> $classOrObject + * + * @param iterable<string|object> $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMethodNotExists($classOrObject, $method, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + static::methodNotExists($entry, $method, $message); + } + } + + /** + * @psalm-pure + * @psalm-param iterable<class-string|object|null> $classOrObject + * + * @param iterable<string|object|null> $classOrObject + * @param mixed $method + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMethodNotExists($classOrObject, $method, $message = '') + { + static::isIterable($classOrObject); + + foreach ($classOrObject as $entry) { + null === $entry || static::methodNotExists($entry, $method, $message); + } + } + + /** + * @psalm-pure + * + * @param array|null $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrKeyExists($array, $key, $message = '') + { + null === $array || static::keyExists($array, $key, $message); + } + + /** + * @psalm-pure + * + * @param iterable<array> $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allKeyExists($array, $key, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::keyExists($entry, $key, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<array|null> $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrKeyExists($array, $key, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::keyExists($entry, $key, $message); + } + } + + /** + * @psalm-pure + * + * @param array|null $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrKeyNotExists($array, $key, $message = '') + { + null === $array || static::keyNotExists($array, $key, $message); + } + + /** + * @psalm-pure + * + * @param iterable<array> $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allKeyNotExists($array, $key, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::keyNotExists($entry, $key, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<array|null> $array + * @param string|int $key + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrKeyNotExists($array, $key, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::keyNotExists($entry, $key, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert array-key|null $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrValidArrayKey($value, $message = '') + { + null === $value || static::validArrayKey($value, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<array-key> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allValidArrayKey($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::validArrayKey($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<array-key|null> $value + * + * @param mixed $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrValidArrayKey($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::validArrayKey($entry, $message); + } + } + + /** + * @param Countable|array|null $array + * @param int $number + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrCount($array, $number, $message = '') + { + null === $array || static::count($array, $number, $message); + } + + /** + * @param iterable<Countable|array> $array + * @param int $number + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allCount($array, $number, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::count($entry, $number, $message); + } + } + + /** + * @param iterable<Countable|array|null> $array + * @param int $number + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrCount($array, $number, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::count($entry, $number, $message); + } + } + + /** + * @param Countable|array|null $array + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMinCount($array, $min, $message = '') + { + null === $array || static::minCount($array, $min, $message); + } + + /** + * @param iterable<Countable|array> $array + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMinCount($array, $min, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::minCount($entry, $min, $message); + } + } + + /** + * @param iterable<Countable|array|null> $array + * @param int|float $min + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMinCount($array, $min, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::minCount($entry, $min, $message); + } + } + + /** + * @param Countable|array|null $array + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrMaxCount($array, $max, $message = '') + { + null === $array || static::maxCount($array, $max, $message); + } + + /** + * @param iterable<Countable|array> $array + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allMaxCount($array, $max, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::maxCount($entry, $max, $message); + } + } + + /** + * @param iterable<Countable|array|null> $array + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrMaxCount($array, $max, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::maxCount($entry, $max, $message); + } + } + + /** + * @param Countable|array|null $array + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrCountBetween($array, $min, $max, $message = '') + { + null === $array || static::countBetween($array, $min, $max, $message); + } + + /** + * @param iterable<Countable|array> $array + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allCountBetween($array, $min, $max, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::countBetween($entry, $min, $max, $message); + } + } + + /** + * @param iterable<Countable|array|null> $array + * @param int|float $min + * @param int|float $max + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrCountBetween($array, $min, $max, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::countBetween($entry, $min, $max, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert list|null $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsList($array, $message = '') + { + null === $array || static::isList($array, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<list> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsList($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::isList($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<list|null> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsList($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::isList($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert non-empty-list|null $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsNonEmptyList($array, $message = '') + { + null === $array || static::isNonEmptyList($array, $message); + } + + /** + * @psalm-pure + * @psalm-assert iterable<non-empty-list> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsNonEmptyList($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::isNonEmptyList($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-assert iterable<non-empty-list|null> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsNonEmptyList($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::isNonEmptyList($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param mixed|array<T>|null $array + * @psalm-assert array<string, T>|null $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsMap($array, $message = '') + { + null === $array || static::isMap($array, $message); + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param iterable<mixed|array<T>> $array + * @psalm-assert iterable<array<string, T>> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsMap($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::isMap($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param iterable<mixed|array<T>|null> $array + * @psalm-assert iterable<array<string, T>|null> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsMap($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::isMap($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param mixed|array<T>|null $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrIsNonEmptyMap($array, $message = '') + { + null === $array || static::isNonEmptyMap($array, $message); + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param iterable<mixed|array<T>> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allIsNonEmptyMap($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + static::isNonEmptyMap($entry, $message); + } + } + + /** + * @psalm-pure + * @psalm-template T + * @psalm-param iterable<mixed|array<T>|null> $array + * @psalm-assert iterable<array<string, T>|null> $array + * @psalm-assert iterable<!empty|null> $array + * + * @param mixed $array + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrIsNonEmptyMap($array, $message = '') + { + static::isIterable($array); + + foreach ($array as $entry) { + null === $entry || static::isNonEmptyMap($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param string|null $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrUuid($value, $message = '') + { + null === $value || static::uuid($value, $message); + } + + /** + * @psalm-pure + * + * @param iterable<string> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allUuid($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + static::uuid($entry, $message); + } + } + + /** + * @psalm-pure + * + * @param iterable<string|null> $value + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrUuid($value, $message = '') + { + static::isIterable($value); + + foreach ($value as $entry) { + null === $entry || static::uuid($entry, $message); + } + } + + /** + * @psalm-param class-string<Throwable> $class + * + * @param Closure|null $expression + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function nullOrThrows($expression, $class = 'Exception', $message = '') + { + null === $expression || static::throws($expression, $class, $message); + } + + /** + * @psalm-param class-string<Throwable> $class + * + * @param iterable<Closure> $expression + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allThrows($expression, $class = 'Exception', $message = '') + { + static::isIterable($expression); + + foreach ($expression as $entry) { + static::throws($entry, $class, $message); + } + } + + /** + * @psalm-param class-string<Throwable> $class + * + * @param iterable<Closure|null> $expression + * @param string $class + * @param string $message + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function allNullOrThrows($expression, $class = 'Exception', $message = '') + { + static::isIterable($expression); + + foreach ($expression as $entry) { + null === $entry || static::throws($entry, $class, $message); + } + } +}